diff --git a/build.gradle b/build.gradle index da6b0daf8..ee9bc6278 100644 --- a/build.gradle +++ b/build.gradle @@ -36,7 +36,7 @@ allprojects { group 'com.fr.design' version frDevVersion sourceCompatibility = languageLevelSetting - targetCompatibility = languageLevelSetting + targetCompatibility = languageLevelSetting tasks.withType(JavaCompile) { options.encoding = "UTF-8" @@ -49,8 +49,8 @@ allprojects { idea { module { inheritOutputDirs = false - outputDir = file(outputPath +"/classes") - testOutputDir = file(outputPath +"/test-classes") + outputDir = file(outputPath + "/classes") + testOutputDir = file(outputPath + "/test-classes") languageLevel = new IdeaLanguageLevel(sourceCompatibility) targetBytecodeVersion = targetCompatibility } @@ -77,6 +77,7 @@ allprojects { implementation 'com.fr.decision:fine-decision:' + frVersion implementation 'com.fr.schedule:fine-schedule:' + frVersion implementation 'com.fr.report:engine-report:' + frDevVersion + implementation 'com.fr.report:engine-x:' + frDevVersion implementation 'com.fr.report:engine-chart:' + frDevVersion implementation 'com.fr.report:engine-i18n:' + frDevVersion implementation 'com.fr.design:design-i18n:' + frDevVersion diff --git a/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java b/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java index ed8f2208e..3eb3b7857 100644 --- a/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java +++ b/designer-base/src/main/java/com/fr/design/DesignModelAdapter.java @@ -302,7 +302,7 @@ public abstract class DesignModelAdapter"); @@ -383,6 +392,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { } } + private File getOldEnvFile(String version) { + return new File(getEnvHome(version) + File.separator + getEnvFile().getName()); + } + private static String getEnvHome(String version) { String userHome = System.getProperty("user.home"); if (userHome == null) { @@ -1349,6 +1362,24 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.maxNumberOrPreviewRow = maxNumberOrPreviewRow; } + /** + * 启动时是否打开空报表 + * + * @return 是否打开空报表 + */ + public boolean isStartWithEmptyFile() { + return startWithEmptyFile; + } + + /** + * 设置启动时是否打开空报表 + * + * @param startWithEmptyFile 是否打开空报表 + */ + public void setStartWithEmptyFile(boolean startWithEmptyFile) { + this.startWithEmptyFile = startWithEmptyFile; + } + /** * 是否展示工程界面 * @@ -1836,6 +1867,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.setSupportCellEditorDef(reader.getAttrAsBoolean("supportCellEditorDef", false)); this.setDragPermited(reader.getAttrAsBoolean("isDragPermited", false)); this.setUndoLimit(reader.getAttrAsInt("undoLimit", 5)); + this.setStartWithEmptyFile(reader.getAttrAsBoolean("startWithEmptyFile", false)); this.setDefaultStringToFormula(reader.getAttrAsBoolean("defaultStringToFormula", false)); if ((tmpVal = reader.getAttrAsString("gridLineColor", null)) != null) { this.setGridLineColor(new Color(Integer.parseInt(tmpVal))); @@ -2211,6 +2243,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { .attr("gridLineColor", this.getGridLineColor().getRGB()) .attr("paginationLineColor", this.getPaginationLineColor().getRGB()) .attr("undoLimit", this.getUndoLimit()) + .attr("startWithEmptyFile", this.isStartWithEmptyFile()) .end(); } diff --git a/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java b/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java index 4aa48591f..4d1493e01 100644 --- a/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java +++ b/designer-base/src/main/java/com/fr/design/ExtraDesignClassManager.java @@ -18,6 +18,7 @@ import com.fr.design.fun.TableDataDefineProvider; import com.fr.design.fun.ToolbarItemProvider; import com.fr.design.gui.core.WidgetOption; import com.fr.design.gui.core.WidgetOptionFactory; +import com.fr.design.mainframe.mobile.utils.MobileStyleProviderManager; import com.fr.design.menu.ShortCut; import com.fr.design.widget.Appearance; import com.fr.design.widget.mobile.WidgetMobilePane; @@ -269,11 +270,10 @@ public class ExtraDesignClassManager extends AbstractExtraClassManager implement public MobileWidgetStyleProvider[] getMobileStyleOfWidget(String xType) { Set set = getArray(MobileWidgetStyleProvider.XML_TAG); - if (set.isEmpty()) { - return new MobileWidgetStyleProvider[0]; - } + Set allSet = MobileStyleProviderManager.getArray(MobileWidgetStyleProvider.XML_TAG); + allSet.addAll(set); List providers = new ArrayList<>(); - for (MobileWidgetStyleProvider provider : set) { + for (MobileWidgetStyleProvider provider : allSet) { if (ComparatorUtils.equalsIgnoreCase(provider.xTypeForWidget(), xType)) { providers.add(provider); } diff --git a/designer-base/src/main/java/com/fr/design/actions/file/BatchCompileAction.java b/designer-base/src/main/java/com/fr/design/actions/file/BatchCompileAction.java new file mode 100644 index 000000000..812d89e5f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/file/BatchCompileAction.java @@ -0,0 +1,47 @@ +package com.fr.design.actions.file; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.transform.ui.BatchTransformPane; + +import javax.swing.KeyStroke; +import java.awt.Dialog; +import java.awt.event.ActionEvent; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchCompileAction extends UpdateAction { + public BatchCompileAction() { + this.setMenuKeySet(COMPILE); + this.setName(getMenuKeySet().getMenuKeySetName() + "..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/batch_transform.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + BatchTransformPane batchTransformPane = new BatchTransformPane(); + Dialog dialog = batchTransformPane.showDialog(); + dialog.setVisible(true); + } + + private static final MenuKeySet COMPILE = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'C'; + } + + @Override + public String getMenuName() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} diff --git a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java index 24e359d6f..2e32eb88c 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java @@ -12,6 +12,7 @@ import com.fr.design.editor.editor.IntegerEditor; import com.fr.design.gui.frpane.UITabbedPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UINoThemeColorButton; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.icombobox.UIDictionaryComboBox; @@ -179,7 +180,7 @@ public class PreferencePane extends BasicPane { private UICheckBox gcEnableCheckBox; private UIButton gcButton; private UILabel remindVcsLabel; - + private UICheckBox startWithEmptyFile; private JDialog gcDialog; private UILabel gcMessage = new UILabel(); private JPanel gcDialogDownPane = new JPanel(); @@ -346,18 +347,23 @@ public class PreferencePane extends BasicPane { } private void createFunctionPane(JPanel generalPane) { - JPanel functionPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Function")); - generalPane.add(functionPane); + JPanel topVerticalTitledBorderPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Function")); + JPanel upper = new JPanel(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); + JPanel lower = new JPanel(FRGUIPaneFactory.createLeftZeroVgapNormalHgapLayout()); + topVerticalTitledBorderPane.add(upper); + topVerticalTitledBorderPane.add(lower); + generalPane.add(topVerticalTitledBorderPane); + //添加supportUndo选择项 supportUndoCheckBox = new UICheckBox(i18nText("Fine-Design_Basic_Preference_Support_Undo")); - functionPane.add(supportUndoCheckBox); + upper.add(supportUndoCheckBox); //添加maxUndoLimit //String[] undoTimes = {"最大撤销次数","5次","10次","15次","20次","50次"}; String[] undoTimes = {i18nText("Fine-Design_Basic_Max_Undo_Limit"), MAX_UNDO_LIMIT_5 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_10 + i18nText("Fine-Design_Basic_Time(s)") , MAX_UNDO_LIMIT_15 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_20 + i18nText("Fine-Design_Basic_Time(s)"), MAX_UNDO_LIMIT_50 + i18nText("Fine-Design_Basic_Time(s)")}; maxUndoLimit = new UIComboBox(undoTimes); - functionPane.add(maxUndoLimit); + upper.add(maxUndoLimit); //不支持撤销则不能选择撤销可缓存,也不能设置最大撤销次数 supportUndoCheckBox.addActionListener(new ActionListener() { @@ -371,12 +377,14 @@ public class PreferencePane extends BasicPane { //添加supportDefaultParentCalculate选择项 supportDefaultParentCalculateCheckBox = new UICheckBox( i18nText("Fine-Design_Basic_Preference_Support_Default_Parent_Calculate")); - functionPane.add(supportDefaultParentCalculateCheckBox); + upper.add(supportDefaultParentCalculateCheckBox); //添加是否展示打开模板提示缺少插件选择项 showTemplateMissingPlugin = new UICheckBox( i18nText("Fine-Design_Basic_Preference_Show-Template-Missing-Plugin")); - functionPane.add(showTemplateMissingPlugin); + upper.add(showTemplateMissingPlugin); + startWithEmptyFile = new UICheckBox(i18nText("Fine-Design_Basic_Preference_Start_Empty_File")); + lower.add(startWithEmptyFile); } private void createEditPane(JPanel generalPane) { @@ -467,10 +475,10 @@ public class PreferencePane extends BasicPane { JPanel colorSettingPane = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Basic_Preference_Setting_Colors")); generalPane.add(colorSettingPane); - gridLineColorTBButton = new UIColorButton(IOUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); + gridLineColorTBButton = new UINoThemeColorButton(IOUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); gridLineColorTBButton.setEnabled(this.isEnabled()); - paginationLineColorTBButton = new UIColorButton(IOUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); + paginationLineColorTBButton = new UINoThemeColorButton(IOUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); paginationLineColorTBButton.setEnabled(this.isEnabled()); JPanel leftPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); @@ -729,6 +737,7 @@ public class PreferencePane extends BasicPane { } this.embedServerLazyStartupCheckBox.setSelected(designerEnvManager.isEmbedServerLazyStartup()); + this.startWithEmptyFile.setSelected(designerEnvManager.isStartWithEmptyFile()); this.imageCompressPanelCheckBox.setSelected(designerEnvManager.isImageCompress()); } @@ -815,7 +824,7 @@ public class PreferencePane extends BasicPane { if (maxUndoLimit.getSelectedIndex() == SELECTED_INDEX_5) { designerEnvManager.setUndoLimit(MAX_UNDO_LIMIT_50); } - + designerEnvManager.setStartWithEmptyFile(startWithEmptyFile.isSelected()); if (WorkContext.getCurrent().isLocal()) { Configurations.update(new Worker() { @Override diff --git a/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java b/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java index f1094d331..51a390c82 100644 --- a/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java @@ -31,10 +31,6 @@ public class TutorialAction extends AbstractDesignerSSO { return CloudCenter.getInstance().acquireUrlByKind(createDocKey(), "http://help.finereport.com"); } - public String getOffLineWarnMessage() { - return Toolkit.i18nText("Fine-Design_Offline_Helptutorial_Msg"); - } - // 生成帮助文档 sitecenter key, help.zh_CN.10 protected String createDocKey() { String locale = GeneralContext.getLocale().toString(); @@ -57,6 +53,10 @@ public class TutorialAction extends AbstractDesignerSSO { } } + public String getOffLineWarnMessage() { + return Toolkit.i18nText("Fine-Design_Offline_Helptutorial_Msg"); + } + public static final MenuKeySet HELP_TUTORIAL = new MenuKeySet() { @Override public char getMnemonic() { diff --git a/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java b/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java index ab85a14dc..bc1445718 100644 --- a/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java @@ -20,6 +20,9 @@ import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrame; import com.fr.design.menu.MenuKeySet; +import com.fr.esd.event.DSMapping; +import com.fr.esd.event.DsNameTarget; +import com.fr.esd.event.StrategyEventsNotifier; import com.fr.file.TableDataConfig; import com.fr.transaction.CallBackAdaptor; @@ -89,6 +92,7 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS protected void renameConnection(final String oldName, final String newName) { tableDataConfig.renameTableData(oldName, newName); + StrategyEventsNotifier.modifyDataSet(DSMapping.ofServerDS(new DsNameTarget(oldName))); } }; final BasicDialog globalTableDataDialog = globalTableDataPane.showWindowWithCustomSize(designerFrame, null, DEFAULT_DIMENSION); diff --git a/designer-base/src/main/java/com/fr/design/actions/server/LocalAnalyzerAction.java b/designer-base/src/main/java/com/fr/design/actions/server/LocalAnalyzerAction.java new file mode 100644 index 000000000..2db6e6aef --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/server/LocalAnalyzerAction.java @@ -0,0 +1,49 @@ +package com.fr.design.actions.server; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.design.utils.DesignUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.web.URLConstants; +import com.fr.stable.StableUtils; + +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; + +/** + * @author Maksim + * Created in 2020/11/5 11:44 上午 + */ +public class LocalAnalyzerAction extends UpdateAction { + + public LocalAnalyzerAction() { + this.setMenuKeySet(ANALYZER); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/analyzer.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + String path = StableUtils.pathJoin("/nx", URLConstants.ANALYZE_VIEW); + DesignUtils.visitEnvServerByParameters(path, new String[]{}, new String[]{}); + } + + private static final MenuKeySet ANALYZER = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'R'; + } + + @Override + public String getMenuName() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Analyzer_Menu_Name"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} diff --git a/designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java b/designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java new file mode 100644 index 000000000..393f217ce --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java @@ -0,0 +1,76 @@ +package com.fr.design.cell; + +import com.fr.base.NameStyle; +import com.fr.base.ScreenResolution; +import com.fr.base.Style; +import com.fr.general.IOUtils; + +import javax.swing.JPanel; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/3 + */ +public class CellStylePreviewPane extends JPanel { + + private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png"); + private final float transparentBackgroundWidth; + private final float transparentBackgroundHeight; + private String paintText = "Report"; + private Style style = Style.DEFAULT_STYLE; + + public CellStylePreviewPane() { + transparentBackgroundWidth = transparentBackgroundImage.getWidth(null); + transparentBackgroundHeight = transparentBackgroundImage.getHeight(null); + } + + public void setStyle(Style style) { + this.style = style; + if (style instanceof NameStyle) { + paintText = ((NameStyle) style).getName(); + } + repaint(); + } + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + int resolution = ScreenResolution.getScreenResolution(); + + int width = getWidth(); + int height = getHeight(); + + float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth; + float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight; + float maxScale = Math.max(scaleWidth, scaleHeight); + + if (maxScale <= 1) { + scaleWidth = scaleHeight = 1; + } else { + scaleHeight = scaleWidth = maxScale; + } + g2d.drawImage(transparentBackgroundImage, 0, 0, (int) (transparentBackgroundWidth * scaleWidth), (int) (transparentBackgroundHeight * scaleHeight), null); + + if (style == Style.DEFAULT_STYLE) { + // 如果是默认的style,就只写"Report"上去 + Style.paintContent(g2d, paintText, style, width, height, resolution); + return; + } + + Style.paintBackground(g2d, style, width, height); + + Style.paintContent(g2d, paintText, style, width, height, resolution); + + Style.paintBorder(g2d, style, width, height); + } + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java b/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java index f1758f068..ab86a0d6f 100644 --- a/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java +++ b/designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java @@ -161,10 +161,18 @@ public abstract class DesignTableDataManager { } public static String getChangedDsNameByOldDsName(String oldDsName) { + String changeName; + if (isDsNameChanged(oldDsName)) { - return dsNameChangedMap.get(oldDsName); + changeName = dsNameChangedMap.get(oldDsName); + } else { + changeName = StringUtils.EMPTY; + } + + if (StringUtils.isNotEmpty(changeName)) { + return getChangedDsNameByOldDsName(changeName); } else { - return StringUtils.EMPTY; + return oldDsName; } } diff --git a/designer-base/src/main/java/com/fr/design/data/StrategyConfigAttrUtils.java b/designer-base/src/main/java/com/fr/design/data/StrategyConfigAttrUtils.java new file mode 100644 index 000000000..e2a75fc11 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/StrategyConfigAttrUtils.java @@ -0,0 +1,136 @@ +package com.fr.design.data; + +import com.fr.base.io.IOFile; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.core.strategy.config.StrategyConfigHelper; +import com.fr.esd.core.strategy.config.service.StrategyConfigService; +import com.fr.esd.core.strategy.persistence.StrategyConfigsAttr; +import com.fr.esd.event.DSMapping; +import com.fr.esd.event.DsNameTarget; +import com.fr.esd.event.StrategyEventsNotifier; +import com.fr.esd.event.xml.XMLSavedHook; +import com.fr.file.FILE; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2020/10/28 + */ +public class StrategyConfigAttrUtils { + + /** + * 获取当前编辑模版的数据集缓存配置属性 + * + * @return + */ + private static StrategyConfigsAttr getStrategyConfigsAttr() { + StrategyConfigsAttr attr; + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (jTemplate != null) { + IOFile ioFile = (IOFile) jTemplate.getTarget(); + + attr = ioFile.getAttrMark(StrategyConfigsAttr.ATTR_MARK); + if (attr == null) { + attr = new StrategyConfigsAttr(); + ioFile.addAttrMark(attr); + } + + //新建模版此时不存在,不需要注册钩子 + if (attr.getXmlSavedHook() == null && WorkContext.getWorkResource().exist(jTemplate.getPath())) { + attr.setXmlSavedHook(new StrategyConfigsAttrSavedHook(jTemplate.getPath(), attr)); + } + return attr; + } else { + throw new IllegalStateException("[ESD]No editing template found."); + } + } + + + /** + * 获取模版数据集配置 + * + * @param dsName + * @return + */ + public static StrategyConfig getStrategyConfig(String dsName) { + + return getStrategyConfigsAttr().getStrategyConfig(dsName); + } + + /** + * 移除模版数据集配置 + * + * @param dsName + * @return + */ + public static StrategyConfig removeStrategyConfig(String dsName) { + + return getStrategyConfigsAttr().removeStrategyConfig(dsName); + } + + /** + * 添加模版数据集配置 + * + * @param strategyConfig + */ + public static void addStrategyConfig(StrategyConfig strategyConfig) { + + getStrategyConfigsAttr().addStrategyConfig(strategyConfig); + } + + + private static class StrategyConfigsAttrSavedHook implements XMLSavedHook { + + private static final long serialVersionUID = -8843201977112289321L; + + private final String tplPath; + private final Map origStrategyConfigs; + + public StrategyConfigsAttrSavedHook(String tplPath, StrategyConfigsAttr raw) { + this.tplPath = tplPath; + this.origStrategyConfigs = new HashMap<>(); + this.initOrigStrategyConfigs(raw); + } + + + private void initOrigStrategyConfigs(StrategyConfigsAttr raw) { + origStrategyConfigs.clear(); + raw.getStrategyConfigs().forEach((k, v) -> { + try { + origStrategyConfigs.put(k, v.clone()); + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + }); + } + + @Override + public void doAfterSaved(StrategyConfigsAttr saved) { + + FineLoggerFactory.getLogger().info("[ESD]Write StrategyConfigsAttr done, now check change."); + Set dsNames = new HashSet<>(); + dsNames.addAll(origStrategyConfigs.keySet()); + dsNames.addAll(saved.getStrategyConfigs().keySet()); + + if (StringUtils.isNotEmpty(tplPath)) { + dsNames.forEach(dsName -> { + if (StringUtils.isNotEmpty(dsName)) { + StrategyEventsNotifier.compareAndFireConfigEvents(origStrategyConfigs.get(dsName), saved.getStrategyConfig(dsName), new DSMapping(tplPath, new DsNameTarget(dsName))); + } + }); + } + + initOrigStrategyConfigs(saved); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java new file mode 100644 index 000000000..1fd840ac7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java @@ -0,0 +1,226 @@ +package com.fr.design.data.datapane; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.ActionLabel; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.esd.common.CacheConstants; +import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.core.strategy.config.StrategyConfigHelper; +import com.fr.esd.util.ESDUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; + +import javax.swing.AbstractAction; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Desktop; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2020/7/22 + */ +public class ESDStrategyConfigPane extends BasicBeanPane { + private static final String CRON_HELP_URL = "http://help.fanruan.com/finereport/doc-view-693.html"; + + private UIRadioButton selectAutoUpdate; + private UIRadioButton selectBySchema; + private UICheckBox shouldEvolve; + private UILabel updateIntervalCheckTips; + private UITextField updateInterval; + private UITextField schemaTime; + private ActionLabel actionLabel; + private UILabel schemaTimeCheckTips; + private final boolean global; + private StrategyConfig strategyConfig; + + + public ESDStrategyConfigPane(boolean global) { + this.global = global; + init(); + } + + private void init() { + setLayout(FRGUIPaneFactory.createM_BorderLayout()); + + this.selectAutoUpdate = new UIRadioButton(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Every_Interval")); + + this.updateInterval = new UITextField(4); + this.shouldEvolve = new UICheckBox(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Auto_Evolved_Strategy"), false); + this.shouldEvolve.setEnabled(false); + this.updateIntervalCheckTips = new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Interval_Format")); + this.updateIntervalCheckTips.setForeground(Color.RED); + this.updateIntervalCheckTips.setVisible(false); + + this.selectBySchema = new UIRadioButton(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cron")); + this.schemaTime = new UITextField(10); + this.schemaTimeCheckTips = new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Time_Format")); + this.schemaTimeCheckTips.setVisible(false); + this.schemaTimeCheckTips.setForeground(Color.RED); + + + this.selectAutoUpdate.addActionListener(new AbstractAction() { + public void actionPerformed(ActionEvent e) { + ESDStrategyConfigPane.this.selectBySchema.setSelected(!ESDStrategyConfigPane.this.selectAutoUpdate.isSelected()); + ESDStrategyConfigPane.this.schemaTime.setEnabled(false); + ESDStrategyConfigPane.this.updateInterval.setEnabled(true); + ESDStrategyConfigPane.this.shouldEvolve.setEnabled(true); + } + }); + + this.selectBySchema.addActionListener(new AbstractAction() { + public void actionPerformed(ActionEvent e) { + ESDStrategyConfigPane.this.selectAutoUpdate.setSelected(!ESDStrategyConfigPane.this.selectBySchema.isSelected()); + ESDStrategyConfigPane.this.schemaTime.setEnabled(true); + ESDStrategyConfigPane.this.updateInterval.setEnabled(false); + ESDStrategyConfigPane.this.shouldEvolve.setEnabled(false); + } + }); + + JPanel pane = FRGUIPaneFactory.createVerticalTitledBorderPane(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cache_Update_Strategy")); + add(pane, BorderLayout.NORTH); + + JPanel row1 = GUICoreUtils.createFlowPane(new Component[]{ + this.selectAutoUpdate, + this.updateInterval, + new UILabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Minute_Update_Cache")), + this.shouldEvolve, + this.updateIntervalCheckTips + }, 0, 5); + pane.add(row1); + + ActionLabel actionLabel = new ActionLabel(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cron_Help")); + actionLabel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + Desktop.getDesktop().browse(new URI(CRON_HELP_URL)); + } catch (Exception exp) { + FineLoggerFactory.getLogger().error(exp.getMessage(), e); + } + } + }); + + JPanel row2 = GUICoreUtils.createFlowPane(new Component[]{ + this.selectBySchema, + this.schemaTime, + actionLabel, + this.schemaTimeCheckTips + }, 0, 5); + pane.add(row2); + } + + + public void populateBean(StrategyConfig ob) { + + if (ob == null && !global) { + ob = StrategyConfigHelper.createStrategyConfig(true, false, true); + } + this.strategyConfig = ob; + + this.updateInterval.setText(ob.getUpdateInterval() <= 0 ? "0" : String.valueOf(ob.getUpdateInterval() / (double) CacheConstants.MILLIS_OF_MINUTE)); + this.schemaTime.setText(StringUtils.join(",", ob.getUpdateSchema().toArray(new String[0]))); + this.shouldEvolve.setSelected(ob.shouldEvolve()); + this.selectBySchema.setSelected(ob.isScheduleBySchema()); + this.selectAutoUpdate.setSelected(!ob.isScheduleBySchema()); + + if (global) { + //使用全局配置,禁用面板编辑 + disablePane(); + } else { + setSchemaEnable(!this.selectAutoUpdate.isSelected()); + } + } + + + private void disablePane() { + this.selectAutoUpdate.setEnabled(false); + this.updateInterval.setEnabled(false); + this.shouldEvolve.setEnabled(false); + + this.selectBySchema.setEnabled(false); + this.schemaTime.setEnabled(false); + } + + private void setSchemaEnable(boolean enable) { + this.updateInterval.setEnabled(!enable); + this.shouldEvolve.setEnabled(!enable); + + this.schemaTime.setEnabled(enable); + } + + + public StrategyConfig updateBean() { + StrategyConfig config = null; + if (!this.global) { + try { + //这里是new的config + config = this.strategyConfig.clone(); + + if (this.selectBySchema.isSelected()) { + List schemaTimes = new ArrayList<>(); + String text = this.schemaTime.getText(); + + if (ESDUtils.checkUpdateTimeSchema(text)) { + if (ESDUtils.isCronExpression(text)) { + schemaTimes.add(text); + } else { + Collections.addAll(schemaTimes, text.split(",")); + } + } else { + this.schemaTimeCheckTips.setVisible(true); + throw new IllegalArgumentException("[ESD]Update schema time format error."); + } + config.setScheduleBySchema(true); + config.setUpdateSchema(schemaTimes); + } else { + String interval = this.updateInterval.getText(); + if (checkUpdateInterval(interval)) { + long intervalMillis = StringUtils.isEmpty(interval) ? 0 : (long) (Double.parseDouble(interval) * CacheConstants.MILLIS_OF_MINUTE); + config.setUpdateInterval(intervalMillis); + } else { + this.updateIntervalCheckTips.setVisible(true); + throw new IllegalArgumentException("[ESD]Error update interval format."); + } + + config.setShouldEvolve(this.shouldEvolve.isSelected()); + config.setScheduleBySchema(false); + } + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + return config; + } + + + private boolean checkUpdateInterval(String intervalValue) { + try { + return !StringUtils.isEmpty(intervalValue) && !(Double.parseDouble(intervalValue) <= 0); + } catch (NumberFormatException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + return false; + } + + + protected String title4PopupWindow() { + return InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Cache_Strategy_Config_Title"); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java index 31630b85c..493d40d79 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java @@ -2,6 +2,7 @@ package com.fr.design.data.datapane; import com.fr.base.TableData; import com.fr.data.TableDataSource; +import com.fr.data.impl.DBTableData; import com.fr.data.impl.TableDataSourceDependent; import com.fr.design.DesignModelAdapter; import com.fr.design.ExtraDesignClassManager; @@ -10,52 +11,74 @@ import com.fr.design.constants.UIConstants; import com.fr.design.data.BasicTableDataTreePane; import com.fr.design.data.BasicTableDataUtils; import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.StrategyConfigAttrUtils; import com.fr.design.data.tabledata.StoreProcedureWorkerListener; import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane; import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; import com.fr.design.dialog.BasicDialog; -import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fun.TableDataPaneProcessor; import com.fr.design.gui.ibutton.UIHeadGroup; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.i18n.Toolkit; import com.fr.design.icon.IconPathConstants; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.LineSeparator; import com.fr.design.menu.MenuDef; import com.fr.design.menu.SeparatorDef; import com.fr.design.menu.ToolBarDef; +import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.core.strategy.config.StrategyConfigHelper; +import com.fr.esd.event.DSMapping; +import com.fr.esd.event.DsNameTarget; +import com.fr.esd.event.StrategyEventsNotifier; +import com.fr.esd.query.StrategicTableData; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; +import com.fr.general.IOUtils; import com.fr.general.NameObject; +import com.fr.log.FineLoggerFactory; import com.fr.plugin.context.PluginContext; import com.fr.plugin.injectable.PluginModule; import com.fr.plugin.manage.PluginFilter; import com.fr.plugin.observer.PluginEvent; import com.fr.plugin.observer.PluginEventListener; import com.fr.stable.core.PropertyChangeAdapter; +import org.jetbrains.annotations.NotNull; import javax.swing.BorderFactory; +import javax.swing.Icon; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import javax.swing.ToolTipManager; +import javax.swing.tree.TreePath; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.dnd.DnDConstants; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutionException; public class TableDataTreePane extends BasicTableDataTreePane { - private static TableDataTreePane singleton = new TableDataTreePane(); + private static final TableDataTreePane singleton = new TableDataTreePane(); public static final int PLUGIN_LISTENER_PRIORITY = 1; @@ -77,31 +100,44 @@ public class TableDataTreePane extends BasicTableDataTreePane { } private TableDataSourceOP op; - private TableDataTree dataTree; + private TableDataTree tableDataTree; private EditAction editAction; private RemoveAction removeAction; + private EsdOnAction esdAction; + private EsdOffAction esdOffAction; private PreviewTableDataAction previewTableDataAction; private TableDataTreePane() { + initPane(); + } + + private void initPane() { this.setLayout(new BorderLayout(4, 0)); this.setBorder(null); - dataTree = new TableDataTree(); - ToolTipManager.sharedInstance().registerComponent(dataTree); + + //TableDataTree + tableDataTree = new TableDataTree(); + ToolTipManager.sharedInstance().registerComponent(tableDataTree); ToolTipManager.sharedInstance().setDismissDelay(3000); ToolTipManager.sharedInstance().setInitialDelay(0); - addMenuDef = new MenuDef(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Action_Add")); - addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH); + + addMenuDef = new MenuDef(Toolkit.i18nText("Fine-Design_Basic_Action_Add")); + addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH); createAddMenuDef(); // 创建插件监听 createPluginListener(); editAction = new EditAction(); removeAction = new RemoveAction(); - previewTableDataAction = new PreviewTableDataAction(dataTree); + previewTableDataAction = new PreviewTableDataAction(tableDataTree); connectionTableAction = new ConnectionTableAction(); + esdAction = new EsdOnAction(); + esdOffAction = new EsdOffAction(); + + toolbarDef = new ToolBarDef(); - toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction); + toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction, esdAction, esdOffAction); UIToolbar toolBar = ToolBarDef.createJToolBar(); toolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.TOOLBAR_BORDER_COLOR)); toolBar.setBorderPainted(true); @@ -111,33 +147,32 @@ public class TableDataTreePane extends BasicTableDataTreePane { toolbarPane.add(toolBar, BorderLayout.CENTER); this.add(toolbarPane, BorderLayout.NORTH); - UIScrollPane scrollPane = new UIScrollPane(dataTree); + UIScrollPane scrollPane = new UIScrollPane(tableDataTree); scrollPane.setBorder(null); - initbuttonGroup(); + initButtonGroup(); JPanel jPanel = new JPanel(new BorderLayout(0, 0)); JPanel buttonPane = new JPanel(new GridLayout()); buttonPane.add(buttonGroup, BorderLayout.CENTER); jPanel.add(buttonPane, BorderLayout.NORTH); jPanel.add(scrollPane, BorderLayout.CENTER); this.add(jPanel, BorderLayout.CENTER); - dataTree.addMouseListener(new MouseAdapter() { + tableDataTree.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { checkButtonEnabled(); } }); - dataTree.addKeyListener(getTableTreeNodeListener(editAction, previewTableDataAction, removeAction, op, dataTree)); + tableDataTree.addKeyListener(getTableTreeNodeListener(editAction, previewTableDataAction, removeAction, op, tableDataTree)); // TreeCellEditor - dataTree.setEditable(true); - TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), dataTree, this); + tableDataTree.setEditable(true); + TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), tableDataTree, this); treeCellEditor.addCellEditorListener(treeCellEditor); - dataTree.setCellEditor(treeCellEditor); - new TableDataTreeDragSource(dataTree, DnDConstants.ACTION_COPY); + tableDataTree.setCellEditor(treeCellEditor); + new TableDataTreeDragSource(tableDataTree, DnDConstants.ACTION_COPY); checkButtonEnabled(); } private void createPluginListener() { - //菜单栏监听 GeneralContext.listenPluginRunningChanged(new PluginEventListener(PLUGIN_LISTENER_PRIORITY) { @@ -157,69 +192,113 @@ public class TableDataTreePane extends BasicTableDataTreePane { }); } - - protected void checkButtonEnabled() { - super.checkButtonEnabled(editAction, previewTableDataAction, removeAction, op, dataTree); - } - /** * 刷新 */ + @Override public void refreshDockingView() { populate(new TableDataSourceOP(tc)); this.checkButtonEnabled(); } - protected void initbuttonGroup() { -// Icon[] iconArray = {BaseUtils.readIcon("/com/fr/design/images/data/datasource.png"), BaseUtils.readIcon("/com/fr/design/images/data/dock/serverdatabase.png")}; - final Integer[] modeArray = {TEMPLATE_TABLE_DATA, SERVER_TABLE_DATA}; - String[] textArray = {com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tabledata_Source_Type_Template"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS_Server_TableData")}; - buttonGroup = new UIHeadGroup(textArray) { - public void tabChanged(int index) { - if (op != null) { - op.setDataMode(modeArray[buttonGroup.getSelectedIndex()]); - addMenuDef.setEnabled(modeArray[buttonGroup.getSelectedIndex()] == TEMPLATE_TABLE_DATA ? true : false); - refreshDockingView(); - } + + @Override + public final void createAddMenuDef() { + TableDataNameObjectCreator[] creators = TableDataCreatorProducer.getInstance().createReportTableDataCreator(); + for (final TableDataNameObjectCreator creator : creators) { + if (creator.shouldInsertSeparator()) { + addMenuDef.addShortCut(new LineSeparator()); } - }; - buttonGroup.setNeedLeftRightOutLine(false); + + addMenuDef.addShortCut(new AddAction() { + @Override + protected String getTDName() { + return creator.menuName(); + } + + @Override + protected Icon getTDIcon() { + return creator.menuIcon(); + } + + @Override + protected String getNamePrefix() { + return creator.getPrefix(); + } + + @Override + protected TemplateTableDataWrapper getTableDataInstance() { + TableData tableData = (TableData) creator.createObject(); + + //11中所有数据集都是StrategicTableData的子类 + if (tableData instanceof StrategicTableData) { + StrategicTableData std = (StrategicTableData) tableData; + tableData = StrategicTableData.Binder + .bind(std) + .setDsName(createDsName(creator.getPrefix())) + .setScope(StrategicTableData.Scope.TEMPLATE) + .done(); + } + return new TemplateTableDataWrapper(tableData); + } + }); + } } /** * 编辑面板 * - * @param uPanel 面板 - * @param originalName 原始名字 + * @param tableDataPane 面板 + * @param originalName 原始名字 */ - public void dgEdit(final AbstractTableDataPane uPanel, String originalName, boolean isUpdate) { - uPanel.addStoreProcedureWorkerListener(new StoreProcedureWorkerListener() { + @Override + public void dgEdit(final AbstractTableDataPane tableDataPane, String originalName, boolean isUpdate) { + tableDataPane.addStoreProcedureWorkerListener(new StoreProcedureWorkerListener() { public void fireDoneAction() { - if (dataTree.getSelectionPath() == null) { - dataTree.refresh(); + if (tableDataTree.getSelectionPath() == null) { + tableDataTree.refresh(); } else { - Object object = dataTree.getSelectionPath().getLastPathComponent(); - int[] rows = dataTree.getSelectionRows(); - dataTree.refreshChildByName(object.toString()); - dataTree.setSelectionRows(rows); + Object object = tableDataTree.getSelectionPath().getLastPathComponent(); + int[] rows = tableDataTree.getSelectionRows(); + tableDataTree.refreshChildByName(object.toString()); + tableDataTree.setSelectionRows(rows); } } }); - final BasicPane.NamePane nPanel = uPanel.asNamePane(); - nPanel.setObjectName(originalName); + final NamePane tdNamePanel = tableDataPane.asNamePane(); + tdNamePanel.setObjectName(originalName); + final String oldName = originalName; - final BasicDialog dg; allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); - dg = nPanel.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() { + + final BasicDialog dg = tdNamePanel.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() { + @Override public void doOk() { DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); - tc.renameTableData(oldName, nPanel.getObjectName(), false); + tc.renameTableData(oldName, tdNamePanel.getObjectName(), false); TableDataSource tds = tc.getBook(); - TableData td = uPanel.updateBean(); + TableData td = tableDataPane.updateBean(); if (td instanceof TableDataSourceDependent) { ((TableDataSourceDependent) td).setTableDataSource(tds); } - String tdName = nPanel.getObjectName(); + String tdName = tdNamePanel.getObjectName(); + + + //模版还没保存的时候不知道后缀,不能设置到策略配置里面 + if (tableDataPane instanceof DBTableDataPane) { + StrategyConfig editingConfig = ((DBTableDataPane) tableDataPane).updateStrategyConfig(); + if (editingConfig != null) { + editingConfig.setDsName(tdName); + if (!ComparatorUtils.equals(oldName, tdName)) { + //重命名 + StrategyConfigAttrUtils.removeStrategyConfig(oldName); + } + + StrategyConfigAttrUtils.addStrategyConfig(editingConfig); + } + ((DBTableData) td).setDsName(tdName); + } + tds.putTableData(tdName, td); Map map = new HashMap(); if (!ComparatorUtils.equals(oldName, tdName)) { @@ -227,83 +306,35 @@ public class TableDataTreePane extends BasicTableDataTreePane { } fireDSChanged(map); tc.fireTargetModified(); - tc.tableDataParametersChanged(oldName, tdName, td); - int[] rows = dataTree.getSelectionRows(); - dataTree.refreshChildByName(tdName); - dataTree.setSelectionRows(rows); + tc.parameterChanged(); + int[] rows = tableDataTree.getSelectionRows(); + tableDataTree.refreshChildByName(tdName); + tableDataTree.setSelectionRows(rows); + + + //单独编辑数据集关闭,修改缓存配置状态,刷新下一键开启/关闭按钮 + checkButtonEnabled(); + } + + @Override + public void doCancel() { + super.doCancel(); } }); - nPanel.addPropertyChangeListener(new PropertyChangeAdapter() { + tdNamePanel.addPropertyChangeListener(new PropertyChangeAdapter() { @Override public void propertyChange() { - doPropertyChange(dg, nPanel, oldName); + doPropertyChange(dg, tdNamePanel, oldName); } }); dg.setVisible(true); } - private class EditAction extends UpdateAction { - public EditAction() { - this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Edit")); - this.setMnemonic('E'); - this.setSmallIcon("/com/fr/design/images/control/edit"); - } - - public void actionPerformed(ActionEvent e) { - final NameObject selectedNO = dataTree.getSelectedNameObject(); - if (selectedNO == null) { - return; - } - DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName()); - dgEdit(((AbstractTableDataWrapper) selectedNO.getObject()).creatTableDataPane(), selectedNO.getName(), false); - } - } - - private class RemoveAction extends UpdateAction { - - public RemoveAction() { - this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove")); - this.setMnemonic('R'); - this.setSmallIcon("/com/fr/design/images/control/remove"); - } - - @Override - public void actionPerformed(ActionEvent e) { - NameObject selectedNO = dataTree.getSelectedNameObject(); - - if (selectedNO == null) { - return; - } - - int returnVal = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + ":" + selectedNO.getName() + "?", - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); - if (returnVal == JOptionPane.OK_OPTION) { - // richer:这个地方为什么要在DataSourceTree里面去remove呢?多此一举吧 - op.removeAction(selectedNO.getName()); - dataTree.refresh(); - // Richie:默认最后一行获得焦点. - dataTree.requestFocus(); - dataTree.setSelectionRow(dataTree.getRowCount() - 1); - fireDSChanged(); - checkButtonEnabled(); - DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName()); - DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(selectedNO.getName()); - } - } - } - - private void populate(TableDataSourceOP op) { - this.op = op; - dataTree.populate(op); - checkButtonEnabled(); - } - - - /** - * @return - */ - public TableDataTree getDataTree() { - return dataTree; + @Override + public void removeTableData(String sourceName) { + TableDataSource tds = this.tc.getBook(); + tds.removeTableData(sourceName); + this.tableDataTree.refresh(); } /** @@ -312,6 +343,7 @@ public class TableDataTreePane extends BasicTableDataTreePane { * @param srcName 数据集来源(比如报表块,就是报表块的名称) * @param tableDataSource 数据集 */ + @Override public Map addTableData(String srcName, TableDataSource tableDataSource, boolean isCover) { Map tdNameMap = new HashMap<>(); allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); @@ -322,39 +354,63 @@ public class TableDataTreePane extends BasicTableDataTreePane { String tdName = (String) tdIterator.next(); String oldName = tdName; TableData td = tableDataSource.getTableData(tdName); - boolean isDsNameRepeaded = isDsNameRepeaded(tdName); - tdName = BasicTableDataUtils.getTableDataName(isCover, tds, tdName, srcName, isDsNameRepeaded); + boolean isDsNameRepeated = isDsNameRepeaded(tdName); + tdName = BasicTableDataUtils.getTableDataName(isCover, tds, tdName, srcName, isDsNameRepeated); tds.putTableData(tdName, td); if (!ComparatorUtils.equals(oldName, tdName)) { tdNameMap.put(oldName, tdName); } } tc.parameterChanged(); - dataTree.refresh(); + tableDataTree.refresh(); return Collections.unmodifiableMap(tdNameMap); } + /** + * 合并数据集 + * + * @param srcName 数据集来源(比如报表块,就是报表块的名称) + * @param tableDataSource 数据集 + */ @Override - public void removeTableData(String sourceName) { + public Map addTableData(String srcName, TableDataSource tableDataSource) { + Map tdNameMap = new HashMap<>(); + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); TableDataSource tds = tc.getBook(); - tds.removeTableData(sourceName); - dataTree.refresh(); + Iterator tdIterator = tableDataSource.getTableDataNameIterator(); + while (tdIterator.hasNext()) { + String tdName = tdIterator.next(); + String oldName = tdName; + TableData td = tableDataSource.getTableData(tdName); + if (tds.getTableData(tdName) != null || isDsNameRepeaded(tdName)) { + //如果有同名的就拼上来源名称 + tdName = srcName + tdName; + } + int i = 0; + while (tds.getTableData(tdName) != null) { + i++;//如果拼上名字后依然已经存在就加编号 + tdName += i; + } + tds.putTableData(tdName, td); + if (!ComparatorUtils.equals(oldName, tdName)) { + tdNameMap.put(oldName, tdName); + } + } + tc.parameterChanged(); + tableDataTree.refresh(); + return Collections.unmodifiableMap(tdNameMap); } @Override - public void checkEnable() { - this.checkButtonEnabled(); - } - public void addDataPane(final AbstractTableDataPane uPanel, String paneName) { final NamePane nPanel = uPanel.asNamePane(); nPanel.setObjectName(paneName); - final String oldName = paneName; allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); - tc.renameTableData(oldName, nPanel.getObjectName(), false); + tc.renameTableData(paneName, nPanel.getObjectName(), false); TableDataSource tds = tc.getBook(); TableData td = uPanel.updateBean(); if (td instanceof TableDataSourceDependent) { @@ -363,14 +419,415 @@ public class TableDataTreePane extends BasicTableDataTreePane { String tdName = nPanel.getObjectName(); tds.putTableData(tdName, td); Map map = new HashMap(); - if (!ComparatorUtils.equals(oldName, tdName)) { - map.put(oldName, tdName); + if (!ComparatorUtils.equals(paneName, tdName)) { + map.put(paneName, tdName); } fireDSChanged(map); tc.fireTargetModified(); - tc.tableDataParametersChanged(oldName, tdName, td); - int[] rows = dataTree.getSelectionRows(); - dataTree.refreshChildByName(tdName); - dataTree.setSelectionRows(rows); + tc.parameterChanged(); + int[] rows = tableDataTree.getSelectionRows(); + tableDataTree.refreshChildByName(tdName); + tableDataTree.setSelectionRows(rows); + } + + @Override + public TableDataTree getDataTree() { + return this.tableDataTree; + } + + private void populate(TableDataSourceOP op) { + this.op = op; + tableDataTree.populate(op); + checkButtonEnabled(); + } + + + private void resetAddMenuDef() { + this.addMenuDef.clearShortCuts(); + this.createAddMenuDef(); + } + + private void checkButtonEnabled() { + super.checkButtonEnabled(editAction, previewTableDataAction, removeAction, op, tableDataTree); + this.checkESDComponentsEnabled(); + } + + + private void checkESDComponentsEnabled() { + if (buttonGroup.getSelectedIndex() == 1) { + //切换到服务器数据集的tab,禁用 + esdAction.setEnabled(false); + esdOffAction.setEnabled(false); + return; + } + + new SwingWorker() { + @Override + protected ButtonStatus doInBackground() throws Exception { + ButtonStatus btnStatus = new ButtonStatus(); + Map statusMap = checkCanBeEsdBatchEnableStatus(); + if (statusMap.size() == 0) { + //没有db数据集 + return btnStatus; + } else { + int canTurnOnCount = 0; + int canTurnOffCount = 0; + for (ESDStatus status : statusMap.values()) { + switch (status) { + case GLOBAL_ON: + case GLOBAL_OFF: + case SINGLE_OFF: + canTurnOnCount++; + break; + case SINGLE_ON: + canTurnOffCount++; + break; + default: + break; + } + } + btnStatus.setOnStatus(canTurnOnCount > 0); + btnStatus.setOffStatus(canTurnOffCount > 0); + } + return btnStatus; + } + + @Override + protected void done() { + try { + ButtonStatus buttonStatus = get(); + esdAction.setEnabled(buttonStatus.isOnStatus()); + esdOffAction.setEnabled(buttonStatus.isOffStatus()); + } catch (InterruptedException | ExecutionException e) { + FineLoggerFactory.getLogger().error("get esd status of ds error for " + e.getMessage(), e); + } + } + }.execute(); + } + + private static class ButtonStatus { + private boolean onStatus = false; + private boolean offStatus = false; + + public boolean isOnStatus() { + return onStatus; + } + + public void setOnStatus(boolean onStatus) { + this.onStatus = onStatus; + } + + public boolean isOffStatus() { + return offStatus; + } + + public void setOffStatus(boolean offStatus) { + this.offStatus = offStatus; + } + } + + //模版数据集 + private void initButtonGroup() { + final Integer[] modeArray = {TEMPLATE_TABLE_DATA, SERVER_TABLE_DATA}; + String[] textArray = {Toolkit.i18nText("Fine-Design_Basic_Tabledata_Source_Type_Template"), Toolkit.i18nText("Fine-Design_Basic_DS_Server_TableData")}; + buttonGroup = new UIHeadGroup(textArray) { + public void tabChanged(int index) { + if (op != null) { + op.setDataMode(modeArray[buttonGroup.getSelectedIndex()]); + addMenuDef.setEnabled(modeArray[buttonGroup.getSelectedIndex()] == TEMPLATE_TABLE_DATA); + refreshDockingView(); + + } + } + }; + buttonGroup.setNeedLeftRightOutLine(false); + } + + + private TableDataWrapper findTableDataWrapper(TreePath treePath) { + if (treePath != null) { + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) treePath.getLastPathComponent(); + Object selectedUserObject = selectedTreeNode.getUserObject(); + NameObject nameObject = null; + if (selectedUserObject instanceof NameObject) { + nameObject = (NameObject) selectedUserObject; + } else { + selectedTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + selectedUserObject = selectedTreeNode.getUserObject(); + if (selectedUserObject instanceof NameObject) { + nameObject = (NameObject) selectedUserObject; + } + } + if (nameObject != null && nameObject.getObject() instanceof TableDataWrapper) { + return (TableDataWrapper) nameObject.getObject(); + } + } + + return null; + } + + private String getTplPath() { + return HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getPath(); + } + + enum ESDStatus { + GLOBAL_ON, + GLOBAL_OFF, + SINGLE_ON, + SINGLE_OFF; + } + + + private Map checkCanBeEsdBatchEnableStatus() { + //<数据集, 是否可以被单独开启> + Map result = new HashMap<>(); + for (int i = 0; i < tableDataTree.getRowCount(); i++) { + TreePath treePath = tableDataTree.getPathForRow(i); + + TableDataWrapper wrapper = findTableDataWrapper(treePath); + if (wrapper.getTableData() instanceof DBTableData) { + DBTableData td = (DBTableData) wrapper.getTableData(); + + StrategyConfig config = StrategyConfigAttrUtils.getStrategyConfig(wrapper.getTableDataName()); + if (config == null) { + result.put(td, td.isShare() ? ESDStatus.SINGLE_ON : ESDStatus.SINGLE_OFF); + } else { + if (config.isUseGlobal()) { + if (StrategyConfigHelper.recommended(getTplPath())) { + result.put(td, ESDStatus.GLOBAL_ON); + } else { + result.put(td, ESDStatus.GLOBAL_OFF); + } + } else { + if (config.enabled()) { + result.put(td, ESDStatus.SINGLE_ON); + } else { + result.put(td, ESDStatus.SINGLE_OFF); + } + } + } + } + } + + return result; + } + + + private class EsdOnAction extends AbstractESDAction { + + @Override + public String getName() { + return Toolkit.i18nText("Fine-Design_ESD_Batch_Enable"); + } + + @Override + public Icon getIcon() { + return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_on.png"); + } + + @Override + public void doWithTableDataWrapper(TableDataWrapper wrapper) { + String dsName = wrapper.getTableDataName(); + if (wrapper.getTableData() instanceof DBTableData) { + StrategyConfig strategyConfig = getOrCreateStrategyConfig(dsName); + strategyConfig.setEnable(true); + strategyConfig.setUseGlobal(false); + StrategyConfigAttrUtils.addStrategyConfig(strategyConfig); + DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified(); + } + } + } + + private @NotNull StrategyConfig getOrCreateStrategyConfig(String dsName) { + StrategyConfig config = StrategyConfigAttrUtils.getStrategyConfig(dsName); + + if (config == null) { + config = StrategyConfigHelper.createStrategyConfig(true); + config.setDsName(dsName); + } + + return config; + } + + + private String createDsName(String prefix) { + int count = 1; + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + while (isDsNameRepeaded(prefix + count)) { + count++; + } + return prefix + count; + } + + + private class EsdOffAction extends AbstractESDAction { + + @Override + public String getName() { + return Toolkit.i18nText("Fine-Design_ESD_Batch_Disable"); + } + + @Override + public Icon getIcon() { + return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_off.png"); + } + + @Override + public void doWithTableDataWrapper(TableDataWrapper wrapper) { + String dsName = wrapper.getTableDataName(); + if (wrapper.getTableData() instanceof DBTableData) { + ((DBTableData) wrapper.getTableData()).setShare(false); + StrategyConfig strategyConfig = getOrCreateStrategyConfig(dsName); + strategyConfig.setEnable(false); + strategyConfig.setUseGlobal(false); + StrategyConfigAttrUtils.addStrategyConfig(strategyConfig); + DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified(); + } + } + } + + private abstract class AbstractESDAction extends UpdateAction { + + public abstract String getName(); + + public abstract Icon getIcon(); + + public abstract void doWithTableDataWrapper(TableDataWrapper tableDataWrapper); + + public AbstractESDAction() { + this.setName(getName()); + this.setMnemonic('R'); + this.setSmallIcon(getIcon()); + } + + @Override + public void actionPerformed(ActionEvent e) { + List tableDataWrapperList = new ArrayList<>(); + + for (int i = 0; i < tableDataTree.getRowCount(); i++) { + TreePath treePath = tableDataTree.getPathForRow(i); + TableDataWrapper wrapper = findTableDataWrapper(treePath); + if (wrapper != null) { + tableDataWrapperList.add(wrapper); + } + } + if (tableDataWrapperList.isEmpty()) { + return; + } + new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + for (TableDataWrapper tableDataWrapper : tableDataWrapperList) { + doWithTableDataWrapper(tableDataWrapper); + } + return null; + } + + @Override + protected void done() { + refreshDockingView(); + } + }.execute(); + } + } + + + /** + * 新建数据集 + *

+ * 抽象化,支持不同类型数据集创建 + */ + private abstract class AddAction extends UpdateAction { + + protected abstract String getTDName(); + + protected abstract Icon getTDIcon(); + + protected abstract String getNamePrefix(); + + protected abstract TemplateTableDataWrapper getTableDataInstance(); + + public AddAction() { + this.setName(this.getTDName()); + this.setSmallIcon(this.getTDIcon()); + } + + @Override + public void actionPerformed(ActionEvent e) { + dgEdit(getTableDataInstance().creatTableDataPane(), createDsName(getNamePrefix()), false); + } + } + + + private class EditAction extends UpdateAction { + public EditAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Edit")); + this.setMnemonic('E'); + this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_EDIT_ICON_PATH)); + } + + @Override + public void actionPerformed(ActionEvent e) { + final NameObject selectedNO = tableDataTree.getSelectedNameObject(); + if (selectedNO == null) { + return; + } + + String dsName = selectedNO.getName(); + DesignTableDataManager.removeSelectedColumnNames(dsName); + + AbstractTableDataWrapper wrapper = (AbstractTableDataWrapper) selectedNO.getObject(); + + AbstractTableDataPane tableDataPane = wrapper.creatTableDataPane(); + + //下面创建creatTableDataPane后会直接populate,所以populate时不能用后设置的一些参数,比如name + dgEdit(tableDataPane, dsName, false); + } + } + + private class RemoveAction extends UpdateAction { + + public RemoveAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Remove")); + this.setMnemonic('R'); + this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH)); + } + + @Override + public void actionPerformed(ActionEvent e) { + NameObject selectedNO = tableDataTree.getSelectedNameObject(); + + if (selectedNO == null) { + return; + } + + int returnVal = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + ":" + selectedNO.getName() + "?", + Toolkit.i18nText("Fine-Design_Basic_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (returnVal == JOptionPane.OK_OPTION) { + // richer:这个地方为什么要在DataSourceTree里面去remove呢?多此一举吧 + op.removeAction(selectedNO.getName()); + tableDataTree.refresh(); + // Richie:默认最后一行获得焦点. + tableDataTree.requestFocus(); + tableDataTree.setSelectionRow(tableDataTree.getRowCount() - 1); + fireDSChanged(); + checkButtonEnabled(); + + //删掉缓存配置 + StrategyConfigAttrUtils.removeStrategyConfig(selectedNO.getName()); + + // 如果一个模版是平台开启,这个数据集的配置不会存xml,预览模版时直接从全局配置copy,这样 + // 导致删除的时候StrategyConfigsAttrSavedHook没有通过前后配置比较感知数据集被删除,因此不会发出事件让其失效 + // 这里额外发出一次数据集修改事件 + StrategyEventsNotifier.modifyDataSet(new DSMapping(getTplPath(), new DsNameTarget(selectedNO.getName()))); + DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName()); + DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(selectedNO.getName()); + } + } + } + + @Override + public void checkEnable() { + this.checkButtonEnabled(); } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataComboBox.java b/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataComboBox.java index 8964ff8de..422a3a49a 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataComboBox.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataComboBox.java @@ -9,6 +9,7 @@ import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.icombobox.UIComboBoxRenderer; import com.fr.file.TableDataConfig; +import com.fr.stable.StringUtils; import javax.swing.*; import java.awt.*; @@ -80,12 +81,13 @@ public class TreeTableDataComboBox extends UIComboBox { } public void setSelectedTableDataByName(String name) { + refresh(); TableDataWrapper tableDataWrapper; - if (res_map.get(name) != null) { - tableDataWrapper = res_map.get(name); - } else { - String changeName = DesignTableDataManager.getChangedDsNameByOldDsName(name); + String changeName = DesignTableDataManager.getChangedDsNameByOldDsName(name); + if (StringUtils.isNotEmpty(changeName)) { tableDataWrapper = res_map.get(changeName); + } else { + tableDataWrapper = res_map.get(name); } this.getModel().setSelectedItem(tableDataWrapper); } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataDictPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataDictPane.java index f1f1c6c75..175ddbfda 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataDictPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TreeTableDataDictPane.java @@ -64,7 +64,7 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable { tableFlowPane.add(tableDataNameComboBox); tableDataNameComboBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { - tdChange(); + tdChange(true); } }); tableFlowPane.add(new PreviewLabel(this)); @@ -73,19 +73,21 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable { this.add(centerPane, BorderLayout.CENTER); parentMarkRadio = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Build_Tree_Accord_Parent_Marked_Filed"), true); lengthMarkRadio = new UIRadioButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Build_Tree_Accord_Marked_Filed_Length")); - parentMarkRadio.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { + parentMarkRadio.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { if (isBuildByParentFiled()) { makeParentEnable(); - tdChange(); + tdChange(false); } } }); - lengthMarkRadio.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { + lengthMarkRadio.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { if (!isBuildByParentFiled()) { makeLengthEnable(); - tdChange(); + tdChange(false); } } }); @@ -169,7 +171,7 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable { } - private void tdChange() { + private void tdChange(boolean isChangeDS) { TableDataWrapper tableDataWrappe = this.tableDataNameComboBox.getSelectedItem(); if (tableDataWrappe == null) { return; @@ -186,7 +188,9 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable { String[] columnNames = new String[len]; namelist.toArray(columnNames); for (int i = 0; i < valueEditorPanes.length; i++) { - valueEditorPanes[i].setEditors(new Editor[]{new ColumnNameEditor(columnNames), new ColumnIndexEditor(len)}, columnNames[0]); + if (isChangeDS || isNoSelectedColumnName(valueEditorPanes[i])) { + valueEditorPanes[i].setEditors(new Editor[]{new ColumnNameEditor(columnNames), new ColumnIndexEditor(len)}, columnNames[0]); + } } } catch (Exception e) { for (int i = 0; i < valueEditorPanes.length; i++) { @@ -197,6 +201,10 @@ public class TreeTableDataDictPane extends BasicPane implements Previewable { } } + private boolean isNoSelectedColumnName(ValueEditorPane valueEditorPane) { + return (Integer) valueEditorPane.update() == -1; + } + @Override protected String title4PopupWindow() { return "TreeTableDataDictionay"; diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/strategy/StrategyConfigHandler.java b/designer-base/src/main/java/com/fr/design/data/tabledata/strategy/StrategyConfigHandler.java new file mode 100644 index 000000000..5b6a744d0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/strategy/StrategyConfigHandler.java @@ -0,0 +1,37 @@ +package com.fr.design.data.tabledata.strategy; + +import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.query.StrategicTableData; + +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2021/3/19 + */ +public abstract class StrategyConfigHandler { + + private final T tableData; + + public StrategyConfigHandler(T tableData) { + this.tableData = tableData; + } + + protected T getTableData() { + return tableData; + } + + /** + * 查找配置 + * + * @return 缓存配置 + */ + public abstract StrategyConfig find(); + + + /** + * 保存配置 + * + * @param config 缓存配置 + */ + public abstract void save(T saved, StrategyConfig config); +} diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java index fecf9c079..173da2fbf 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java @@ -1,6 +1,5 @@ package com.fr.design.data.tabledata.tabledatapane; -import com.fr.base.BaseUtils; import com.fr.base.Parameter; import com.fr.base.ParameterHelper; import com.fr.data.core.db.TableProcedure; @@ -13,16 +12,22 @@ import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.UpdateAction; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.UIConstants; +import com.fr.design.data.StrategyConfigAttrUtils; +import com.fr.design.data.datapane.ESDStrategyConfigPane; import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane; -import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener; import com.fr.design.data.datapane.preview.PreviewTablePane; import com.fr.design.data.datapane.preview.sql.PreviewPerformedSqlPane; import com.fr.design.data.datapane.sqlpane.SQLEditPane; +import com.fr.design.data.tabledata.strategy.StrategyConfigHandler; +import com.fr.design.data.tabledata.tabledatapane.db.StrategyConfigFrom; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fun.DBTableDataMenuHandler; +import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itableeditorpane.ParameterTableModel; import com.fr.design.gui.itableeditorpane.UITableEditAction; @@ -30,11 +35,20 @@ import com.fr.design.gui.itableeditorpane.UITableEditorPane; import com.fr.design.gui.itoolbar.UIToolbar; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane; +import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.design.menu.SeparatorDef; import com.fr.design.menu.ToolBarDef; import com.fr.design.utils.ParameterUtils; import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.esd.core.strategy.config.StrategyConfig; +import com.fr.esd.core.strategy.config.StrategyConfigHelper; +import com.fr.esd.core.strategy.config.service.StrategyConfigService; +import com.fr.esd.data.db.DBTableDataSavedHook; +import com.fr.esd.event.DSMapping; +import com.fr.esd.event.DsNameTarget; +import com.fr.esd.event.StrategyEventsNotifier; +import com.fr.esd.query.StrategicTableData; import com.fr.general.ComparatorUtils; import com.fr.general.IOUtils; import com.fr.general.sql.SqlUtils; @@ -43,6 +57,7 @@ import com.fr.script.Calculator; import com.fr.stable.ArrayUtils; import com.fr.stable.ParameterProvider; import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; import javax.swing.BorderFactory; import javax.swing.Box; @@ -57,6 +72,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; @@ -64,25 +80,45 @@ import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.List; +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2020/7/22 + */ public class DBTableDataPane extends AbstractTableDataPane { + private static final int BOTTOM = 6; - private static final String PREVIEW_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"); - private static final String REFRESH_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Refresh"); + private static final String PREVIEW_BUTTON = Toolkit.i18nText("Fine-Design_Basic_Preview"); + private static final String REFRESH_BUTTON = Toolkit.i18nText("Fine-Design_Basic_Refresh"); private ConnectionTableProcedurePane connectionTableProcedurePane; private UITableEditorPane editorPane; - private DBTableDataMenuHandler dbTableDataMenuHandler; private SQLEditPane sqlTextPane; - private UICheckBox isShareCheckBox; - private MaxMemRowCountPanel maxPanel; - private String pageQuery = null; + private String pageQuery; private DBTableData dbTableData; + //ESD + private UILabel esdSettingsLabel; + private UIComboBox esdConfigOption; + private UICheckBox esdEnabled; + private UIButton esdSettingsBtn; + private UILabel barErrorTips; + //配置 + private StrategyConfig strategyConfig; + + private StrategyConfigHandler configHandler; + + + public DBTableDataPane() { + init(); + initMainSplitPane(); + } + private void init() { - this.setLayout(new BorderLayout(4, 4)); + setLayout(new BorderLayout(4, 4)); - sqlTextPane = new SQLEditPane(); - sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); + this.sqlTextPane = new SQLEditPane(); + this.sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); ParameterTableModel model = new ParameterTableModel() { @Override @@ -90,25 +126,27 @@ public class DBTableDataPane extends AbstractTableDataPane { return ArrayUtils.add(super.createDBTableAction(), new RefreshAction()); } }; - editorPane = new UITableEditorPane(model); + editorPane = new UITableEditorPane<>(model); - // 左边的Panel,上面是选择DatabaseConnection的ComboBox,下面DatabaseConnection对应的Table - connectionTableProcedurePane = new ConnectionTableProcedurePane() { + + this.connectionTableProcedurePane = new ConnectionTableProcedurePane() { @Override protected void filter(Connection connection, String conName, List nameList) { - - connection.addConnection(nameList, conName, new Class[]{JDBCDatabaseConnection.class, JNDIDatabaseConnection.class}); + connection.addConnection(nameList, conName, new Class[]{ + JDBCDatabaseConnection.class, + JNDIDatabaseConnection.class + }); } + @Override protected void addKeyMonitor() { - searchField.addKeyListener(new KeyListener() { - + this.searchField.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { - //do nothing } + @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { @@ -117,45 +155,44 @@ public class DBTableDataPane extends AbstractTableDataPane { } } + @Override public void keyReleased(KeyEvent e) { - //do nothing } }); } }; - connectionTableProcedurePane.addDoubleClickListener(new DoubleClickSelectedNodeOnTreeListener() { - + this.connectionTableProcedurePane.addDoubleClickListener(new ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener() { @Override public void actionPerformed(TableProcedure target) { - Document document = sqlTextPane.getDocument(); + Document document = DBTableDataPane.this.sqlTextPane.getDocument(); try { - document.insertString(sqlTextPane.getCaretPosition(), target.toString(), null); + document.insertString(DBTableDataPane.this.sqlTextPane.getCaretPosition(), target.toString(), null); } catch (BadLocationException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } - // 这里开始作色,本来可以给sqlTextPane添加DocumentListener来实现的, - // 后来发现insertString的时候,锁定了JTextPane,不能调用setXXX来作色,先这样了. - // sqlTextPane.syntaxTexts(); - sqlTextPane.requestFocus(); + + + DBTableDataPane.this.sqlTextPane.requestFocus(); } }); - sqlTextPane.addFocusListener(new FocusListener() { + + this.sqlTextPane.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { - // do nothing + barErrorTips.setVisible(false); } + @Override public void focusLost(FocusEvent e) { - if (isPreviewOrRefreshButton(e)) { - checkParameter(); + if (DBTableDataPane.this.isPreviewOrRefreshButton(e)) { + DBTableDataPane.this.checkParameter(); } } }); } - private void initMainSplitPane() { Box box = new Box(BoxLayout.Y_AXIS); @@ -165,106 +202,189 @@ public class DBTableDataPane extends AbstractTableDataPane { northPane.add(editToolBar, BorderLayout.CENTER); northPane.setBorder(BorderFactory.createEmptyBorder(0, 0, BOTTOM, 0)); - RTextScrollPane sqlTextScrollPane = new RTextScrollPane(sqlTextPane); + RTextScrollPane sqlTextScrollPane = new RTextScrollPane(this.sqlTextPane); sqlTextScrollPane.setLineNumbersEnabled(true); sqlTextScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); sqlTextScrollPane.setPreferredSize(new Dimension(680, 600)); JPanel paraMeanPane = new JPanel(new BorderLayout()); paraMeanPane.setPreferredSize(new Dimension(680, 90)); - UILabel paraMean = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Datasource_Param_DES")); + UILabel paraMean = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Datasource_Param_DES")); paraMeanPane.add(paraMean, BorderLayout.CENTER); box.add(northPane); box.add(sqlTextScrollPane); box.add(paraMeanPane); - box.add(editorPane); + box.add(this.editorPane); JPanel sqlSplitPane = new JPanel(new BorderLayout(4, 4)); sqlSplitPane.add(box, BorderLayout.CENTER); box.setMinimumSize(new Dimension(300, 400)); - // 防止数据连接名过长时影响 split pane 分割效果 - // 本界面中给MaxMemRowCountPanel留的空间太小,造成MaxMemRowCountPanel显示异常,这边减小一点最小宽度,拉长MaxMemRowCountPanel - connectionTableProcedurePane.setMinimumSize(new Dimension(230, 400)); - connectionTableProcedurePane.setMaximumSize(new Dimension(500, 400)); - // 使用SplitPane - JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, connectionTableProcedurePane, sqlSplitPane); + + this.connectionTableProcedurePane.setMinimumSize(new Dimension(230, 400)); + this.connectionTableProcedurePane.setMaximumSize(new Dimension(500, 400)); + + JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.connectionTableProcedurePane, sqlSplitPane); mainSplitPane.setBorder(BorderFactory.createLineBorder(GUICoreUtils.getTitleLineBorderColor())); mainSplitPane.setOneTouchExpandable(true); - this.add(mainSplitPane, BorderLayout.CENTER); + add(mainSplitPane, BorderLayout.CENTER); } - public DBTableDataPane() { - init(); - initMainSplitPane(); - } - - private boolean isPreviewOrRefreshButton(FocusEvent e) { if (e.getOppositeComponent() != null) { String name = e.getOppositeComponent().getName(); - return ComparatorUtils.equals(name, PREVIEW_BUTTON) || ComparatorUtils.equals(name, REFRESH_BUTTON); + return (ComparatorUtils.equals(name, PREVIEW_BUTTON) || ComparatorUtils.equals(name, REFRESH_BUTTON)); } return false; } @Override protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query"); + return Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query"); } - private void refresh() { + private void refreshParameters() { String[] paramTexts = new String[2]; - paramTexts[0] = SqlUtils.tryPureSqlText(sqlTextPane.getText()); - paramTexts[1] = SqlUtils.tryPureSqlText(pageQuery); - List existParameterList = editorPane.update(); - Parameter[] ps = existParameterList == null ? new Parameter[0] : existParameterList.toArray(new Parameter[0]); - editorPane.populate(ParameterUtils.analyzeAndUnionParameters(paramTexts, ps)); + paramTexts[0] = SqlUtils.tryPureSqlText(this.sqlTextPane.getText()); + paramTexts[1] = SqlUtils.tryPureSqlText(this.pageQuery); + List existParameterList = this.editorPane.update(); + Parameter[] ps = (existParameterList == null) ? new Parameter[0] : existParameterList.toArray(new Parameter[0]); + + this.editorPane.populate(ParameterUtils.analyzeAndUnionParameters(paramTexts, ps)); } private JToolBar createToolBar() { - // p:工具栏. ToolBarDef toolBarDef = new ToolBarDef(); toolBarDef.addShortCut(new PreviewAction()); toolBarDef.addShortCut(new PreviewPerformedSQLAction()); toolBarDef.addShortCut(SeparatorDef.DEFAULT); toolBarDef.addShortCut(new EditPageQueryAction()); - dbTableDataMenuHandler = ExtraDesignClassManager.getInstance().getSingle(DBTableDataMenuHandler.MARK_STRING); - if (dbTableDataMenuHandler != null) { + this.dbTableDataMenuHandler = ExtraDesignClassManager.getInstance().getSingle("DBTableDataMenuHandler"); + if (this.dbTableDataMenuHandler != null) { toolBarDef.addShortCut(SeparatorDef.DEFAULT); - toolBarDef.addShortCut(dbTableDataMenuHandler.createQueryAction()); + toolBarDef.addShortCut(this.dbTableDataMenuHandler.createQueryAction()); } - isShareCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Is_Share_DBTableData")); - isShareCheckBox.setBackground(Color.WHITE); - maxPanel = new MaxMemRowCountPanel(); - maxPanel.setBorder(null); + UIToolbar editToolBar = ToolBarDef.createJToolBar(); toolBarDef.updateToolBar(editToolBar); - editToolBar.add(isShareCheckBox); - editToolBar.add(maxPanel); + + //esd相关组件初始化 + createToolbarEsdComponents(editToolBar); return editToolBar; } + private void createToolbarEsdComponents(final UIToolbar editToolBar) { + this.esdSettingsLabel = new UILabel(Toolkit.i18nText("Fine-Design_ESD_Cache_Settings")); + this.esdConfigOption = new UIComboBox(StrategyConfigFrom.values()); + this.esdEnabled = new UICheckBox(Toolkit.i18nText("Fine-Design_ESD_Enable_Cache")); + this.barErrorTips = new UILabel(); + this.barErrorTips.setForeground(Color.RED); + this.barErrorTips.setVisible(false); + + esdSettingsBtn = new UIButton(Toolkit.i18nText("Fine-Design_ESD_Strategy_Config")); + esdSettingsBtn.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + final boolean global = globalOptionSelected(); + + final ESDStrategyConfigPane strategyConfigPane = new ESDStrategyConfigPane(global); + + StrategyConfig populateStrategyConfig; + if (global) { + populateStrategyConfig = StrategyConfigService.getGlobalConfig(); + } else { + populateStrategyConfig = strategyConfig; + } + + //显示对应的配置 + strategyConfigPane.populateBean(populateStrategyConfig); + + BasicDialog dlg = strategyConfigPane.showMediumWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + super.doOk(); + if (!global) { + //点击策略配置面板的确定,重新设置策略配置 + strategyConfig = strategyConfigPane.updateBean(); + // TODO: 2021/3/12 这个直接使用不太好 + } + } + }); + dlg.setAlwaysOnTop(true); + dlg.setVisible(true); + } + }); + + this.esdConfigOption.setSelectedIndex(StrategyConfigFrom.GLOBAL.getIndex()); + this.esdConfigOption.addActionListener(e -> setEsdEnabled()); + + + //工具栏加上esd相关组件 + editToolBar.add(this.esdSettingsLabel); + editToolBar.add(this.esdConfigOption); + editToolBar.add(this.esdEnabled); + editToolBar.add(this.esdSettingsBtn); + editToolBar.add(this.barErrorTips); + } + + private boolean globalOptionSelected() { + return esdConfigOption.getSelectedIndex() == StrategyConfigFrom.GLOBAL.getIndex(); + } + + private void setEsdEnableStatus(boolean selected, boolean enabled) { + this.esdEnabled.setSelected(selected); + this.esdEnabled.setEnabled(enabled); + } + + private void setEsdEnabled() { + boolean useIndividualConfig = !this.globalOptionSelected(); + if (useIndividualConfig) { + if (this.strategyConfig == null) { + //新建的数据集,选择单独时,可用但是不勾选 + setEsdEnableStatus(false, true); + } else { + setEsdEnableStatus(!this.strategyConfig.isUseGlobal() && this.strategyConfig.enabled(), true); + } + } else { + //判断是不是模版数据集 + switch (this.dbTableData.getScope()) { + case TEMPLATE: + String tplPath = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getEditingFILE().getPath(); + setEsdEnableStatus(StrategyConfigService.isTemplateEnabled(tplPath), false); + break; + case SERVER: + //不会走到这里 + default: + break; + } + } + } + + public StrategyConfig updateStrategyConfig() { + return this.strategyConfig; + } + private void checkParameter() { String[] paramTexts = new String[2]; - paramTexts[0] = sqlTextPane.getText(); - paramTexts[1] = pageQuery; + paramTexts[0] = this.sqlTextPane.getText(); + paramTexts[1] = this.pageQuery; Parameter[] parameters = ParameterHelper.analyze4Parameters(paramTexts, false); - if (parameters.length < 1 && editorPane.update().size() < 1) { + if (parameters.length < 1 && this.editorPane.update().size() < 1) { return; } boolean isIn = true; - List list = editorPane.update(); - List name = new ArrayList(); - for (int i = 0; i < list.size(); i++) { - name.add(list.get(i).getName()); + List list = this.editorPane.update(); + List name = new ArrayList<>(); + for (ParameterProvider parameter : list) { + name.add(parameter.getName()); } - for (int i = 0; i < parameters.length; i++) { - if (!name.contains(parameters[i].getName())) { + for (Parameter parameter : parameters) { + if (!name.contains(parameter.getName())) { isIn = false; break; } @@ -272,101 +392,162 @@ public class DBTableDataPane extends AbstractTableDataPane { if (list.size() == parameters.length && isIn) { return; } - // bug:34175 删了是否刷新对话框, 均直接刷新 - refresh(); + + refreshParameters(); } @Override - public void populateBean(DBTableData dbtabledata) { - this.dbTableData = dbtabledata; - if (dbTableDataMenuHandler != null) { - dbTableDataMenuHandler.populate(dbtabledata); + public void populateBean(DBTableData dbTableData) { + this.dbTableData = dbTableData; + if (this.dbTableDataMenuHandler != null) { + this.dbTableDataMenuHandler.populate(dbTableData); } - ParameterProvider[] parameters = null; + Calculator c = Calculator.createCalculator(); - parameters = dbtabledata.getParameters(c); - editorPane.populate(parameters); + ParameterProvider[] parameters = dbTableData.getParameters(c); + this.editorPane.populate(parameters); - com.fr.data.impl.Connection db = null; - String query = null; - boolean isShare = false; - int maxMemeryRow = -1; - db = dbtabledata.getDatabase(); - query = dbtabledata.getQuery(); - isShare = dbtabledata.isShare(); - maxMemeryRow = dbtabledata.getMaxMemRowCount(); - this.pageQuery = dbtabledata.getPageQuerySql(); + Connection db = dbTableData.getDatabase(); + String query = dbTableData.getQuery(); + this.pageQuery = dbTableData.getPageQuerySql(); this.connectionTableProcedurePane.setSelectedDatabaseConnection(db); this.sqlTextPane.setText(query); this.sqlTextPane.requestFocus(); this.sqlTextPane.moveCaretPosition(this.sqlTextPane.getCaretPosition()); - isShareCheckBox.setSelected(isShare); - maxPanel.setValue(maxMemeryRow); + + switch (dbTableData.getScope()) { + + case TEMPLATE: + this.configHandler = new TemplateStrategyConfigHandler(dbTableData); + break; + case SERVER: + //服务器数据集 + default: + //新建服务器数据集 + this.configHandler = new ServerStrategyConfigHandler(dbTableData); + break; + } + //设置esd相关组件显示状态 + populateESDComponents(); + } + + private void populateESDComponents() { + //查找映射的配置 + this.strategyConfig = configHandler.find(); + + boolean shouldEnable = false; + StrategyConfigFrom from = StrategyConfigFrom.GLOBAL; + + if (this.strategyConfig != null) { + if (this.strategyConfig.enabled()) { + shouldEnable = true; + } + if (!this.strategyConfig.isUseGlobal()) { + from = StrategyConfigFrom.INDIVIDUAL; + } + } + + //服务器数据集不允许设置来源,只能单独配置 + if (dbTableData.getScope() != StrategicTableData.Scope.TEMPLATE) { + from = StrategyConfigFrom.INDIVIDUAL; + this.esdConfigOption.setEnabled(false); + } + this.esdEnabled.setSelected(shouldEnable); + this.esdConfigOption.setSelectedIndex(from.getIndex()); } @Override public DBTableData updateBean() { + + updateDBTableData(); + internalUpdateStrategyConfig(); + + return this.dbTableData; + } + + private void internalUpdateStrategyConfig() { + //这边只修改enable和useGlobal + boolean global = globalOptionSelected(); + boolean enable = this.esdEnabled.isSelected(); + + + //未开启缓存的,如果选择了单独配置,需要创建配置 + if (this.strategyConfig == null && !global) { + this.strategyConfig = StrategyConfig.createDefault(); + } + + //设置配置来源和开启状态 + if (this.strategyConfig != null) { + this.strategyConfig.setEnable(enable); + this.strategyConfig.setUseGlobal(global); + } + + //保存 + this.configHandler.save(this.dbTableData, this.strategyConfig); + } + + private void updateDBTableData() { String dbName = this.connectionTableProcedurePane.getSelectedDatabaseConnnectonName(); if (StringUtils.isBlank(dbName) || StringUtils.isBlank(this.sqlTextPane.getText())) { try { - throw new Exception(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + "."); - } catch (Exception ignore) { - // JOptionPane.showMessageDialog(DBTableDataPane.this, - // com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + "."); + throw new Exception(Toolkit.i18nText("Fine-Design_Basic_Connect_SQL_Cannot_Null") + "."); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); } } + + // 保存前 刷新下参数列表 保证获取到最新的参数 - refresh(); - List parameterList = editorPane.update(); - Parameter[] parameters = parameterList.toArray(new Parameter[parameterList.size()]); + refreshParameters(); + + List parameterList = this.editorPane.update(); + ParameterProvider[] parameters = parameterList.toArray(new ParameterProvider[0]); dbTableData.setDatabase(new NameDatabaseConnection(dbName)); - // p:必须先设置Parameters数组,因为setQuery里面会自动设置的 dbTableData.setParameters(parameters); - dbTableData.setQuery(this.sqlTextPane.getText()); + dbTableData.setQuery(this.sqlTextPane.getText().trim()); - dbTableData.setShare(isShareCheckBox.isSelected()); - dbTableData.setMaxMemRowCount(maxPanel.getValue()); dbTableData.setPageQuerySql(this.pageQuery); - if (dbTableDataMenuHandler != null) { - dbTableDataMenuHandler.update(); + if (this.dbTableDataMenuHandler != null) { + this.dbTableDataMenuHandler.update(); } - return dbTableData; } protected class RefreshAction extends UITableEditAction { public RefreshAction() { - this.setName(REFRESH_BUTTON); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); + setName(REFRESH_BUTTON); + setSmallIcon(IOUtils.readIcon("/com/fr/design/images/control/refresh.png")); } + @Override public void actionPerformed(ActionEvent e) { - refresh(); + DBTableDataPane.this.refreshParameters(); } + @Override public void checkEnabled() { - // do nothing } } private class PreviewAction extends UpdateAction { public PreviewAction() { - this.setName(PREVIEW_BUTTON); - this.setMnemonic('P'); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/preview.png")); + setName(PREVIEW_BUTTON); + setMnemonic('P'); + setSmallIcon(IOUtils.readIcon("/com/fr/design/images/m_file/preview.png")); } + @Override public void actionPerformed(ActionEvent evt) { - checkParameter(); + DBTableDataPane.this.checkParameter(); PreviewTablePane.previewTableData(DBTableDataPane.this.updateBean()); } } @@ -387,14 +568,14 @@ public class DBTableDataPane extends AbstractTableDataPane { private class EditPageQueryAction extends UpdateAction { public EditPageQueryAction() { - this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Page_Query")); + this.setName(Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Page_Query")); this.setMnemonic('L'); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/text.png")); + this.setSmallIcon(IOUtils.readIcon("/com/fr/design/images/m_file/text.png")); } @Override public void actionPerformed(ActionEvent e) { - final QueryPane pane = new QueryPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Define_Page_Query_SQL")); + final QueryPane pane = new QueryPane(Toolkit.i18nText("Fine-Design_Basic_Layer_Page_Report_Define_Page_Query_SQL")); pane.populate(pageQuery); BasicDialog dialog = pane.showWindow(DesignerContext.getDesignerFrame()); dialog.addDialogActionListener(new DialogActionAdapter() { @@ -408,9 +589,9 @@ public class DBTableDataPane extends AbstractTableDataPane { } } - private class QueryPane extends BasicPane { + private static class QueryPane extends BasicPane { private SQLEditPane pageQueryPane; - private String title; + private final String title; public QueryPane(String title) { this.title = title; @@ -427,21 +608,135 @@ public class DBTableDataPane extends AbstractTableDataPane { if (StringUtils.isBlank(text)) { return; } - pageQueryPane.setText(text); + this.pageQueryPane.setText(text); } public String update() { - String text = pageQueryPane.getText(); + String text = this.pageQueryPane.getText(); if (StringUtils.isBlank(text)) { return null; - } else { - return text; } + return text; } + @Override protected String title4PopupWindow() { - return title; + return this.title; + } + } + + /** + * 服务器数据集配置处理器 + */ + private static class ServerStrategyConfigHandler extends StrategyConfigHandler { + private final String origName; + + private final String origConnection; + + private final String origQuery; + + public ServerStrategyConfigHandler(DBTableData tableData) { + super(tableData); + this.origName = tableData.getDsName(); + this.origConnection = tableData.getDatabase().toString(); + this.origQuery = tableData.getQuery(); + } + + @Override + public StrategyConfig find() { + StrategyConfig strategyConfig = null; + if (getTableData() != null) { + strategyConfig = getTableData().getStrategyConfig(); + if (strategyConfig == null) { + //共享数据集 + if (getTableData().isShare()) { + strategyConfig = StrategyConfigHelper.createStrategyConfig(true, false, true); + } + } + } + + return strategyConfig; + } + + @Override + public void save(DBTableData saved, StrategyConfig strategyConfig) { + String conn = saved.getDatabase().toString(); + String query = saved.getQuery(); + + + //检查数据链接和sql是否修改,如果修改需要触发缓存监听事件 + if (!conn.equals(origConnection) || !query.equals(origQuery)) { + if (StringUtils.isNotEmpty(origName)) { + //新建数据集的origName为null,不用触发 + StrategyEventsNotifier.modifyDataSet(DSMapping.ofServerDS(new DsNameTarget(origName))); + } + } + + + //配置变动事件 + try { + final StrategyConfig orig = getTableData().getStrategyConfig(); + saved.setStrategyConfig(strategyConfig.clone()); + StrategyEventsNotifier.compareAndFireConfigEvents(orig, strategyConfig, DSMapping.ofServerDS(new DsNameTarget(saved.getDsName()))); + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + + + /** + * 模版数据集配置处理器 + */ + private static class TemplateStrategyConfigHandler extends StrategyConfigHandler { + public TemplateStrategyConfigHandler(DBTableData tableData) { + super(tableData); + } + + @Override + public StrategyConfig find() { + StrategyConfig strategyConfig = null; + String tplPath = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getEditingFILE().getPath(); + if (getTableData() != null && StringUtils.isNotEmpty(tplPath)) { + //设置保存数据集的事件检查钩子 + //新建模版此时不存在,不需要注册钩子 + if (getTableData().getXmlSavedHook() == null && WorkContext.getWorkResource().exist(tplPath)) { + getTableData().setXmlSavedHook(new DBTableDataSavedHook(tplPath, getTableData())); + } + + //获取当前的缓存配置,没有就创建一份 + String dsName = getTableData().getDsName(); + + //这里为了之前兼容插件创建的配置,缓存配置不在DBTableData,而是从模版attr读取 + strategyConfig = StrategyConfigAttrUtils.getStrategyConfig(dsName); + + + if (useGlobal(getTableData(), strategyConfig)) { + //使用全局配置 + strategyConfig = StrategyConfigHelper.createStrategyConfig(true); + } else if (getTableData().isShare()) { + //使用共享数据集兼容配置 + strategyConfig = StrategyConfigHelper.createStrategyConfig(true, false, true); + } + } + + return strategyConfig; + } + + private boolean useGlobal(DBTableData dbTableData, StrategyConfig strategyConfig) { + //非共享且配置为空或者指定使用全局配置时,检查是否全局开启 + if (strategyConfig == null) { + return !dbTableData.isShare(); + } else { + return strategyConfig.isUseGlobal(); + } + } + + @Override + public void save(DBTableData saved, StrategyConfig config) { + + //DBTableDataSavedHook处理了 } } } diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java index f1d2433db..d2a1918d4 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java @@ -8,10 +8,12 @@ import com.fr.data.impl.NameDatabaseConnection; import com.fr.data.impl.storeproc.ProcedureDataModel; import com.fr.data.impl.storeproc.StoreProcedure; import com.fr.data.operator.DataOperator; +import com.fr.design.DesignModelAdapter; import com.fr.design.actions.UpdateAction; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.UIConstants; import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.TableDataTreePane; import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane; import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener; import com.fr.design.data.datapane.sqlpane.SQLEditPane; @@ -291,6 +293,7 @@ public class ProcedureDataPane extends AbstractTableDataPane imp sp.setCalculating(false); doAfterProcudureDone(); fireDSChanged(); + TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); } }; diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/db/StrategyConfigFrom.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/db/StrategyConfigFrom.java new file mode 100644 index 000000000..a1a07ee11 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/db/StrategyConfigFrom.java @@ -0,0 +1,33 @@ +package com.fr.design.data.tabledata.tabledatapane.db; + +import com.fr.design.i18n.Toolkit; + +public enum StrategyConfigFrom { + GLOBAL(0, Toolkit.i18nText("Fine-Design_ESD_Use_Global_Settings")), + + INDIVIDUAL(1, Toolkit.i18nText("Fine-Design_ESD_Use_Individual_Settings")); + + int index; + + String displayText; + + StrategyConfigFrom(int index, String displayText) { + this.index = index; + this.displayText = displayText; + } + + + public int getIndex() { + return this.index; + } + + + public String getDisplayText() { + return this.displayText; + } + + + public String toString() { + return getDisplayText(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java b/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java index 87b7f2f25..6c3323600 100644 --- a/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java +++ b/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java @@ -731,6 +731,16 @@ public class MutilTempalteTabPane extends JComponent { } } + /** + * 后台关闭当前编辑模板 + */ + public void closeCurrentTpl(){ + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + this.setIsCloseCurrent(true); + this.closeFormat(jTemplate); + this.closeSpecifiedTemplate(jTemplate); + } + /** * 关闭模板 * @@ -765,8 +775,8 @@ public class MutilTempalteTabPane extends JComponent { // 如果关闭的模板是当前选中的模板,则重新激活当前 selectIndex 的模板; // selectIndex 没有变化,但是对应的模板已经变成了前一张模板 if (closeIconIndex == selectedIndex || isCloseCurrent) { - // 如果 closeIconIndex 是最后一个被渲染画出的,那么预览上一个,防止数组越界 - if (closeIconIndex >= maxPaintIndex) { + // 如果当前关闭的模板在最右侧,那么预览上一个,防止数组越界 + if (selectedIndex >= maxPaintIndex) { // selectIndex 不会 <0 因为如果关闭的是打开的最后一个模板,那么关闭之后 openedTemplate.isEmpty() = true selectedIndex--; } diff --git a/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java b/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java index 2c0d860fb..363eb1ab0 100644 --- a/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java +++ b/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java @@ -17,6 +17,7 @@ import com.fr.file.FILE; import com.fr.file.FileNodeFILE; import com.fr.file.filetree.FileNode; import com.fr.file.filetree.IOFileNodeFilter; +import com.fr.form.fit.web.editpreview.FileLockStateObservable; import com.fr.general.ComparatorUtils; import com.fr.general.IOUtils; import com.fr.log.FineLoggerFactory; @@ -47,6 +48,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.Enumeration; import java.util.Objects; +import java.util.Observable; +import java.util.Observer; import static javax.swing.JOptionPane.WARNING_MESSAGE; import static javax.swing.JOptionPane.YES_NO_OPTION; @@ -76,6 +79,13 @@ public class TemplateTreePane extends JPanel implements FileOperations { scrollPane.setBorder(null); contentPane.add(scrollPane, BorderLayout.CENTER); + FileLockStateObservable.getInstance().addObserver(new Observer() { + @Override + public void update(Observable o, Object arg) { + TemplateTreePane.this.refresh(); + } + }); + /* * Tree.MouseAdapter */ @@ -202,15 +212,13 @@ public class TemplateTreePane extends JPanel implements FileOperations { @Override public void openFile() { // 判断是否是远程设计的锁定文件 - if (!WorkContext.getCurrent().isLocal()) { - FileNode node = reportletsTree.getSelectedFileNode(); - if (node == null) { - return; - } - String lock = node.getLock(); - if (lock != null && !lock.equals(node.getUserID())) { - return; - } + FileNode node = reportletsTree.getSelectedFileNode(); + if (node == null) { + return; + } + String lock = node.getLock(); + if (lock != null && !lock.equals(node.getUserID())) { + return; } String reportPath = reportletsTree.getSelectedTemplatePath(); final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, reportPath); diff --git a/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java b/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java index 8b68dcdbe..52807a6cb 100644 --- a/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java +++ b/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java @@ -2,32 +2,78 @@ package com.fr.design.formula; import com.fr.base.BaseFormula; import com.fr.base.BaseUtils; +import com.fr.base.Parameter; +import com.fr.base.ParameterMapNameSpace; +import com.fr.base.TableDataNameSpace; +import com.fr.base.Utils; +import com.fr.base.io.IOFile; +import com.fr.data.TableDataSource; import com.fr.design.actions.UpdateAction; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.UIConstants; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ilist.QuickList; +import com.fr.design.gui.itableeditorpane.ParameterTableModel; +import com.fr.design.gui.itableeditorpane.UITableEditorPane; import com.fr.design.gui.itextarea.UITextArea; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; +import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.parameter.ParameterInputPane; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.ComparatorUtils; +import com.fr.general.FArray; import com.fr.log.FineLoggerFactory; +import com.fr.parser.ArrayExpression; +import com.fr.parser.BlockIntervalLiteral; +import com.fr.parser.ColumnRowRangeInPage; import com.fr.parser.FRLexer; import com.fr.parser.FRParser; +import com.fr.parser.NumberLiteral; +import com.fr.parser.SheetIntervalLiteral; +import com.fr.report.core.namespace.SimpleCellValueNameSpace; +import com.fr.script.Calculator; +import com.fr.script.ScriptConstants; +import com.fr.script.checker.FunctionCheckerDispatcher; +import com.fr.script.checker.exception.ConditionCheckWrongException; +import com.fr.script.checker.exception.FunctionCheckWrongException; +import com.fr.script.rules.FunctionParameterType; +import com.fr.script.rules.FunctionRule; import com.fr.stable.EncodeConstants; +import com.fr.stable.EssentialUtils; +import com.fr.stable.ParameterProvider; import com.fr.stable.StringUtils; +import com.fr.stable.UtilEvalError; +import com.fr.stable.script.CRAddress; +import com.fr.stable.script.ColumnRowRange; import com.fr.stable.script.Expression; - -import javax.swing.*; +import com.fr.stable.script.Node; +import com.fr.stable.script.Tiny; +import com.fr.stable.script.TinyHunter; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JTree; +import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.TreeSelectionEvent; @@ -37,7 +83,10 @@ import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreePath; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; @@ -52,10 +101,16 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; +import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; /** * 公式编辑面板 @@ -65,6 +120,10 @@ import java.util.List; */ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { + public static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula"); + public static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula"); + public static final int DEFUAL_FOMULA_LENGTH = 103; + public static final String ELLIPSIS = "..."; private VariableTreeAndDescriptionArea variableTreeAndDescriptionArea; private RSyntaxTextArea formulaTextArea; private UITextField keyWordTextField = new UITextField(18); @@ -78,6 +137,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { private QuickList functionTypeList; private DefaultListModel functionNameModel; private JList functionNameList; + private UITableEditorPane editor4CalPane; public FormulaPane() { initComponents(); @@ -201,6 +261,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { private void initTextPane() { // text + JPanel textPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); this.add(textPane, BorderLayout.CENTER); JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); @@ -217,13 +278,19 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { UIButton checkValidButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Check_Valid")); + UIButton calButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Button")); checkValidButton.addActionListener(checkValidActionListener); + calButton.addActionListener(calculateActionListener); JPanel checkBoxPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); checkBoxPane.setPreferredSize(new Dimension(450, 30)); checkBoxandbuttonPane.add(checkBoxPane, BorderLayout.WEST); checkBoxandbuttonPane.add(checkValidButton, BorderLayout.EAST); + checkBoxandbuttonPane.add(calButton, BorderLayout.EAST); extendCheckBoxPane(checkBoxPane); + + ParameterTableModel model = new ParameterTableModel(0); + editor4CalPane = new UITableEditorPane<>(model); } @@ -585,40 +652,254 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { } // check valid - private ActionListener checkValidActionListener = new ActionListener() { + private final ActionListener checkValidActionListener = new ActionListener() { public void actionPerformed(ActionEvent evt) { // Execute Formula default cell element. String formulaText = formulaTextArea.getText().trim(); + String formulaValidMessage = getFormulaValidMessage(formulaText); + FineJOptionPane.showMessageDialog( + FormulaPane.this, + formulaValidMessage + ".", + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), + JOptionPane.INFORMATION_MESSAGE); + } + }; - if (formulaText != null && formulaText.length() > 0) { - StringReader in = new StringReader(formulaText); - - FRLexer lexer = new FRLexer(in); - FRParser parser = new FRParser(lexer); - - Expression expression = null; - try { - expression = parser.parse(); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - // alex:继续往下面走,expression为null时告知不合法公式 + private static String getFormulaValidMessage(String formulaText) { + StringReader in = new StringReader(formulaText); + + FRLexer lexer = new FRLexer(in); + FRParser parser = new FRParser(lexer); + + try { + Expression expression = parser.parse(); + Node node = expression.getConditionalExpression(); + return FunctionCheckerDispatcher.getInstance() + .getFunctionChecker(node) + .checkFunction(node) ? VALID_FORMULA : INVALID_FORMULA; + } catch (ConditionCheckWrongException cce) { + String functionName = cce.getFunctionName(); + StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Condition_Tips") + ":"); + return errorMsg.toString(); + } catch (FunctionCheckWrongException ce) { + List rules = ce.getRules(); + String functionName = ce.getFunctionName(); + StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + ":"); + for (int i = 0; i < rules.size(); i++) { + errorMsg.append("("); + if (rules.get(i).getParameterList().isEmpty()) { + errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param")); + } + for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) { + errorMsg.append(getTypeString(functionParameterType)).append(","); } + if (",".equals(errorMsg.charAt(errorMsg.length() - 1) + "")) { + errorMsg.deleteCharAt(errorMsg.length() - 1); + } + errorMsg.append(")"); + if (i != rules.size() - 1) { + errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or")); + } + } + return errorMsg.toString(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return INVALID_FORMULA; + // alex:继续往下面走,expression为null时告知不合法公式 + } + } + + private static String getTypeString(FunctionParameterType type) { + switch (type) { + case NUMBER: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number"); + case STRING: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String"); + case ANY: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any"); + case DATE: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date"); + case BOOLEAN: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean"); + case ARRAY: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array"); + } + return ""; + } + private final ActionListener calculateActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String formulaText = formulaTextArea.getText().trim(); + String formulaValidMessage = getFormulaValidMessage(formulaText); + String unSupportFormula = containsUnsupportedSimulationFormulas(formulaText); + if (unSupportFormula != null) { FineJOptionPane.showMessageDialog( FormulaPane.this, - /* - * alex:仅仅只需要根据expression是否为null作合法性判断 - * 不需要eval - * TODO 但有个问题,有些函数的参数个数是有规定的,何以判别之 - */ - (expression != null ? com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula") : com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula")) + ".", + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Unsupported_Formulas") + ":" + unSupportFormula, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), JOptionPane.INFORMATION_MESSAGE); + return; + } + String messageTips; + if (formulaValidMessage.equals(INVALID_FORMULA)) { + messageTips = INVALID_FORMULA; + } else { + messageTips = formulaValidMessage.equals(VALID_FORMULA) ? "" : formulaValidMessage + "\n"; + Map paramsMap = setParamsIfExist(formulaText); + Calculator calculator = Calculator.createCalculator(); + ParameterMapNameSpace parameterMapNameSpace = ParameterMapNameSpace.create(paramsMap); + calculator.pushNameSpace(parameterMapNameSpace); + + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (currentEditingTemplate != null) { + IOFile file = (IOFile) currentEditingTemplate.getTarget(); + calculator.setAttribute(TableDataSource.KEY, file); + calculator.pushNameSpace(TableDataNameSpace.getInstance()); + calculator.pushNameSpace(SimpleCellValueNameSpace.getInstance()); + } + + BaseFormula baseFormula = BaseFormula.createFormulaBuilder().build(formulaText); + try { + Object value = calculator.evalValue(baseFormula); + String objectToString = EssentialUtils.objectToString(value); + String result = objectToString.length() > DEFUAL_FOMULA_LENGTH ? + objectToString.substring(0, DEFUAL_FOMULA_LENGTH - ELLIPSIS.length()) + ELLIPSIS : objectToString; + messageTips = messageTips + + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Result") + ":" + result; + FineLoggerFactory.getLogger().info("value:{}", value); + } catch (UtilEvalError utilEvalError) { + FineLoggerFactory.getLogger().error("", utilEvalError); + } } + FineJOptionPane.showMessageDialog( + FormulaPane.this, + messageTips, + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), + JOptionPane.INFORMATION_MESSAGE); } }; + private String containsUnsupportedSimulationFormulas(String formulaText) { + try { + Expression expression = Calculator.createCalculator().parse(formulaText); + UnsupportedFormulaScanner scanner = new UnsupportedFormulaScanner(); + if (!scanner.travelFormula(expression.getConditionalExpression())) { + return scanner.getUnSupportFormula(); + } + + UnsupportedSimulationNodeHunter unsupportedSimulationFormulaHunter = new UnsupportedSimulationNodeHunter(); + expression.traversal4Tiny(unsupportedSimulationFormulaHunter); + return unsupportedSimulationFormulaHunter.isSupported() ? null : unsupportedSimulationFormulaHunter.getUnSupportedNode(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("", e); + } + return null; + } + + private Map setParamsIfExist(String formulaText) { + Map parameterMap = new HashMap<>(); + try { + Calculator calculator = Calculator.createCalculator(); + Expression expression = calculator.parse(formulaText); + ParameterCellHunter parameterCellHunter = new ParameterCellHunter(); + expression.traversal4Tiny(parameterCellHunter); + Parameter[] parameters = parameterCellHunter.getParameterBooty(); + + if (parameters.length < 1 && editor4CalPane.update().size() < 1) { + return parameterMap; + } + ParameterInputPane pPane = new ParameterInputPane(parameters); + pPane.showSmallWindow(new JFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + parameterMap.putAll(pPane.update()); + } + }).setVisible(true); + //过滤出数组参数,如:[1,2] + for (Map.Entry entry : parameterMap.entrySet()) { + if (entry.getValue().toString().startsWith("[") && entry.getValue().toString().endsWith("]")) { + Expression parse = calculator.parse(entry.getValue()); + ArrayExpression arrayExpression = (ArrayExpression) parse.getConditionalExpression(); + Node[] arrays = arrayExpression.getArrays(); + List arrayList = new ArrayList<>(); + for (Node array : arrays) { + if (array instanceof NumberLiteral) { + arrayList.add(NumberFormat.getInstance().parse(array.toString())); + } else { + arrayList.add(array); + } + } + FArray fArray = new FArray<>(arrayList); + parameterMap.put(entry.getKey(), fArray); + } else if (Utils.isNumeric(entry.getValue().toString())) { + try { + Number number = NumberFormat.getInstance().parse(entry.getValue().toString()); + parameterMap.put(entry.getKey(), number); + } catch (Exception e) { + FineLoggerFactory.getLogger().warn("", e); + } + } + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error("", e); + } + return parameterMap; + } + + private static class ParameterCellHunter extends TinyHunter { + + private final Set parameterList = new HashSet<>(); + + Parameter[] getParameterBooty() { + return parameterList.toArray(new Parameter[0]); + } + + public void hunter4Tiny(Tiny tiny) { + String statement = tiny.getStatement(); + if (StringUtils.isNotBlank(statement) && statement.startsWith(ScriptConstants.DETAIL_TAG)) { + if (statement.startsWith(ScriptConstants.SUMMARY_TAG)) { + parameterList.add(new Parameter(statement)); + } else { + parameterList.add(new Parameter(statement.substring(1))); + } + } else if (tiny.getClass() == ColumnRowRange.class || + tiny.getClass() == SheetIntervalLiteral.class || tiny.getClass() == BlockIntervalLiteral.class) { + parameterList.add(new Parameter(tiny.toString())); + } + } + } + + private static class UnsupportedSimulationNodeHunter extends TinyHunter { + + private boolean supported = true; + + private String unSupportedNode; + + private String[] curReportVariables; + + public UnsupportedSimulationNodeHunter() { + curReportVariables = VariableResolver.DEFAULT.resolveCurReportVariables(); + } + + public boolean isSupported() { + return supported; + } + + public String getUnSupportedNode() { + return unSupportedNode; + } + + public void hunter4Tiny(Tiny tiny) { + if (tiny.getClass() == ColumnRowRangeInPage.class || tiny.getClass() == CRAddress.class + || Arrays.asList(curReportVariables).contains(tiny.toString())) { + supported = false; + unSupportedNode = tiny.toString(); + } + } + } + public class VariableTreeAndDescriptionArea extends JPanel { private JTree variablesTree; @@ -805,13 +1086,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { public void valueChanged(TreeSelectionEvent e) { DefaultMutableTreeNode selectedTreeNode = (DefaultMutableTreeNode) variablesTree.getLastSelectedPathComponent(); Object selectedValue = selectedTreeNode.getUserObject(); - Object selectedParentValue = ((DefaultMutableTreeNode)selectedTreeNode.getParent()).getUserObject(); + Object selectedParentValue = ((DefaultMutableTreeNode) selectedTreeNode.getParent()).getUserObject(); if (selectedValue == null) { return; } - if (selectedValue instanceof TextUserObject) { + if (selectedValue instanceof TextUserObject) { //有公式说明的条件:1.属于TextUserObject 2.parent是系统参数 if (ComparatorUtils.equals(((TextFolderUserObject) selectedParentValue).getText(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Variables"))) { @@ -1010,6 +1291,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { /** * 把以关键词开头的和不以关键词开头的分别按照字母表顺序排序 + * * @param o1 待比较对象1 * @param o2 待比较对象2 * @return 比较结果,1表示 o1 > o2, -1表示 o1 < o2, 0表示 o1 = o2 diff --git a/designer-base/src/main/java/com/fr/design/formula/UnsupportedFormulaScanner.java b/designer-base/src/main/java/com/fr/design/formula/UnsupportedFormulaScanner.java new file mode 100644 index 000000000..88f7a24b3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/UnsupportedFormulaScanner.java @@ -0,0 +1,54 @@ +package com.fr.design.formula; + +import com.fr.parser.BinaryExpression; +import com.fr.parser.DatasetFunctionCall; +import com.fr.parser.FunctionCall; +import com.fr.stable.script.Node; + +import java.util.Arrays; + +/** + * @author Hoky + * @date 2021/8/30 + */ +public class UnsupportedFormulaScanner { + public final static String[] UNSUPPORTED_FORMULAS = new String[]{"PROPORTION", "TOIMAGE", + "WEBIMAGE", "SORT", "CROSSLAYERTOTAL", "CIRCULAR", "LAYERTOTAL", "MOM", "HIERARCHY", + "FILENAME", "FILESIZE", "FILETYPE", "TREELAYER", "GETUSERDEPARTMENTS", "GETUSERJOBTITLES"}; + + private String unSupportFormula = ""; + + public boolean travelFormula(Node node) { + if (node instanceof FunctionCall) { + if (isUnsupportedFomula(((FunctionCall) node).getName())) { + unSupportFormula = ((FunctionCall) node).getName(); + return false; + } else { + for (Node argument : ((FunctionCall) node).getArguments()) { + if (!travelFormula(argument)) { + return false; + } + } + } + } else if (node instanceof BinaryExpression) { + for (Node array : ((BinaryExpression) node).getNodes()) { + if (!travelFormula(array)) { + return false; + } + } + } else if (node instanceof DatasetFunctionCall) { + DatasetFunctionCall datasetFunctionCall = (DatasetFunctionCall) node; + unSupportFormula = datasetFunctionCall.getSourceName() + "." + datasetFunctionCall.getFnName() + "()"; + return false; + } + return true; + } + + public String getUnSupportFormula() { + return unSupportFormula; + } + + private static boolean isUnsupportedFomula(String formula) { + return Arrays.asList(UNSUPPORTED_FORMULAS).contains(formula.toUpperCase()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/fun/PcFitProvider.java b/designer-base/src/main/java/com/fr/design/fun/PcFitProvider.java new file mode 100644 index 000000000..46437917e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/PcFitProvider.java @@ -0,0 +1,19 @@ +package com.fr.design.fun; + +import com.fr.stable.fun.mark.Mutable; + + +public interface PcFitProvider extends Mutable { + String XML_TAG = "PcFitProvider"; + int CURRENT_LEVEL = 1; + + //设计器上看到的选项 + String getContentDisplayValue(); + + //返回给前端的值 + int getContentDisplayKey(); + + //设计器上的提示信息 + String getContentDisplayTip(); + +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/fun/PreviewProvider.java b/designer-base/src/main/java/com/fr/design/fun/PreviewProvider.java index c07a4efe0..76b5037ef 100644 --- a/designer-base/src/main/java/com/fr/design/fun/PreviewProvider.java +++ b/designer-base/src/main/java/com/fr/design/fun/PreviewProvider.java @@ -2,6 +2,7 @@ package com.fr.design.fun; import com.fr.design.mainframe.JTemplate; import com.fr.stable.Filter; +import com.fr.stable.StringUtils; import com.fr.stable.fun.mark.Mutable; import java.util.Map; @@ -62,5 +63,13 @@ public interface PreviewProvider extends Mutable, Filter { */ String getActionType(); + /** + * 下拉弹出菜单的提示 + * @return 弹出菜单的提示 + */ + default String tooltipForPopItem() { + return StringUtils.EMPTY; + } + } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractPcFitProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractPcFitProvider.java new file mode 100644 index 000000000..b3a43754e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractPcFitProvider.java @@ -0,0 +1,19 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.PcFitProvider; +import com.fr.stable.fun.mark.API; + + +@API(level = PcFitProvider.CURRENT_LEVEL) +public abstract class AbstractPcFitProvider implements PcFitProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public String mark4Provider() { + return getClass().getName(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/DesignerStartWithEmptyFile.java b/designer-base/src/main/java/com/fr/design/fun/impl/DesignerStartWithEmptyFile.java new file mode 100644 index 000000000..12ad01dcc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/DesignerStartWithEmptyFile.java @@ -0,0 +1,28 @@ +package com.fr.design.fun.impl; + +import com.fr.file.FILE; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.record.analyzer.EnableMetrics; + +/** + * Created by rinoux on 2016/12/16. + */ +@EnableMetrics +public class DesignerStartWithEmptyFile extends AbstractDesignerStartOpenFileProcessor { + + private static final DesignerStartWithEmptyFile INSTANCE = new DesignerStartWithEmptyFile(); + + private DesignerStartWithEmptyFile() { + } + + public static DesignerStartWithEmptyFile getInstance() { + return INSTANCE; + } + + @Override + @Focus(id = "com.fr.dzstartemptyfile", text = "Fine_Design_Start_Empty_File", source = Original.REPORT) + public FILE fileToShow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeAutoBuildPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeAutoBuildPane.java index 6103e6800..83c52ac78 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeAutoBuildPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/JTreeAutoBuildPane.java @@ -27,13 +27,16 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.stable.StringUtils; -import java.awt.*; + +import javax.swing.JPanel; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.List; -import javax.swing.*; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; public class JTreeAutoBuildPane extends BasicPane implements PreviewLabel.Previewable, EditOrNewLabel.Editable { private TreeTableDataComboBox treeTableDataComboBox; diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java index bab3e8851..5769fdacf 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/UnitInputPane.java @@ -10,6 +10,7 @@ import com.fr.design.gui.ispinner.UIBasicSpinner; import com.fr.design.gui.itextfield.UINumberField; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.GeneralUtils; import com.fr.stable.AssistUtils; import com.fr.stable.StringUtils; @@ -27,7 +28,8 @@ import java.math.BigDecimal; * For input Number. */ public abstract class UnitInputPane extends BasicPane { - private static final double NUM_POINT = 0.000001; + private static final double MAX_NUM = 3000.0D; + private static final double NUM_POINT = 0.000001; private int scale = -1; String title; @@ -46,7 +48,7 @@ public abstract class UnitInputPane extends BasicPane { centerPane.add(titleLabel); // Denny:在对话框中加入JSpinner对象 - numberFieldSpinner = new UIBasicSpinner(new SpinnerNumberModel(0, 0, 999, 1)); + numberFieldSpinner = new UIBasicSpinner(new SpinnerNumberModel(0, 0, MAX_NUM, 1)); GUICoreUtils.setColumnForSpinner(numberFieldSpinner, 24); numberFieldSpinner.setPreferredSize(new Dimension(60, 20)); numberFieldSpinner.setMinimumSize(new Dimension(60, 20)); @@ -71,17 +73,17 @@ public abstract class UnitInputPane extends BasicPane { public void populate(float floatValue) { popValue = floatValue; - numberFieldSpinner.setModel(new SpinnerNumberModel(0.00, 0.00, 999.00, 0.01)); + numberFieldSpinner.setModel(new SpinnerNumberModel(0.00, 0.00, MAX_NUM, 0.01)); JFormattedTextField temp = GUICoreUtils.getSpinnerTextField(numberFieldSpinner); addChangeListener(temp); - BigDecimal de = new BigDecimal(floatValue + ""); + BigDecimal de = new BigDecimal(GeneralUtils.objectToString(floatValue)); if (scale > 0) { floatValue = de.setScale(scale, BigDecimal.ROUND_DOWN).floatValue(); } else { floatValue = de.floatValue(); } - //选中多列, 并且列宽不完全一致的话, 就不显示值了. + //选中多列, 并且列宽不完全一致的话, 就不显示值了. temp.setText(AssistUtils.equals(floatValue, 0) ? StringUtils.EMPTY : Utils.convertNumberStringToString(new Float(floatValue))); // denny:默认应该为选中,方便用户修改 @@ -99,8 +101,8 @@ public abstract class UnitInputPane extends BasicPane { public double update() throws ValueNotChangeException { // 值没变就不改 if (!changed) { - throw vncExp; - } + throw vncExp; + } // Denny: get numberFieldSpinner 的 TextField JFormattedTextField temp = GUICoreUtils.getSpinnerTextField(numberFieldSpinner); @@ -108,7 +110,8 @@ public abstract class UnitInputPane extends BasicPane { if (temp.getText().length() == 0) { return 0; } - BigDecimal de = new BigDecimal(temp.getText()); + + BigDecimal de = new BigDecimal(GeneralUtils.objectToString(temp.getValue())); if (scale > 0) { return de.setScale(scale, BigDecimal.ROUND_DOWN).floatValue(); } else { @@ -176,4 +179,4 @@ public abstract class UnitInputPane extends BasicPane { // 鼠标按键在组件上单击时 } }; -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIColorButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIColorButton.java index 28f583061..31a6d963d 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIColorButton.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIColorButton.java @@ -136,6 +136,7 @@ public class UIColorButton extends UIButton implements PopupHider, UIObserver, G } popupWin = this.getColorControlWindow(); + popupWin.setColor(color); GUICoreUtils.showPopupMenu(popupWin, this, POPUP_MENU_SHIFT, this.getSize().height); } @@ -154,18 +155,22 @@ public class UIColorButton extends UIButton implements PopupHider, UIObserver, G protected ColorControlWindow getColorControlWindow() { //find parant. if (this.popupWin == null) { - this.popupWin = new ColorControlWindow(UIColorButton.this) { - @Override - protected void colorChanged() { - UIColorButton.this.setColor(this.getColor()); - } - - }; + this.popupWin = initColorControlWindow(); } return popupWin; } + protected ColorControlWindow initColorControlWindow(){ + return new ColorControlWindow(UIColorButton.this) { + @Override + protected void colorChanged() { + UIColorButton.this.setColor(this.getColor()); + } + + }; + } + /** * 添加监听 * diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UINoThemeColorButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UINoThemeColorButton.java new file mode 100644 index 000000000..da071458a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UINoThemeColorButton.java @@ -0,0 +1,36 @@ +package com.fr.design.gui.ibutton; + +import com.fr.design.gui.ipoppane.PopupHider; +import com.fr.design.style.color.ColorControlWindow; + +import javax.swing.Icon; + + +public class UINoThemeColorButton extends UIColorButton{ + + public UINoThemeColorButton(Icon icon) { + super(icon); + } + + protected ColorControlWindow initColorControlWindow(){ + return new NoThemeColorControlWindow(this); + } + + private class NoThemeColorControlWindow extends ColorControlWindow{ + + + public NoThemeColorControlWindow(PopupHider popupHider) { + super(popupHider); + } + + protected boolean supportThemeColor(){ + return false; + } + + + @Override + protected void colorChanged() { + UINoThemeColorButton.this.setColor(this.getColor()); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/ColorSchemeComboBox.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/ColorSchemeComboBox.java index 044bb6518..f8816a184 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombobox/ColorSchemeComboBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombobox/ColorSchemeComboBox.java @@ -2,14 +2,18 @@ package com.fr.design.gui.icombobox; import com.fr.base.ChartColorMatching; import com.fr.base.ChartPreStyleConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.chart.ThemedChartSeriesColor; import com.fr.cert.token.lang.Collections; import com.fr.chart.base.ChartConstants; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.i18n.Toolkit; import com.fr.general.GeneralUtils; import javax.swing.DefaultComboBoxModel; import javax.swing.JLabel; import javax.swing.JList; +import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -65,7 +69,21 @@ public class ColorSchemeComboBox extends UIComboBox { Iterator names = config.names(); if (preDefined) { - colorSchemes.put(Toolkit.i18nText("Fine-Design_Chart_Predefined"), null); + ColorInfo colorInfo = new ColorInfo(); + List list = new ArrayList<>(); + colorInfo.setColors(list); + TemplateTheme templateTheme = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getTemplateTheme(); + ThemedChartSeriesColor themedChartSeriesColor = templateTheme.getChartStyle().getThemedChartSeriesColor(); + if (themedChartSeriesColor.isCombineColor()) { + colorInfo.setGradient(false); + list.addAll(templateTheme.getColorScheme().getColors()); + } else { + colorInfo.setGradient(true); + list.add(themedChartSeriesColor.getBeginColor()); + list.add(themedChartSeriesColor.getEndColor()); + } + colorSchemes.put(Toolkit.i18nText("Fine-Design_Chart_Follow_Theme"), colorInfo); + } else { //添加默认的方案和第一个方案 String defaultName = config.getCurrentStyle(); diff --git a/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java b/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java index 347dd768f..709fdece7 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java +++ b/designer-base/src/main/java/com/fr/design/gui/itoolbar/UIToolbar.java @@ -2,9 +2,12 @@ package com.fr.design.gui.itoolbar; import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.mainframe.JTemplate; + import java.awt.Component; import java.awt.FlowLayout; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import javax.swing.JToolBar; public class UIToolbar extends JToolBar { @@ -35,13 +38,18 @@ public class UIToolbar extends JToolBar { } } - public void refreshUIToolBar() { - JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - if (template != null) { - for (int i = 0; i < getComponentCount(); i++) { - Component component = getComponents()[i]; - component.setEnabled(template.checkEnable()); - } + public Map getComponentState() { + Map componentState = new HashMap<>(); + for (int i = 0; i < getComponentCount(); i++) { + Component component = getComponent(i); + componentState.put(component, component.isEnabled()); + } + return componentState; + } + + public static void resetComponentState(Map componentState) { + for (Component component : componentState.keySet()) { + component.setEnabled(componentState.get(component)); } } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java index f3771a0f9..a748fa320 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java @@ -67,7 +67,7 @@ public class EnvFileTree extends RefreshableJTree { String lock = node.getLock(); String name = node.getName(); if (treeNode.hasFullAuthority()) { - if (lock != null && !node.getUserID().equals(lock)) { + if (lock != null && !lock.equals(node.getUserID())) { name = name + Toolkit.i18nText("Fine-Design_Basic_Template_Status_Locked", "(", ")"); } this.setIcon(FileTreeIcon.getIcon(node)); diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java index b418c1db4..e0515fe81 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java @@ -48,6 +48,9 @@ public class FileTreeIcon { public static final Icon MODERN_CHT_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/modern_style_cht_file_icon_16x16.png"); + public static final Icon CPTX_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/cptx_file_icon.png"); + public static final Icon CPTX_LOCKED_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/cptx_file_icon_locked.png"); + public static final LockIcon FOLDER_LOCK_ICON = new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/fold.png")); public static final LockIcon FILE_LOCK_ICON = @@ -108,6 +111,7 @@ public class FileTreeIcon { public final static int CPT_FILE = 11; //.cpt public final static int FRM_FILE = 12; //.form .frm public final static int CHT_FILE = 13; //.chart .cht + public final static int CPTX_FILE = 14; //.cptx public static Icon getIcon(File file) { return FileTreeIcon.getIcon(file, false); @@ -252,6 +256,12 @@ public class FileTreeIcon { } else { return FileTreeIcon.MODERN_CPT_FILE_IMAGE_ICON; } + } else if (fileType == CPTX_FILE) { + if (isLocked) { + return FileTreeIcon.CPTX_LOCKED_ICON; + } else { + return FileTreeIcon.CPTX_ICON; + } } else if (fileType == FRM_FILE) { //form frm if (isLocked) { return FileTreeIcon.FRM_FILE_LOCK_ICON; @@ -314,6 +324,8 @@ public class FileTreeIcon { return BMP_FILE; } else if (fileName.endsWith(".cpt")) { return CPT_FILE; + } else if (fileName.endsWith(".cptx")) { + return CPTX_FILE; } else if (fileName.endsWith(".frm") || fileName.endsWith(".form")) { return FRM_FILE; } else if (fileName.endsWith(".cht") || fileName.endsWith(".chart")) { diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/ReportletPane.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/ReportletPane.java index 3f5fff689..69e5a2c8a 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/ReportletPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/ReportletPane.java @@ -53,7 +53,7 @@ public class ReportletPane extends BasicPane { centerPane.add(cardPane, BorderLayout.CENTER); cardPane.setLayout(card = new CardLayout()); templateReportletTree = new TemplateFileTree(); - IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{".cpt", ".class", ".frm", ".form"}); + IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{".cpt", ".class", ".frm", ".form", ".cptx"}); templateReportletTree.setFileNodeFilter(filter); cardPane.add(t_panel = new JScrollPane(templateReportletTree), "TEMPLATE"); classReportletTree = new ClassFileTree(); diff --git a/designer-base/src/main/java/com/fr/design/gui/style/AbstractBorderPackerPane.java b/designer-base/src/main/java/com/fr/design/gui/style/AbstractBorderPackerPane.java new file mode 100644 index 000000000..4356f133a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/AbstractBorderPackerPane.java @@ -0,0 +1,20 @@ +package com.fr.design.gui.style; + +import com.fr.design.dialog.BasicPane; +import com.fr.general.act.BorderPacker; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public abstract class AbstractBorderPackerPane extends BasicPane { + + public abstract void populateBean(BorderPacker style); + public abstract void updateBean(BorderPacker style); + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/AbstractTranslucentBackgroundSpecialPane.java b/designer-base/src/main/java/com/fr/design/gui/style/AbstractTranslucentBackgroundSpecialPane.java new file mode 100644 index 000000000..fe6318ad3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/AbstractTranslucentBackgroundSpecialPane.java @@ -0,0 +1,99 @@ +package com.fr.design.gui.style; + +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.gui.frpane.UIPercentDragPane; +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.backgroundpane.GradientBackgroundQuickPane; +import com.fr.general.Background; +import com.fr.general.act.BackgroundPacker; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public abstract class AbstractTranslucentBackgroundSpecialPane extends BasicPane { + + private final int uiLabelWidth; + private final int uiSettingWidth; + // 背景名称:如主题背景 或 标题背景 + private final String backgroundName; + // 背景 + protected BackgroundSpecialPane backgroundPane = new LayoutBackgroundSpecialPane(); + // 背景透明度 + protected UIPercentDragPane opacityPane = new UIPercentDragPane(); + + public AbstractTranslucentBackgroundSpecialPane(int uiLabelWidth, int uiSettingWidth, String backgroundName) { + this.uiLabelWidth = uiLabelWidth; + this.uiSettingWidth = uiSettingWidth; + this.backgroundName = backgroundName; + this.initializePane(); + } + + private void initializePane() { + setLayout(new BorderLayout(0, 0)); + + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; + + // 确保BackgroundSpecialPane高度变化时,Label依然保持与其顶部对齐 + JPanel backgroundLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + backgroundLabelPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); + backgroundLabelPane.add(new UILabel(backgroundName), BorderLayout.NORTH); + + JPanel backgroundComposedPane = TableLayoutHelper.createGapTableLayoutPane( + new JComponent[][]{ + {backgroundLabelPane, backgroundPane} + }, + new double[]{p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); + + JPanel opacityComposedPane = TableLayoutHelper.createGapTableLayoutPane( + new JComponent[][]{ + {new UILabel(""), new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))}, + {new UILabel(""), opacityPane} + }, + new double[]{p, p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); + opacityComposedPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); + opacityComposedPane.setVisible(false); + + backgroundPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + Background background = backgroundPane.update(); + opacityComposedPane.setVisible(background != null); + } + }); + + add(backgroundComposedPane, BorderLayout.NORTH, 0); + add(opacityComposedPane, BorderLayout.CENTER, 1); + } + + @Override + protected String title4PopupWindow() { + return null; + } + + public abstract void populateBean(T style); + + public abstract void updateBean(T style); + + protected static class LayoutBackgroundSpecialPane extends BackgroundSpecialPane { + @Override + protected GradientBackgroundQuickPane createGradientBackgroundQuickPane() { + return new GradientBackgroundQuickPane(140); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java b/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java index 9f948e7a1..2e04b6ce5 100644 --- a/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java @@ -95,8 +95,14 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse borderPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Border"), 280, 24, panel); this.add(borderPanel, BorderLayout.NORTH); + UILabel backgroundFillLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Background_Fill")); + backgroundFillLabel.setPreferredSize(new Dimension(60, 20)); + backgroundPane = new BackgroundPane(); - backgroundPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background"), 280, 24, backgroundPane); + JPanel backgroundContainPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{backgroundFillLabel, backgroundPane}}, + TableLayoutHelper.FILL_LASTCOLUMN, LayoutConstants.VGAP_SMALL, LayoutConstants.VGAP_MEDIUM); + + backgroundPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background"), 280, 24, backgroundContainPane); this.add(backgroundPanel, BorderLayout.CENTER); initAllNames(); outerToggleButton.addChangeListener(outerToggleButtonChangeListener); diff --git a/designer-base/src/main/java/com/fr/design/gui/style/ComponentBodyStylePane.java b/designer-base/src/main/java/com/fr/design/gui/style/ComponentBodyStylePane.java new file mode 100644 index 000000000..8463ed6f5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/ComponentBodyStylePane.java @@ -0,0 +1,33 @@ +package com.fr.design.gui.style; + +import com.fr.general.act.BorderPacker; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public class ComponentBodyStylePane extends AbstractTranslucentBackgroundSpecialPane { + + public ComponentBodyStylePane(int uiLabelWidth) { + this(uiLabelWidth, -1); + } + + public ComponentBodyStylePane(int uiLabelWidth, int uiSettingWidth) { + super(uiLabelWidth, uiSettingWidth, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Fill")); + } + + @Override + public void populateBean(BorderPacker style) { + this.backgroundPane.populateBean(style.getBackground()); + if (this.opacityPane != null) { + this.opacityPane.populateBean(style.getAlpha()); + } + } + + @Override + public void updateBean(BorderPacker style) { + style.setBackground(backgroundPane.update()); + style.setAlpha((float)opacityPane.updateBean()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/ComponentIntegralStylePane.java b/designer-base/src/main/java/com/fr/design/gui/style/ComponentIntegralStylePane.java new file mode 100644 index 000000000..ef47a148b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/ComponentIntegralStylePane.java @@ -0,0 +1,109 @@ +package com.fr.design.gui.style; + +import com.fr.design.designer.IntervalConstants; +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.general.act.BorderPacker; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import java.awt.BorderLayout; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public class ComponentIntegralStylePane extends AbstractBorderPackerPane { + public static final String[] BORDER_STYLE = new String[]{ + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Common"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Shadow") + }; + + //渲染风格:有无阴影 + protected UIComboBox borderStyleCombo; + // 含图片类型边框的边框配置面板(图片类型边框 + 阴影时存在默认的阴影颜色) + protected TranslucentBorderSpecialPane borderPane; + //边框圆角或圆角裁剪 + protected UISpinner cornerSpinner; + + private final int uiLabelWidth; + private final int uiSettingWidth; + private final boolean supportBorderImage; + private final boolean supportCornerRadius; + + public ComponentIntegralStylePane(int uiLabelWidth, + boolean supportBorderImage, boolean supportCornerRadius) { + this(uiLabelWidth, -1, supportBorderImage, supportCornerRadius); + } + + public ComponentIntegralStylePane(int uiLabelWidth, int uiSettingWidth) { + this(uiLabelWidth, uiSettingWidth, true, true); + } + + public ComponentIntegralStylePane( + int uiLabelWidth, int uiSettingWidth, + boolean supportBorderImage, boolean supportCornerRadius) { + this.uiLabelWidth = uiLabelWidth; + this.uiSettingWidth = uiSettingWidth; + this.supportBorderImage = supportBorderImage; + this.supportCornerRadius = supportCornerRadius; + + this.initializePane(); + } + + private void initializeComponents() { + borderStyleCombo = new UIComboBox(BORDER_STYLE); + borderPane = new TranslucentBorderSpecialPane(this.supportBorderImage); + cornerSpinner = new UISpinner(0,1000,1,0); + } + + protected void initializePane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + this.initializeComponents(); + + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] rowSize = supportCornerRadius ? new double[] {p, p, p} : new double[]{p, p}; + double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; + + JPanel content = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ + {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Render_Style")), borderStyleCombo}, + {this.borderPane, null}, + {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Radius")), cornerSpinner}, + }, + rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); + + this.add(content, BorderLayout.NORTH); + } + + @Override + public void populateBean(BorderPacker style) { + if (this.borderStyleCombo != null) { + this.borderStyleCombo.setSelectedIndex(style.getBorderStyle()); + } + if (cornerSpinner != null) { + this.cornerSpinner.setValue(style.getBorderRadius()); + } + if (this.borderPane != null) { + this.borderPane.populateBean(style); + } + } + + @Override + public void updateBean(BorderPacker style) { + if (borderStyleCombo != null) { + style.setBorderStyle(borderStyleCombo.getSelectedIndex()); + } + if (cornerSpinner != null) { + style.setBorderRadius((int) cornerSpinner.getValue()); + } + if (borderPane != null) { + borderPane.updateBean(style); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/ComponentTitleStylePane.java b/designer-base/src/main/java/com/fr/design/gui/style/ComponentTitleStylePane.java new file mode 100644 index 000000000..8f9a8503d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/ComponentTitleStylePane.java @@ -0,0 +1,351 @@ +package com.fr.design.gui.style; + +import com.fr.base.Utils; +import com.fr.base.svg.IconUtils; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.formula.TinyFormulaPane; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UIToggleButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.WidgetTitle; +import com.fr.general.FRFont; +import com.fr.general.IOUtils; +import com.fr.general.act.BorderPacker; +import com.fr.general.act.TitlePacker; +import com.fr.stable.Constants; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Font; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public class ComponentTitleStylePane extends AbstractBorderPackerPane { + private static final Dimension BUTTON_SIZE = new Dimension(20, 20); + public static final TitlePacker DEFAULT_TITLE_PACKER = new WidgetTitle(); + + // 标题可见 + protected UICheckBox visibleCheckbox; + //标题文字内容 + protected TinyFormulaPane textContentPane; + //标题字体格式 + protected UIComboBox fontFamilyComboBox; + //标题字体大小 + protected UIComboBox fontSizeComboBox; + //标题字体颜色 + protected UIColorButton fontColorSelectPane; + //标题字体特殊效果:粗体、斜体、下划线 + private UIToggleButton fontBoldButton; + private UIToggleButton fontItalicButton; + private UIToggleButton fontUnderlineButton; + // 标题图文混排 + protected TextInsetImageBackgroundSpecialPane insetImagePane; + //对齐方式 + protected UIButtonGroup alignPane; + //标题整体背景 + protected TitleTranslucentBackgroundSpecialPane backgroundPane; + + // 是否支持用户编辑这些属性(不支持时: 设置面板总是不可见) + private boolean isSupportTitleVisible = true; + private boolean isSupportTitleContent = true; + private boolean isSupportTitleOtherSetting = true; + + // 用于控制各部分设置的可见性 + private JPanel titleVisiblePane; + private JPanel titleContentPane; + private JPanel titleOtherSettingPane; + + private final int uiLabelWidth; + private final int uiSettingWidth; + + public ComponentTitleStylePane(int uiLabelWidth) { + this(uiLabelWidth, -1); + } + + public ComponentTitleStylePane( + int uiLabelWidth, int uiSettingWidth) { + this.uiLabelWidth = uiLabelWidth; + this.uiSettingWidth = uiSettingWidth; + this.initializePane(); + } + + private void initializeComponents() { + visibleCheckbox = new UICheckBox(); + + textContentPane = new TinyFormulaPane(); + + fontFamilyComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); + FRFont frFont = DEFAULT_TITLE_PACKER.getFrFont(); + if (frFont != null) { + String fontFamily = frFont.getFamily(); + // 使用style中默认的字体初始化titleFontFamilyComboBox,保证UI和数据的一致性 + this.fontFamilyComboBox.setSelectedItem(fontFamily); + } + fontFamilyComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Family")); + + fontSizeComboBox = new UIComboBox(FRFontPane.FONT_SIZES); + fontSizeComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Size")); + + fontColorSelectPane = new UIColorButton(); + fontColorSelectPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); + fontColorSelectPane.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); + + fontBoldButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); + fontBoldButton.setPreferredSize(BUTTON_SIZE); + fontBoldButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); + fontBoldButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); + + fontItalicButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); + fontItalicButton.setPreferredSize(BUTTON_SIZE); + fontItalicButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); + fontItalicButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); + + fontUnderlineButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png")); + fontUnderlineButton.setPreferredSize(BUTTON_SIZE); + fontUnderlineButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); + fontUnderlineButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); + + insetImagePane = new TextInsetImageBackgroundSpecialPane(); + + alignPane = new UIButtonGroup<>( + new Icon[]{ + IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), + IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), + IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png") + }, + new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT}); + alignPane.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") + }); + alignPane.setSelectedItem(DEFAULT_TITLE_PACKER.getPosition()); + + backgroundPane = new TitleTranslucentBackgroundSpecialPane(this.uiLabelWidth, this.uiSettingWidth); + } + + private void initializePane() { + this.setLayout(new BorderLayout(0, 0)); + this.initializeComponents(); + + titleVisiblePane = this.createTitleVisiblePane(); + titleContentPane = this.createTitleContentPane(); + titleOtherSettingPane = this.createTitleOtherSettingPane(); + + if (isSupportTitleVisible) { + titleVisiblePane.setVisible(true); + } + if (isSupportTitleVisible) { + titleContentPane.setVisible(false); + } + if (isSupportTitleVisible) { + titleOtherSettingPane.setVisible(false); + } + + addComponents(titleVisiblePane, titleContentPane, titleOtherSettingPane); + } + + private JPanel createTitleVisiblePane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + visibleCheckbox.setSelected(false); + + container.add(visibleCheckbox, BorderLayout.WEST); + container.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Visible")), BorderLayout.CENTER); + + visibleCheckbox.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + boolean visible = visibleCheckbox.isSelected(); + if (titleContentPane != null) { + titleContentPane.setVisible(visible && isSupportTitleContent); + } + if (titleOtherSettingPane != null) { + titleOtherSettingPane.setVisible(visible && isSupportTitleOtherSetting); + } + } + }); + return container; + } + + private JPanel createTitleContentPane() { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] rowSize = {p}; + double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; + + return TableLayoutHelper.createCommonTableLayoutPane( + new JComponent[][]{{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Content")), textContentPane}}, + rowSize, columnSize, IntervalConstants.INTERVAL_L1); + } + + private JPanel createTitleOtherSettingPane() { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] rowSize = {p, p, p, p, p}; + double[] columnSize = {this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f}; + + JComponent[][] components = new JComponent[][]{ + {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Format")), fontFamilyComboBox}, + {null, createTitleFontButtonPane()}, + {insetImagePane, null}, + {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Text_Align")), alignPane}, + {backgroundPane, null} + }; + + return TableLayoutHelper.createCommonTableLayoutPane(components, rowSize, columnSize, IntervalConstants.INTERVAL_L1); + } + + protected JPanel createTitleFontButtonPane(){ + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] rowSize = {p}; + double[] columnSize = {f, p, p, p, p}; + + JPanel buttonPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] { + {fontSizeComboBox, fontColorSelectPane, fontItalicButton, fontBoldButton, fontUnderlineButton}, + }, rowSize, columnSize, IntervalConstants.INTERVAL_W0); + + JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + containerPane.add(buttonPane, BorderLayout.NORTH); + + return containerPane; + } + + @Override + public void populateBean(BorderPacker style) { + TitlePacker widgetTitle = style == null ? new WidgetTitle() : style.getTitle(); + widgetTitle = widgetTitle == null ? new WidgetTitle() : widgetTitle; + boolean titleVisible = style != null && style.getType() != LayoutBorderStyle.STANDARD; + visibleCheckbox.setSelected(isSupportTitleVisible && titleVisible); + titleContentPane.setVisible(isSupportTitleContent && titleVisible); + titleOtherSettingPane.setVisible(isSupportTitleOtherSetting && titleVisible); + + this.textContentPane.populateBean(widgetTitle.getTextObject().toString()); + + FRFont frFont = widgetTitle.getFrFont(); + this.fontSizeComboBox.setSelectedItem(frFont.getSize()); + this.fontFamilyComboBox.setSelectedItem(frFont.getFamily()); + this.fontColorSelectPane.setColor(frFont.getForeground()); + this.fontColorSelectPane.repaint(); + fontBoldButton.setSelected(frFont.isBold()); + fontItalicButton.setSelected(frFont.isItalic()); + + int line = frFont.getUnderline(); + if (line == Constants.LINE_NONE) { + fontUnderlineButton.setSelected(false); + } else { + fontUnderlineButton.setSelected(true); + } + + alignPane.setSelectedItem(widgetTitle.getPosition()); + insetImagePane.populateBean(widgetTitle); + backgroundPane.populateBean(widgetTitle); + } + + @Override + public void updateBean(BorderPacker style) { + style.setType(visibleCheckbox != null && visibleCheckbox.isSelected() ? LayoutBorderStyle.TITLE : LayoutBorderStyle.STANDARD); + TitlePacker title = style.getTitle() == null ? new WidgetTitle() : style.getTitle(); + title.setTextObject(textContentPane.updateBean()); + FRFont frFont = title.getFrFont(); + frFont = frFont.applySize((Integer) fontSizeComboBox.getSelectedItem()); + frFont = frFont.applyName(fontFamilyComboBox.getSelectedItem().toString()); + frFont = frFont.applyForeground(fontColorSelectPane.getColor()); + frFont = updateTitleFontItalicBold(frFont); + int line = fontUnderlineButton.isSelected() ? Constants.LINE_THIN : Constants.LINE_NONE; + frFont = frFont.applyUnderline(line); + title.setFrFont(frFont); + title.setPosition((Integer) alignPane.getSelectedItem()); + insetImagePane.updateBean(title); + backgroundPane.updateBean(title); + style.setTitle(title); + } + + private FRFont updateTitleFontItalicBold(FRFont frFont) { + int italic_bold = frFont.getStyle(); + boolean isItalic = italic_bold == Font.ITALIC || italic_bold == (Font.BOLD + Font.ITALIC); + boolean isBold = italic_bold == Font.BOLD || italic_bold == (Font.BOLD + Font.ITALIC); + if (fontItalicButton.isSelected() && !isItalic) { + italic_bold += Font.ITALIC; + } else if (!fontItalicButton.isSelected() && isItalic) { + italic_bold -= Font.ITALIC; + } + frFont = frFont.applyStyle(italic_bold); + if (fontBoldButton.isSelected() && !isBold) { + italic_bold += Font.BOLD; + } else if (!fontBoldButton.isSelected() && isBold) { + italic_bold -= Font.BOLD; + } + frFont = frFont.applyStyle(italic_bold); + return frFont; + } + + private void addComponents(JComponent... components) { + if (components == null) { + return; + } + JPanel container = this; + for (int i = 0; i < components.length; i++) { + JComponent component = components[i]; + if (component != null) { + container.add(component, BorderLayout.NORTH); + component.setBorder(BorderFactory.createEmptyBorder(i == 0 ? 0 : IntervalConstants.INTERVAL_L1, 0, 0, 0)); + if (i < components.length - 1) { + JPanel nextContainer = new JPanel(FRGUIPaneFactory.createBorderLayout()); + container.add(nextContainer, BorderLayout.CENTER); + container = nextContainer; + } + } + } + } + + + public void setSupportTitleVisible(boolean supporting) { + isSupportTitleVisible = supporting; + if (titleVisiblePane != null) { + titleVisiblePane.setVisible(supporting); + } + } + + public void setSupportTitleContent(boolean supporting) { + isSupportTitleContent = supporting; + if (titleContentPane != null) { + boolean titleVisible = visibleCheckbox.isSelected(); + if (isSupportTitleContent) { + titleContentPane.setVisible(titleVisible); + } else { + titleContentPane.setVisible(false); + } + } + } + + public void setSupportOtherSetting(boolean supporting) { + isSupportTitleOtherSetting = supporting; + if (titleOtherSettingPane != null) { + boolean titleVisible = visibleCheckbox.isSelected(); + if (isSupportTitleOtherSetting) { + titleOtherSettingPane.setVisible(titleVisible); + } else { + titleOtherSettingPane.setVisible(false); + } + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/FollowingThemePane.java b/designer-base/src/main/java/com/fr/design/gui/style/FollowingThemePane.java new file mode 100644 index 000000000..55f4612a2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/FollowingThemePane.java @@ -0,0 +1,138 @@ +package com.fr.design.gui.style; + +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.design.dialog.BasicPane; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ibutton.UIButtonGroup; +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.design.mainframe.JTemplate; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/19 + */ +public class FollowingThemePane extends BasicPane implements UIObserver { + public static final int SETTING_LABEL_WIDTH = 60; + + public static final String[] FOLLOWING_THEME_STRING_ARRAYS = new String[]{ + Toolkit.i18nText("Fine-Design_Style_Follow_Theme"), + Toolkit.i18nText("Fine-Design_Style_Not_Follow_Theme"), + }; + + private final UIButtonGroup followingThemeButtonGroup; + private final List changeListeners = new ArrayList<>(); + private UIObserverListener uiObserverListener; + + private JPanel container; + + public FollowingThemePane(String name) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + + followingThemeButtonGroup = new UIButtonGroup<>(FOLLOWING_THEME_STRING_ARRAYS); + followingThemeButtonGroup.setSelectedIndex(1); + followingThemeButtonGroup.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + for (FollowingThemeActionChangeListener changeListener : changeListeners) { + changeListener.onFollowingTheme(isFollowingTheme()); + } + invalidate(); + + // 与主题相关的属性面板更新完毕后,再通知外层更新数据 + if (uiObserverListener != null) { + uiObserverListener.doChange(); + } + } + }); + + UILabel followingThemeLabel = new UILabel(name); + + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + JPanel followingThemePane = + TableLayoutHelper.createGapTableLayoutPane( new Component[][]{new Component[] { followingThemeLabel, followingThemeButtonGroup}}, + new double[] { p }, new double[] { SETTING_LABEL_WIDTH, f }, 10, 0); + followingThemePane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + followingThemePane.setVisible(false); + + add(followingThemePane, BorderLayout.NORTH); + container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + add(container, BorderLayout.CENTER); + } + + public void addFollowThemePane(JPanel content, FollowingThemeActionChangeListener changeListener) { + if (content != null) { + container.add(content, BorderLayout.NORTH); + changeListeners.add(changeListener); + + JPanel nextContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.add(nextContainer, BorderLayout.CENTER); + container = nextContainer; + } + } + + @Override + protected String title4PopupWindow() { + return null; + } + + @Override + public void registerChangeListener(UIObserverListener uiObserverListener) { + this.uiObserverListener = uiObserverListener; + } + + @Override + public boolean shouldResponseChangeListener() { + return true; + } + + public interface FollowingThemeActionChangeListener { + void onFollowingTheme(boolean following); + } + + public TemplateTheme getUsingTheme() { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + return template.getTemplateTheme(); + } + return null; + } + + public void supportFollowingTheme(boolean supporting) { + getComponent(0).setVisible(supporting); + if (!supporting) { + setFollowingTheme(false); + } + } + + public void setFollowingTheme(boolean following) { + followingThemeButtonGroup.setSelectedIndex(following ? 0 : 1); + for (FollowingThemeActionChangeListener changeListener : changeListeners) { + changeListener.onFollowingTheme(isFollowingTheme()); + } + } + public boolean isFollowingTheme() { + return followingThemeButtonGroup.getSelectedIndex() == 0; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/style/ReportBackgroundSpecialPane.java b/designer-base/src/main/java/com/fr/design/gui/style/ReportBackgroundSpecialPane.java new file mode 100644 index 000000000..aeb2938a2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/ReportBackgroundSpecialPane.java @@ -0,0 +1,102 @@ +package com.fr.design.gui.style; + +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.event.UIObserverListener; +import com.fr.design.fun.BackgroundQuickUIProvider; +import com.fr.design.mainframe.backgroundpane.BackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.ColorBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.GradientBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.ImageBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.NullBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.PatternBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.TextureBackgroundQuickPane; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/19 + */ +public class ReportBackgroundSpecialPane extends BackgroundPane { + public ReportBackgroundSpecialPane(){ + super(); + } + + @Override + protected BackgroundQuickPane[] supportKindsOfBackgroundUI() { + NullBackgroundQuickPane nullBackgroundPane = new NullBackgroundQuickPane(); + + ColorBackgroundQuickPane colorBackgroundPane = new ColorBackgroundQuickPane(); + colorBackgroundPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + + ImageBackgroundQuickPane imageBackgroundPane = new ImageBackgroundQuickPane(); + imageBackgroundPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + + GradientBackgroundQuickPane gradientBackgroundPane = createGradientBackgroundQuickPane(); + gradientBackgroundPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + + TextureBackgroundQuickPane textureBackgroundPane = new TextureBackgroundQuickPane(); + textureBackgroundPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + + PatternBackgroundQuickPane patternBackgroundPane = new PatternBackgroundQuickPane(); + patternBackgroundPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + + + + List kinds = new ArrayList(); + + kinds.add(nullBackgroundPane); + kinds.add(colorBackgroundPane); + kinds.add(imageBackgroundPane); + kinds.add(gradientBackgroundPane); + kinds.add(textureBackgroundPane); + kinds.add(patternBackgroundPane); + + Set providers = ExtraDesignClassManager.getInstance().getArray(BackgroundQuickUIProvider.MARK_STRING); + for (BackgroundQuickUIProvider provider : providers) { + BackgroundQuickPane newTypePane = provider.appearanceForBackground(); + newTypePane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireStateChanged(); + } + }); + kinds.add(newTypePane); + } + + return kinds.toArray(new BackgroundQuickPane[kinds.size()]); + } + + protected GradientBackgroundQuickPane createGradientBackgroundQuickPane() { + // 使用默认的150宽度构建渐变条 + return new GradientBackgroundQuickPane(); + } +} diff --git a/designer-form/src/main/java/com/fr/design/gui/xpane/TitleInsetImagePane.java b/designer-base/src/main/java/com/fr/design/gui/style/TextInsetImageBackgroundSpecialPane.java similarity index 95% rename from designer-form/src/main/java/com/fr/design/gui/xpane/TitleInsetImagePane.java rename to designer-base/src/main/java/com/fr/design/gui/style/TextInsetImageBackgroundSpecialPane.java index 3671259a2..b3556dc6f 100644 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/TitleInsetImagePane.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/TextInsetImageBackgroundSpecialPane.java @@ -1,4 +1,4 @@ -package com.fr.design.gui.xpane; +package com.fr.design.gui.style; import com.fr.base.Style; import com.fr.base.background.ImageBackground; @@ -18,7 +18,6 @@ import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.backgroundpane.ImagePreviewPane; import com.fr.design.style.background.image.ImageFileChooser; -import com.fr.design.widget.ui.designer.component.UIBoundSpinner; import com.fr.form.ui.WidgetTitle; import com.fr.general.Background; import com.fr.general.IOUtils; @@ -26,11 +25,20 @@ import com.fr.general.ImageWithSuffix; import com.fr.general.act.TitlePacker; import com.fr.stable.Constants; -import javax.swing.*; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.basic.BasicButtonUI; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.Shape; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; @@ -42,8 +50,8 @@ import java.awt.geom.RoundRectangle2D; * @version 10.0.18 * Created by Starryi on 2021/7/3 */ -public class TitleInsetImagePane extends JPanel implements UIObserver { - private final int SETTING_LABEL_WIDTH = LayoutStylePane.SETTING_LABEL_WIDTH; +public class TextInsetImageBackgroundSpecialPane extends JPanel implements UIObserver { + private final int SETTING_LABEL_WIDTH = 60; private final int DELETE_BUTTON_SIZE = 24; private final int IMAGE_PREVIEW_SIZE = 145; private final Color IMAGE_PREVIEW_OVERLAY_COLOR = new Color(255, 255, 255, 51); @@ -62,7 +70,7 @@ public class TitleInsetImagePane extends JPanel implements UIObserver { private ImageFileChooser imageFileChooser; - public TitleInsetImagePane() { + public TextInsetImageBackgroundSpecialPane() { this.initComponents(); this.initLayout(); } @@ -198,7 +206,7 @@ public class TitleInsetImagePane extends JPanel implements UIObserver { com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Inset_Relative_Right_Tooltip"), }); - imagePaddingPane = new UIBoundSpinner(0, Integer.MAX_VALUE, 1, WidgetTitle.DEFAULT_INSET_PADDING); + imagePaddingPane = new UISpinner(0, Integer.MAX_VALUE, 1, WidgetTitle.DEFAULT_INSET_PADDING); imagePaddingPane.setValue(DEFAULT_INSET_PADDING); } diff --git a/designer-base/src/main/java/com/fr/design/gui/style/TitleTranslucentBackgroundSpecialPane.java b/designer-base/src/main/java/com/fr/design/gui/style/TitleTranslucentBackgroundSpecialPane.java new file mode 100644 index 000000000..db8c64e19 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/style/TitleTranslucentBackgroundSpecialPane.java @@ -0,0 +1,27 @@ +package com.fr.design.gui.style; + +import com.fr.general.act.TitlePacker; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/11 + */ +public class TitleTranslucentBackgroundSpecialPane extends AbstractTranslucentBackgroundSpecialPane { + + public TitleTranslucentBackgroundSpecialPane(int uiLabelWidth, int uiSettingWidth) { + super(uiLabelWidth, uiSettingWidth, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Background")); + } + + @Override + public void populateBean(TitlePacker style) { + backgroundPane.populateBean(style.getBackground()); + opacityPane.populateBean(style.getBackgroundOpacity()); + } + + @Override + public void updateBean(TitlePacker style) { + style.setBackground(backgroundPane.update()); + style.setBackgroundOpacity((float)opacityPane.updateBean()); + } +} diff --git a/designer-form/src/main/java/com/fr/design/gui/xpane/BorderLineAndImagePane.java b/designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java similarity index 96% rename from designer-form/src/main/java/com/fr/design/gui/xpane/BorderLineAndImagePane.java rename to designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java index 0f2b853d1..237a5659a 100644 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/BorderLineAndImagePane.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java @@ -1,8 +1,6 @@ -package com.fr.design.gui.xpane; +package com.fr.design.gui.style; -import com.fr.base.GraphHelper; import com.fr.base.Style; -import com.fr.base.Utils; import com.fr.base.background.ImageBackground; import com.fr.base.background.ImageFileBackground; import com.fr.design.border.UIRoundedBorder; @@ -16,8 +14,6 @@ import com.fr.design.event.UIObserverListener; import com.fr.design.gui.frpane.ImgChooseWrapper; import com.fr.design.gui.frpane.UIPercentDragPane; import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.gui.ibutton.UIButtonUI; -import com.fr.design.gui.ibutton.UIColorButton; import com.fr.design.gui.icombobox.LineComboBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.FRGUIPaneFactory; @@ -28,9 +24,9 @@ import com.fr.design.mainframe.backgroundpane.ImagePreviewPane; import com.fr.design.style.background.image.ImageFileChooser; import com.fr.design.style.color.NewColorSelectBox; import com.fr.env.utils.DesignerInteractionHistory; -import com.fr.form.ui.LayoutBorderStyle; import com.fr.general.Background; import com.fr.general.IOUtils; +import com.fr.general.act.BorderPacker; import com.fr.stable.Constants; import com.fr.stable.GraphDrawHelper; import com.fr.stable.ProjectLibrary; @@ -78,8 +74,8 @@ import java.util.Arrays; * * 可配置图片类型边框的样式设置面板 */ -public class BorderLineAndImagePane extends JPanel implements UIObserver { - private final int SETTING_LABEL_WIDTH = LayoutStylePane.SETTING_LABEL_WIDTH; +public class TranslucentBorderSpecialPane extends AbstractBorderPackerPane implements UIObserver { + private final int SETTING_LABEL_WIDTH = 60; private final Style DEFAULT_IMAGE_LAYOUT_STYLE = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_DEFAULT); private final String TWEAK_NINE_POINT_HELP_URL = "https://help.fanruan.com/finereport/doc-view-4135.html"; @@ -98,7 +94,7 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { private int[] ninePoint = new int[] {-1, -1, -1, -1}; - public BorderLineAndImagePane(boolean supportBorderImage) { + public TranslucentBorderSpecialPane(boolean supportBorderImage) { this.initComponents(supportBorderImage); this.initLayout(); } @@ -273,7 +269,7 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { if (imagePreviewPane.getImage() != null) { tweakPane.previewPane.setNinePoint(ninePoint); - BasicDialog dialog = tweakPane.showWindow(SwingUtilities.getWindowAncestor(BorderLineAndImagePane.this)); + BasicDialog dialog = tweakPane.showWindow(SwingUtilities.getWindowAncestor(TranslucentBorderSpecialPane.this)); dialog.addDialogActionListener(new DialogActionAdapter() { @Override public void doOk() { @@ -287,7 +283,13 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { }); } - public void populateBean(LayoutBorderStyle style) { + @Override + protected String title4PopupWindow() { + return null; + } + + @Override + public void populateBean(BorderPacker style) { int borderLine = style.getBorder(); Color borderColor = style.getColor(); @@ -333,7 +335,8 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { this.borderColorPane.setSelectObject(style.getColor()); } - public void updateBean(LayoutBorderStyle style) { + @Override + public void updateBean(BorderPacker style) { style.setBorder(this.borderLineCombo.getSelectedLineStyle()); style.setColor(this.borderColorPane.getSelectObject()); @@ -366,24 +369,6 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { return true; } - protected UIButtonUI createButtonUI(final UIColorButton uiColorButton) { - return new UIButtonUI() { - - public void paint(Graphics g, JComponent c) { - UIButton b = (UIButton) c; - g.setColor(Color.black); - GraphHelper.draw(g, new RoundRectangle2D.Double(1, 1, b.getWidth() - 2, b.getHeight() - 2, 0, 0), 1); - - if (b.getModel().isEnabled()) { - g.setColor(uiColorButton.getColor()); - } else { - g.setColor(new Color(Utils.filterRGB(uiColorButton.getColor().getRGB(), 50))); - } - g.fillRect(2, 2, b.getWidth() - 3, b.getHeight() - 3); - } - }; - } - protected static class BorderLineAndImageComboBox extends LineComboBox { public static final int LINE_PICTURE = -1; public final static int[] BORDER_LINE_AND_IMAGE_STYLE_ARRAY = new int[] { diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/ContentSettingPane.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/ContentSettingPane.java new file mode 100644 index 000000000..848ac9e57 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/ContentSettingPane.java @@ -0,0 +1,328 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.base.BaseFormula; +import com.fr.base.BaseUtils; +import com.fr.base.Parameter; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.formula.TinyFormulaPane; +import com.fr.design.gui.frpane.ReportletParameterViewPane; +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.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.itree.filetree.ReportletPane; +import com.fr.design.hyperlink.AbstractHyperLinkPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.module.DesignModuleFactory; +import com.fr.design.parameter.ParameterReader; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.js.MobilePopupHyperlink; +import com.fr.stable.CommonUtils; +import com.fr.stable.FormulaProvider; +import com.fr.stable.ParameterProvider; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +public class ContentSettingPane extends AbstractHyperLinkPane { + private JPanel popupTargetPane; + private UIRadioButton templatePopupButton; + private UIRadioButton textPopupButton; + private ButtonGroup popupTargetButtons; + + private JPanel templateContentPane; + private UITextField templatePathTextField; + private UICheckBox extendParametersCheckBox; + + private JPanel textSettingPanel; + private TinyFormulaPane textContentPane; + private CustomFontPane fontPane; + + public ContentSettingPane() { + super(); + this.initCompoennt(); + } + + public void addTargetRadioActionListener(ActionListener listener) { + templatePopupButton.addActionListener(listener); + textPopupButton.addActionListener(listener); + } + + public String getTargetType() { + if (templatePopupButton.isSelected()) { + return MobilePopupConstants.Target_Template; + } else { + return MobilePopupConstants.Target_Text; + } + + } + + private void initCompoennt() { + this.setLayout(FRGUIPaneFactory.createM_BorderLayout()); + this.setBorder(GUICoreUtils.createTitledBorder(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Content"))); + + popupTargetPane = this.createPopupTargetPane(); + this.add(popupTargetPane, BorderLayout.NORTH); + + templateContentPane= this.createTemplateContentPane(); + textSettingPanel = this.createTextSettingPane(); + } + + private JPanel createPopupTargetPane() { + templatePopupButton = new UIRadioButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Template")); + templatePopupButton.addActionListener(radioActionListener); + + textPopupButton = new UIRadioButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Text")); + textPopupButton.addActionListener(radioActionListener); + + popupTargetButtons = new ButtonGroup(); + popupTargetButtons.add(templatePopupButton); + popupTargetButtons.add(textPopupButton); + + JPanel popupButtonsPanel = new JPanel(); + popupButtonsPanel.setLayout( new FlowLayout(FlowLayout.LEFT, 10, 0)); + popupButtonsPanel.add(templatePopupButton); + popupButtonsPanel.add(textPopupButton); + return MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Target"), popupButtonsPanel); + } + + private ActionListener radioActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if(templatePopupButton.isSelected()) { + ContentSettingPane.this.add(templateContentPane); + ContentSettingPane.this.remove(textSettingPanel); + } else if (textPopupButton.isSelected()) { + ContentSettingPane.this.add(textSettingPanel); + ContentSettingPane.this.remove(templateContentPane); + } + ContentSettingPane.this.revalidate(); + ContentSettingPane.this.repaint(); + } + }; + + private JPanel createTemplateContentPane() { + JPanel templateContentPane = new JPanel(); + templateContentPane.setLayout(new BorderLayout(0,8)); + + templateContentPane.add(this.createTemplateSelectPanel(), BorderLayout.NORTH); + + parameterViewPane = this.createReportletParameterViewPane(); + templateContentPane.add(parameterViewPane, BorderLayout.CENTER); + + extendParametersCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Hyperlink_Extends_Report_Parameters")); + templateContentPane.add(GUICoreUtils.createFlowPane(extendParametersCheckBox, FlowLayout.LEFT), BorderLayout.SOUTH); + + return templateContentPane; + } + + private JPanel createTemplateSelectPanel() { + JPanel templatePanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + // 路径输入框 + templatePathTextField = new UITextField(20); + templatePanel.add(templatePathTextField, BorderLayout.CENTER); + + // 选择路径按钮 + UIButton templateSelectButton = new UIButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Select")); + templateSelectButton.setPreferredSize(new Dimension(templateSelectButton.getPreferredSize().width, 20)); + templatePanel.add(templateSelectButton, BorderLayout.EAST); + templateSelectButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + final ReportletPane reportletPane = new ReportletPane(); + reportletPane.setSelectedReportletPath(templatePathTextField.getText()); + BasicDialog reportletDialog = reportletPane.showWindow(SwingUtilities.getWindowAncestor(ContentSettingPane.this)); + + reportletDialog.addDialogActionListener(new DialogActionAdapter() { + @Override + public void doOk() { + templatePathTextField.setText(reportletPane.getSelectedReportletPath()); + } + }); + reportletDialog.setVisible(true); + } + }); + return MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Template"), templatePanel); + } + + private ReportletParameterViewPane createReportletParameterViewPane() { + ReportletParameterViewPane templateParameterViewPane = new ReportletParameterViewPane( + new UITableEditAction[]{ + new HyperlinkParametersAction() + }, + getChartParaType(), + getValueEditorPane(), + getValueEditorPane() + ); + templateParameterViewPane.setBorder(GUICoreUtils.createTitledBorder(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Parameter"), null)); + templateParameterViewPane.setPreferredSize(new Dimension(this.getWidth(), 200)); + return templateParameterViewPane; + } + + private JPanel createTextSettingPane() { + JPanel textSettingPanel = new JPanel(); + textSettingPanel.setLayout(new BorderLayout(0,8)); + + textContentPane = new TinyFormulaPane(); + textContentPane.getUITextField().setColumns(20); + textSettingPanel.add( + MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Text"), textContentPane), + BorderLayout.CENTER); + + fontPane = new CustomFontPane(); + textSettingPanel.add( + MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Style"), fontPane), + BorderLayout.SOUTH); + return MobilePopupUIUtils.createTitleSplitLineContentPane("", textSettingPanel); + } + + private String getReportletName() { + String text = this.templatePathTextField.getText(); + return StringUtils.isBlank(text) ? StringUtils.EMPTY : text.substring(1); + } + + @Override + public void populateBean(MobilePopupHyperlink link) { + this.populatePopupTargetBean(link.getPopupTarget()); + this.populateTemplateContentBean(link); + this.populateTextContentBean(link); + + } + + @Override + public MobilePopupHyperlink updateBean() { + return null; + } + + @Override + public void updateBean(MobilePopupHyperlink link) { + this.updatePopupTargetBean(link); + this.updateTemplateContentBean(link); + this.updateTextContentBean(link); + } + + @Override + public String title4PopupWindow() { + return StringUtils.EMPTY; + } + + /** + * 自动添加模板参数的按钮操作 + */ + private class HyperlinkParametersAction extends UITableEditAction { + public HyperlinkParametersAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Template_Parameter")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_report/p.gif")); + } + + @Override + public void actionPerformed(ActionEvent e) { + String tpl = getReportletName(); + if (StringUtils.isBlank(tpl)) { + JOptionPane.showMessageDialog( + ContentSettingPane.this, + Toolkit.i18nText("Fine-Design_Basic_Hyperlink_Please_Select_Reportlet") + ".", + Toolkit.i18nText("Fine-Design_Basic_Message"), + JOptionPane.WARNING_MESSAGE); + return; + } + + //根据模板路径返回参数 + //与当前模块、当前文件无关 + Parameter[] parameters = new Parameter[0]; + + ParameterReader[] readers = DesignModuleFactory.getParameterReaders(); + for (ParameterReader reader : readers) { + Parameter[] ps = reader.readParameterFromPath(tpl); + if (ps != null) { + parameters = ps; + } + } + parameterViewPane.populate(parameters); + } + + @Override + public void checkEnabled() { + //do nothing + } + } + + private void populatePopupTargetBean(String target) { + if (StringUtils.equals(target, MobilePopupConstants.Target_Text)) { + popupTargetButtons.setSelected(textPopupButton.getModel(), true); + this.remove(templateContentPane); + this.add(textSettingPanel, BorderLayout.CENTER); + } else { + popupTargetButtons.setSelected(templatePopupButton.getModel(), true); + this.remove(textSettingPanel); + this.add(templateContentPane, BorderLayout.CENTER); + } + + } + + private void updatePopupTargetBean(MobilePopupHyperlink mobilePopupHyperlink) { + if (templatePopupButton.isSelected()) { + mobilePopupHyperlink.setPopupTarget(MobilePopupConstants.Target_Template); + } else if (textPopupButton.isSelected()) { + mobilePopupHyperlink.setPopupTarget(MobilePopupConstants.Target_Text); + } + } + + private void populateTemplateContentBean(MobilePopupHyperlink link) { + // 模板路径 + templatePathTextField.setText(link.getReportletPath()); + + // 参数面板 + List parameterList = this.parameterViewPane.update(); + parameterList.clear(); + ParameterProvider[] parameters =link.getParameters(); + parameterViewPane.populate(parameters); + + // 继承参数 + extendParametersCheckBox.setSelected(link.isExtendParameters()); + } + + private void updateTemplateContentBean(MobilePopupHyperlink link) { + link.setReportletPath(templatePathTextField.getText()); + + List parameterList = this.parameterViewPane.update(); + if (!parameterList.isEmpty()) { + Parameter[] parameters = new Parameter[parameterList.size()]; + parameterList.toArray(parameters); + link.setParameters(parameters); + } else { + link.setParameters(null); + } + + link.setExtendParameters(extendParametersCheckBox.isSelected()); + + } + + private void populateTextContentBean(MobilePopupHyperlink link) { + Object text = link.getPopupText(); + if (text instanceof FormulaProvider) { + textContentPane.populateBean(((FormulaProvider) text).getContent()); + } else { + textContentPane.populateBean(text == null ? StringUtils.EMPTY : text.toString()); + } + fontPane.populateBean(link.getFRFont()); + } + private void updateTextContentBean(MobilePopupHyperlink link) { + link.setPopupText(textContentPane.getUITextField().getText()); + String text = textContentPane.updateBean(); + if (CommonUtils.maybeFormula(text)) { + link.setPopupText(BaseFormula.createFormulaBuilder().build(textContentPane.updateBean())); + } else { + link.setPopupText(text); + } + + link.setFRFont(fontPane.updateBean()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/CustomFontPane.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/CustomFontPane.java new file mode 100644 index 000000000..aa3e3f868 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/CustomFontPane.java @@ -0,0 +1,100 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UIToggleButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.i18n.Toolkit; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.FRFont; +import com.fr.stable.Constants; + +import javax.swing.*; +import java.awt.*; +import java.util.Vector; + +public class CustomFontPane extends JPanel { + private static final int MAX_FONT_SIZE = 100; + private static final Dimension BUTTON_SIZE = new Dimension(20, 18); + + public static Vector getFontSizes() { + Vector FONT_SIZES = new Vector(); + for (int i = 1; i < MAX_FONT_SIZE; i++) { + FONT_SIZES.add(i); + } + return FONT_SIZES; + } + + private UIComboBox fontSizeComboBox; + private UIToggleButton bold; + private UIToggleButton italic; + private UIToggleButton underline; + private UIColorButton colorSelectPane; + + public CustomFontPane() { + this.initComponent(); + } + + private void initComponent() { + + fontSizeComboBox = new UIComboBox(getFontSizes()); + fontSizeComboBox.setPreferredSize(new Dimension(60, 20)); + fontSizeComboBox.setEditable(true); + + colorSelectPane = new UIColorButton(); + bold = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); + italic = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); + underline = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png")); + + this.setButtonsTips(); + this.setButtonsSize(BUTTON_SIZE); + + Component[] components_font = new Component[]{ + fontSizeComboBox, colorSelectPane, bold, underline, italic + }; + + JPanel buttonPane = new JPanel(new BorderLayout()); + buttonPane.add(GUICoreUtils.createFlowPane(components_font, FlowLayout.LEFT, LayoutConstants.HGAP_SMALL)); + + this.setLayout(new BorderLayout(0,0)); + this.add(buttonPane, BorderLayout.CENTER); + } + + private void setButtonsTips() { + colorSelectPane.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Foreground")); + italic.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Italic")); + bold.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Bold")); + underline.setToolTipText(Toolkit.i18nText("Fine-Design_Report_Underline")); + } + + private void setButtonsSize(Dimension size) { + colorSelectPane.setPreferredSize(size); + bold.setPreferredSize(size); + italic.setPreferredSize(size); + underline.setPreferredSize(size); + } + + + public void populateBean(FRFont frFont) { + fontSizeComboBox.setSelectedItem(frFont.getSize()); + colorSelectPane.setColor(frFont.getForeground()); + bold.setSelected(frFont.isBold()); + italic.setSelected(frFont.isItalic()); + underline.setSelected(frFont.getUnderline() != Constants.LINE_NONE); + } + + public FRFont updateBean() { + int style = Font.PLAIN; + style += this.bold.isSelected() ? Font.BOLD : Font.PLAIN; + style += this.italic.isSelected() ? Font.ITALIC : Font.PLAIN; + return FRFont.getInstance( + FRFont.DEFAULT_FONTNAME, + style, + Float.parseFloat(fontSizeComboBox.getSelectedItem().toString()), + colorSelectPane.getColor(), + underline.isSelected() ? Constants.LINE_THIN : Constants.LINE_NONE + ); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupConstants.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupConstants.java new file mode 100644 index 000000000..d4423d679 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupConstants.java @@ -0,0 +1,22 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.stable.Constants; + +public interface MobilePopupConstants { + int[] BORDER_LINE_STYLE_ARRAY = new int[]{ + Constants.LINE_NONE, + Constants.LINE_THIN, + Constants.LINE_MEDIUM, + Constants.LINE_THICK, + }; + + String Target_Template= "template"; + String Target_Text = "text"; + String Regular_Custom = "custom"; + String Regular_Auto_Height = "auto_height"; + + double Popup_Center_Default_Width = 95; + double Popup_Center_Default_Height = 95; + double Popup_Follow_Default_Width = 40; + double Popup_Follow_Default_Height = 10; +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupPane.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupPane.java new file mode 100644 index 000000000..f4389d953 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupPane.java @@ -0,0 +1,81 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.design.beans.FurtherBasicBeanPane; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.i18n.Toolkit; +import com.fr.js.MobilePopupHyperlink; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class MobilePopupPane extends FurtherBasicBeanPane { + private ContentSettingPane contentSettingPane; + private StyleSettingPane styleSettingPane; + + public MobilePopupPane() { + this.initComponents(); + this.setDefaultBean(); + } + + protected void initComponents() { + this.setLayout(new BorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + + JPanel scrollContent = new JPanel(); + scrollContent.setLayout(new BorderLayout(10, 10)); + contentSettingPane = new ContentSettingPane(); + scrollContent.add(contentSettingPane, BorderLayout.NORTH); + styleSettingPane = new StyleSettingPane(); + scrollContent.add(styleSettingPane, BorderLayout.CENTER); + + contentSettingPane.addTargetRadioActionListener(radioActionListener); + + UIScrollPane scrollPane= new UIScrollPane(scrollContent); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + + JComponent scrollComponent = new JLayer(scrollPane, new WheelScrollLayerUI()); + + this.add(scrollComponent, BorderLayout.CENTER); + } + + private void setDefaultBean() { + this.populateBean(new MobilePopupHyperlink()); + } + private ActionListener radioActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + styleSettingPane.resetPane(contentSettingPane.getTargetType()); + } + }; + + @Override + public void populateBean(MobilePopupHyperlink mobilePopupHyperlink) { + contentSettingPane.populateBean(mobilePopupHyperlink); + styleSettingPane.populateBean(mobilePopupHyperlink); + } + + @Override + public MobilePopupHyperlink updateBean() { + MobilePopupHyperlink mobilePopupHyperlink = new MobilePopupHyperlink(); + contentSettingPane.updateBean(mobilePopupHyperlink); + styleSettingPane.updateBean(mobilePopupHyperlink); + return mobilePopupHyperlink; + } + + @Override + public boolean accept(Object ob) { + return ob instanceof MobilePopupHyperlink; + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup"); + } + + @Override + public void reset() { + this.setDefaultBean(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupRegularPane.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupRegularPane.java new file mode 100644 index 000000000..65e5085d1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupRegularPane.java @@ -0,0 +1,157 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.VerticalFlowLayout; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class MobilePopupRegularPane extends BasicPane { + private String label; + + private JPanel radiosPane; + private UIRadioButton customRadio; + private UIRadioButton autoRadio; + private ButtonGroup radioButtons; + + private JPanel spinnerGroupPane; + private UISpinner widthSpinner; + private JPanel widthSpinnerPane; + private UISpinner heightSpinner; + private JPanel heightSpinnerPane; + + + public MobilePopupRegularPane(String label) { + this.label = label; + this.initComponent(); + } + + private void initComponent() { + this.setLayout(new BorderLayout()); + this.add(this.createRadioButtonGroupPane(), BorderLayout.NORTH); + spinnerGroupPane = this.createSpinnerPane(); + this.add(spinnerGroupPane, BorderLayout.CENTER); + } + + private JPanel createRadioButtonGroupPane() { + radiosPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5)); + + customRadio = new UIRadioButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Custom")); + customRadio.addActionListener(radioActionListener); + autoRadio = new UIRadioButton(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Height_Adaptive")); + autoRadio.addActionListener(radioActionListener); + + radioButtons = new ButtonGroup(); + radioButtons.add(customRadio); + radioButtons.add(autoRadio); + + radiosPane.add(customRadio); + radiosPane.add(autoRadio); + + return MobilePopupUIUtils.createLeftTileRightContentPanel(this.label, radiosPane); + } + + private ActionListener radioActionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + resetSpinnerGroupPane(customRadio.isSelected()); + } + }; + + private JPanel createSpinnerPane() { + JPanel spinnerPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 15, 5)); + spinnerPane.setBorder(BorderFactory.createEmptyBorder(0, MobilePopupUIUtils.Left_Title_width, 0, 0)); + widthSpinner = new UISpinner(0, 100, 1, 95); + widthSpinnerPane = this.createSpinnerLabelPane(widthSpinner, Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Width")); + heightSpinner = new UISpinner(0, 100, 1, 95); + heightSpinnerPane = this.createSpinnerLabelPane(heightSpinner, Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Height")); + + spinnerPane.add(widthSpinnerPane); + spinnerPane.add(heightSpinnerPane); + + return spinnerPane; + } + + private JPanel createSpinnerLabelPane(UISpinner spinner, String labelText) { + JPanel spinnerLabelPane = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 5)); + + JPanel spinnerPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 2,0)); + Dimension dimension = new Dimension(60, 20); + spinner.setPreferredSize(dimension); + UILabel percent = new UILabel("%"); + spinnerPane.add(spinner); + spinnerPane.add(percent); + + UILabel label = new UILabel(labelText); + label.setPreferredSize(dimension); + label.setHorizontalAlignment(SwingConstants.CENTER); + + spinnerLabelPane.add(spinnerPane); + spinnerLabelPane.add(label); + + return spinnerLabelPane; + } + + private void resetSpinnerGroupPane(boolean showHeightSpinnerPane) { + spinnerGroupPane.removeAll(); + spinnerGroupPane.add(widthSpinnerPane); + if(showHeightSpinnerPane) { + spinnerGroupPane.add(heightSpinnerPane); + } + spinnerGroupPane.revalidate(); + spinnerGroupPane.repaint(); + } + + @Override + protected String title4PopupWindow() { + return StringUtils.EMPTY; + } + + public void setRegularType(String regularType) { + if (StringUtils.equals(regularType, MobilePopupConstants.Regular_Auto_Height)) { + radioButtons.setSelected(autoRadio.getModel(), true); + } else { + radioButtons.setSelected(customRadio.getModel(), true); + } + resetSpinnerGroupPane(customRadio.isSelected()); + } + + public String getRegularType() { + if (autoRadio.isSelected()) { + return MobilePopupConstants.Regular_Auto_Height; + } else { + return MobilePopupConstants.Regular_Custom; + } + } + + public void setWidthSpinnerValue(double width) { + widthSpinner.setValue(width); + } + + public double getWidthSpinnerValue() { + return widthSpinner.getValue(); + } + + public void setHeightSpinnerValue(double height) { + heightSpinner.setValue(height); + } + + public double getHeightSpinnerValue() { + return heightSpinner.getValue(); + } + + public void resetPane(String regularType, double width, double height) { + this.setRegularType(regularType); + this.setWidthSpinnerValue(width); + this.setHeightSpinnerValue(height); + resetSpinnerGroupPane(StringUtils.equals(regularType, MobilePopupConstants.Regular_Custom)); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupUIUtils.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupUIUtils.java new file mode 100644 index 000000000..cb3fbad58 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/MobilePopupUIUtils.java @@ -0,0 +1,36 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.widget.UITitleSplitLine; + +import javax.swing.*; +import java.awt.*; + +public class MobilePopupUIUtils { + static public int Line_Height = 20; + static public int SplitLineWidth = 520; + static public int Left_Title_width = 80; + + static public JPanel createLeftTileRightContentPanel(String title, JComponent contentPanel) { + JPanel jp = new JPanel(); + jp.setBorder(BorderFactory.createEmptyBorder(0,0,0, 30)); + jp.setLayout(new BorderLayout(10,0)); + UILabel titleLabel = new UILabel(title + ":"); + titleLabel.setPreferredSize(new Dimension(MobilePopupUIUtils.Left_Title_width, Line_Height)); + titleLabel.setHorizontalAlignment(SwingConstants.RIGHT); + jp.add(titleLabel, BorderLayout.WEST); + jp.add(contentPanel, BorderLayout.CENTER); + return jp; + } + + static public JPanel createTitleSplitLineContentPane(String title, JComponent contentPanel) { + JPanel jp = new JPanel(); + jp.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + jp.setLayout(new BorderLayout(0, 10)); + UITitleSplitLine titleLine = new UITitleSplitLine(title, SplitLineWidth); + titleLine.setPreferredSize(new Dimension(SplitLineWidth, Line_Height)); + jp.add(titleLine, BorderLayout.NORTH); + jp.add(contentPanel, BorderLayout.CENTER); + return jp; + } +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/StyleSettingPane.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/StyleSettingPane.java new file mode 100644 index 000000000..1bebe3dfc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/StyleSettingPane.java @@ -0,0 +1,205 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.frpane.UINumberDragPane; +import com.fr.design.gui.icombobox.LineComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.VerticalFlowLayout; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.js.MobilePopupHyperlink; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; + +public class StyleSettingPane extends BasicBeanPane { + private double maxNumber = 100; + private double maxBorderRadius = 24; + + JPanel typePane; + UILabel popupTypeLabel; + + JPanel stylePane; + LineComboBox borderType; + NewColorSelectBox borderColor; + UISpinner borderRadiusSpinner; + + NewColorSelectBox bgColor; + //透明度 + UINumberDragPane numberDragPane; + + MobilePopupRegularPane mobileRegularPane; + MobilePopupRegularPane padRegularPane; + + public StyleSettingPane() { + this.initComponent(); + } + + private void initComponent() { + this.setLayout(new BorderLayout(0, 10)); + this.setBorder(GUICoreUtils.createTitledBorder(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Style"))); + + typePane = this.createTypePane(); + this.add(typePane, BorderLayout.NORTH); + stylePane = this.createStylePane(); + this.add(stylePane, BorderLayout.CENTER); + } + + private JPanel createTypePane() { + JPanel typePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + popupTypeLabel = new UILabel(""); + typePane.add(popupTypeLabel, BorderLayout.CENTER); + return MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Type"), typePane); + } + + private JPanel createStylePane() { + JPanel stylePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + stylePane.add(this.createBorderSettingPane(), BorderLayout.NORTH); + stylePane.add(this.createBackgroundSettingPane(), BorderLayout.CENTER); + stylePane.add(this.createPopupSizePane(), BorderLayout.SOUTH); + return stylePane; + } + + private JPanel createBorderSettingPane() { + JPanel borderPane = new JPanel(); + VerticalFlowLayout layout = new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 10); + layout.setAlignLeft(true); + borderPane.setLayout(layout); + + borderType = new LineComboBox(MobilePopupConstants.BORDER_LINE_STYLE_ARRAY); + borderType.setPreferredSize(new Dimension(115, 20)); + borderPane.add(MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Line"), borderType)); + borderColor = new NewColorSelectBox(100); + borderPane.add(MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Colors"), borderColor)); + borderRadiusSpinner = new UISpinner(0, maxBorderRadius, 1, 20); + borderRadiusSpinner.setPreferredSize(new Dimension(120, 20)); + borderPane.add(MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Radius"), borderRadiusSpinner)); + return MobilePopupUIUtils.createTitleSplitLineContentPane(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Border"), borderPane); + } + + private JPanel createBackgroundSettingPane() { + JPanel bgPane = new JPanel(); + VerticalFlowLayout layout = new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 10); + layout.setAlignLeft(true); + bgPane.setLayout(layout); + + JPanel colorPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0,0)); + bgColor = new NewColorSelectBox(100); + colorPane.add(MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Colors"), bgColor)); + bgPane.add(colorPane); + + JPanel transparencyPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.numberDragPane = new UINumberDragPane(0,100); + this.numberDragPane.setPreferredSize(new Dimension(140, 20)); + transparencyPane.add(numberDragPane, BorderLayout.CENTER); + transparencyPane.add(new UILabel(" %"), BorderLayout.EAST); + bgPane.add(MobilePopupUIUtils.createLeftTileRightContentPanel(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Opacity"), transparencyPane)); + return MobilePopupUIUtils.createTitleSplitLineContentPane(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Background"), bgPane); + } + + private JPanel createPopupSizePane() { + JPanel sizePane = new JPanel(new BorderLayout()); + + mobileRegularPane = new MobilePopupRegularPane(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Mobile_Rules")); + padRegularPane = new MobilePopupRegularPane(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Pad_Rules")); + + sizePane.add(mobileRegularPane, BorderLayout.NORTH); + sizePane.add(padRegularPane, BorderLayout.CENTER); + + return MobilePopupUIUtils.createTitleSplitLineContentPane(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Size"), sizePane); + } + + @Override + protected String title4PopupWindow() { + return StringUtils.EMPTY; + } + + public void resetPane(String popupTargetType) { + if (StringUtils.equals(popupTargetType, MobilePopupConstants.Target_Template)) { + popupTypeLabel.setText(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Center")); + mobileRegularPane.resetPane(MobilePopupConstants.Regular_Custom, MobilePopupConstants.Popup_Center_Default_Width, MobilePopupConstants.Popup_Center_Default_Height); + padRegularPane.resetPane(MobilePopupConstants.Regular_Custom, MobilePopupConstants.Popup_Center_Default_Width, MobilePopupConstants.Popup_Center_Default_Height); + } else { + popupTypeLabel.setText(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Follow")); + mobileRegularPane.resetPane(MobilePopupConstants.Regular_Custom, MobilePopupConstants.Popup_Follow_Default_Width, MobilePopupConstants.Popup_Follow_Default_Height); + padRegularPane.resetPane(MobilePopupConstants.Regular_Custom, MobilePopupConstants.Popup_Follow_Default_Width, MobilePopupConstants.Popup_Follow_Default_Height); + } + + } + + @Override + public void populateBean(MobilePopupHyperlink link) { + this.populateTypeBean(link); + this.populateBorderSettingBean(link); + this.populateBackgroundSettingBean(link); + this.populatePopupSizeBean(link); + } + + @Override + public MobilePopupHyperlink updateBean() { + return null; + } + + @Override + public void updateBean(MobilePopupHyperlink link) { + this.updateBorderSettingBean(link); + this.updateBackgroundSettingBean(link); + this.updatePopupSizeBean(link); + + } + + private void populateTypeBean(MobilePopupHyperlink link) { + if (StringUtils.equals(link.getPopupTarget(), MobilePopupConstants.Target_Text)) { + popupTypeLabel.setText(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Follow")); + } else { + popupTypeLabel.setText(Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup_Center")); + } + } + + private void populateBorderSettingBean(MobilePopupHyperlink link) { + borderType.setSelectedLineStyle(link.getBorderType()); + borderColor.setSelectObject(link.getBorderColor()); + borderRadiusSpinner.setValue(link.getBorderRadius()); + + } + + private void updateBorderSettingBean(MobilePopupHyperlink link) { + link.setBorderType(borderType.getSelectedLineStyle()); + link.setBorderColor(borderColor.getSelectObject()); + link.setBorderRadius(borderRadiusSpinner.getValue()); + + } + + private void populateBackgroundSettingBean(MobilePopupHyperlink link) { + bgColor.setSelectObject(link.getBgColor()); + numberDragPane.populateBean(link.getBgOpacity() * maxNumber); + } + + private void updateBackgroundSettingBean(MobilePopupHyperlink link) { + link.setBgColor(bgColor.getSelectObject()); + link.setBgOpacity((float)(numberDragPane.updateBean() / maxNumber)); + } + + private void populatePopupSizeBean(MobilePopupHyperlink link) { + mobileRegularPane.setRegularType(link.getMobileRegularType()); + mobileRegularPane.setWidthSpinnerValue(link.getMobileWidth()); + mobileRegularPane.setHeightSpinnerValue(link.getMobileHeight()); + padRegularPane.setRegularType(link.getPadRegularType()); + padRegularPane.setWidthSpinnerValue(link.getPadWidth()); + padRegularPane.setHeightSpinnerValue(link.getPadHeight()); + + } + + private void updatePopupSizeBean(MobilePopupHyperlink link) { + link.setMobileRegularType(mobileRegularPane.getRegularType()); + link.setMobileWidth(mobileRegularPane.getWidthSpinnerValue()); + link.setMobileHeight(mobileRegularPane.getHeightSpinnerValue()); + link.setPadRegularType(padRegularPane.getRegularType()); + link.setPadWidth(padRegularPane.getWidthSpinnerValue()); + link.setPadHeight(padRegularPane.getHeightSpinnerValue()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/hyperlink/popup/WheelScrollLayerUI.java b/designer-base/src/main/java/com/fr/design/hyperlink/popup/WheelScrollLayerUI.java new file mode 100644 index 000000000..8ab06766d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/hyperlink/popup/WheelScrollLayerUI.java @@ -0,0 +1,42 @@ +package com.fr.design.hyperlink.popup; + +import com.fr.design.gui.icontainer.UIScrollPane; + +import javax.swing.*; +import javax.swing.plaf.LayerUI; +import java.awt.*; +import java.awt.event.MouseWheelEvent; + +class WheelScrollLayerUI extends LayerUI { + @Override + public void installUI(JComponent c) { + super.installUI(c); + if (c instanceof JLayer) { + ((JLayer) c).setLayerEventMask(AWTEvent.MOUSE_WHEEL_EVENT_MASK); + } + } + @Override + public void uninstallUI(JComponent c) { + if (c instanceof JLayer) { + ((JLayer) c).setLayerEventMask(0); + } + super.uninstallUI(c); + } + @Override + protected void processMouseWheelEvent(MouseWheelEvent e, JLayer l) { + Component c = e.getComponent(); + int dir = e.getWheelRotation(); + JScrollPane main = l.getView(); + if (c instanceof JScrollPane && !c.equals(main)) { + JScrollPane child = (JScrollPane) c; + BoundedRangeModel m = child.getVerticalScrollBar().getModel(); + int extent = m.getExtent(); + int minimum = m.getMinimum(); + int maximum = m.getMaximum(); + int value = m.getValue(); + if (value + extent >= maximum && dir > 0 || value <= minimum && dir < 0) { + main.dispatchEvent(SwingUtilities.convertMouseEvent(c, e, main)); + } + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/javascript/JavaScriptActionPane.java b/designer-base/src/main/java/com/fr/design/javascript/JavaScriptActionPane.java index 89c9741eb..999a1a029 100644 --- a/designer-base/src/main/java/com/fr/design/javascript/JavaScriptActionPane.java +++ b/designer-base/src/main/java/com/fr/design/javascript/JavaScriptActionPane.java @@ -7,6 +7,7 @@ import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.fun.JavaScriptActionProvider; import com.fr.design.gui.frpane.UIComboBoxPane; import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.hyperlink.popup.MobilePopupPane; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; import com.fr.design.write.submit.DBManipulationPane; @@ -51,6 +52,7 @@ public abstract class JavaScriptActionPane extends UIComboBoxPane { if (workbook) { paneList.add(new ExportJavaScriptPane()); } + paneList.add(new MobilePopupPane()); Set javaScriptActionProviders = ExtraDesignClassManager.getInstance().getArray(JavaScriptActionProvider.XML_TAG); if (javaScriptActionProviders != null) { for (JavaScriptActionProvider jsp : javaScriptActionProviders) { diff --git a/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java b/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java index da0a2131c..0077f9b87 100644 --- a/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java +++ b/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java @@ -2,8 +2,8 @@ package com.fr.design.layout; import com.fr.design.border.UITitledBorder; import com.fr.design.gui.ilable.UILabel; - import com.fr.stable.AssistUtils; + import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.Icon; @@ -46,6 +46,16 @@ public class FRGUIPaneFactory { return new FlowLayout(FlowLayout.LEFT, 0, 0); } + /** + * 创建一个靠左的布局,上下间隔为0,左右间隔为常量,首间隔为0 + * + * @return FlowLayout对象 + */ + public static LayoutManager createLeftZeroVgapNormalHgapLayout() { + return new FRLeftFlowLayout(0, 5, 0); + } + + /** * 创建一个靠右的布局 * @@ -581,6 +591,15 @@ public class FRGUIPaneFactory { return jp; } + public static JPanel createBorderLayout_NO_Opaque_Pane() { + JPanel jp = new JPanel(); + jp.setOpaque(false); + jp.setBackground(null); + jp.setLayout(FRGUIPaneFactory.createBorderLayout()); + return jp; + } + + /** * 创建卡片式布局 * diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/DoubleSplashMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/DoubleSplashMark.java new file mode 100644 index 000000000..78ee72b50 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/locale/impl/DoubleSplashMark.java @@ -0,0 +1,33 @@ +package com.fr.design.locale.impl; + +import com.fr.design.DesignerEnvManager; +import com.fr.general.locale.LocaleMark; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2021/9/2 + */ +public class DoubleSplashMark implements LocaleMark { + + private final Map map = new HashMap(); + private static final String SPLASH_PATH_X2 = "/com/fr/design/images/splash@2x.png"; + private static final String SPLASH_PATH_EN_X2 = "/com/fr/design/images/splash_en@2x.png"; + + public DoubleSplashMark() { + map.put(Locale.CHINA, SPLASH_PATH_X2); + map.put(Locale.KOREA, SPLASH_PATH_EN_X2); + map.put(Locale.JAPAN, SPLASH_PATH_EN_X2); + map.put(Locale.US, SPLASH_PATH_EN_X2); + map.put(Locale.TAIWAN, SPLASH_PATH_EN_X2); + } + + @Override + public String getValue() { + String result = map.get(DesignerEnvManager.getEnvManager().getLanguage()); + return result == null ? SPLASH_PATH_EN_X2 : result; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/SplashMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/SplashMark.java index 8cf75c058..93995eedd 100644 --- a/designer-base/src/main/java/com/fr/design/locale/impl/SplashMark.java +++ b/designer-base/src/main/java/com/fr/design/locale/impl/SplashMark.java @@ -15,8 +15,8 @@ import java.util.Map; public class SplashMark implements LocaleMark { private Map map = new HashMap(); - private static final String SPLASH_PATH = "/com/fr/design/images/splash_10.png"; - private static final String SPLASH_EN_PATH = "/com/fr/design/images/splash_10_en.png"; + private static final String SPLASH_PATH = "/com/fr/design/images/splash.png"; + private static final String SPLASH_EN_PATH = "/com/fr/design/images/splash_en.png"; public SplashMark() { map.put(Locale.CHINA, SPLASH_PATH); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java index 36507cf37..d31b5ede0 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java @@ -19,10 +19,14 @@ import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.border.MatteBorder; import java.awt.BorderLayout; +import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Insets; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + /** * @author shine @@ -96,7 +100,7 @@ public class CenterRegionContainerPane extends JPanel { } - private ToolBarMenuDock getToolBarMenuDock() { + public ToolBarMenuDock getToolBarMenuDock() { return DesignerContext.getDesignerFrame().getToolBarMenuDock(); } @@ -267,12 +271,13 @@ public class CenterRegionContainerPane extends JPanel { return centerTemplateCardPane; } - protected void refreshUIToolBar() { + public Map getToolbarComponentState() { + Map toolbarComponentState = new HashMap<>(); if (toolbarComponent instanceof UIToolbar) { - ((UIToolbar ) toolbarComponent).refreshUIToolBar(); + toolbarComponentState.putAll(((UIToolbar) toolbarComponent).getComponentState()); } - combineUp.refreshUIToolBar(); - getToolBarMenuDock().updateEnable(); + toolbarComponentState.putAll(combineUp.getComponentState()); + return toolbarComponentState; } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java index 798441c53..6270413f5 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java @@ -136,6 +136,8 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta //用于判断设计器是否打开了 private boolean designerOpened = false; + private boolean serverConfig = false; + private int contentWidth = (int) (java.awt.Toolkit.getDefaultToolkit().getScreenSize().getWidth()); private int contentHeight = (int) (java.awt.Toolkit.getDefaultToolkit().getScreenSize().getHeight()); @@ -365,14 +367,9 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta } public DesktopCardPane getCenterTemplateCardPane() { - return CenterRegionContainerPane.getInstance().getCenterTemplateCardPane(); } - public void refreshUIToolBar() { - CenterRegionContainerPane.getInstance().refreshUIToolBar(); - } - /** * 初始menuPane的方法 方便OEM时修改该组件 */ @@ -1182,4 +1179,19 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta return designerOpened; } + /** + * 判断是否正在进行服务器配置 + * @return boolean + */ + public boolean isServerConfig() { + return serverConfig; + } + + /** + * 设置是否正在进行服务器配置 + * @param serverConfig + */ + public void setServerConfig(boolean serverConfig) { + this.serverConfig = serverConfig; + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java b/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java index 0e26ff3de..0c10ac2e1 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java @@ -10,11 +10,14 @@ import com.fr.design.data.BasicTableDataTreePane; import com.fr.design.dialog.BasicPane; import com.fr.design.event.TargetModifiedEvent; import com.fr.design.event.TargetModifiedListener; +import com.fr.design.gui.itoolbar.UIToolbar; import javax.swing.JComponent; import javax.swing.JLayeredPane; import java.awt.BorderLayout; import java.awt.Component; +import java.util.HashMap; +import java.util.Map; /** @@ -33,6 +36,9 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener private TransparentPane transparentPane = new TransparentPane(); private OpenLoadingPane loadingPane = new OpenLoadingPane(); private OpenFailedPane failedPane = new OpenFailedPane(); + + Map backUpToolbarComponentState = new HashMap<>(); + private JLayeredPane layeredPane = new JLayeredPane() { @Override public void doLayout() { @@ -103,7 +109,7 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener } private void showOpenStatus() { - DesignerContext.getDesignerFrame().refreshUIToolBar(); + forbidToolBar(); DesignerFrameFileDealerPane.getInstance().stateChange(); EastRegionContainerPane.getInstance().updateAllPropertyPane(); JComponent downPane = WestRegionContainerPane.getInstance().getDownPane(); @@ -120,9 +126,9 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener } public void showCover() { + forbidToolBar(); transparentPane.start(); layeredPane.moveToFront(transparentPane); - DesignerContext.getDesignerFrame().refreshUIToolBar(); EastRegionContainerPane.getInstance().updateAllPropertyPane(); JComponent downPane = WestRegionContainerPane.getInstance().getDownPane(); if (downPane instanceof BasicTableDataTreePane) { @@ -132,6 +138,7 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener } public void hideCover() { + recoverToolBar(); transparentPane.stop(); layeredPane.moveToFront(component); EastRegionContainerPane.getInstance().updateAllPropertyPane(); @@ -142,6 +149,22 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener } } + private void forbidToolBar() { + CenterRegionContainerPane centerRegionContainerPane = CenterRegionContainerPane.getInstance(); + backUpToolbarComponentState = centerRegionContainerPane.getToolbarComponentState(); + for (Component component : backUpToolbarComponentState.keySet()) { + component.setEnabled(false); + } + centerRegionContainerPane.getToolBarMenuDock().updateEnable(); + } + + private void recoverToolBar() { + UIToolbar.resetComponentState(backUpToolbarComponentState); + backUpToolbarComponentState.clear(); + CenterRegionContainerPane centerRegionContainerPane = CenterRegionContainerPane.getInstance(); + centerRegionContainerPane.getToolBarMenuDock().updateEnable(); + } + protected JTemplate getSelectedJTemplate() { return component; } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/EastRegionContainerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/EastRegionContainerPane.java index 84993411e..588b4e256 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/EastRegionContainerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/EastRegionContainerPane.java @@ -458,6 +458,7 @@ public class EastRegionContainerPane extends UIEastResizableContainer { for (PropertyItem item : propertyItemMap.values()) { item.onResize(); } + super.onResize(); } public EastRegionContainerPane(JPanel leftPane, JPanel rightPane) { @@ -1006,7 +1007,7 @@ public class EastRegionContainerPane extends UIEastResizableContainer { button.setToolTipText(title); } - public void processSnapChat(){ + public void processSnapChat() { if (snapChat != null && !snapChat.hasRead()) { snapChat.markRead(); if (promptWindow != null) { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java index d4931763c..89bb1b798 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java @@ -2,10 +2,16 @@ package com.fr.design.mainframe; import com.fr.base.BaseUtils; import com.fr.base.Parameter; +import com.fr.base.extension.FileExtension; import com.fr.base.io.BaseBook; import com.fr.base.iofile.attr.DesignBanCopyAttrMark; import com.fr.base.iofile.attr.TemplateIdAttrMark; +import com.fr.base.iofile.attr.TemplateThemeAttrMark; +import com.fr.base.theme.TemplateThemeCompatible; +import com.fr.base.theme.ThemedTemplate; import com.fr.base.vcs.DesignerMode; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; import com.fr.design.DesignModelAdapter; import com.fr.design.DesignState; import com.fr.design.DesignerEnvManager; @@ -13,6 +19,7 @@ import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.TableDataSourceAction; import com.fr.design.actions.edit.RedoAction; import com.fr.design.actions.edit.UndoAction; +import com.fr.design.actions.file.BatchCompileAction; import com.fr.design.actions.file.SaveAsTemplateAction; import com.fr.design.actions.file.SaveTemplateAction; import com.fr.design.actions.file.WebPreviewUtils; @@ -36,6 +43,7 @@ import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.authority.JTemplateAuthorityChecker; import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.design.mainframe.check.CheckButton; import com.fr.design.mainframe.template.info.TemplateProcessInfo; @@ -59,9 +67,12 @@ import com.fr.file.MemFILE; import com.fr.form.ui.NoneWidget; import com.fr.form.ui.Widget; import com.fr.general.ComparatorUtils; +import com.fr.general.IOUtils; import com.fr.log.FineLoggerFactory; import com.fr.plugin.context.PluginContext; import com.fr.plugin.context.PluginRuntime; +import com.fr.nx.app.designer.toolbar.CompileAction; +import com.fr.nx.app.designer.toolbar.TemplateTransformer; import com.fr.plugin.injectable.PluginModule; import com.fr.plugin.manage.PluginFilter; import com.fr.plugin.observer.PluginEvent; @@ -82,22 +93,27 @@ import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JOptionPane; +import javax.swing.SwingConstants; import javax.swing.undo.UndoManager; import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FontMetrics; import java.util.Set; import java.util.concurrent.Callable; /** * 报表设计和表单设计的编辑区域(设计器编辑的IO文件) */ -public abstract class JTemplate> extends TargetComponent implements ToolBarMenuDockPlus, DesignerProxy, JTemplateSave, TabChangeListener { +public abstract class JTemplate> extends TargetComponent implements ToolBarMenuDockPlus, DesignerProxy, JTemplateSave, TabChangeListener, ThemedTemplate { // TODO ALEX_SEP editingFILE这个属性一定要吗?如果非要不可,有没有可能保证不为null + private static final int PREDEFINED_ICON_WIDTH = 27; private static final int PREFIX_NUM = 3000; protected FILE editingFILE = null; // alex:初始状态为saved,这样不管是新建模板,还是打开模板,如果未做任何操作直接关闭,不提示保存 private boolean saved = true; private boolean authoritySaved = true; + private UIButton templateThemeButton; private UndoManager undoMananger; private UndoManager authorityUndoManager; protected U undoState; @@ -131,9 +147,12 @@ public abstract class JTemplate> private final String runtimeId = UUID.randomUUID().toString(); private PluginEventListener pluginListener; + // 监听全局主题数据更新 + private TemplateThemeConfig.ThemeConfigChangeListener themeConfigChangeListener; public JTemplate() { initAndStartPlugin(); + startListenThemeConfig(); } public JTemplate(T t, String defaultFileName) { @@ -172,9 +191,14 @@ public abstract class JTemplate> designModel = createDesignModel(parameters); } addCenterPane(); + if (isNewFile) { + // REPORT-58486: 必须在初始的UndoState创建前设置主题,使得初始的UndoState就包含了主题效果 + setUpTheme4NewTemplate(); + } this.undoState = createUndoState(); initAndStartPlugin(); + startListenThemeConfig(); } private void initAndStartPlugin() { @@ -204,6 +228,36 @@ public abstract class JTemplate> PluginListenerRegistration.getInstance().listen(PluginEventType.AfterRun, this.pluginListener, filter); } + private void startListenThemeConfig() { + if (themeConfigChangeListener == null) { + themeConfigChangeListener = new TemplateThemeConfig.ThemeConfigChangeListener() { + @Override + public void onThemeConfigChanged(TemplateThemeConfig.ThemeConfigEvent event) { + TemplateTheme usingTheme = getTemplateTheme(); + boolean isUsingThemeChanged = StringUtils.equals(event.themName, usingTheme.getName()); + + if (isUsingThemeChanged && (event.action == TemplateThemeConfig.ThemeConfigAction.REMOVE || + event.action == TemplateThemeConfig.ThemeConfigAction.UPDATE)) { + checkAndResetTheme(); + } + } + }; + TemplateThemeConfig config = getUsingTemplateThemeConfig(); + if (config != null) { + config.addThemeConfigChangeListener(themeConfigChangeListener); + } + } + } + + private void stopListenThemeConfig() { + if (themeConfigChangeListener != null) { + TemplateThemeConfig config = getUsingTemplateThemeConfig(); + if (config != null) { + config.removeThemeConfigChangeListener(themeConfigChangeListener); + } + } + } + private void initPluginPane() { ExtraDesignClassManager classManager = PluginModule.getAgent(PluginModule.ExtraDesign); @@ -217,7 +271,7 @@ public abstract class JTemplate> public void fireTabChange() { // do nothing } - + protected void addPane(PropertyItemPaneProvider provider) { // do nothing } @@ -367,6 +421,7 @@ public abstract class JTemplate> public void whenClose() { // stop的时候 pluginListener 和 PluginFilter 都会移除 PluginListenerRegistration.getInstance().stopListen(this.pluginListener); + stopListenThemeConfig(); } @@ -562,6 +617,8 @@ public abstract class JTemplate> */ public void undo() { this.getUndoManager().undo(); + // 撤销前模版使用主题可能已经被删除或修改,需要重置模版样式 + checkAndResetTheme(); fireSuperTargetModified(); } @@ -570,7 +627,6 @@ public abstract class JTemplate> */ public void redo() { this.getUndoManager().redo(); - fireSuperTargetModified(); } @@ -622,6 +678,14 @@ public abstract class JTemplate> super.fireTargetModified(); } + public void fireTargetModified(boolean shouldCreateNewUndoState) { + if (shouldCreateNewUndoState) { + fireTargetModified(); + } else { + super.fireTargetModified(); + } + } + protected abstract U createUndoState(); protected abstract void applyUndoState(U u); @@ -817,10 +881,12 @@ public abstract class JTemplate> protected boolean saveToNewFile(String oldName) { boolean result = false; + String path = this.editingFILE.getPath(); Set providers = ExtraDesignClassManager.getInstance().getArray(ReportSupportedFileUIProvider.XML_TAG); for (ReportSupportedFileUIProvider provider : providers) { - result = result || provider.saveToNewFile(this.editingFILE.getPath(), this); + result = result || provider.saveToNewFile(path, this); } + result = result || saveToNewFile4Cptx(path); if (!result) { result = this.saveFile(); //更换最近打开 @@ -830,6 +896,14 @@ public abstract class JTemplate> return result; } + private boolean saveToNewFile4Cptx(String targetPath) { + if (FileExtension.CPTX.matchExtension(targetPath)) { + TemplateTransformer.TO_CPTX.transform(this); + return true; + } + return false; + } + protected void mkNewFile(FILE file) { try { file.mkfile(); @@ -895,7 +969,7 @@ public abstract class JTemplate> } else if (DesignerMode.isAuthorityEditing()) { return new ShortCut[]{new SaveTemplateAction(this), new UndoAction(this), new RedoAction(this)}; } else { - return new ShortCut[]{new SaveTemplateAction(this), new SaveAsTemplateAction(this), new UndoAction(this), new RedoAction(this)}; + return new ShortCut[]{new SaveTemplateAction(this), new SaveAsTemplateAction(this), new BatchCompileAction(), new UndoAction(this), new RedoAction(this)}; } } @@ -1332,11 +1406,15 @@ public abstract class JTemplate> * @return 按钮组 */ public UIButton[] createExtraButtons() { + UIButton[] uiButtons = new UIButton[]{ + (UIButton) new CompileAction().createToolBarComponent() + }; Set providers = ExtraDesignClassManager.getInstance().getArray(DesignerFrameUpButtonProvider.XML_TAG); - UIButton[] uiButtons = new UIButton[0]; for (DesignerFrameUpButtonProvider provider : providers) { uiButtons = ArrayUtils.addAll(uiButtons, provider.getUpButtons(getMenuState())); } + templateThemeButton = createTemplateThemeButton(); + uiButtons = ArrayUtils.addAll(uiButtons, templateThemeButton); return uiButtons; } @@ -1345,6 +1423,23 @@ public abstract class JTemplate> return new UIButton[]{new CheckButton()}; } + protected UIButton createTemplateThemeButton() { + UIButton button = new UIButton(IOUtils.readIcon("/com/fr/design/icon/icon_predefined_style.png")) { + @Override + public Dimension getPreferredSize() { + FontMetrics metrics = getFontMetrics(getFont()); + int width = Math.min(metrics.stringWidth(getText()) + PREDEFINED_ICON_WIDTH, 100); + return new Dimension(width, 20); + } + }; + button.setToolTipText(getTemplateTheme().getName()); + button.setText(getTemplateTheme().getName()); + button.setAlignmentX(SwingConstants.LEFT); + button.set4ToolbarButton(); + button.setEnabled(true); + return button; + } + /** * 由于老版本的模板没有模板ID,当勾选使用参数模板时候,就加一个模板ID attr * @@ -1456,13 +1551,19 @@ public abstract class JTemplate> } private boolean saveRealFile() throws Exception { - FILE editingFILE = this.getEditingFILE(); - if (editingFILE == null || editingFILE instanceof MemFILE) { + JTemplateAuthorityChecker jTemplateAuthorityChecker = new JTemplateAuthorityChecker(this); + if (jTemplateAuthorityChecker.isAuthority()) { + FILE editingFILE = this.getEditingFILE(); + if (editingFILE == null || editingFILE instanceof MemFILE) { + return false; + } + this.getTarget().export(TemplateResourceManager.getResource().saveTemplate(editingFILE)); + this.editingFILE = editingFILE; + return true; + } else { + jTemplateAuthorityChecker.showAuthorityFailPromptDialog(); return false; } - this.getTarget().export(TemplateResourceManager.getResource().saveTemplate(editingFILE)); - this.editingFILE = editingFILE; - return true; } private CallbackSaveWorker saveAs(boolean showLoc) { @@ -1628,4 +1729,23 @@ public abstract class JTemplate> public String getRuntimeId() { return runtimeId; } + + protected void setUpTheme4NewTemplate() { + TemplateTheme theme = getUsingTemplateThemeConfig().cachedFetchTheme4NewTemplate(); + TemplateThemeAttrMark themeAttrMark = template.getAttrMark(TemplateThemeAttrMark.XML_TAG); + if (themeAttrMark == null) { + themeAttrMark = new TemplateThemeAttrMark(); + template.addAttrMark(themeAttrMark); + } + themeAttrMark.setName(theme.getName()); + themeAttrMark.setDark(theme.isDark()); + } + + @Override + public void setTemplateTheme(TemplateTheme newTheme, TemplateThemeCompatible compatible) { + ThemedTemplate.super.setTemplateTheme(newTheme, compatible); + String name = newTheme.getName(); + templateThemeButton.setText(name); + templateThemeButton.setToolTipText(name); + } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/DSColumnAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/DSColumnAuthorityChecker.java new file mode 100644 index 000000000..fdab6ea2a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/DSColumnAuthorityChecker.java @@ -0,0 +1,20 @@ +package com.fr.design.mainframe.authority; + +import com.fr.report.cell.cellattr.core.group.DSColumn; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class DSColumnAuthorityChecker extends ElementAuthorityChecker { + + @Override + @Nullable + Set getNoAuthDatasetNames(DSColumn dsColumn, Set authDatasetNames) { + if (!authDatasetNames.contains(dsColumn.getDSName())) { + return new HashSet<>(Arrays.asList(dsColumn.getDSName())); + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/ElementAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/ElementAuthorityChecker.java new file mode 100644 index 000000000..67d0f1da3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/ElementAuthorityChecker.java @@ -0,0 +1,45 @@ +package com.fr.design.mainframe.authority; + +import org.jetbrains.annotations.Nullable; +import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; + +import java.lang.reflect.Type; +import java.util.Set; + + +public abstract class ElementAuthorityChecker { + + + /** + * @Description 获取越权的数据连接 + * @param: t 待检查的对象 + * @param: authConnectionNames 有权限的数据连接名 + * @return 如果有返回名称,没有返回null + */ + @Nullable + Set getNoAuthConnectionNames(T t, Set authConnectionNames) { + return null; + } + + + /** + * @Description 获取越权的服务器数据集 + * @param: t 待检查的对象 + * @param: authDatasetNames 有权限的服务器数据集名 + * @return 如果有返回名称,没有返回null + */ + @Nullable + Set getNoAuthDatasetNames(T t, Set authDatasetNames) { + return null; + } + + /** + * @Description 要检查对象的className + * @return className + */ + String getCheckClassName() { + ParameterizedTypeImpl parameterizedType = (ParameterizedTypeImpl) this.getClass().getGenericSuperclass(); + Type type = parameterizedType.getActualTypeArguments()[0]; + return type.getTypeName(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java new file mode 100644 index 000000000..d108c18d4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java @@ -0,0 +1,27 @@ +package com.fr.design.mainframe.authority; + +import com.fr.base.Formula; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FormulaAuthorityChecker extends ElementAuthorityChecker { + private static final Pattern FORMULA_PATTERN = Pattern.compile("^=SQL\\(\"(.+?)\","); + + @Override + @Nullable + public Set getNoAuthConnectionNames(Formula formula, Set authConnectionNames) { + String content = formula.getContent(); + Matcher matcher = FORMULA_PATTERN.matcher(content); + if (matcher.find()) { + if (!authConnectionNames.contains(matcher.group(1))) { + return new HashSet<>(Arrays.asList(matcher.group(1))); + } + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java new file mode 100644 index 000000000..f8b2c8ce6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java @@ -0,0 +1,184 @@ +package com.fr.design.mainframe.authority; + + +import com.fr.design.dialog.FineJOptionPane; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mod.ModClassFilter; +import com.fr.invoke.ClassHelper; + +import com.fr.log.FineLoggerFactory; +import com.fr.rpc.ExceptionHandler; +import com.fr.rpc.RPCInvokerExceptionInfo; +import com.fr.stable.Filter; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.authority.user.UserAuthority; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + + +import static javax.swing.JOptionPane.WARNING_MESSAGE; + + +public class JTemplateAuthorityChecker { + JTemplate jTemplate; + Set authConnectionNames; + Set authDatasetNames; + Map checkerMap = new HashMap<>(); + Set authFailConnectionNames = new HashSet<>(); + Set authFailDatasetNames = new HashSet<>(); + + + public JTemplateAuthorityChecker(JTemplate jTemplate) { + long s = System.currentTimeMillis(); + this.jTemplate = jTemplate; + this.initAuthNames(); + this.initChecker(); + FineLoggerFactory.getLogger().info("JTemplateAuthorityChecker init time consume:" + (System.currentTimeMillis() - s)); + } + + private void initAuthNames() { + UserAuthority templateAuthority = WorkContext.getCurrent().get(UserAuthority.class); + Map> authNamesMap = templateAuthority.getAuthServerDataSetAndConnectionNames(); + if (authNamesMap != null) { + //有权限的数据连接名称 + authConnectionNames = authNamesMap.get(UserAuthority.AUTH_CONNECTION_NAMES); + //有权限的数据集名称(模板数据集和服务器数据集) + authDatasetNames = authNamesMap.get(UserAuthority.AUTH_SERVER_DATASET_NAMES); + Iterator iterator = jTemplate.getTarget().getTableDataNameIterator(); + while (iterator.hasNext()) { + String datasetName = iterator.next(); + authDatasetNames.add(datasetName); + } + } + } + + private void initChecker() { + registerChecker(new NameDatabaseConnectionAuthorityChecker()); + registerChecker(new DSColumnAuthorityChecker()); + registerChecker(new FormulaAuthorityChecker()); + registerChecker(new NameTableDataAuthorityChecker()); + } + + private void registerChecker(ElementAuthorityChecker checker) { + checkerMap.put(checker.getCheckClassName(), checker); + } + + + public boolean isAuthority() { + long s = System.currentTimeMillis(); + //遍历模板对象,根据checkerMap.keySet()把感兴趣的对象找出来 + Map> targetObjects = ClassHelper.searchObject(jTemplate.getTarget(), checkerMap.keySet(), ClassFilter.getInstance()); + + //找到对应的checker,对对象进行检查 + for (String name : targetObjects.keySet()) { + ElementAuthorityChecker checker = checkerMap.get(name); + for (Object object : targetObjects.get(name)) { + if (authConnectionNames != null) { + Set noAuthName = checker.getNoAuthConnectionNames(object, authConnectionNames); + if (noAuthName != null) { + authFailConnectionNames.addAll(noAuthName); + } + } + if (authDatasetNames != null) { + Set noAuthName = checker.getNoAuthDatasetNames(object, authDatasetNames); + if (noAuthName != null) { + authFailDatasetNames.addAll(noAuthName); + } + } + } + } + + FineLoggerFactory.getLogger().info("JTemplateAuthorityChecker check time consume:" + (System.currentTimeMillis() - s)); + return authFailConnectionNames.size() == 0 && authFailDatasetNames.size() == 0; + } + + public void showAuthorityFailPromptDialog() { + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(Toolkit.i18nText("Fine-Design-Basic_Save_Failure")); + stringBuffer.append("\n"); + stringBuffer.append(getPromptInfo(authFailDatasetNames, + Toolkit.i18nText("Fine-Design_Template_Authority_Check_Server_Dataset_Authority"))); + stringBuffer.append(getPromptInfo(authFailConnectionNames, + Toolkit.i18nText("Fine-Design_Template_Authority_Check_Data_Connection_Authority"))); + FineJOptionPane.showMessageDialog( + DesignerContext.getDesignerFrame(), + stringBuffer.toString(), + Toolkit.i18nText("Fine-Design_Basic_Alert"), + WARNING_MESSAGE); + } + + private String getPromptInfo(Set authFailNames, String message) { + StringBuffer stringBuffer = new StringBuffer(); + if (authFailNames.size() > 0) { + stringBuffer.append(Toolkit.i18nText("Fine-Design_Template_Authority_Check_Current_Operator_Miss")); + stringBuffer.append(authFailNames.size()); + stringBuffer.append(Toolkit.i18nText("Fine-Design_Report_Ge")); + stringBuffer.append(message); + stringBuffer.append("\n"); + stringBuffer.append(getNoAuthNameSequence(authFailNames)); + } + return stringBuffer.toString(); + } + + private String getNoAuthNameSequence(Set names) { + StringBuffer stringBuffer = new StringBuffer(); + int showMaxCount = 3; + int count = 0; + for (String name : names) { + if (count == showMaxCount) { + stringBuffer.append(Toolkit.i18nText("Fine-Design_Template_Authority_Check_Etc")); + break; + } + stringBuffer.append(name); + if (count != names.size() - 1 && count != showMaxCount - 1) { + stringBuffer.append(";"); + } + count++; + } + stringBuffer.append("\n"); + return stringBuffer.toString(); + } + + static class ClassFilter implements Filter { + + private static final Set FILTER_SET = new HashSet<>(); + private static final Set START_WITH_SET = new HashSet<>(); + private static final Filter INSTANCE = new ModClassFilter(); + + public static Filter getInstance() { + return INSTANCE; + } + + static { + FILTER_SET.add("java.awt.image.BufferedImage"); + FILTER_SET.add("sun.awt.AppContext"); + FILTER_SET.add("com.fr.poly.creator.ECBlockCreator"); + FILTER_SET.add("io.netty.channel.nio.SelectedSelectionKeySet"); + FILTER_SET.add("com.fr.form.ui.ElementCaseImage"); + FILTER_SET.add("this$0"); + START_WITH_SET.add("com.fr.design"); + } + + @Override + public boolean accept(String s) { + if (FILTER_SET.contains(s)) { + return true; + } + for (String start : START_WITH_SET) { + if (s.startsWith(start)) { + return true; + } + } + return false; + } + } +} + diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/NameDatabaseConnectionAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/NameDatabaseConnectionAuthorityChecker.java new file mode 100644 index 000000000..96bc0b8c5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/NameDatabaseConnectionAuthorityChecker.java @@ -0,0 +1,22 @@ +package com.fr.design.mainframe.authority; + +import com.fr.data.impl.NameDatabaseConnection; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +public class NameDatabaseConnectionAuthorityChecker extends ElementAuthorityChecker { + @Override + @Nullable + Set getNoAuthConnectionNames(NameDatabaseConnection nameDatabaseConnection, Set authConnectionNames) { + String name = nameDatabaseConnection.getName(); + if (!authConnectionNames.contains(name)) { + return new HashSet<>(Arrays.asList(name)); + } + return null; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/NameTableDataAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/NameTableDataAuthorityChecker.java new file mode 100644 index 000000000..13e730085 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/NameTableDataAuthorityChecker.java @@ -0,0 +1,19 @@ +package com.fr.design.mainframe.authority; + +import com.fr.data.impl.NameTableData; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class NameTableDataAuthorityChecker extends ElementAuthorityChecker { + @Override + @Nullable + Set getNoAuthDatasetNames(NameTableData nameTableData, Set authDatasetNames) { + if (!authDatasetNames.contains(nameTableData.getName())) { + return new HashSet<>(Arrays.asList(nameTableData.getName())); + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/backgroundpane/ColorBackgroundQuickPane.java b/designer-base/src/main/java/com/fr/design/mainframe/backgroundpane/ColorBackgroundQuickPane.java index f9b4c160e..2fbdb974e 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/backgroundpane/ColorBackgroundQuickPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/backgroundpane/ColorBackgroundQuickPane.java @@ -3,12 +3,8 @@ package com.fr.design.mainframe.backgroundpane; import com.fr.base.background.ColorBackground; import com.fr.design.event.UIObserverListener; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.style.color.NewColorSelectPane; +import com.fr.design.style.color.NewColorSelectBox; import com.fr.general.Background; - - -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import java.awt.BorderLayout; import java.awt.Color; @@ -18,13 +14,13 @@ import java.awt.Color; */ public class ColorBackgroundQuickPane extends BackgroundQuickPane { - private NewColorSelectPane detailColorSelectPane; + private NewColorSelectBox colorSelectBox; + public ColorBackgroundQuickPane() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); - - detailColorSelectPane = new NewColorSelectPane(); - this.add(detailColorSelectPane, BorderLayout.NORTH); + colorSelectBox = new NewColorSelectBox(100); + this.add(colorSelectBox, BorderLayout.NORTH); } public void populateBean(Background background) { @@ -37,12 +33,11 @@ public class ColorBackgroundQuickPane extends BackgroundQuickPane { } public void populateColor(Color color) { - this.detailColorSelectPane.setColor(color); + this.colorSelectBox.setSelectObject(color); } public Color updateColor() { - this.detailColorSelectPane.updateUsedColor(); - return this.detailColorSelectPane.getNotNoneColor(); + return this.colorSelectBox.getSelectObject(); } /** @@ -52,7 +47,7 @@ public class ColorBackgroundQuickPane extends BackgroundQuickPane { */ @Override public void registerChangeListener(final UIObserverListener listener) { - detailColorSelectPane.addChangeListener(new ChangeListenerImpl(listener)); + this.colorSelectBox.addSelectChangeListener(new ChangeListenerImpl(listener)); } @Override @@ -78,6 +73,6 @@ public class ColorBackgroundQuickPane extends BackgroundQuickPane { @Override public void reset() { - this.detailColorSelectPane.setColor(null); + this.colorSelectBox.setSelectObject(null); } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboCheckBoxStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboCheckBoxStyleProvider.java new file mode 100644 index 000000000..027e95df3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboCheckBoxStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.combo; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.combo.SimpleComboPane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.combo.SimpleComboStyle; + +public class SimpleComboCheckBoxStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return SimpleComboStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return SimpleComboPane.class; + } + + @Override + public String xTypeForWidget() { + return "tagcombocheckbox"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-SimpleCombo_SimpleComboStyle"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboStyleProvider.java new file mode 100644 index 000000000..23aa3f946 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/combo/SimpleComboStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.combo; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.combo.SimpleComboPane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.combo.SimpleComboStyle; + +public class SimpleComboStyleProvider extends AbstractMobileWidgetStyleProvider{ + @Override + public Class classForMobileStyle() { + return SimpleComboStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return SimpleComboPane.class; + } + + @Override + public String xTypeForWidget() { + return "combo"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-SimpleCombo_SimpleComboStyle"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/NavigationStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/NavigationStyleProvider.java new file mode 100644 index 000000000..89a64eb6d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/NavigationStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.date; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.date.NavigationCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.NavigationMobileStyle; + +public class NavigationStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return NavigationMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return NavigationCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "datetime"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-Date_Navigation_Calendar"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleDateStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleDateStyleProvider.java new file mode 100644 index 000000000..f9743acbf --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleDateStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.date; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.date.SimpleDateCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.SimpleDateMobileStyle; + +public class SimpleDateStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return SimpleDateMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return SimpleDateCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "datetime"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-SimpleDate_Style"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleStyleProvider.java new file mode 100644 index 000000000..2fa34625e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/date/SimpleStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.date; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.date.SimpleCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.SimpleMobileStyle; + +public class SimpleStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return SimpleMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return SimpleCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "datetime"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-Date_Simple_Calendar"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/CapsuleRadioGroupStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/CapsuleRadioGroupStyleProvider.java new file mode 100644 index 000000000..0f8f005eb --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/CapsuleRadioGroupStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.radiogroup; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.radiogroup.CapsuleCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.CapsuleMobileStyle; + +public class CapsuleRadioGroupStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return CapsuleMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return CapsuleCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "radiogroup"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-RadioGroup_Capsule_Button"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/ImageRadioGroupStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/ImageRadioGroupStyleProvider.java new file mode 100644 index 000000000..1bdcc6a2c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/ImageRadioGroupStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.radiogroup; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.radiogroup.ImageCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.ImageMobileStyle; + +public class ImageRadioGroupStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return ImageMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return ImageCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "radiogroup"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-RadioGroup_Graphic_Button"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/UnitedRadioGroupStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/UnitedRadioGroupStyleProvider.java new file mode 100644 index 000000000..91e1dde04 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/radiogroup/UnitedRadioGroupStyleProvider.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.mobile.provider.radiogroup; + +import com.fr.design.fun.impl.AbstractMobileWidgetStyleProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.ui.radiogroup.UnitedCustomDefinePane; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.UnitedMobileStyle; + +public class UnitedRadioGroupStyleProvider extends AbstractMobileWidgetStyleProvider { + @Override + public Class classForMobileStyle() { + return UnitedMobileStyle.class; + } + + @Override + public Class classForWidgetAppearance() { + return UnitedCustomDefinePane.class; + } + + @Override + public String xTypeForWidget() { + return "radiogroup"; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-RadioGroup_Linkage_Button"); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/topparam/MobileTopParamStyleProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/topparam/MobileTopParamStyleProvider.java new file mode 100644 index 000000000..9e91527a4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/provider/topparam/MobileTopParamStyleProvider.java @@ -0,0 +1,25 @@ +package com.fr.design.mainframe.mobile.provider.topparam; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.fun.impl.AbstractMobileParamUIProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.mobile.ui.topparam.MobileTopParamPane; +import com.fr.form.ui.mobile.MobileParamStyle; +import com.fr.form.ui.mobile.impl.MobileTopParamStyle; + +public class MobileTopParamStyleProvider extends AbstractMobileParamUIProvider { + @Override + public Class classForMobileParamStyle() { + return MobileTopParamStyle.class; + } + + @Override + public Class> classForMobileParamAppearance() { + return MobileTopParamPane.class; + } + + @Override + public String displayName() { + return Toolkit.i18nText("Fine-Plugin-TopParam_Name"); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileParamSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileParamSettingPane.java index 7f1d270af..eb7496607 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileParamSettingPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/MobileParamSettingPane.java @@ -7,7 +7,7 @@ import com.fr.design.fun.MobileParamUIProvider; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.mobile.provider.DefaultMobileParamUIProvider; import com.fr.design.mainframe.mobile.provider.EmptyMobileParamUIProvider; -import com.fr.form.ui.container.WParameterLayout; +import com.fr.design.mainframe.mobile.utils.MobileStyleProviderManager; import com.fr.form.ui.mobile.MobileParamStyle; import com.fr.general.ComparatorUtils; import com.fr.report.ExtraReportClassManager; @@ -101,7 +101,7 @@ public class MobileParamSettingPane extends BasicPane { MobileParamUIProvider[] mobileParamUIProviders = getMobileParamUIProviders(); for (int i = 0; i < mobileParamUIProviders.length; i++) { MobileParamUIProvider provider = mobileParamUIProviders[i]; - if (ComparatorUtils.equals(mobileParamStyle.disPlayName(), provider.displayName())) { + if (ComparatorUtils.equals(mobileParamStyle.displayName(), provider.displayName())) { String displayName = provider.displayName(); paramStyleList.setSelectedIndex(i); // 如果是兼容空类型 无须填充面板 @@ -136,9 +136,11 @@ public class MobileParamSettingPane extends BasicPane { private MobileParamUIProvider[] getMobileParamUIProviders() { Set paramUIProviders = ExtraDesignClassManager.getInstance().getArray(MobileParamUIProvider.XML_TAG); + Set otherParamUIProviders = MobileStyleProviderManager.getArray(MobileParamUIProvider.XML_TAG); List result = new ArrayList<>(); result.add(new DefaultMobileParamUIProvider()); result.addAll(paramUIProviders); + result.addAll(otherParamUIProviders); Set nameSets = paramUIProviders.stream().map(MobileParamUIProvider::displayName).collect(Collectors.toSet()); // 兼容老接口 Set paramStyleProviders = ExtraReportClassManager.getInstance().getArray(MobileParamStyleProvider.MARK_STRING); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/combo/SimpleComboPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/combo/SimpleComboPane.java new file mode 100644 index 000000000..b71588ebf --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/combo/SimpleComboPane.java @@ -0,0 +1,304 @@ +package com.fr.design.mainframe.mobile.ui.combo; + +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icombobox.LineComboBox; +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.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.mainframe.mobile.utils.FontConfigPane; +import com.fr.design.mainframe.mobile.utils.IconConfigPane; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.combo.SimpleComboStyle; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class SimpleComboPane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + private FontConfigPane labelFontPane; + private FontConfigPane valueFontPane; + private IconConfigPane expandIconPane; + private IconConfigPane unexpandIconPane; + private NewColorSelectBox background; + private LineComboBox borderType; + private NewColorSelectBox borderColor; + private UISpinner borderRadius; + private UIRadioButton fillButton; + private UIRadioButton customButton; + private UISpinner widthSpinner; + + private UIRadioButton floatFillButton; + private UIRadioButton floatSameWidthButton; + + public SimpleComboPane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Control_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-SimpleCombo_Style_Default"), Toolkit.i18nText("Fine-Plugin-SimpleCombo_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + JPanel stylePanel = DesignerUtils.createLeftRightComponentsPane(buttonStyleLabel, custom); + panel.add(stylePanel); + scrollPanel.add(panel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + addLabelNamePane(); + addValuePane(); + addIconPane(); + addWidgetSettingPane(); + scrollPanel.add(centerPane, BorderLayout.CENTER); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + private void addLabelNamePane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Label_Name"))); + labelFontPane = new FontConfigPane(); + JPanel fontPanel = createFontPane(labelFontPane); + centerPane.add(fontPanel); + } + + private void addValuePane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Control_Value"))); + valueFontPane = new FontConfigPane(); + JPanel fontPanel = createFontPane(valueFontPane); + valueFontPane.setFontColor(new Color(153, 153, 153)); + centerPane.add(fontPanel); + } + + private JPanel createFontPane(FontConfigPane fontConfigPane) { + UILabel fontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Character")); + JPanel fontPanel = DesignerUtils.createLeftRightComponentsPane(fontLabel, fontConfigPane); + return fontPanel; + } + + private void addIconPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Arrow"))); + UILabel tipLabel = new UILabel(); + tipLabel.setFont(new Font(tipLabel.getName(), Font.PLAIN, 10)); + tipLabel.setSize(470, 40); + tipLabel.setText(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Tips")); + tipLabel.setForeground(Color.decode("#9B9B9B")); + centerPane.add(tipLabel); + + + UILabel expandLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Expand_Icon")); + UILabel unexpandLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Collapse_Icon")); + + expandIconPane = new IconConfigPane(); + unexpandIconPane = new IconConfigPane(); + + JPanel expandPane = DesignerUtils.createLeftRightComponentsPane(expandLabel, expandIconPane); + centerPane.add(expandPane); + + JPanel unexpandPane = DesignerUtils.createLeftRightComponentsPane(unexpandLabel, unexpandIconPane); + centerPane.add(unexpandPane); + } + + private void addWidgetSettingPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Control_Region"))); + background = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + borderType = new LineComboBox(DesignerUtils.BORDER_LINE_STYLE_ARRAY); + borderType.setSelectedLineStyle(Constants.LINE_THIN); + borderType.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + borderColor = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + borderRadius = new UISpinner(0, Integer.MAX_VALUE, 1, 2); + borderRadius.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + + JComponent[] controlComponents = new JComponent[]{background, borderType, borderColor, borderRadius}; + String[] comboBoxNames = new String[]{ + Toolkit.i18nText("Fine-Plugin-SimpleCombo_Control_Background"), + Toolkit.i18nText("Fine-Plugin-SimpleCombo_Control_Border"), + Toolkit.i18nText("Fine-Plugin-SimpleCombo_Border_Color"), + Toolkit.i18nText("Fine-Plugin-SimpleCombo_Radius"), + }; + + Component[][] components = new Component[4][]; + + for (int i = 0; i < 4; i++) { + UILabel label = DesignerUtils.createConfigLabel(comboBoxNames[i]); + components[i] = new Component[]{label, controlComponents[i]}; + } + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p, }; + double[] columnSize = {p, p}; + JPanel controlPanel = TableLayoutHelper.createCommonTableLayoutPane(components, rowSize, columnSize, 10); + centerPane.add(controlPanel); + + fillButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Horizontal_Fill")); + fillButton.setSelected(true); + customButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Custom_Width")); + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + widthSpinner.setVisible(customButton.isSelected()); + } + }; + fillButton.addActionListener(listener); + customButton.addActionListener(listener); + ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(fillButton); + buttonGroup.add(customButton); + widthSpinner = new UISpinner(1, Integer.MAX_VALUE, 1, 200); + widthSpinner.setPreferredSize(new Dimension(78, 20)); + widthSpinner.setVisible(false); + UILabel widthLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Width")); + JPanel buttonsPane = createButtonPane(); + buttonsPane.add(fillButton); + buttonsPane.add(customButton); + JPanel widthSetting = DesignerUtils.createLeftRightComponentsPane(widthLabel, buttonsPane, widthSpinner); + centerPane.add(widthSetting); + + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Floating_Layer"))); + UILabel floatLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Width")); + floatFillButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Horizontal_Fill")); + floatFillButton.setSelected(true); + floatSameWidthButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleCombo_Follow_Control")); + ButtonGroup floatButtonGroup = new ButtonGroup(); + floatButtonGroup.add(floatFillButton); + floatButtonGroup.add(floatSameWidthButton); + JPanel floatButtonPane = createButtonPane(); + floatButtonPane.add(floatFillButton); + floatButtonPane.add(floatSameWidthButton); + JPanel floatSetting = DesignerUtils.createLeftRightComponentsPane(floatLabel, floatFillButton, floatSameWidthButton); + centerPane.add(floatSetting); + } + + private JPanel createButtonPane() { + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new GridLayout(0, 2, 14, 0)); + buttonPane.setPreferredSize(new Dimension(220, 20)); + return buttonPane; + } + + @Override + public void populateBean(MobileStyle ob) { + SimpleComboStyle mobileStyle = (SimpleComboStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + expandIconPane.populate(mobileStyle.getExpandIcon()); + unexpandIconPane.populate(mobileStyle.getUnexpandIcon()); + if (mobileStyle.getLabelFont() != null) { + labelFontPane.populate(mobileStyle.getLabelFont()); + } + if (mobileStyle.getValueFont() != null) { + valueFontPane.populate(mobileStyle.getValueFont()); + } + if (mobileStyle.getBackgroundColor() != null) { + background.setSelectObject(mobileStyle.getBackgroundColor()); + } + if (mobileStyle.getBorderColor() != null) { + borderColor.setSelectObject(mobileStyle.getBorderColor()); + } + borderType.setSelectedLineStyle(mobileStyle.getBorderType()); + borderRadius.setValue(mobileStyle.getBorderRadius()); + if (mobileStyle.isCustomWidth()) { + fillButton.setSelected(false); + customButton.setSelected(true); + widthSpinner.setVisible(true); + widthSpinner.setValue(mobileStyle.getWidth()); + } else { + fillButton.setSelected(true); + customButton.setSelected(false); + widthSpinner.setVisible(false); + } + if (mobileStyle.isFloatWidthFollow()) { + floatFillButton.setSelected(false); + floatSameWidthButton.setSelected(true); + } else { + floatFillButton.setSelected(true); + floatSameWidthButton.setSelected(false); + } + } + + @Override + public MobileStyle updateBean() { + SimpleComboStyle mobileStyle = (SimpleComboStyle) this.widget.getMobileStyle(); + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setExpandIcon(expandIconPane.update()); + mobileStyle.setUnexpandIcon(unexpandIconPane.update()); + mobileStyle.setLabelFont(labelFontPane.update()); + mobileStyle.setValueFont(valueFontPane.update()); + mobileStyle.setBackgroundColor(background.getSelectObject()); + mobileStyle.setBorderColor(borderColor.getSelectObject()); + mobileStyle.setBorderType(borderType.getSelectedLineStyle()); + mobileStyle.setBorderRadius(borderRadius.getValue()); + mobileStyle.setCustomWidth(customButton.isSelected()); + mobileStyle.setWidth(widthSpinner.getValue()); + mobileStyle.setFloatWidthFollow(floatSameWidthButton.isSelected()); + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/NavigationCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/NavigationCustomDefinePane.java new file mode 100644 index 000000000..e64ba926d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/NavigationCustomDefinePane.java @@ -0,0 +1,272 @@ +package com.fr.design.mainframe.mobile.ui.date; + +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.NavigationMobileStyle; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class NavigationCustomDefinePane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + + private UIComboBox expand; + private UIComboBox dateFontSize; + private NewColorSelectBox buttonColorSelectBox; + private NewColorSelectBox titleSplitLineColorSelectBox; + private UICheckBox showTitleEditor; + private NewColorSelectBox arrowColorSelectBox; + private UIColorButton mainFontColor; + private UIColorButton specialFontColor; + + private Color titleSplitLineDisableColor = new Color(234, 234, 234); + private Color titleSplitLineColor; + + public NavigationCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-Date_Style_Default"), Toolkit.i18nText("Fine-Plugin-Date_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + addExpandPane(); + addHeaderLinePane(); + addButtonColorPane(); + addFontColorPane(); + addArrowPane(); + scrollPanel.add(centerPane, BorderLayout.CENTER); + custom.setSelectedIndex(1); + } + + private void addExpandPane() { + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Status")); + expand = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-Date_Status_Collapse"), Toolkit.i18nText("Fine-Plugin-Date_Status_Expand")}); + expand.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(expand); + centerPane.add(panel); + } + + private void addButtonColorPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Button"))); + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Button_Color")); + buttonColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + buttonColorSelectBox.setSelectObject(new Color(31, 173, 229)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(buttonColorSelectBox); + centerPane.add(panel); + } + + private void addHeaderLinePane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Title_Line"))); + + UILabel titleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_SubTitle_Line")); + showTitleEditor = DesignerUtils.createCheckBox(Toolkit.i18nText("Fine-Plugin-Date_Show_Title_Line"), true); + JPanel headerPanel = new JPanel(); + headerPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + headerPanel.add(titleLabel); + headerPanel.add(showTitleEditor); + centerPane.add(headerPanel); + + final UILabel splitLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Title_Split_Line_Color")); + titleSplitLineColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if(showTitleEditor.isSelected()) { + titleSplitLineColor = titleSplitLineColorSelectBox.getSelectObject(); + } + } + }); + titleSplitLineColorSelectBox.setSelectObject(new Color(234, 234, 234)); + final JPanel splitLineColorPanel = new JPanel(); + splitLineColorPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + splitLineColorPanel.add(splitLabel); + splitLineColorPanel.add(titleSplitLineColorSelectBox); + + + showTitleEditor.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + if(showTitleEditor.isSelected()) { + titleSplitLineColorSelectBox.setSelectObject(titleSplitLineColor); + } else { + titleSplitLineColorSelectBox.setSelectObject(titleSplitLineDisableColor); + } + + titleSplitLineColorSelectBox.setEnabled(showTitleEditor.isSelected()); + splitLabel.setEnabled(showTitleEditor.isSelected()); + } + }); + centerPane.add(splitLineColorPanel); + } + + private void addFontColorPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Font"))); + UILabel mainLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Main")); + mainFontColor = new UIColorButton(); + mainFontColor.setColor(new Color(51, 51, 51)); + mainFontColor.setPreferredSize(new Dimension(20, 20)); + + UILabel specialLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Special")); + specialFontColor = new UIColorButton(); + specialFontColor.setColor(new Color(255, 148, 84)); + specialFontColor.setPreferredSize(new Dimension(20, 20)); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, p}; + JPanel panel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][] { + {mainLabel, mainFontColor}, + {specialLabel, specialFontColor} + }, rowSize, columnSize, 10); + + centerPane.add(panel); + + + UILabel fontSizeLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Size")); + dateFontSize = new UIComboBox(new Integer[]{12, 13, 14, 15, 16, 17, 18}); + dateFontSize.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + dateFontSize.setSelectedItem(14); + JPanel fontPanel = new JPanel(); + fontPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + fontPanel.add(fontSizeLabel); + fontPanel.add(dateFontSize); + centerPane.add(fontPanel); + } + + private void addArrowPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Arrow"))); + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Arrow_Color")); + arrowColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + arrowColorSelectBox.setSelectObject(new Color(234, 234, 234)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(arrowColorSelectBox ); + centerPane.add(panel); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + @Override + public void populateBean(MobileStyle ob) { + NavigationMobileStyle mobileStyle = (NavigationMobileStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + expand.setSelectedIndex(mobileStyle.isExpand() ? 1 : 0); + buttonColorSelectBox.setSelectObject(mobileStyle.getButtonBackgroundColor()); + mainFontColor.setColor(mobileStyle.getMainFontColor()); + specialFontColor.setColor(mobileStyle.getSpecialFontColor()); + showTitleEditor.setSelected(mobileStyle.isShowTitleLine()); + if(mobileStyle.isShowTitleLine()) { + titleSplitLineColorSelectBox.setSelectObject(mobileStyle.getTitleSplitLineColor()); + } else { + titleSplitLineColorSelectBox.setSelectObject(titleSplitLineDisableColor); + titleSplitLineColor = mobileStyle.getTitleSplitLineColor(); + } + dateFontSize.setSelectedItem(mobileStyle.getDateFontSize()); + arrowColorSelectBox.setSelectObject(mobileStyle.getArrowColor()); + } + + @Override + public MobileStyle updateBean() { + NavigationMobileStyle mobileStyle = (NavigationMobileStyle)this.widget.getMobileStyle(); + + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setExpand(expand.getSelectedIndex() == 1); + mobileStyle.setButtonBackgroundColor(buttonColorSelectBox.getSelectObject()); + mobileStyle.setMainFontColor(mainFontColor.getColor()); + mobileStyle.setSpecialFontColor(specialFontColor.getColor()); + mobileStyle.setShowTitleLine(showTitleEditor.isSelected()); + if(showTitleEditor.isSelected()) { + mobileStyle.setTitleSplitLineColor(titleSplitLineColorSelectBox.getSelectObject()); + } else { + mobileStyle.setTitleSplitLineColor(titleSplitLineColor); + } + mobileStyle.setDateFontSize(Integer.parseInt(dateFontSize.getSelectedItem().toString())); + mobileStyle.setArrowColor(arrowColorSelectBox.getSelectObject()); + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleCustomDefinePane.java new file mode 100644 index 000000000..3a5cb5444 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleCustomDefinePane.java @@ -0,0 +1,230 @@ +package com.fr.design.mainframe.mobile.ui.date; + +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.icombobox.UIComboBox; +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.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.SimpleMobileStyle; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class SimpleCustomDefinePane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + + private UIComboBox expand; + private UIComboBox dateFontSize; + private NewColorSelectBox buttonColorSelectBox; + private NewColorSelectBox titleSplitLineColorSelectBox; + private NewColorSelectBox arrowColorSelectBox; + private UIColorButton mainFontColor; + private UIColorButton specialFontColor; + + public SimpleCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-Date_Style_Default"), + Toolkit.i18nText("Fine-Plugin-Date_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + addExpandPane(); + addHeaderLinePane(); + addButtonColorPane(); + addFontColorPane(); + addArrowPane(); + scrollPanel.add(centerPane, BorderLayout.CENTER); + custom.setSelectedIndex(1); + } + + private void addExpandPane() { + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Status")); + expand = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-Date_Status_Collapse"), Toolkit.i18nText("Fine-Plugin-Date_Status_Expand")}); + expand.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(expand); + centerPane.add(panel); + } + + private void addHeaderLinePane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Title_Line"))); + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Title_Split_Line_Color")); + titleSplitLineColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + titleSplitLineColorSelectBox.setSelectObject(new Color(234, 234, 234)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(titleSplitLineColorSelectBox); + centerPane.add(panel); + } + + private void addButtonColorPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Button"))); + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Button_Color")); + buttonColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + buttonColorSelectBox.setSelectObject(new Color(31, 173, 229)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(buttonColorSelectBox); + centerPane.add(panel); + } + + private void addFontColorPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Font"))); + UILabel mainLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Main")); + mainFontColor = new UIColorButton(); + mainFontColor.setColor(new Color(51, 51, 51)); + mainFontColor.setPreferredSize(new Dimension(20, 20)); + + UILabel specialLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Special")); + specialFontColor = new UIColorButton(); + specialFontColor.setColor(new Color(255, 148, 84)); + specialFontColor.setPreferredSize(new Dimension(20, 20)); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, p}; + JPanel panel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][] { + {mainLabel, mainFontColor}, + {specialLabel, specialFontColor} + }, rowSize, columnSize, 10); + + centerPane.add(panel); + + UILabel fontSizeLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Font_Size")); + dateFontSize = new UIComboBox(new Integer[]{12, 13, 14, 15, 16, 17, 18}); + dateFontSize.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + dateFontSize.setSelectedItem(14); + JPanel fontPanel = new JPanel(); + fontPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + fontPanel.add(fontSizeLabel); + fontPanel.add(dateFontSize); + centerPane.add(fontPanel); + } + + private void addArrowPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-Date_Arrow"))); + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-Date_Arrow_Color")); + arrowColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + arrowColorSelectBox.setSelectObject(new Color(234, 234, 234)); + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + panel.add(label); + panel.add(arrowColorSelectBox ); + centerPane.add(panel); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + @Override + public void populateBean(MobileStyle ob) { + SimpleMobileStyle mobileStyle = (SimpleMobileStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + expand.setSelectedIndex(mobileStyle.isExpand() ? 1 : 0); + buttonColorSelectBox.setSelectObject(mobileStyle.getButtonBackgroundColor()); + mainFontColor.setColor(mobileStyle.getMainFontColor()); + specialFontColor.setColor(mobileStyle.getSpecialFontColor()); + titleSplitLineColorSelectBox.setSelectObject(mobileStyle.getTitleSplitLineColor()); + dateFontSize.setSelectedItem(mobileStyle.getDateFontSize()); + arrowColorSelectBox.setSelectObject(mobileStyle.getArrowColor()); + } + + @Override + public MobileStyle updateBean() { + SimpleMobileStyle mobileStyle = (SimpleMobileStyle)this.widget.getMobileStyle(); + + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setExpand(expand.getSelectedIndex() == 1); + mobileStyle.setButtonBackgroundColor(buttonColorSelectBox.getSelectObject()); + mobileStyle.setMainFontColor(mainFontColor.getColor()); + mobileStyle.setSpecialFontColor(specialFontColor.getColor()); + mobileStyle.setTitleSplitLineColor(titleSplitLineColorSelectBox.getSelectObject()); + mobileStyle.setDateFontSize(Integer.parseInt(dateFontSize.getSelectedItem().toString())); + mobileStyle.setArrowColor(arrowColorSelectBox.getSelectObject()); + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleDateCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleDateCustomDefinePane.java new file mode 100644 index 000000000..ad79f499e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/date/SimpleDateCustomDefinePane.java @@ -0,0 +1,267 @@ +package com.fr.design.mainframe.mobile.ui.date; + +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icombobox.LineComboBox; +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.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.mainframe.mobile.utils.FontConfigPane; +import com.fr.design.mainframe.mobile.utils.IconConfigPane; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.date.ControlStyle; +import com.fr.form.ui.mobile.date.SimpleDateMobileStyle; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class SimpleDateCustomDefinePane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + private FontConfigPane labelFontConfigPane; + private FontConfigPane controlValueConfigPane; + private NewColorSelectBox controlBackground; + private LineComboBox controlBorder; + private NewColorSelectBox controlBorderColor; + private UISpinner controlWidgetRadius; + private UISpinner widthSpinner; + private UIRadioButton fillButton; + private UIRadioButton customButton; + private IconConfigPane iconConfigPane; + + public SimpleDateCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleDate_Control_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-SimpleDate_Style_Default"), + Toolkit.i18nText("Fine-Plugin-SimpleDate_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + centerPane.setVisible(false); + + addFontConfigPane(); + addIconConfigPane(); + addControlConfigPane(); + + scrollPanel.add(centerPane, BorderLayout.CENTER); + } + + private void addControlConfigPane() { + + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleDate_Control_Region"))); + controlBackground = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + controlBorder = new LineComboBox(DesignerUtils.BORDER_LINE_STYLE_ARRAY); + controlBorder.setSelectedLineStyle(Constants.LINE_THIN); + controlBorder.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + controlBorderColor = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + controlWidgetRadius = new UISpinner(0, Integer.MAX_VALUE, 1, 2); + controlWidgetRadius.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + + JComponent[] controlComponents = new JComponent[]{controlBackground, controlBorder, controlBorderColor, controlWidgetRadius}; + String[] comboBoxNames = new String[]{ + Toolkit.i18nText("Fine-Plugin-SimpleDate_Control_Background"), + Toolkit.i18nText("Fine-Plugin-SimpleDate_Control_Border"), + Toolkit.i18nText("Fine-Plugin-SimpleDate_Border_Color"), + Toolkit.i18nText("Fine-Plugin-SimpleDate_Radius") + }; + + Component[][] components = new Component[4][]; + + for (int i = 0; i < 4; i++) { + UILabel label = DesignerUtils.createConfigLabel(comboBoxNames[i]); + components[i] = new Component[]{label, controlComponents[i]}; + } + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p}; + double[] columnSize = {p, p}; + JPanel controlPanel = TableLayoutHelper.createCommonTableLayoutPane(components, rowSize, columnSize, 10); + centerPane.add(controlPanel); + + this.fillButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleDate_Horizontal_Fill")); + this.customButton = new UIRadioButton(Toolkit.i18nText("Fine-Plugin-SimpleDate_Width_Custom")); + + ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(fillButton); + buttonGroup.add(customButton); + + JPanel panel = new JPanel(); + panel.add(fillButton); + panel.add(customButton); + panel.setLayout(new GridLayout(0, 2, 14, 0)); + panel.setPreferredSize(new Dimension(174, 20)); + fillButton.setSelected(true); + + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + widthSpinner.setVisible(customButton.isSelected()); + } + }; + + fillButton.addActionListener(listener); + customButton.addActionListener(listener); + + UILabel label = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleDate_Width")); + widthSpinner = new UISpinner(1, Integer.MAX_VALUE, 1, 200); + widthSpinner.setPreferredSize(new Dimension(78, 20)); + widthSpinner.setVisible(false); + centerPane.add(DesignerUtils.createLeftRightComponentsPane(label, panel, widthSpinner)); + + } + + private void addFontConfigPane() { + + String[] titleSplitLineNames = new String[]{ + Toolkit.i18nText("Fine-Plugin-SimpleDate_Label_Name"), + Toolkit.i18nText("Fine-Plugin-SimpleDate_Control_Value") + }; + labelFontConfigPane = new FontConfigPane(); + controlValueConfigPane = new FontConfigPane(); + FontConfigPane[] fontConfigPanes = new FontConfigPane[]{labelFontConfigPane, controlValueConfigPane}; + for (int i = 0; i < 2; i++) { + centerPane.add(DesignerUtils.createTitleSplitLine(titleSplitLineNames[i])); + UILabel fontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-SimpleDate_Character")); + JPanel fontPanel = DesignerUtils.createLeftRightComponentsPane(fontLabel, fontConfigPanes[i]); + centerPane.add(fontPanel); + } + } + + private void addIconConfigPane() { + + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-SimpleDate_Icon"))); + UILabel tipLabel = new UILabel(); + tipLabel.setFont(new Font(tipLabel.getName(), Font.PLAIN, 10)); + tipLabel.setSize(470, 40); + tipLabel.setText(Toolkit.i18nText("Fine-Plugin-SimpleDate_Tip")); + tipLabel.setForeground(Color.decode("#9B9B9B")); + centerPane.add(tipLabel); + + JPanel panel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + + + iconConfigPane = new IconConfigPane(); + centerPane.add(iconConfigPane); + + } + + @Override + public void populateBean(MobileStyle mobileStyle) { + SimpleDateMobileStyle simpleDateMobileStyle = (SimpleDateMobileStyle) mobileStyle; + custom.setSelectedIndex(simpleDateMobileStyle.isCustom() ? 1 : 0); + iconConfigPane.populate(simpleDateMobileStyle.getIconValue()); + labelFontConfigPane.populate(simpleDateMobileStyle.getLabelFontStyle()); + controlValueConfigPane.populate(simpleDateMobileStyle.getValueFontStyle()); + + ControlStyle controlStyle = simpleDateMobileStyle.getControlStyle(); + + if (controlStyle != null) { + controlBackground.setSelectObject(controlStyle.getBackground()); + controlBorderColor.setSelectObject(controlStyle.getBorderColor()); + controlBorder.setSelectedLineStyle(controlStyle.getBorderType()); + controlWidgetRadius.setValue(controlStyle.getBorderRadius()); + if (controlStyle.isCustomWidth()) { + widthSpinner.setVisible(true); + widthSpinner.setValue(controlStyle.getWidth()); + customButton.setSelected(true); + fillButton.setSelected(false); + } else { + widthSpinner.setVisible(false); + customButton.setSelected(false); + fillButton.setSelected(true); + } + } + + } + + @Override + public MobileStyle updateBean() { + SimpleDateMobileStyle simpleDateMobileStyle = (SimpleDateMobileStyle) this.widget.getMobileStyle(); + simpleDateMobileStyle.setCustom(custom.getSelectedIndex() == 1); + simpleDateMobileStyle.setIconValue(iconConfigPane.update()); + simpleDateMobileStyle.setLabelFontStyle(labelFontConfigPane.update()); + simpleDateMobileStyle.setValueFontStyle(controlValueConfigPane.update()); + ControlStyle controlStyle = new ControlStyle(); + controlStyle.setBackground(controlBackground.getSelectObject()); + controlStyle.setBorderColor(controlBorderColor.getSelectObject()); + controlStyle.setBorderType(controlBorder.getSelectedLineStyle()); + controlStyle.setBorderRadius(controlWidgetRadius.getValue()); + controlStyle.setCustomWidth(customButton.isSelected()); + controlStyle.setWidth(widthSpinner.getValue()); + simpleDateMobileStyle.setControlStyle(controlStyle); + return simpleDateMobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/CapsuleCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/CapsuleCustomDefinePane.java new file mode 100644 index 000000000..072a7a57a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/CapsuleCustomDefinePane.java @@ -0,0 +1,310 @@ +package com.fr.design.mainframe.mobile.ui.radiogroup; + +import com.fr.design.constants.LayoutConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.icombobox.LineComboBox; +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.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.mainframe.mobile.utils.FontConfigPane; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.CapsuleMobileStyle; +import com.fr.general.FRFont; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class CapsuleCustomDefinePane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + + private UISpinner leftSpinner; + private UISpinner rightSpinner; + private UISpinner topSpinner; + private UISpinner bottomSpinner; + + private JRadioButton leftAlignRadioButton; + private JRadioButton centerAlignRadioButton; + + private NewColorSelectBox initialColorSelectBox; + private NewColorSelectBox selectedColorSelectBox; + + private LineComboBox borderLineCombo; + private NewColorSelectBox initialBorderColor; + private NewColorSelectBox selectedBorderColor; + private UISpinner borderRadiusSpinner; + + private FontConfigPane initialFontConfPane; + private UIColorButton selectedFontColor; + + + public CapsuleCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Default"), + Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + + addPaddingPane(); + addBackgroundPane(); + addBorderPane(); + addFontPane(); + + scrollPanel.add(centerPane, BorderLayout.CENTER); + custom.setSelectedIndex(1); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + private void addPaddingPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Layout"))); + + UILabel paddingHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Button_Padding")); + UILabel emptyHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("")); + UILabel buttonAlignHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Alignment")); + + UILabel leftLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Left")); + leftSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel rightLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Right")); + rightSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel topLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Top")); + topSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + UILabel bottomLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Bottom")); + bottomSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + leftAlignRadioButton = new JRadioButton(Toolkit.i18nText("Fine-Plugin-RadioGroup_Alignment_Left"), true); + centerAlignRadioButton = new JRadioButton(Toolkit.i18nText("Fine-Plugin-RadioGroup_Alignment_Center"), false); + + JPanel leftSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftLabel, leftSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel rightSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{rightLabel, rightSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel topSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topLabel, topSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel bottomSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{bottomLabel, bottomSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + + JPanel vPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topSpinnerPanel, bottomSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + + JPanel hPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftSpinnerPanel, rightSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + + JPanel layoutPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftAlignRadioButton, centerAlignRadioButton}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + + ButtonGroup layoutRadioButtonGroup = new ButtonGroup(); + layoutRadioButtonGroup.add(leftAlignRadioButton); + layoutRadioButtonGroup.add(centerAlignRadioButton); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p}; + double[] columnSize = {p, p}; + JPanel paddingPanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{ + {paddingHintLabel, vPaddingSpinnerPanel}, + {emptyHintLabel, hPaddingSpinnerPanel}, + {buttonAlignHintLabel, layoutPanel}, + }, rowSize, columnSize, 10); + centerPane.add(paddingPanel); + } + + private void addBackgroundPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background"))); + + UILabel initialColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background_Init")); + initialColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + initialColorSelectBox.setSelectObject(new Color(244, 244, 244)); + JPanel initialColorSelectPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{initialColorLabel, initialColorSelectBox}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(initialColorSelectPane); + + UILabel selectedColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background_Select")); + selectedColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + + } + }); + selectedColorSelectBox.setSelectObject(new Color(31, 173, 229)); + JPanel selectedColorSelectPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{selectedColorLabel, selectedColorSelectBox}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(selectedColorSelectPane); + } + + private void addBorderPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border"))); + + UILabel borderTypeLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Line")); + borderLineCombo = new LineComboBox(DesignerUtils.BORDER_LINE_STYLE_ARRAY); + borderLineCombo.setSelectedLineStyle(Constants.LINE_THIN); + + UILabel initialColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Init_Color")); + initialBorderColor = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + initialBorderColor.setSelectObject(new Color(244, 244, 244)); + + UILabel selectedColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Select_Color")); + selectedBorderColor = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + selectedBorderColor.setSelectObject(new Color(31, 173, 229)); + + UILabel radiusLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Radius")); + borderRadiusSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, 20); + borderRadiusSpinner.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p}; + double[] columnSize = {p, p}; + JPanel borderPanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{ + {borderTypeLabel, borderLineCombo}, + {initialColorLabel, initialBorderColor}, + {selectedColorLabel, selectedBorderColor}, + {radiusLabel, borderRadiusSpinner} + }, rowSize, columnSize, 10); + + centerPane.add(borderPanel); + + } + + private void addFontPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font"))); + + UILabel initialFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_init")); + initialFontConfPane = new FontConfigPane(); + initialFontConfPane.setFontColor(new Color(204, 204, 204)); + JPanel fontPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{initialFontLabel, initialFontConfPane}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(fontPanel); + UILabel selectedFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_Select")); + selectedFontColor = new UIColorButton(); + selectedFontColor.setColor(Color.WHITE); + selectedFontColor.setPreferredSize(new Dimension(20, 20)); + JPanel selectFontColorPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{selectedFontLabel, selectedFontColor}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(selectFontColorPanel); + + } + + @Override + public void populateBean(MobileStyle ob) { + CapsuleMobileStyle mobileStyle = (CapsuleMobileStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + leftSpinner.setValue(mobileStyle.getLeftPadding()); + rightSpinner.setValue(mobileStyle.getRightPadding()); + topSpinner.setValue(mobileStyle.getTopPadding()); + bottomSpinner.setValue(mobileStyle.getBottomPadding()); + leftAlignRadioButton.setSelected(mobileStyle.getButtonAlign() == DesignerUtils.kAlignLeft); + centerAlignRadioButton.setSelected(mobileStyle.getButtonAlign() == DesignerUtils.kAlignCenter); + initialColorSelectBox.setSelectObject(mobileStyle.getInitialBackgroundColor()); + selectedColorSelectBox.setSelectObject(mobileStyle.getSelectedBackgroundColor()); + borderLineCombo.setSelectedLineStyle(mobileStyle.getBorderType()); + initialBorderColor.setSelectObject(mobileStyle.getInitialBorderColor()); + selectedBorderColor.setSelectObject(mobileStyle.getSelectedBorderColor()); + borderRadiusSpinner.setValue(mobileStyle.getBorderRadius()); + if (mobileStyle.getInitialFont() != null) { + initialFontConfPane.populate(mobileStyle.getInitialFont()); + } + if (mobileStyle.getSelectedFont() != null) { + selectedFontColor.setColor(mobileStyle.getSelectedFont().getForeground()); + } + } + + @Override + public MobileStyle updateBean() { + CapsuleMobileStyle mobileStyle = (CapsuleMobileStyle) this.widget.getMobileStyle(); + + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setLeftPadding(leftSpinner.getValue()); + mobileStyle.setRightPadding(rightSpinner.getValue()); + mobileStyle.setTopPadding(topSpinner.getValue()); + mobileStyle.setBottomPadding(bottomSpinner.getValue()); + mobileStyle.setButtonAlign(leftAlignRadioButton.isSelected() ? DesignerUtils.kAlignLeft : DesignerUtils.kAlignCenter); + mobileStyle.setInitialBackgroundColor(initialColorSelectBox.getSelectObject()); + mobileStyle.setSelectedBackgroundColor(selectedColorSelectBox.getSelectObject()); + mobileStyle.setBorderType(borderLineCombo.getSelectedLineStyle()); + mobileStyle.setInitialBorderColor(initialBorderColor.getSelectObject()); + mobileStyle.setSelectedBorderColor(selectedBorderColor.getSelectObject()); + mobileStyle.setBorderRadius(borderRadiusSpinner.getValue()); + + FRFont initialFont = initialFontConfPane.updateFont(null, null, null); + FRFont selectedFont = initialFontConfPane.updateFont(selectedFontColor.getColor(), null, null); + + mobileStyle.setInitialFont(initialFont); + mobileStyle.setSelectedFont(selectedFont); + + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/IconConfigPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/IconConfigPane.java new file mode 100644 index 000000000..08e0ecd09 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/IconConfigPane.java @@ -0,0 +1,195 @@ +package com.fr.design.mainframe.mobile.ui.radiogroup; + +import com.fr.base.IconManager; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.utils.DrawRoutines; +import com.fr.design.web.CustomIconPane; +import com.fr.form.ui.WidgetInfoConfig; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRFont; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.basic.BasicButtonUI; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; + +public class IconConfigPane extends JPanel { + private UIButton editIconButton; + private UIButton deleteIconButton; + private String curIconName; + private IconButton selectIconButton; + private ArrayList iconButtons = new ArrayList(); + + public IconConfigPane(int count) { + initComp(count); + } + + public void initComp(int count) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel panel = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); + panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + editIconButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Edit")); + editIconButton.setFont(FRFont.getInstance("Helvetica", Font.PLAIN, 12, Color.decode("#3A383A"))); + editIconButton.setPreferredSize(new Dimension(62, 20)); + panel.add(editIconButton); + editIconButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final CustomIconPane cip = new CustomIconPane(){ + protected String createDescriptionText(){ + return Toolkit.i18nText("Fine-Design_Mobile_Custom_Icon_Message"); + } + }; + BasicDialog editDialog = cip.showWindow(DesignerContext.getDesignerFrame()); + editDialog.addDialogActionListener(new DialogActionAdapter() { + @Override + public void doOk() { + curIconName = cip.update(); + setShowIconImage(); + IconConfigPane.this.repaint(); + } + }); + editDialog.setVisible(true); + } + }); + editIconButton.setEnabled(false); + + deleteIconButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Delete")); + deleteIconButton.setFont(FRFont.getInstance("Helvetica", Font.PLAIN, 12, Color.decode("#3A383A"))); + deleteIconButton.setPreferredSize(new Dimension(62, 20)); + panel.add(deleteIconButton); + deleteIconButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + selectIconButton.setIconName(StringUtils.EMPTY); + IconConfigPane.this.repaint(); + } + }); + deleteIconButton.setEnabled(false); + + + this.add(panel, BorderLayout.CENTER); + + JPanel northPane = new JPanel(); + northPane.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + for (int i = 0; i < count; i++) { + IconButton iconButton = new IconButton(""); + northPane.add(iconButton); + iconButtons.add(iconButton); + } + this.add(northPane, BorderLayout.NORTH); + } + + public void setShowIconImage() { + selectIconButton.setIconName(curIconName); + } + + public void populate(ArrayList iconArr) { + for (int i = 0; i < iconButtons.size(); i++) { + iconButtons.get(i).setIconName(iconArr.get(i)); + } + } + + public ArrayList update() { + ArrayList iconNames = new ArrayList(); + for (int i = 0; i < iconButtons.size(); i++) { + iconNames.add(iconButtons.get(i).getIconName()); + } + return iconNames; + } + + + private class IconButton extends JToggleButton implements ActionListener { + private String iconName; + private Image iconImage = null; + private static final int ICON_BUTTON_SIZE = 20; + private static final int ICON_X = 2; + private static final int ICON_Y = 2; + + public IconButton(String name) { + this.iconName = name; + this.addActionListener(this); + this.setBackground(Color.WHITE); + this.setCursor(new Cursor(Cursor.HAND_CURSOR)); + this.iconImage = WidgetInfoConfig.getInstance().getIconManager().getIconImage(name); + } + + @Override + public void updateUI() { + setUI(new BasicButtonUI() { + public void paint(Graphics g, JComponent c) { + super.paint(g, c); + } + }); + } + + protected void paintBorder(Graphics g) { + super.paintBorder(g); + if (ComparatorUtils.equals(this, selectIconButton)) { + DrawRoutines.drawRoundedBorder( + g, Color.decode("#419BF9"), 0, 0, 20, 20); + } else { + DrawRoutines.drawRoundedBorder( + g, Color.decode("#D9DADD"), 0, 0, 20, 20); + } + + } + + public String getIconName() { + return iconName; + } + + public void setIconName(String iconName) { + this.iconName = iconName; + this.iconImage = WidgetInfoConfig.getInstance().getIconManager().getIconImage(iconName); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2d = (Graphics2D) g; + // carl:这里缩放显示 16 × 16 + if (iconImage != null) { + g2d.drawImage(iconImage, ICON_X, ICON_Y, IconManager.DEFAULT_ICONWIDTH, IconManager.DEFAULT_ICONHEIGHT, null); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(ICON_BUTTON_SIZE, ICON_BUTTON_SIZE); + } + + public void actionPerformed(ActionEvent evt) { + selectIconButton = this; + editIconButton.setEnabled(true); + if(StringUtils.isNotEmpty(this.iconName)) { + deleteIconButton.setEnabled(true); + } else { + deleteIconButton.setEnabled(false); + } + IconConfigPane.this.repaint();// repaint + } + + @Override + public void addChangeListener(ChangeListener changeListener) { + this.changeListener = changeListener; + } + + private void fireChagneListener() { + if (this.changeListener != null) { + ChangeEvent evt = new ChangeEvent(this); + this.changeListener.stateChanged(evt); + } + } + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/ImageCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/ImageCustomDefinePane.java new file mode 100644 index 000000000..7288d3263 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/ImageCustomDefinePane.java @@ -0,0 +1,242 @@ +package com.fr.design.mainframe.mobile.ui.radiogroup; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UIToggleButton; +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.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.mainframe.mobile.utils.FontConfigPane; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.ImageMobileStyle; +import com.fr.general.FRFont; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.ArrayList; +import java.util.Arrays; + +public class ImageCustomDefinePane extends MobileStyleCustomDefinePane { + + private static final Icon[] BOLD_ICONS = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold_white.png")}; + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + + private UISpinner leftSpinner; + private UISpinner rightSpinner; + private UISpinner topSpinner; + private UISpinner bottomSpinner; + + private IconConfigPane initialIconConfigPane; + private IconConfigPane selectedIconConfigPane; + + private FontConfigPane initialFontConfPane; + private UIColorButton selectedFontColor; + private UIToggleButton selectedFontBold; + + public ImageCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Default"), + Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + + addPaddingPane(); + + addIconPane(); + + addFontPane(); + + scrollPanel.add(centerPane, BorderLayout.CENTER); + custom.setSelectedIndex(1); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + private void addPaddingPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Layout"))); + + UILabel paddingHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Button_Padding")); + UILabel emptyHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("")); + + UILabel leftLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Left")); + leftSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel rightLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Right")); + rightSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel topLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Top")); + topSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + UILabel bottomLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Bottom")); + bottomSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + JPanel leftSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftLabel, leftSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel rightSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{rightLabel, rightSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel topSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topLabel, topSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel bottomSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{bottomLabel, bottomSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + + JPanel vPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topSpinnerPanel, bottomSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + JPanel hPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftSpinnerPanel, rightSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, p}; + JPanel paddingPanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{ + {paddingHintLabel, vPaddingSpinnerPanel}, + {emptyHintLabel, hPaddingSpinnerPanel}, + }, rowSize, columnSize, 10); + + centerPane.add(paddingPanel); + } + + private void addIconPane() { + + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Icon"))); + + UILabel initialLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Icon_Init")); + UILabel selectedLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Icon_Select")); + + initialIconConfigPane = new IconConfigPane(8); + selectedIconConfigPane = new IconConfigPane(8); + + JPanel container = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 5); + + JPanel initialPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + initialPane.add(initialLabel); + initialPane.add(initialIconConfigPane); + container.add(initialPane); + + JPanel selectedPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + selectedPane.add(selectedLabel); + selectedPane.add(selectedIconConfigPane); + container.add(selectedPane); + + centerPane.add(container); + + } + + private void addFontPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font"))); + + UILabel initialFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_init")); + initialFontConfPane = new FontConfigPane(); + initialFontConfPane.setFontColor(new Color(204, 204, 204)); + JPanel fontPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{initialFontLabel, initialFontConfPane}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(fontPanel); + UILabel selectedFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_Select")); + selectedFontColor = new UIColorButton(); + selectedFontColor.setColor(new Color(31, 173, 229)); + selectedFontColor.setPreferredSize(new Dimension(20, 20)); + selectedFontBold = new UIToggleButton(BOLD_ICONS, true); + selectedFontBold.setPreferredSize(new Dimension(20, 20)); + JPanel selectFontColorPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{selectedFontLabel, selectedFontColor, selectedFontBold}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(selectFontColorPanel); + + } + + @Override + public void populateBean(MobileStyle ob) { + ImageMobileStyle mobileStyle = (ImageMobileStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + leftSpinner.setValue(mobileStyle.getLeftPadding()); + rightSpinner.setValue(mobileStyle.getRightPadding()); + topSpinner.setValue(mobileStyle.getTopPadding()); + bottomSpinner.setValue(mobileStyle.getBottomPadding()); + initialIconConfigPane.populate(new ArrayList<>(Arrays.asList(mobileStyle.getInitialIconNames()))); + selectedIconConfigPane.populate(new ArrayList<>(Arrays.asList(mobileStyle.getSelectedIconNames()))); + if(mobileStyle.getInitialFont() != null) { + initialFontConfPane.populate(mobileStyle.getInitialFont()); + } + if(mobileStyle.getSelectedFont() != null) { + selectedFontColor.setColor(mobileStyle.getSelectedFont().getForeground()); + selectedFontBold.setSelected(mobileStyle.getSelectedFont().isBold()); + } + } + + @Override + public MobileStyle updateBean() { + ImageMobileStyle mobileStyle = (ImageMobileStyle)this.widget.getMobileStyle(); + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setLeftPadding(leftSpinner.getValue()); + mobileStyle.setRightPadding(rightSpinner.getValue()); + mobileStyle.setTopPadding(topSpinner.getValue()); + mobileStyle.setBottomPadding(bottomSpinner.getValue()); + ArrayList initialIconNamesList = initialIconConfigPane.update(); + ArrayList selectedIconNamesList = selectedIconConfigPane.update(); + mobileStyle.setInitialIconNames(initialIconNamesList.toArray(new String[initialIconNamesList.size()])); + mobileStyle.setSelectedIconNames(selectedIconNamesList.toArray(new String[selectedIconNamesList.size()])); + FRFont initialFont = initialFontConfPane.updateFont(null, null, null); + FRFont selectedFont = initialFontConfPane.updateFont(selectedFontColor.getColor(), selectedFontBold.isSelected(), null); + mobileStyle.setInitialFont(initialFont); + mobileStyle.setSelectedFont(selectedFont); + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/UnitedCustomDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/UnitedCustomDefinePane.java new file mode 100644 index 000000000..8d9b42574 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/radiogroup/UnitedCustomDefinePane.java @@ -0,0 +1,279 @@ +package com.fr.design.mainframe.mobile.ui.radiogroup; + +import com.fr.design.constants.LayoutConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.icombobox.LineComboBox; +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.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.mobile.ui.MobileStyleCustomDefinePane; +import com.fr.design.mainframe.mobile.utils.DesignerUtils; +import com.fr.design.mainframe.mobile.utils.FontConfigPane; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.form.ui.Widget; +import com.fr.form.ui.mobile.MobileStyle; +import com.fr.form.ui.mobile.radiogroup.UnitedMobileStyle; +import com.fr.general.FRFont; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class UnitedCustomDefinePane extends MobileStyleCustomDefinePane { + + private JPanel scrollPanel; + private UIComboBox custom; + private JPanel centerPane; + + private UISpinner leftSpinner; + private UISpinner rightSpinner; + private UISpinner topSpinner; + private UISpinner bottomSpinner; + + private NewColorSelectBox initialColorSelectBox; + private NewColorSelectBox selectedColorSelectBox; + + private LineComboBox borderLineCombo; + private NewColorSelectBox borderColor; + private UISpinner borderRadiusSpinner; + + private FontConfigPane initialFontConfPane; + private UIColorButton selectedFontColor; + + public UnitedCustomDefinePane(Widget widget) { + super(widget); + } + + @Override + protected JPanel createPreviewPane() { + return null; + } + + @Override + protected void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.addScrollPane(); + this.addStyleSelectPane(); + this.addConfigPane(); + } + + private void addScrollPane() { + scrollPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return scrollPanel; + } + }; + this.add(basicScrollPane); + } + + private void addStyleSelectPane() { + JPanel stylePanel = new JPanel(); + stylePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + UILabel buttonStyleLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Style")); + custom = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Default"), + Toolkit.i18nText("Fine-Plugin-RadioGroup_Style_Custom")}); + custom.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + custom.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + boolean isCustom = custom.getSelectedIndex() == 1; + centerPane.setVisible(isCustom); + } + }); + stylePanel.add(buttonStyleLabel); + stylePanel.add(custom); + scrollPanel.add(stylePanel, BorderLayout.NORTH); + } + + private void addConfigPane() { + centerPane = createCenterPane(); + centerPane.setVisible(false); + + addPaddingPane(); + addBackgroundPane(); + addBorderPane(); + addFontPane(); + + scrollPanel.add(centerPane, BorderLayout.CENTER); + custom.setSelectedIndex(1); + } + + private JPanel createCenterPane() { + return FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10); + } + + private void addPaddingPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Layout"))); + + UILabel paddingHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Button_Padding")); + UILabel emptyHintLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("")); + + UILabel leftLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Left")); + leftSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel rightLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Right")); + rightSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultHorizontalPadding); + + UILabel topLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Top")); + topSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + UILabel bottomLabel = new UILabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Padding_Bottom")); + bottomSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, DesignerUtils.kDefaultVerticalPadding); + + JPanel leftSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftLabel, leftSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel rightSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{rightLabel, rightSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel topSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topLabel, topSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + JPanel bottomSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{bottomLabel, bottomSpinner}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_SMALL); + + JPanel vPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{topSpinnerPanel, bottomSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + JPanel hPaddingSpinnerPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{leftSpinnerPanel, rightSpinnerPanel}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, LayoutConstants.VGAP_SMALL); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, p}; + JPanel paddingPanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{ + {paddingHintLabel, vPaddingSpinnerPanel}, + {emptyHintLabel, hPaddingSpinnerPanel}, + }, rowSize, columnSize, 10); + + centerPane.add(paddingPanel); + } + + private void addBackgroundPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background"))); + + UILabel initialColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background_Init")); + initialColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + initialColorSelectBox.setSelectObject(Color.WHITE); + JPanel initialColorSelectPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{initialColorLabel, initialColorSelectBox}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(initialColorSelectPane); + + UILabel selectedColorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Background_Select")); + selectedColorSelectBox = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + + } + }); + selectedColorSelectBox.setSelectObject(new Color(31, 173, 229)); + JPanel selectedColorSelectPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{selectedColorLabel, selectedColorSelectBox}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(selectedColorSelectPane); + } + + private void addBorderPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border"))); + + UILabel borderTypeLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Line")); + borderLineCombo = new LineComboBox(DesignerUtils.BORDER_LINE_STYLE_ARRAY); + borderLineCombo.setSelectedLineStyle(Constants.LINE_THIN); + + UILabel colorLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Color")); + borderColor = DesignerUtils.createNormalColorSelectBox(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + } + }); + borderColor.setSelectObject(new Color(31, 173, 229) ); + + UILabel radiusLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Border_Radius")); + borderRadiusSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, 2); + borderRadiusSpinner.setPreferredSize(new Dimension(DesignerUtils.NORMAL_COMBO_WIDTH, 20)); + + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p}; + double[] columnSize = {p, p}; + JPanel borderPanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][] { + {borderTypeLabel, borderLineCombo}, + {colorLabel, borderColor}, + {radiusLabel, borderRadiusSpinner} + }, rowSize, columnSize, 10); + + centerPane.add(borderPanel); + + } + + private void addFontPane() { + centerPane.add(DesignerUtils.createTitleSplitLine(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font"))); + + UILabel initialFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_init")); + initialFontConfPane = new FontConfigPane(); + initialFontConfPane.setFontColor(new Color(31, 173, 229)); + JPanel fontPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{initialFontLabel, initialFontConfPane}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(fontPanel); + UILabel selectedFontLabel = DesignerUtils.createConfigLabel(Toolkit.i18nText("Fine-Plugin-RadioGroup_Font_Select")); + selectedFontColor = new UIColorButton(); + selectedFontColor.setPreferredSize(new Dimension(20, 20)); + selectedFontColor.setColor(Color.WHITE); + JPanel selectFontColorPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{selectedFontLabel, selectedFontColor}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + centerPane.add(selectFontColorPanel); + + } + + @Override + public void populateBean(MobileStyle ob) { + UnitedMobileStyle mobileStyle = (UnitedMobileStyle) ob; + custom.setSelectedIndex(mobileStyle.isCustom() ? 1 : 0); + leftSpinner.setValue(mobileStyle.getLeftPadding()); + rightSpinner.setValue(mobileStyle.getRightPadding()); + topSpinner.setValue(mobileStyle.getTopPadding()); + bottomSpinner.setValue(mobileStyle.getBottomPadding()); + initialColorSelectBox.setSelectObject(mobileStyle.getInitialBackgroundColor()); + selectedColorSelectBox.setSelectObject(mobileStyle.getSelectedBackgroundColor()); + borderLineCombo.setSelectedLineStyle(mobileStyle.getBorderType()); + borderColor.setSelectObject(mobileStyle.getBorderColor()); + borderRadiusSpinner.setValue(mobileStyle.getBorderRadius()); + if(mobileStyle.getInitialFont() != null) { + initialFontConfPane.populate(mobileStyle.getInitialFont()); + } + if(mobileStyle.getSelectedFont() != null) { + selectedFontColor.setColor(mobileStyle.getSelectedFont().getForeground()); + } + } + + @Override + public MobileStyle updateBean() { + UnitedMobileStyle mobileStyle = (UnitedMobileStyle)this.widget.getMobileStyle(); + + mobileStyle.setCustom(custom.getSelectedIndex() == 1); + mobileStyle.setLeftPadding(leftSpinner.getValue()); + mobileStyle.setRightPadding(rightSpinner.getValue()); + mobileStyle.setTopPadding(topSpinner.getValue()); + mobileStyle.setBottomPadding(bottomSpinner.getValue()); + mobileStyle.setInitialBackgroundColor(initialColorSelectBox.getSelectObject()); + mobileStyle.setSelectedBackgroundColor(selectedColorSelectBox.getSelectObject()); + mobileStyle.setBorderType(borderLineCombo.getSelectedLineStyle()); + mobileStyle.setBorderColor(borderColor.getSelectObject()); + mobileStyle.setBorderRadius(borderRadiusSpinner.getValue()); + + FRFont initialFont = initialFontConfPane.updateFont(null, null, null); + FRFont selectedFont = initialFontConfPane.updateFont(selectedFontColor.getColor(), null, null); + selectedFont.setForeground(selectedFontColor.getColor()); + + mobileStyle.setInitialFont(initialFont); + mobileStyle.setSelectedFont(selectedFont); + + return mobileStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/topparam/MobileTopParamPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/topparam/MobileTopParamPane.java new file mode 100644 index 000000000..7f19bd368 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/topparam/MobileTopParamPane.java @@ -0,0 +1,44 @@ +package com.fr.design.mainframe.mobile.ui.topparam; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.form.ui.mobile.impl.MobileTopParamStyle; + +import javax.swing.*; +import java.awt.*; + +public class MobileTopParamPane extends BasicBeanPane { + private UICheckBox autoCommitCheckBox; + + public MobileTopParamPane() { + this.init(); + } + + private void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel panel = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Plugin-TopParam_Setting")); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + autoCommitCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Plugin-TopParam_AutoCommit"), true); + panel.add(autoCommitCheckBox); + this.add(panel, BorderLayout.CENTER); + } + + @Override + public void populateBean(MobileTopParamStyle topParamStyle) { + autoCommitCheckBox.setSelected(topParamStyle.isAutoCommit()); + } + + @Override + public MobileTopParamStyle updateBean() { + MobileTopParamStyle topParamStyle = new MobileTopParamStyle(); + topParamStyle.setAutoCommit(autoCommitCheckBox.isSelected()); + return topParamStyle; + } + + @Override + protected String title4PopupWindow() { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/DesignerUtils.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/DesignerUtils.java new file mode 100644 index 000000000..bcadac1c7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/DesignerUtils.java @@ -0,0 +1,57 @@ +package com.fr.design.mainframe.mobile.utils; + +import com.fr.design.constants.LayoutConstants; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.widget.UITitleSplitLine; +import com.fr.design.style.color.NewColorSelectBox; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.ChangeListener; +import java.awt.*; + +public class DesignerUtils { + + public static final int NORMAL_COMBO_WIDTH = 152; + public static final int kDefaultHorizontalPadding = 0; + public static final int kDefaultVerticalPadding = 15; + public static final int kAlignLeft = 0; + public static final int kAlignCenter = 1; + public static final int[] BORDER_LINE_STYLE_ARRAY = new int[]{ + Constants.LINE_NONE, + Constants.LINE_THIN, + Constants.LINE_MEDIUM, + Constants.LINE_THICK, + }; + + public static UITitleSplitLine createTitleSplitLine(String title) { + UITitleSplitLine splitLine = new UITitleSplitLine(title, 520); + splitLine.setPreferredSize(new Dimension(520, 20)); + return splitLine; + } + + public static UILabel createConfigLabel(String title) { + UILabel label = new UILabel(title, UILabel.RIGHT); + label.setPreferredSize(new Dimension(100, 20)); + return label; + } + + public static NewColorSelectBox createNormalColorSelectBox(ChangeListener changeListener) { + NewColorSelectBox colorSelectBox = new NewColorSelectBox(NORMAL_COMBO_WIDTH); + colorSelectBox.addSelectChangeListener(changeListener); + return colorSelectBox; + } + + public static UICheckBox createCheckBox(String text, boolean selected) { + UICheckBox uiCheckBox = new UICheckBox(text, selected); + return uiCheckBox; + } + + public static JPanel createLeftRightComponentsPane(Component... components) { + return TableLayoutHelper.createGapTableLayoutPane(new Component[][]{components}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/FontConfigPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/FontConfigPane.java new file mode 100644 index 000000000..6386e31e0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/FontConfigPane.java @@ -0,0 +1,137 @@ +package com.fr.design.mainframe.mobile.utils; + +import com.fr.base.BaseUtils; +import com.fr.base.Utils; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UIToggleButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.general.FRFont; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Vector; + +public class FontConfigPane extends JPanel { + private static final Icon[] ITALIC_ICONS = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic_white.png")}; + private static final Icon[] BOLD_ICONS = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold_white.png")}; + + private EventListenerList fontChangeListener = new EventListenerList(); + private UIComboBox fontFamily; + private UIComboBox fontSize; + private UIToggleButton bold; + private UIColorButton color; + private UIToggleButton italic; + + + public FontConfigPane() { + super(); + init(); + } + + private void init() { + this.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + fontFamily = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); + Vector integerList = new Vector<>(); + for (int i = 1; i < 100; i++) { + integerList.add(i); + } + fontFamily.setPreferredSize(new Dimension(152, 20)); + fontSize = new UIComboBox(integerList); + fontSize.setSelectedIndex(14); + color = new UIColorButton(); + bold = new UIToggleButton(BOLD_ICONS, true); + italic = new UIToggleButton(ITALIC_ICONS, true); + fontFamily.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + fireFontStateChanged(); + } + }); + fontSize.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + fireFontStateChanged(); + } + }); + bold.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + fireFontStateChanged(); + } + }); + italic.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + fireFontStateChanged(); + } + }); + color.addColorChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + fireFontStateChanged(); + } + }); + this.add(fontFamily); + this.add(fontSize); + this.add(color); + this.add(bold); + this.add(italic); + + } + + public void setFontColor(Color fontColor) { + color.setColor(fontColor); + } + + public FRFont updateFont(Color fontColor, Boolean isBold, Boolean isItalic) { + String family = (String) fontFamily.getSelectedItem(); + int size = (int) fontSize.getSelectedItem(); + int style = Font.PLAIN; + boolean bold = (isBold == null) ? this.bold.isSelected() : isBold; + boolean italic = (isItalic == null) ? this.italic.isSelected() : isItalic; + style += bold ? Font.BOLD : Font.PLAIN; + style += italic ? Font.ITALIC : Font.PLAIN; + FRFont frFont = FRFont.getInstance(family, style, size, fontColor == null ? color.getColor() : fontColor); + return frFont; + } + + public FRFont update() { + String family = (String) fontFamily.getSelectedItem(); + int size = (int) fontSize.getSelectedItem(); + int style = Font.PLAIN; + style += this.bold.isSelected() ? Font.BOLD : Font.PLAIN; + style += this.italic.isSelected() ? Font.ITALIC : Font.PLAIN; + return FRFont.getInstance(family, style, size, color.getColor()); + } + + public void populate(FRFont frFont) { + fontFamily.setSelectedItem(frFont.getFamily()); + fontSize.setSelectedItem(frFont.getSize()); + color.setColor(frFont.getForeground()); + bold.setSelected(frFont.isBold()); + italic.setSelected(frFont.isItalic()); + + } + + /** + * 颜色状态改变 + */ + public void fireFontStateChanged() { + Object[] listeners = fontChangeListener.getListenerList(); + ChangeEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + if (e == null) { + e = new ChangeEvent(this); + } + ((ChangeListener) listeners[i + 1]).stateChanged(e); + } + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/IconConfigPane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/IconConfigPane.java new file mode 100644 index 000000000..6f8e188e3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/IconConfigPane.java @@ -0,0 +1,185 @@ +package com.fr.design.mainframe.mobile.utils; + +import com.fr.base.IconManager; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.DrawRoutines; +import com.fr.design.web.CustomIconPane; +import com.fr.form.ui.WidgetInfoConfig; +import com.fr.general.FRFont; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.basic.BasicButtonUI; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class IconConfigPane extends JPanel { + private UIButton editIconButton; + private UIButton deleteIconButton; + private IconButton iconButton; + + public IconConfigPane() { + initComp(); + } + + public void initComp() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel panel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0)); + editIconButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Edit")); + editIconButton.setFont(FRFont.getInstance("Helvetica", Font.PLAIN, 12, Color.decode("#3A383A"))); + editIconButton.setPreferredSize(new Dimension(62, 20)); + panel.add(editIconButton); + editIconButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final CustomIconPane cip = new CustomIconPane(){ + protected String createDescriptionText(){ + return Toolkit.i18nText("Fine-Design_Mobile_Custom_Icon_Message"); + } + }; + BasicDialog editDialog = cip.showWindow(new JFrame()); + editDialog.addDialogActionListener(new DialogActionAdapter() { + @Override + public void doOk() { + IconConfigPane.this.iconButton.setIconName(cip.update()); + IconConfigPane.this.deleteIconButton.setEnabled(true); + IconConfigPane.this.repaint(); + } + }); + editDialog.setVisible(true); + } + }); + editIconButton.setEnabled(true); + + deleteIconButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Delete")); + deleteIconButton.setFont(FRFont.getInstance("Helvetica", Font.PLAIN, 12, Color.decode("#3A383A"))); + deleteIconButton.setPreferredSize(new Dimension(62, 20)); + panel.add(deleteIconButton); + deleteIconButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + IconConfigPane.this.iconButton.setIconName(StringUtils.EMPTY); + IconConfigPane.this.deleteIconButton.setEnabled(false); + IconConfigPane.this.repaint(); + } + }); + deleteIconButton.setEnabled(false); + + + this.add(panel, BorderLayout.CENTER); + + JPanel westPane = new JPanel(); + iconButton = new IconButton(""); + westPane.add(iconButton); + this.add(westPane, BorderLayout.WEST); + } + + public void populate(String iconName) { + if(StringUtils.isNotEmpty(iconName)) { + deleteIconButton.setEnabled(true); + } else { + deleteIconButton.setEnabled(false); + } + iconButton.setIconName(iconName); + } + + public String update() { + return iconButton.getIconName(); + } + + + private class IconButton extends JToggleButton implements ActionListener { + private String iconName; + private Image iconImage = null; + private static final int ICON_BUTTON_SIZE = 20; + private static final int ICON_X = 2; + private static final int ICON_Y = 2; + + public IconButton(String name) { + this.iconName = name; + this.addActionListener(this); + this.setBackground(Color.WHITE); + this.setCursor(new Cursor(Cursor.HAND_CURSOR)); + this.iconImage = WidgetInfoConfig.getInstance().getIconManager().getIconImage(name); + } + + @Override + public void updateUI() { + setUI(new BasicButtonUI() { + public void paint(Graphics g, JComponent c) { + super.paint(g, c); + } + }); + } + + protected void paintBorder(Graphics g) { + super.paintBorder(g); + if (StringUtils.isNotEmpty(iconButton.getIconName())) { + DrawRoutines.drawRoundedBorder( + g, Color.decode("#419BF9"), 0, 0, 20, 20); + } else { + DrawRoutines.drawRoundedBorder( + g, Color.decode("#D9DADD"), 0, 0, 20, 20); + } + + } + + public String getIconName() { + return iconName; + } + + public void setIconName(String iconName) { + this.iconName = iconName; + this.iconImage = WidgetInfoConfig.getInstance().getIconManager().getIconImage(iconName); + this.repaint(); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2d = (Graphics2D) g; + // carl:这里缩放显示 16 × 16 + if (iconImage != null) { + g2d.drawImage(iconImage, ICON_X, ICON_Y, IconManager.DEFAULT_ICONWIDTH, IconManager.DEFAULT_ICONHEIGHT, null); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(ICON_BUTTON_SIZE, ICON_BUTTON_SIZE); + } + + public void actionPerformed(ActionEvent evt) { + IconConfigPane.this.repaint();// repaint + } + + @Override + public void addChangeListener(ChangeListener changeListener) { + this.changeListener = changeListener; + } + + private void fireChagneListener() { + if (this.changeListener != null) { + ChangeEvent evt = new ChangeEvent(this); + this.changeListener.stateChanged(evt); + } + } + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/MobileStyleProviderManager.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/MobileStyleProviderManager.java new file mode 100644 index 000000000..7c3194ba6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/utils/MobileStyleProviderManager.java @@ -0,0 +1,41 @@ +package com.fr.design.mainframe.mobile.utils; + +import com.fr.design.mainframe.mobile.provider.combo.SimpleComboCheckBoxStyleProvider; +import com.fr.design.mainframe.mobile.provider.combo.SimpleComboStyleProvider; +import com.fr.design.mainframe.mobile.provider.date.NavigationStyleProvider; +import com.fr.design.mainframe.mobile.provider.date.SimpleDateStyleProvider; +import com.fr.design.mainframe.mobile.provider.date.SimpleStyleProvider; +import com.fr.design.mainframe.mobile.provider.radiogroup.CapsuleRadioGroupStyleProvider; +import com.fr.design.mainframe.mobile.provider.radiogroup.ImageRadioGroupStyleProvider; +import com.fr.design.mainframe.mobile.provider.radiogroup.UnitedRadioGroupStyleProvider; +import com.fr.design.mainframe.mobile.provider.topparam.MobileTopParamStyleProvider; +import com.fr.stable.fun.mark.Mutable; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class MobileStyleProviderManager { + private static Set mobileWidgetStyleProviderSet = new HashSet() {{ + add(new SimpleStyleProvider()); + add(new NavigationStyleProvider()); + add(new SimpleDateStyleProvider()); + add(new SimpleComboStyleProvider()); + add(new SimpleComboCheckBoxStyleProvider()); + add(new CapsuleRadioGroupStyleProvider()); + add(new UnitedRadioGroupStyleProvider()); + add(new ImageRadioGroupStyleProvider()); + }}; + private static Set mobileParamUIProviderSet = new HashSet() {{ + add(new MobileTopParamStyleProvider()); + }}; + private static Map> map = new HashMap>() {{ + put("MobileWidgetStyleProvider", mobileWidgetStyleProviderSet); + put("MobileParamUIProvider", mobileParamUIProviderSet); + }}; + + public static Set getArray(String mark) { + return (Set) map.get(mark); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ColorFillStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ColorFillStylePane.java index 9e2a0d5ef..823dd6ff3 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ColorFillStylePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/ColorFillStylePane.java @@ -15,7 +15,7 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.style.background.gradient.FixedGradientBar; +import com.fr.design.style.background.gradient.FixedGradientBarNoTheme; import com.fr.design.style.color.ColorAdjustPane; import com.fr.stable.StringUtils; @@ -40,7 +40,7 @@ public class ColorFillStylePane extends BasicBeanPane { private ColorSchemeComboBox styleSelectBox; private JPanel customPane; private JPanel changeColorSetPane; - private FixedGradientBar colorGradient; + private FixedGradientBarNoTheme colorGradient; private CardLayout cardLayout; @@ -69,8 +69,8 @@ public class ColorFillStylePane extends BasicBeanPane { }; changeColorSetPane = new JPanel(cardLayout = new CardLayout()); - changeColorSetPane.add(colorGradient = new FixedGradientBar(4, 130), "gradient"); - gradientColors = new Color[]{Color.WHITE, FixedGradientBar.NEW_CHARACTER}; + changeColorSetPane.add(colorGradient = new FixedGradientBarNoTheme(4, 130), "gradient"); + gradientColors = new Color[]{Color.WHITE, FixedGradientBarNoTheme.NEW_CHARACTER}; changeColorSetPane.add(colorAdjustPane = new ColorAdjustPane(), "acc"); accColors = ColorAdjustPane.DEFAULT_COLORS; cardLayout.show(changeColorSetPane, "acc"); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/ColorDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/ColorDetailPane.java index b7034fd66..43d20d1bd 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/ColorDetailPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/detail/background/ColorDetailPane.java @@ -3,20 +3,10 @@ package com.fr.design.mainframe.predefined.ui.detail.background; import com.fr.base.background.ColorBackground; import com.fr.design.event.UIObserver; import com.fr.design.event.UIObserverListener; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayoutHelper; -import com.fr.design.style.color.ColorSelectPane; +import com.fr.design.style.color.NewColorSelectPane; import com.fr.general.Background; - -import javax.swing.BorderFactory; -import javax.swing.JPanel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; /** * Created by kerry on 2020-08-31 @@ -50,48 +40,9 @@ public class ColorDetailPane extends AbstractBackgroundDetailPane chartPreStyleProviders = vanChart.getChartPreStyleProvider(); - for (ChartPreStyleProvider chartPreStyleProvider : chartPreStyleProviders) { - chartPreStyleProvider.updatePreDefinedStyle(style); + /*VanChart vanChart = chartCollection.getSelectedChartProvider(VanChart.class); + List chartThemeStyleProviders = vanChart.getChartPreStyleProvider(); + for (ChartThemeStyleProvider chartThemeStyleProvider : chartThemeStyleProviders) { + chartThemeStyleProvider.updateThemeStyle(style); } componentBackground = style.getComponentStyle().getBorderStyle().getBackground(); - vanChart.attrChange(); + vanChart.attrChange();*/ } @Override diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/AsyncThemeFetcher.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/AsyncThemeFetcher.java new file mode 100644 index 000000000..3df87ac65 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/AsyncThemeFetcher.java @@ -0,0 +1,81 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.concurrent.NamedThreadFactory; +import com.fr.module.ModuleContext; + +import javax.swing.SwingUtilities; +import java.util.concurrent.ExecutorService; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/24 + */ +public class AsyncThemeFetcher { + + private final ExecutorService executorService; + private final TemplateThemeConfig config; + + public AsyncThemeFetcher(int threads, TemplateThemeConfig config) { + this.executorService = ModuleContext.getExecutor().newFixedThreadPool( + threads, + new NamedThreadFactory(this.getClass().getName()) + ); + this.config = config; + } + + public void shutdown() { + executorService.shutdown(); + } + + public boolean isShutdown() { + return executorService.isShutdown(); + } + + public void submit(String themeName, AsyncThemeFetchCallback callback) { + if (callback != null) { + callback.beforeCachedFetch(); + } + executorService.submit(new Runnable() { + @Override + public void run() { + if (executorService.isShutdown()) { + return; + } + T theme = config.cachedFetch(themeName); + if (executorService.isShutdown()) { + return; + } + if (callback != null) { + // 后续任务不要在工作线程中执行,从而确保只在EDT线程操作UI + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + callback.afterCachedFetch(theme); + } + }); + } + } + }); + } + + public interface AsyncThemeFetchCallback { + void beforeCachedFetch(); + void afterCachedFetch(T theme); + } + + public static class AsyncThemeFetchCallbackAdapter implements AsyncThemeFetchCallback { + + @Override + public void beforeCachedFetch() { + + } + + @Override + public void afterCachedFetch(T theme) { + + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java new file mode 100644 index 000000000..f34f8a27f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/FormThemeProfilePane.java @@ -0,0 +1,81 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.theme.settings.ThemedComponentStyle; +import com.fr.base.theme.settings.ThemedFormBodyStyle; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.edit.ChartStyleFormEditPane; +import com.fr.design.mainframe.theme.edit.ComponentStyleEditPane; +import com.fr.design.mainframe.theme.edit.FormBodyStyleEditPane; +import com.fr.design.mainframe.theme.preview.FormThemePreviewPane; + +import javax.swing.JPanel; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class FormThemeProfilePane extends TemplateThemeProfilePane { + public static final int LABEL_WIDTH = 60; + + private FormBodyStyleEditPane formBodyStyleSettingPane; + private ComponentStyleEditPane componentStyleSettingPane; + + public FormThemeProfilePane(TemplateThemeConfig config) { + super(config); + } + + @Override + public FormThemePreviewPane createThemePreviewPane() { + return new FormThemePreviewPane(); + } + + @Override + protected JPanel createCustomEditorsPane() { + JPanel container = super.createCustomEditorsPane(); + formBodyStyleSettingPane = new FormBodyStyleEditPane(); + addCustomEditorPane(i18nText("Fine-Design_Predefined_Template_Background"), formBodyStyleSettingPane); + + addCustomEditorPane(i18nText("Fine-Design_Predefined_Cell_Style"), createCellStyleSettingPane()); + addCustomEditorPane(i18nText("Fine-Design_Predefined_Chart_Style"), createChartStyleSettingPane()); + + + componentStyleSettingPane = new ComponentStyleEditPane(); + addCustomEditorPane(i18nText("Fine-Design_Predefined_Component_Style"), componentStyleSettingPane); + return container; + } + + @Override + protected JPanel createChartStyleSettingPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + chartStyleSettingPane = new ChartStyleFormEditPane(); + container.add(chartStyleSettingPane); + return container; + } + + @Override + public void populateBean4CustomEditors(FormTheme theme) { + super.populateBean4CustomEditors(theme); + formBodyStyleSettingPane.populateBean(theme.getBodyStyle()); + componentStyleSettingPane.populateBean(theme.getComponentStyle()); + } + + @Override + public void updateBean(FormTheme theme) { + ThemedFormBodyStyle formBodyStyle = formBodyStyleSettingPane.updateBean(); + theme.setBodyStyle(formBodyStyle); + + ThemedComponentStyle componentStyle = componentStyleSettingPane.updateBean(); + theme.setComponentStyle(componentStyle); + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Form_Theme_Profile_Dialog_Title"); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java new file mode 100644 index 000000000..1158a8eb5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ReportThemeProfilePane.java @@ -0,0 +1,52 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.theme.edit.ReportBodyStyleEditPane; +import com.fr.design.mainframe.theme.preview.ReportThemePreviewPane; +import javax.swing.JPanel; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ReportThemeProfilePane extends TemplateThemeProfilePane { + private ReportBodyStyleEditPane reportBodyStyleSettingPane; + + public ReportThemeProfilePane(TemplateThemeConfig config) { + super(config); + } + + @Override + public ReportThemePreviewPane createThemePreviewPane() { + return new ReportThemePreviewPane(); + } + + @Override + protected JPanel createCustomEditorsPane() { + JPanel container = super.createCustomEditorsPane(); + this.reportBodyStyleSettingPane = new ReportBodyStyleEditPane(); + addCustomEditorPane(Toolkit.i18nText("Fine-Design_Predefined_Template_Background"), reportBodyStyleSettingPane); + addCustomEditorPane(Toolkit.i18nText("Fine-Design_Predefined_Cell_Style"), createCellStyleSettingPane()); + addCustomEditorPane(Toolkit.i18nText("Fine-Design_Predefined_Chart_Style"), createChartStyleSettingPane()); + return container; + } + + @Override + public void populateBean4CustomEditors(ReportTheme theme) { + super.populateBean4CustomEditors(theme); + reportBodyStyleSettingPane.populateBean(theme.getBodyStyle()); + } + + @Override + public void updateBean(ReportTheme theme) { + theme.setBodyStyle(this.reportBodyStyleSettingPane.updateBean()); + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Report_Theme_Profile_Dialog_Title"); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java new file mode 100644 index 000000000..543df64eb --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeBlock.java @@ -0,0 +1,263 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.GraphHelper; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.theme.settings.ThemeThumbnail; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog; +import com.fr.general.IOUtils; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeBlock extends JPanel { + public static final int INFO_HEIGHT = 30; + public static final int CONTENT_WIDTH = ThemeThumbnail.WIDTH; + public static final int CONTENT_HEIGHT = ThemeThumbnail.HEIGHT + INFO_HEIGHT; + private static final Color HOVERING_BORDER_COLOR = new Color(65, 155, 249); + + private final String name; + private final TemplateThemeConfig config; + private T theme; + private final TemplateThemeProfilePane profilePane; + private final Icon theme4currentTemplateMarkIcon = IOUtils.readIcon("/com/fr/design/form/images/theme4currentTemplate.png"); + private final Icon theme4NewTemplateMarkIcon= IOUtils.readIcon("/com/fr/design/form/images/theme4newTemplate.png"); + private final Icon profileIcon = IOUtils.readIcon("/com/fr/design/icon/icon_edit.png"); + private final boolean displayTheme4NewTemplateMarker; + + private final ThumbnailPane thumbnailPane; + // UIButton会影响Block的手势监听,这里使用UILabel代替,点击事件也有Block代为处理 + private UILabel profileButton; + private boolean selected = false; + private boolean hovering = false; + + private MouseAdapter clickListener; + + public TemplateThemeBlock(String name, + boolean displayTheme4NewTemplateMarker, + TemplateThemeConfig config, + TemplateThemeProfilePane profilePane) { + this.name = name; + this.displayTheme4NewTemplateMarker = displayTheme4NewTemplateMarker; + this.config = config; + this.profilePane = profilePane; + this.thumbnailPane = new ThumbnailPane(); + + initializePane(); + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (clickListener != null) { + clickListener.mouseClicked(e); + } + + if (profileButton != null && profilePane != null) { + delegateProfileButtonClick(e); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + hovering = true; + repaint(); + } + + @Override + public void mouseExited(MouseEvent e) { + hovering = false; + repaint(); + } + }); + } + + private void initializePane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT)); + setBackground(Color.WHITE); + + thumbnailPane.setBackground(Color.WHITE); + thumbnailPane.setPreferredSize(new Dimension(ThemeThumbnail.WIDTH, ThemeThumbnail.HEIGHT)); + + JPanel infoPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + infoPane.setPreferredSize(new Dimension(CONTENT_WIDTH, INFO_HEIGHT)); + infoPane.setBackground(Color.WHITE); + infoPane.setBorder(BorderFactory.createEmptyBorder(0, IntervalConstants.INTERVAL_L7,0,IntervalConstants.INTERVAL_L7)); + + UILabel titleLabel = new UILabel(name); + titleLabel.setToolTipText(name); + infoPane.add(titleLabel, BorderLayout.CENTER); + + if (profilePane != null) { + addProfileButton(infoPane); + } + + add(thumbnailPane, BorderLayout.CENTER); + add(infoPane, BorderLayout.SOUTH); + } + + public void setTheme(T theme) { + this.theme = theme; + Image image = null; + if (theme != null) { + ThemeThumbnail thumbnail = theme.getThumbnail(); + if (thumbnail != null) { + image = thumbnail.getImage(); + } + } + thumbnailPane.setThumbnail(image); + invalidate(); + repaint(); + } + + public T getTheme() { + return this.theme; + } + + public void setSelected(boolean selected) { + this.selected = selected; + repaint(); + } + + public void addClickListener(MouseAdapter clickListener) { + this.clickListener = clickListener; + } + + private void addProfileButton(JPanel panel) { + profileButton = new UILabel(profileIcon); + profileButton.setPreferredSize(new Dimension(24, 24)); + panel.add(profileButton, BorderLayout.EAST); + } + + private void delegateProfileButtonClick(MouseEvent e) { + int x = e.getX(); + int y = e.getY(); + + int profileButtonX = profileButton.getX(); + int profileButtonY = thumbnailPane.getHeight() + profileButton.getY(); + + boolean inX = profileButtonX <= x && x <= profileButtonX + profileButton.getWidth(); + boolean inY = profileButtonY <= y && y <= profileButtonY + profileButton.getHeight(); + if (inX && inY) { + openProfileDialog(); + } + } + + private void openProfileDialog() { + if (theme == null) { + return; + } + Window parent = SwingUtilities.getWindowAncestor(TemplateThemeBlock.this); + TemplateThemeProfileDialog profileDialog = new TemplateThemeProfileDialog<>(parent, profilePane); + try { + profilePane.populateBean((T) theme.clone()); + } catch (CloneNotSupportedException ex) { + ex.printStackTrace(); + } + profileDialog.setVisible(true); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateThemeConfig templateUsingConfig = template.getUsingTemplateThemeConfig(); + TemplateTheme templateTheme = template.getTemplateTheme(); + if (templateUsingConfig == this.config && StringUtils.equals(templateTheme.getName(), name)) { + theme4currentTemplateMarkIcon.paintIcon(this, g, getWidth() - 25, 0); + } + } + + if (displayTheme4NewTemplateMarker && StringUtils.equals(config.getThemeName4NewTemplate(), name)) { + theme4NewTemplateMarkIcon.paintIcon(this, g, 0, thumbnailPane.getHeight() - 16); + } + + if (selected || this.hovering) { + g.setColor(HOVERING_BORDER_COLOR); + Rectangle rectangle = new Rectangle(1, 1, this.getWidth() - 2, this.getHeight() - 2); + GraphHelper.draw(g, rectangle, Constants.LINE_MEDIUM); + } + } + + private static class ThumbnailPane extends JPanel { + private static final Image LOADING_IMAGE = Toolkit.getDefaultToolkit().createImage(ThumbnailPane.class.getResource("/com/fr/design/images/mainframe/loading.gif")); + private Image thumbnail = null; + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + Color oldColor = g2d.getColor(); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.setColor(oldColor); + + paintCenterImage(g2d, thumbnail != null ? thumbnail : LOADING_IMAGE); + } + + private void paintCenterImage(Graphics2D g2d, Image image) { + if (image == null) { + return; + } + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + int width = getWidth(); + int height = getHeight(); + int imgWidth = image.getWidth(null); + int imgHeight = image.getHeight(null); + + if (width <= 0 || height <= 0 || imgWidth <= 0 || imgHeight <= 0) { + return; + } + + float imgAspect = 1.0F * imgWidth / imgHeight; + + if (1.0F * width / height > 1.0F * imgWidth / imgHeight) { + imgHeight = height; + imgWidth = (int) (1.0F * imgHeight * imgAspect); + } else { + imgWidth = width; + imgHeight = (int) (1.0F * imgWidth / imgAspect); + } + int x = (width - imgWidth) / 2; + int y = (height - imgHeight) / 2; + + g2d.drawImage(image, x, y, imgWidth, imgHeight, null); + } + + public void setThumbnail(Image thumbnail) { + this.thumbnail = thumbnail; + invalidate(); + repaint(); + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeListPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeListPane.java new file mode 100644 index 000000000..fca01386c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeListPane.java @@ -0,0 +1,250 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.theme.settings.ThemeThumbnail; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.event.ChangeEvent; +import com.fr.design.event.ChangeListener; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeListPane extends BasicPane { + public static final int BLOCK_COUNT_ROW_LINE = 3; + public static final int BLOCK_GAP = IntervalConstants.INTERVAL_L1; + public static final int CONTENT_WIDTH = TemplateThemeBlock.CONTENT_WIDTH * BLOCK_COUNT_ROW_LINE + BLOCK_GAP * (BLOCK_COUNT_ROW_LINE - 1) + 10; + public static final int BLOCK_ROWS_PER_PAGE = 3; + public static final int CONTENT_HEIGHT = TemplateThemeBlock.CONTENT_HEIGHT * BLOCK_ROWS_PER_PAGE + BLOCK_GAP * (BLOCK_ROWS_PER_PAGE + 1); + public static final int ASYNC_FETCH_THEME_THREAD_COUNT = 10; + + private final AsyncThemeFetcher asyncThemeFetcher; + + private final boolean displayTheme4NewTemplateMarker; + protected final TemplateThemeConfig config; + private final TemplateThemeProfilePane profilePane; + private final JPanel contentListPane; + + private final Map> blockCache = new HashMap<>(); + + private TemplateThemeBlock selectedBlock; + private TemplateThemeBlock block4newTemplate; + + private TemplateThemeConfig.ThemeConfigChangeListener themeConfigChangeListener; + + private ChangeListener changeListener; + + public TemplateThemeListPane(boolean displayTheme4NewTemplateMarker, TemplateThemeConfig config, TemplateThemeProfilePane profilePane) { + this.displayTheme4NewTemplateMarker = displayTheme4NewTemplateMarker; + this.config = config; + this.profilePane = profilePane; + this.contentListPane = new JPanel(); + this.asyncThemeFetcher = new AsyncThemeFetcher<>(ASYNC_FETCH_THEME_THREAD_COUNT, config); + initializePane(); + } + + private void initializePane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT)); + + contentListPane.setBorder(BorderFactory.createEmptyBorder(BLOCK_GAP, 0, BLOCK_GAP, 0)); + contentListPane.setLayout(new GridLayout(0, BLOCK_COUNT_ROW_LINE, BLOCK_GAP, BLOCK_GAP)); + fillContentListPane(); + + JPanel wrapper = FRGUIPaneFactory.createBorderLayout_S_Pane(); + wrapper.add(contentListPane, BorderLayout.NORTH); + + UIScrollPane scrollPane = new UIScrollPane(wrapper); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + add(scrollPane, BorderLayout.CENTER); + + } + + public void fillContentListPane() { + contentListPane.removeAll(); + List names = config.getThemeNames(); + for (String name: names) { + if (config.contains(name)) { + TemplateThemeBlock block = createCachedTemplateThemeBlock(name); + contentListPane.add(block); + if (StringUtils.equals(name, config.getThemeName4NewTemplate())) { + block4newTemplate = block; + } + } + } + } + private TemplateThemeBlock createCachedTemplateThemeBlock(String name) { + TemplateThemeBlock block = blockCache.get(name); + if (block == null) { + block = createNewTemplateThemeBlock(name); + blockCache.put(name, block); + } + return block; + } + + private TemplateThemeBlock createNewTemplateThemeBlock(String name) { + final TemplateThemeBlock block = new TemplateThemeBlock<>(name, displayTheme4NewTemplateMarker, config, profilePane); + block.addClickListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + setSelectedBlock(block); + } + }); + asyncThemeFetcher.submit(name, new AsyncThemeFetcher.AsyncThemeFetchCallbackAdapter() { + @Override + public void beforeCachedFetch() { + super.beforeCachedFetch(); + block.setTheme(null); + } + + @Override + public void afterCachedFetch(T theme) { + super.afterCachedFetch(theme); + block.setTheme(theme); + } + }); + return block; + } + + public void setSelectedChangeListener(ChangeListener changeListener) { + this.changeListener = changeListener; + } + + private void setSelectedBlock(TemplateThemeBlock block) { + if (selectedBlock != block) { + if (selectedBlock != null) { + selectedBlock.setSelected(false); + } + selectedBlock = block; + if (selectedBlock != null) { + selectedBlock.setSelected(true); + } + if (changeListener != null) { + changeListener.fireChanged(new ChangeEvent(this)); + } + } + } + + private void asyncFetchTheme(String themeName) { + asyncThemeFetcher.submit(themeName, new AsyncThemeListItemFetchCallback(themeName)); + } + + @Override + protected String title4PopupWindow() { + return null; + } + + public T getSelectedTheme() { + return selectedBlock != null ? selectedBlock.getTheme() : null; + } + + public void startListenThemeConfig() { + if (themeConfigChangeListener == null) { + themeConfigChangeListener = new TemplateThemeConfig.ThemeConfigChangeListener() { + @Override + public void onThemeConfigChanged(TemplateThemeConfig.ThemeConfigEvent event) { + String themeName = event.themName; + TemplateThemeBlock existingBlock = blockCache.get(event.themName); + switch (event.action) { + case DEFAULT_THEME_4_NEW_TEMPLATE_UPDATE: { + if (block4newTemplate != null) { + block4newTemplate.repaint(); + } + if (existingBlock != null) { + existingBlock.repaint(); + } + block4newTemplate = existingBlock; + break; + } + case UPDATE: { + if (existingBlock != null) { + fillContentListPane(); + asyncFetchTheme(themeName); + validate(); + repaint(); + } + break; + } + case REMOVE: { + if (existingBlock != null) { + contentListPane.remove(existingBlock); + if (existingBlock == selectedBlock) { + setSelectedBlock(null); + } + validate(); + repaint(); + blockCache.remove(event.themName); + } + break; + } + case ADD: { + if (existingBlock == null) { + // TODO 这里是否还能继续优化? + fillContentListPane(); + asyncFetchTheme(themeName); + validate(); + repaint(); + } + break; + } + } + } + }; + config.addThemeConfigChangeListener(themeConfigChangeListener); + } + } + + public void stopListenThemeConfig() { + if (themeConfigChangeListener != null) { + config.removeThemeConfigChangeListener(themeConfigChangeListener); + themeConfigChangeListener = null; + } + } + + public void stopAsyncFetchTheme() { + asyncThemeFetcher.shutdown(); + } + + private class AsyncThemeListItemFetchCallback extends AsyncThemeFetcher.AsyncThemeFetchCallbackAdapter { + private final String themeName; + public AsyncThemeListItemFetchCallback(String themeName) { + this.themeName = themeName; + } + + @Override + public void beforeCachedFetch() { + super.beforeCachedFetch(); + TemplateThemeBlock block = blockCache.get(themeName); + if (block != null) { + block.setTheme(null); + } + } + + @Override + public void afterCachedFetch(T theme) { + super.afterCachedFetch(theme); + TemplateThemeBlock block = blockCache.get(themeName); + if (block != null) { + block.setTheme(theme); + } + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeManagePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeManagePane.java new file mode 100644 index 000000000..be9dec160 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeManagePane.java @@ -0,0 +1,324 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.FormThemeConfig; +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.ReportThemeConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.actions.UpdateAction; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.event.ChangeEvent; +import com.fr.design.event.ChangeListener; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.i18n.Toolkit; +import com.fr.design.icon.IconPathConstants; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog; +import com.fr.design.menu.MenuDef; +import com.fr.design.menu.ToolBarDef; +import com.fr.general.IOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.transaction.CallBackAdaptor; + +import javax.swing.BorderFactory; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.SwingUtilities; +import javax.swing.border.LineBorder; +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeManagePane extends BasicPane { + public static final int CONTENT_WIDTH = TemplateThemeListPane.CONTENT_WIDTH + 10; + public static final int CONTENT_HEIGHT = TemplateThemeListPane.CONTENT_HEIGHT + 37; + private final RemoveThemeAction removeAction; + private final UIButton setTheme4NewTemplateButton; + + private final TemplateThemeConfig config; + private final TemplateThemeListPane themeListPane; + private final TemplateThemeProfilePane profilePane; + + private final AsyncThemeFetcher asyncThemeFetcher; + + public static TemplateThemeManagePane createFormThemesManagerPane() { + FormThemeConfig config = FormThemeConfig.getInstance(); + FormThemeProfilePane editPane = new FormThemeProfilePane(config); + return new TemplateThemeManagePane<>(config, editPane); + } + + public static TemplateThemeManagePane createReportThemesManagerPane() { + ReportThemeConfig config = ReportThemeConfig.getInstance(); + ReportThemeProfilePane editPane = new ReportThemeProfilePane(config); + return new TemplateThemeManagePane<>(config, editPane); + } + + public TemplateThemeManagePane(TemplateThemeConfig config, TemplateThemeProfilePane profilePane) { + this.config = config; + this.profilePane = profilePane; + this.themeListPane = new TemplateThemeListPane<>(true, config, profilePane); + this.removeAction = new RemoveThemeAction(false); + this.setTheme4NewTemplateButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Pane_Default_Setting")); + this.asyncThemeFetcher = new AsyncThemeFetcher<>(1, config); + + initializePane(); + } + + public TemplateThemeConfig getConfig() { + return config; + } + + private void initializePane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5)); + setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT)); + + add(createActionsContainer(), BorderLayout.NORTH); + + JPanel nextContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + add(nextContainer, BorderLayout.CENTER); + + nextContainer.add(new JSeparator(), BorderLayout.NORTH); + + themeListPane.setSelectedChangeListener(new ChangeListener() { + @Override + public void fireChanged(ChangeEvent event) { + resetEnableRemoveAction(themeListPane.getSelectedTheme(), removeAction); + resetEnableSetTheme4NewTemplateButton(themeListPane.getSelectedTheme(), setTheme4NewTemplateButton); + } + }); + nextContainer.add(themeListPane, BorderLayout.CENTER); + + resetEnableRemoveAction(themeListPane.getSelectedTheme(), removeAction); + resetEnableSetTheme4NewTemplateButton(themeListPane.getSelectedTheme(), setTheme4NewTemplateButton); + + repaint(); + } + + private void resetEnableRemoveAction(T selectedTheme, RemoveThemeAction removeAction) { + if (selectedTheme == null) { + removeAction.setEnabled(false); + return; + } + String selectedThemeName = selectedTheme.getName(); + if (StringUtils.isEmpty(selectedThemeName)) { + removeAction.setEnabled(false); + return; + } + + removeAction.setEnabled(selectedTheme.isRemovable()); + } + + private void resetEnableSetTheme4NewTemplateButton(T selectedTheme, UIButton setTheme4NewTemplateButton) { + if (selectedTheme == null) { + setTheme4NewTemplateButton.setEnabled(false); + return; + } + String selectedThemeName = selectedTheme.getName(); + if (StringUtils.isEmpty(selectedThemeName)) { + setTheme4NewTemplateButton.setEnabled(false); + return; + } + + T currentTheme4NewTemplate = config.cachedFetchTheme4NewTemplate(); + if (currentTheme4NewTemplate == null) { + setTheme4NewTemplateButton.setEnabled(true); + return; + } + String currentThemeName4NewTemplate = currentTheme4NewTemplate.getName(); + if (StringUtils.isEmpty(currentThemeName4NewTemplate)) { + setTheme4NewTemplateButton.setEnabled(true); + return; + } + + setTheme4NewTemplateButton.setEnabled(!StringUtils.equals(currentThemeName4NewTemplate, selectedTheme.getName())); + } + + private JPanel createActionsContainer() { + JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane(); + content.setPreferredSize(new Dimension(content.getPreferredSize().width, 20)); + + UIToolbar toolBar = ToolBarDef.createJToolBar(); + toolBar.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + content.add(toolBar, BorderLayout.CENTER); + + MenuDef addMenuDef = createAddMenuDef(); + + ToolBarDef toolbarDef = new ToolBarDef(); + toolbarDef.addShortCut(addMenuDef, removeAction); + toolbarDef.updateToolBar(toolBar); + + setTheme4NewTemplateButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + T theme = themeListPane.getSelectedTheme(); + if (theme != null) { + config.setThemeName4NewTemplate(theme.getName(), new CallBackAdaptor() { + @Override + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeManagePane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + } + }); + } + } + }); + content.add(setTheme4NewTemplateButton, BorderLayout.EAST); + + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); + container.add(content, BorderLayout.CENTER); + + container.setPreferredSize(new Dimension(container.getPreferredSize().width, 30)); + + return container; + } + + private MenuDef createAddMenuDef() { + MenuDef menuDef = new MenuDef(Toolkit.i18nText("Fine-Design_Basic_Action_Add")); + menuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH); + menuDef.setRePaint(true); + menuDef.addShortCut(new AddThemeAction(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Pane_Create_Light_Theme"), config.getDefaultLightThemeName())); + menuDef.addShortCut(new AddThemeAction(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Pane_Create_Dark_Theme"), config.getDefaultDarkThemeName())); + + return menuDef; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Title"); + } + + private class RemoveThemeAction extends UpdateAction { + + public RemoveThemeAction(boolean initialEnabled) { + setEnabled(initialEnabled); + setName(Toolkit.i18nText("Fine-Design_Basic_Remove")); + setMnemonic('R'); + setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH)); + } + + @Override + public void actionPerformed(ActionEvent e) { + T theme = TemplateThemeManagePane.this.themeListPane.getSelectedTheme(); + if (theme == null) { + return; + } + int result = FineJOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(TemplateThemeManagePane.this), + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Pane_Delete_Tip", theme.getName()), + Toolkit.i18nText("Fine-Design_Basic_Delete"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (result == JOptionPane.YES_OPTION) { + config.removeTheme(theme.getName(), new CallBackAdaptor() { + @Override + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeManagePane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + } + }); + } + } + } + + private class AddThemeAction extends UpdateAction { + private final String prototypeThemeName; + + public AddThemeAction(String name, String prototypeThemeName) { + setName(name); + setMnemonic('R'); + this.prototypeThemeName = prototypeThemeName; + asyncThemeFetcher.submit(prototypeThemeName, null); + } + + @Override + public void actionPerformed(ActionEvent e) { + asyncThemeFetcher.submit(prototypeThemeName, new AsyncThemeFetcher.AsyncThemeFetchCallbackAdapter() { + @Override + public void afterCachedFetch(T theme) { + super.afterCachedFetch(theme); + createNewTheme(theme); + } + }); + } + + private void createNewTheme(T prototypeTheme) { + Window parent = SwingUtilities.getWindowAncestor(TemplateThemeManagePane.this); + TemplateThemeProfileDialog profileDialog = new TemplateThemeProfileDialog<>(parent, profilePane); + try { + T theme = (T) prototypeTheme.clone(); + theme.setName(StringUtils.EMPTY); + theme.setMutable(true); + theme.setRemovable(true); + profilePane.populateBean(theme); + profileDialog.setVisible(true); + } catch (CloneNotSupportedException ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + } + } + + public static class BottomLineBorder extends LineBorder { + + private BottomLineBorder(Color color, int thickness) { + super(color, thickness); + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Graphics2D g2d = (Graphics2D)g; + + Color oldColor = g2d.getColor(); + Stroke oldStroke = g2d.getStroke(); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setColor(getLineColor()); + g2d.setStroke(new BasicStroke(getThickness() * 2)); + g2d.drawLine(0, height, width, height + getThickness() * 2); + + g2d.setStroke(oldStroke); + g2d.setColor(oldColor); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + } + + public void startListenThemeConfig() { + themeListPane.startListenThemeConfig(); + } + + public void stopListenThemeConfig() { + themeListPane.stopListenThemeConfig(); + } + + public void stopAsyncFetchTheme() { + asyncThemeFetcher.shutdown(); + themeListPane.stopAsyncFetchTheme(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemePreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemePreviewPane.java new file mode 100644 index 000000000..19885763c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemePreviewPane.java @@ -0,0 +1,87 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.chart.chartdata.CallbackEvent; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemeThumbnail; +import com.fr.design.mainframe.theme.preview.ThemePreviewed; +import com.fr.log.FineLoggerFactory; + +import javax.swing.JPanel; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.Transparency; +import java.awt.image.BufferedImage; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public abstract class TemplateThemePreviewPane extends JPanel implements CallbackEvent, ThemePreviewed { + private JPanel parent; + public static final int PREVIEW_WIDTH = 627; + public static final int PREVIEW_HEIGHT = 532; + + public void setParent(JPanel parent) { + this.parent = parent; + } + + @Override + public void callback() { + if (parent != null) { + parent.repaint(); + } else { + this.repaint(); + } + } + + protected Image createThumbnailImage() { + BufferedImage image = null; + + int thumbnailWidth = ThemeThumbnail.WIDTH; + int thumbnailHeight = ThemeThumbnail.HEIGHT; + + int width = getWidth(); + int height = getHeight(); + + try { + // 使用TYPE_INT_RGB和new Color(255, 255, 255, 1)设置有透明背景buffer image, + // 使得创建出来的透明像素是(255, 255, 255, 1),而不是(0, 0, 0, 0) + // 这样不支持透明通道缩略图的旧设计器打开新设计器创建的模版时,就不会创建出拥有黑色背景的缩略图 + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = image.createGraphics(); + // 创建一个支持透明背景的buffer image + image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT); + g2d.dispose(); + g2d = image.createGraphics(); + + g2d.fillRect(0, 0, width, height); + + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.clipRect(0, 0, width, height); + + paint(g2d); + + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + if (image != null) { + return image.getScaledInstance(thumbnailWidth, thumbnailHeight, BufferedImage.SCALE_SMOOTH); + } + + return null; + } + + @Override + public void paintComponent(Graphics g) { + g.clearRect(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT); + paintBackground((Graphics2D) g); + } + + protected abstract void paintBackground(Graphics2D g); +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java new file mode 100644 index 000000000..9544b2563 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/TemplateThemeProfilePane.java @@ -0,0 +1,629 @@ +package com.fr.design.mainframe.theme; + +import com.fr.base.theme.FineColorFlushUtils; +import com.fr.base.theme.FineColorManager; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.theme.settings.ThemeThumbnail; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.base.theme.settings.ThemedColorScheme; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; +import com.fr.design.gui.frpane.AttributeChangeListener; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog; +import com.fr.design.mainframe.theme.edit.CellStyleListEditPane; +import com.fr.design.mainframe.theme.edit.ChartStyleEditPane; +import com.fr.design.mainframe.theme.edit.ui.ColorListExtendedPane; +import com.fr.design.mainframe.theme.edit.ui.ColorListPane; +import com.fr.design.mainframe.theme.edit.ui.LabelUtils; +import com.fr.design.mainframe.theme.ui.BorderUtils; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.Inter; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.transaction.CallBackAdaptor; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.List; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public abstract class TemplateThemeProfilePane extends AbstractAttrNoScrollPane { + public static final int TITLE_BORDER_FONT = 12; + public static final int LEFT_TITLE_PANE_WIDTH = 627; + public static final int LEFT_TITLE_PANE_HEIGHT = 539; + public static final int PREVIEW_PANE_WIDTH = LEFT_TITLE_PANE_WIDTH - 10; + public static final int PREVIEW_PANE_HEIGHT = LEFT_TITLE_PANE_HEIGHT - TITLE_BORDER_FONT - 16; + + public static final int RIGHT_PANE_WIDTH = 362; + public static final int RIGHT_PANE_HEIGHT = LEFT_TITLE_PANE_HEIGHT; + public static final int COLOR_SCHEME_TITLE_PANE_WIDTH = 298; + public static final int COLOR_SCHEME_TITLE_PANE_HEIGHT = 174 + TITLE_BORDER_FONT / 2; + + protected TemplateThemePreviewPane themePreviewPane; + + protected UITextField nameTextField; + private UILabel nameErrorLabel; + protected ColorListPane colorListPane; + private ColorListExtendedPane colorListExtendedPane; + protected CellStyleListEditPane cellStyleSettingPane; + protected ChartStyleEditPane chartStyleSettingPane; + + protected boolean isPopulating = false; + protected UITabbedPane uiTabbedPane; + + private final TemplateThemeConfig config; + + private UIButton saveButton = new UIButton(); + private UIButton saveAsButton = new UIButton(); + + private boolean refreshingThemedColor = false; + + private boolean currentIsNewTheme; + private T theme; + + public TemplateThemeProfilePane(TemplateThemeConfig config) { + this.config = config; + theme = config.createNewTheme(); + } + @Override + protected JPanel createContentPane() { + JPanel container = new JPanel(new BorderLayout(5, 0)); + container.add(createLeftPane(), BorderLayout.CENTER); + container.add(createRightPane(), BorderLayout.EAST); + addAttributeChangeListener(new AttributeChangeListener() { + @Override + public void attributeChange() { + if (!isPopulating) { + valueChangeAction(); + } + } + }); + return container; + } + + @Override + protected void initContentPane() { + super.initContentPane(); + if (leftContentPane != null) { + // 修正 AbstractAttrNoScrollPane 的默认行为 + leftContentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 6)); + } + } + + public void valueChangeAction() { + themePreviewPane.refresh(updateBean()); + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Dialog_Title"); + } + + private JPanel createLeftPane() { + JPanel titleContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + titleContainer.setPreferredSize(new Dimension(LEFT_TITLE_PANE_WIDTH, LEFT_TITLE_PANE_HEIGHT)); + titleContainer.setBorder(BorderUtils.createTitleBorder(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Preview_Pane_Title"), TITLE_BORDER_FONT)); + + JPanel previewContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + previewContainer.setBorder(BorderFactory.createEmptyBorder(5, 4, 10, 4)); + titleContainer.add(previewContainer, BorderLayout.CENTER); + + themePreviewPane = createThemePreviewPane(); + themePreviewPane.setPreferredSize(new Dimension(PREVIEW_PANE_WIDTH, PREVIEW_PANE_HEIGHT)); + previewContainer.add(themePreviewPane, BorderLayout.CENTER); + + return titleContainer; + } + private JPanel createRightPane() { + JPanel container = new JPanel(new BorderLayout(0, 0)); + container.setPreferredSize(new Dimension(RIGHT_PANE_WIDTH, RIGHT_PANE_HEIGHT)); + JPanel nameEditPane = createNameEditPane(); + container.add(nameEditPane, BorderLayout.NORTH); + + JPanel settingPane = new JPanel(new BorderLayout(0, IntervalConstants.INTERVAL_L1)); + container.add(settingPane, BorderLayout.CENTER); + settingPane.add(createColorSchemeEditPane(), BorderLayout.NORTH); + settingPane.add(createCustomEditorsPane(), BorderLayout.CENTER); + + uiTabbedPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + valueChangeAction(); + } + }); + + return container; + } + + private JPanel createNameEditPane() { + nameErrorLabel = LabelUtils.createLabel(StringUtils.EMPTY, Color.RED); + nameErrorLabel.setVisible(false); + + nameTextField = new UITextField(); + nameTextField.setEnabled(false); + nameTextField.setPreferredSize(new Dimension(165, 20)); + nameTextField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + if (isEnabled()) { + checkThemeCanBeSavedAndUpdateUI(currentIsNewTheme, false, currentIsNewTheme, true, nameTextField, nameErrorLabel, saveButton); + } + } + + @Override + public void removeUpdate(DocumentEvent e) { + if (isEnabled()) { + checkThemeCanBeSavedAndUpdateUI(currentIsNewTheme, false, currentIsNewTheme, true, nameTextField, nameErrorLabel, saveButton); + } + } + + @Override + public void changedUpdate(DocumentEvent e) { + + } + }); + nameTextField.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + if (isEnabled()) { + checkThemeCanBeSavedAndUpdateUI(currentIsNewTheme, false, currentIsNewTheme, true, nameTextField, nameErrorLabel, saveButton); + } + } + + @Override + public void focusLost(FocusEvent e) { + if (isEnabled()) { + checkThemeCanBeSavedAndUpdateUI(currentIsNewTheme, true, currentIsNewTheme, true, nameTextField, nameErrorLabel, saveButton); + } + } + }); + + double p = TableLayout.PREFERRED; + + JPanel container = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{ + new Component[] { LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Name")), nameTextField }, + new Component[] { null, nameErrorLabel }, + }, new double[] { 20, 20}, new double[] { p, 165}, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_W0); + + container.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); + return container; + } + private JPanel createColorSchemeEditPane() { + colorListPane = new ColorListPane(); + colorListExtendedPane = new ColorListExtendedPane(); + + JPanel extendedContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + colorListExtendedPane.setBackground(null); + colorListExtendedPane.setOpaque(false); + extendedContainer.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + extendedContainer.setBackground(Color.WHITE); + extendedContainer.add(colorListExtendedPane); + + double p = TableLayout.PREFERRED; + double[] rowSize = new double[]{p, p, p}; + double[] columnSize = {p, p}; + + JPanel colorListContainerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + colorListContainerPane.add(colorListPane, BorderLayout.WEST); + + JPanel previewLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + previewLabelPane.add(LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Preview_Label")), BorderLayout.NORTH); + + UILabel tipLabel = LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Edit_Tip"), new Color(153, 153, 153)); + tipLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); + + JPanel content = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ + {LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Edit_Label")), colorListContainerPane}, + {null, tipLabel}, + {previewLabelPane, extendedContainer}, + }, + rowSize, columnSize, 18, 7); + content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + JPanel borderContainer = new JPanel(new BorderLayout()); + borderContainer.setPreferredSize(new Dimension(COLOR_SCHEME_TITLE_PANE_WIDTH, COLOR_SCHEME_TITLE_PANE_HEIGHT)); + borderContainer.setBorder(BorderUtils.createTitleBorder(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Color_Scheme_Title"))); + borderContainer.add(content); + + JPanel container = new JPanel(new BorderLayout()); + container.add(borderContainer, BorderLayout.WEST); + + colorListPane.addColorChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (refreshingThemedColor) { + return; + } + List colors = colorListPane.update(); + refreshingThemedColor = true; + onColorSchemeChanged(colors); + refreshingThemedColor = false; + } + }); + + return container; + } + protected JPanel createCustomEditorsPane() { + JPanel container = new JPanel(new BorderLayout()); + container.setBorder(BorderUtils.createTitleBorder(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Custom_Settings_Title"))); + + uiTabbedPane = new UITabbedPane(); + uiTabbedPane.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 1)); + container.add(uiTabbedPane, BorderLayout.NORTH); + + return container; + } + public void addCustomEditorPane(String title, JComponent component) { + component.setPreferredSize(new Dimension(317, 239)); + uiTabbedPane.addTab(title, component); + } + protected JPanel createCellStyleSettingPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + cellStyleSettingPane = new CellStyleListEditPane(); + cellStyleSettingPane.registerAttrChangeListener(new AttributeChangeListener() { + @Override + public void attributeChange() { + valueChangeAction(); + } + }); + container.add(cellStyleSettingPane); + return container; + } + protected JPanel createChartStyleSettingPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + chartStyleSettingPane = new ChartStyleEditPane(); + container.add(chartStyleSettingPane); + return container; + } + + public abstract TemplateThemePreviewPane createThemePreviewPane(); + + public void onColorSchemeChanged(List colors) { + colorListExtendedPane.populate(colors); + FineColorManager.FineColorReplaceByColorScheme replaceByColorScheme = new FineColorManager.FineColorReplaceByColorScheme(colors); + T theme = updateBean(); + FineColorFlushUtils.replaceCacheObject(theme, replaceByColorScheme); + FineColorManager.traverse(theme, replaceByColorScheme); + populateBean4CustomEditors(theme); + //图表渐变色 + chartStyleSettingPane.populateGradientBar(colors); + + themePreviewPane.refresh(theme); + this.repaint(); + } + + public void populateBean(T theme) { + this.theme = theme; + isPopulating = true; + + String name = theme.getName(); + + currentIsNewTheme = config.cachedFetch(name) == null; + + nameTextField.setText(name); + nameTextField.setEnabled(StringUtils.isEmpty(name)); + if (saveButton != null) { + saveButton.setEnabled(theme.isMutable() && !currentIsNewTheme); + } + if (saveAsButton != null) { + saveAsButton.setEnabled(!currentIsNewTheme); + } + + colorListPane.populate(theme.getColorScheme().getColors()); + colorListExtendedPane.populate(colorListPane.update()); + + populateBean4CustomEditors(theme); + + themePreviewPane.refresh(theme); + isPopulating = false; + } + + protected void populateBean4CustomEditors(T theme) { + cellStyleSettingPane.populateBean(theme.getCellStyleList()); + chartStyleSettingPane.populateBean(theme.getChartStyle()); + } + + public T updateBean() { + if (theme == null) { + theme = config.createNewTheme(); + } + + theme.setName(this.nameTextField.getText()); + + Image thumbnailImage = themePreviewPane.createThumbnailImage(); + if (thumbnailImage != null) { + ThemeThumbnail thumbnail = new ThemeThumbnail(); + thumbnail.setImage(thumbnailImage); + theme.setThumbnail(thumbnail); + } + + ThemedCellStyleList cellStyleConfig = this.cellStyleSettingPane.updateBean(); + theme.setCellStyleList(cellStyleConfig); + + ThemedColorScheme colorScheme = theme.getColorScheme(); + colorScheme.setColors(this.colorListPane.update()); + theme.setColorScheme(colorScheme); + + theme.setChartStyle(this.chartStyleSettingPane.updateBean()); + + updateBean(theme); + return theme; + } + + public List getCurrentColorScheme() { + return colorListPane.update(); + } + + protected abstract void updateBean(T theme); + + public UIButton createSaveButton() { + saveButton = new UIButton(); + saveButton.setText(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Save")); + saveButton.setEnabled(false); + saveButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + T theme = updateBean(); + boolean canBeSaved = checkThemeCanBeSavedAndUpdateUI(currentIsNewTheme, true, currentIsNewTheme, true, nameTextField, nameErrorLabel, saveButton); + if (canBeSaved && theme != null) { + theme.setName(nameTextField.getText()); + config.addTheme(theme, true, new CallBackAdaptor() { + @Override + public void afterCommit() { + super.afterCommit(); + currentIsNewTheme = false; + nameTextField.setEnabled(false); + saveAsButton.setEnabled(true); + } + + @Override + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeProfilePane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + } + }); + } + } + }); + return saveButton; + } + public UIButton createSaveAsButton(final TemplateThemeProfileDialog profileDialog) { + saveAsButton = new UIButton(); + saveAsButton.removeAll(); + saveAsButton.setText(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Save_As")); + saveAsButton.setEnabled(false); + saveAsButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + new SaveAsDialog(profileDialog).setVisible(true); + } + }); + return saveAsButton; + } + private class SaveAsDialog extends JDialog { + private final TemplateThemeProfileDialog parent; + + private UITextField nameTextField; + private UILabel nameErrorLabel; + private UIButton confirmButton; + + public SaveAsDialog(TemplateThemeProfileDialog dialog) { + super(dialog, ModalityType.APPLICATION_MODAL); + + setTitle(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Save_As_Dialog_Title")); + setResizable(false); + setSize(new Dimension(300, 140)); + GUICoreUtils.centerWindow(this); + + parent = dialog; + + initializeComponents(); + add(createContentPane(), BorderLayout.CENTER); + add(createActionsContainer(), BorderLayout.SOUTH); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + exit(); + } + }); + } + + private void initializeComponents() { + nameErrorLabel = LabelUtils.createLabel(StringUtils.EMPTY, Color.RED); + nameErrorLabel.setBorder(BorderFactory.createEmptyBorder(10, 20, 0, 0)); + + confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Confirm")); + confirmButton.setEnabled(false); + confirmButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + saveAsNew(nameTextField.getText()); + } + }); + + nameTextField = new UITextField(); + nameTextField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + if (isEnabled()) { + checkThemeCanBeSavedAndUpdateUI(true, false, true, true, nameTextField, nameErrorLabel, confirmButton); + } + } + + @Override + public void removeUpdate(DocumentEvent e) { + if (isEnabled()) { + checkThemeCanBeSavedAndUpdateUI(true, false, true, true, nameTextField, nameErrorLabel, confirmButton); + } + } + + @Override + public void changedUpdate(DocumentEvent e) { + + } + }); + nameTextField.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + if (isEnabled()) { + checkThemeCanBeSavedAndUpdateUI(true, false, true, true, nameTextField, nameErrorLabel, confirmButton); + } + } + + @Override + public void focusLost(FocusEvent e) { + if (isEnabled()) { + checkThemeCanBeSavedAndUpdateUI(true, true, true, true, nameTextField, nameErrorLabel, confirmButton); + } + } + }); + nameTextField.setPreferredSize(new Dimension(180, 20)); + } + + private JPanel createActionsContainer() { + + UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel")); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + exit(); + } + }); + + JPanel container = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + container.add(confirmButton); + container.add(cancelButton); + + return container; + } + + private JPanel createContentPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + JPanel nameTextPane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(20, 5); + nameTextPane.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); + nameTextPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Save_As_Pane_Name_Label"))); + nameTextPane.add(nameTextField); + + container.add(nameTextPane, BorderLayout.CENTER); + container.add(nameErrorLabel, BorderLayout.SOUTH); + + return container; + } + + private void saveAsNew(String name) { + T newThemeObject = null; + try { + newThemeObject = (T) updateBean().clone(); + } catch (CloneNotSupportedException ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + return; + } + boolean canBeSaved = checkThemeCanBeSavedAndUpdateUI(true, true, true, true, nameTextField, nameErrorLabel, confirmButton); + if (canBeSaved && newThemeObject != null) { + newThemeObject.setName(name); + newThemeObject.setRemovable(true); + newThemeObject.setMutable(true); + config.addTheme(newThemeObject, true, new CallBackAdaptor() { + @Override + public void afterCommit() { + super.afterCommit(); + exit(); + parent.exit(); + } + + @Override + public void afterRollback() { + super.afterRollback(); + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TemplateThemeProfilePane.this), + i18nText("Fine-Design_Basic_Template_Theme_Operation_Failed_Tip"), + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + } + }); + } + } + + public void exit() { + this.dispose(); + } + } + + private boolean isThemeNameEmpty(String name) { + return StringUtils.isEmpty(name); + } + private boolean isThemeNameDuplicated(String name) { + return config.cachedFetch(name) != null; + } + private boolean checkThemeCanBeSavedAndUpdateUI( + boolean checkEmpty, + boolean displayEmptyTip, + boolean checkDuplicated, + boolean displayDuplicatedTip, + UITextField textField, + UILabel errorLabel, UIButton... actionButtons) { + String name = textField.getText(); + + boolean valid = true; + errorLabel.setText(StringUtils.EMPTY); + if (checkEmpty && isThemeNameEmpty(name)) { + valid = false; + if (displayEmptyTip) { + errorLabel.setText(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Empty_Name_Error_Tip")); + } + } else if (checkDuplicated && isThemeNameDuplicated(name)) { + valid = false; + if (displayDuplicatedTip) { + errorLabel.setText(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Duplicated_Name_Error_Tip")); + } + } + + errorLabel.setVisible(!valid); + if (actionButtons != null && actionButtons.length > 0) { + for (UIButton button : actionButtons) { + if (button != null) { + button.setEnabled(valid); + } + } + } + + return valid; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeDialog.java new file mode 100644 index 000000000..ed2e22d29 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeDialog.java @@ -0,0 +1,107 @@ +package com.fr.design.mainframe.theme.dialog; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.BorderFactory; +import javax.swing.JDialog; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Window; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/16 + */ +public abstract class TemplateThemeDialog extends JDialog { + public static final int DIALOG_TITLE_HEIGHT = 28; + + public static final int DIALOG_BOTTOM_ACTION_BAR_HEIGHT = 30; + public static final int DIALOG_BOTTOM_ACTION_BUTTON_GAP = 10; + public static final int DIALOG_BOTTOM_ACTION_BUTTON_HEIGHT = 20; + + public TemplateThemeDialog(Window parent, String title, int contentWidth, int contentHeight) { + super(parent, ModalityType.APPLICATION_MODAL); + + setTitle(title); + setResizable(false); + setLayout(FRGUIPaneFactory.createBorderLayout()); + + int dialogContentHeight = contentHeight + DIALOG_BOTTOM_ACTION_BAR_HEIGHT; + int dialogWindowHeight = dialogContentHeight + DIALOG_TITLE_HEIGHT; + + setSize(new Dimension(contentWidth, dialogWindowHeight)); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + exit(); + } + }); + GUICoreUtils.centerWindow(this); + } + + protected final JPanel createDialogContentPane(JPanel contentPane, UIButton[] rightButtons) { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.add(contentPane, BorderLayout.CENTER); + container.add(createActionsContainer(rightButtons), BorderLayout.SOUTH); + return container; + } + + protected final JPanel createDialogContentPane(JPanel contentPane, UIButton[] leftButtons, UIButton[] rightButtons) { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.add(contentPane, BorderLayout.CENTER); + container.add(createActionsContainer(leftButtons, rightButtons), BorderLayout.SOUTH); + return container; + } + + + private JPanel createActionsContainer(UIButton... buttons) { + return this.createActionsContainer(FlowLayout.RIGHT, buttons); + } + + private JPanel createActionsContainer(int align, UIButton... buttons) { + JPanel container = new JPanel(new FlowLayout(align, DIALOG_BOTTOM_ACTION_BUTTON_GAP, 0)); + int paddingVertical = getPaddingVertical(); + container.setBorder(BorderFactory.createEmptyBorder(paddingVertical, 0, paddingVertical, 0)); + + if (buttons == null || buttons.length == 0) { + return container; + } + + for (UIButton button: buttons) { + if (button != null) { + button.setPreferredSize(new Dimension(button.getPreferredSize().width, DIALOG_BOTTOM_ACTION_BUTTON_HEIGHT)); + container.add(button); + } + } + + return container; + } + + protected int getPaddingVertical(){ + return (DIALOG_BOTTOM_ACTION_BAR_HEIGHT - DIALOG_BOTTOM_ACTION_BUTTON_HEIGHT) / 2; + } + + + + private JPanel createActionsContainer(UIButton[] leftButtons, UIButton[] rightButtons) { + JPanel leftPane = createActionsContainer(FlowLayout.LEFT, leftButtons); + JPanel rightPane = createActionsContainer(FlowLayout.RIGHT, rightButtons); + + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.add(leftPane, BorderLayout.WEST); + container.add(rightPane, BorderLayout.EAST); + + return container; + } + + public void exit() { + this.dispose(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeManageDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeManageDialog.java new file mode 100644 index 000000000..0049092a0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeManageDialog.java @@ -0,0 +1,137 @@ +package com.fr.design.mainframe.theme.dialog; + +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.FormThemeConfig; +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.ReportThemeConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.theme.TemplateThemeManagePane; +import com.fr.design.mainframe.theme.provider.ThemeManageActionProvider; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeManageDialog extends TemplateThemeDialog { + + private final TemplateThemeManageDialogContentPane contentPane; + + public TemplateThemeManageDialog(Window parent) { + super(parent, Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Title"), + TemplateThemeManageDialogContentPane.CONTENT_WIDTH, TemplateThemeManageDialogContentPane.CONTENT_HEIGHT); + contentPane = new TemplateThemeManageDialogContentPane(); + + setContentPane(createDialogContentPane(contentPane, createActionButtons())); + } + + @Override + public void exit(){ + contentPane.exit(); + super.exit(); + } + + private UIButton[] createActionButtons() { + List uiButtonList = new ArrayList<>(); + + Set providers = ExtraDesignClassManager.getInstance().getArray(ThemeManageActionProvider.MARK_STRING); + for (ThemeManageActionProvider provider : providers) { + uiButtonList.add(provider.createButton(new ThemeManageActionProvider.ThemeManageActionContext() { + + @Override + public TemplateThemeDialog getDialog() { + return TemplateThemeManageDialog.this; + } + + @Override + public TemplateThemeConfig getConfig() { + return contentPane.getConfig(); + } + })); + } + + uiButtonList.add(createCompleteButton()); + + return uiButtonList.toArray(new UIButton[]{}); + } + + private UIButton createCompleteButton() { + UIButton button = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Complete")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + exit(); + } + }); + return button; + } + + public static class TemplateThemeManageDialogContentPane extends JPanel { + public static final int CONTENT_WIDTH = TemplateThemeManagePane.CONTENT_WIDTH + 24; + public static final int CONTENT_HEIGHT = TemplateThemeManagePane.CONTENT_HEIGHT + 40; + + private final UITabbedPane tabbedPane; + private final TemplateThemeManagePane formThemesManagerPane; + private final TemplateThemeManagePane reportThemesManagerPane; + + public TemplateThemeManageDialogContentPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); + setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT)); + + tabbedPane = new UITabbedPane(); + add(tabbedPane, BorderLayout.NORTH); + + formThemesManagerPane = TemplateThemeManagePane.createFormThemesManagerPane(); + formThemesManagerPane.startListenThemeConfig(); + reportThemesManagerPane = TemplateThemeManagePane.createReportThemesManagerPane(); + reportThemesManagerPane.startListenThemeConfig(); + + tabbedPane.addTab(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Form_Tab"), formThemesManagerPane); + tabbedPane.addTab(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Report_Tab"), reportThemesManagerPane); + + tabbedPane.setSelectedIndex(0); + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateThemeConfig config = template.getUsingTemplateThemeConfig(); + if (config == reportThemesManagerPane.getConfig()) { + tabbedPane.setSelectedIndex(1); + } + } + } + + public TemplateThemeConfig getConfig() { + if (tabbedPane.getSelectedIndex() == 0) { + return FormThemeConfig.getInstance(); + } else { + return ReportThemeConfig.getInstance(); + } + } + + public void exit() { + formThemesManagerPane.stopListenThemeConfig(); + formThemesManagerPane.stopAsyncFetchTheme(); + reportThemesManagerPane.stopListenThemeConfig(); + reportThemesManagerPane.stopAsyncFetchTheme(); + } + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeProfileDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeProfileDialog.java new file mode 100644 index 000000000..3a6a9d383 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeProfileDialog.java @@ -0,0 +1,103 @@ +package com.fr.design.mainframe.theme.dialog; + +import com.fr.base.theme.TemplateTheme; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.TemplateThemeProfilePane; +import com.fr.design.mainframe.theme.provider.ThemeProfileActionProvider; + +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class TemplateThemeProfileDialog extends TemplateThemeDialog { + private static final int PADDING_VERTICAL = 4; + public static TemplateThemeProfilePane currentVisibleProfilePane; + + public static final int CONTENT_WIDTH = 1010; + public static final int CONTENT_HEIGHT = 542; + + public TemplateThemeProfileDialog(Window parent, TemplateThemeProfilePane profilePane) { + super(parent, profilePane.getTitle(), CONTENT_WIDTH, CONTENT_HEIGHT); + + JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane(); + content.setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT)); + content.add(profilePane, BorderLayout.CENTER); + + setContentPane(createDialogContentPane(content, createActionButtons(profilePane))); + + currentVisibleProfilePane = profilePane; + } + + @Override + public void exit() { + currentVisibleProfilePane = null; + super.exit(); + } + + public static List getEditingColorScheme() { + if (currentVisibleProfilePane != null) { + return currentVisibleProfilePane.getCurrentColorScheme(); + } + return null; + } + + public static boolean isEditingTheme() { + return currentVisibleProfilePane != null; + } + + protected int getPaddingVertical(){ + return PADDING_VERTICAL; + } + + + private UIButton[] createActionButtons(final TemplateThemeProfilePane profilePane) { + List uiButtonList = new ArrayList<>(); + + Set providers = ExtraDesignClassManager.getInstance().getArray(ThemeProfileActionProvider.MARK_STRING); + for (ThemeProfileActionProvider provider : providers) { + uiButtonList.add(provider.createButton(new ThemeProfileActionProvider.ThemeProfileActionContext() { + @Override + public TemplateThemeDialog getDialog() { + return TemplateThemeProfileDialog.this; + } + + @Override + public TemplateThemeProfilePane getProfilePane() { + return profilePane; + } + })); + } + + uiButtonList.add(profilePane.createSaveButton()); + uiButtonList.add(profilePane.createSaveAsButton(TemplateThemeProfileDialog.this)); + uiButtonList.add(createCancelButton()); + + return uiButtonList.toArray(new UIButton[]{}); + } + + private UIButton createCancelButton() { + UIButton button = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + exit(); + } + }); + return button; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java new file mode 100644 index 000000000..9c9f9220e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/dialog/TemplateThemeUsingDialog.java @@ -0,0 +1,111 @@ +package com.fr.design.mainframe.theme.dialog; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.base.theme.ThemedTemplate; +import com.fr.design.event.ChangeEvent; +import com.fr.design.event.ChangeListener; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.TemplateThemeListPane; +import com.fr.design.mainframe.theme.ui.BorderUtils; +import com.fr.workspace.WorkContext; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.border.CompoundBorder; +import java.awt.BorderLayout; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class +TemplateThemeUsingDialog extends TemplateThemeDialog { + public static final int CONTENT_WIDTH = TemplateThemeListPane.CONTENT_WIDTH + 42; + public static final int CONTENT_HEIGHT = TemplateThemeListPane.CONTENT_HEIGHT + 23; + + private final TemplateThemeListPane themeListPane; + private final ThemedTemplate currentTemplate; + + public TemplateThemeUsingDialog(Window parent, ThemedTemplate template, TemplateThemeConfig config) { + super(parent, Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Using_Dialog_Title"), CONTENT_WIDTH, CONTENT_HEIGHT); + + this.currentTemplate = template; + this.themeListPane = new TemplateThemeListPane<>(false, config, null); + + JPanel content = createContent(); + UIButton openThemeManagerButton = createOpenThemeManagerButton(); + UIButton completeButton = createCompleteButton(); + + setContentPane(createDialogContentPane(content, + new UIButton[]{ openThemeManagerButton }, + new UIButton[]{ completeButton } + )); + + themeListPane.startListenThemeConfig(); + + themeListPane.setSelectedChangeListener(new ChangeListener() { + @Override + public void fireChanged(ChangeEvent event) { + TemplateTheme theme = themeListPane.getSelectedTheme(); + if (theme != null) { + currentTemplate.setTemplateTheme(theme); + themeListPane.repaint(); + } + } + }); + } + + private JPanel createContent() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); + + JPanel themeListPaneContainer = FRGUIPaneFactory.createBorderLayout_S_Pane(); + themeListPaneContainer.setBorder(new CompoundBorder( + BorderUtils.createTitleBorder(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Using_Dialog_Select"), 12), + BorderFactory.createEmptyBorder(0, 10, 0, 10) + )); + themeListPaneContainer.add(themeListPane, BorderLayout.CENTER); + container.add(themeListPaneContainer, BorderLayout.CENTER); + + return container; + } + + private UIButton createOpenThemeManagerButton() { + if (WorkContext.getCurrent().isRoot()) { + UIButton button = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Manager_Dialog_Title")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + TemplateThemeManageDialog dialog = new TemplateThemeManageDialog(TemplateThemeUsingDialog.this); + dialog.setVisible(true); + } + }); + return button; + } + return null; + } + + private UIButton createCompleteButton() { + UIButton button = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Using_Dialog_Complete")); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + exit(); + } + }); + return button; + } + + public void exit() { + themeListPane.stopListenThemeConfig(); + themeListPane.stopAsyncFetchTheme(); + super.exit(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/CellStyleListEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/CellStyleListEditPane.java new file mode 100644 index 000000000..6b12c37d4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/CellStyleListEditPane.java @@ -0,0 +1,307 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.base.Style; +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.config.predefined.PredefinedCellStyle; +import com.fr.design.actions.UpdateAction; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.gui.NameInspector; +import com.fr.design.gui.controlpane.JListControlPane; +import com.fr.design.gui.controlpane.NameObjectCreator; +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.design.gui.controlpane.ShortCut4JControlPane; +import com.fr.design.gui.controlpane.UnrepeatedNameHelper; +import com.fr.design.gui.frpane.AttributeChangeListener; +import com.fr.design.gui.ilist.DefaultListCellEditor; +import com.fr.design.gui.ilist.JNameEdList; +import com.fr.design.gui.ilist.ListModelElement; +import com.fr.design.gui.ilist.ModNameActionListener; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.icon.IconPathConstants; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.edit.cell.CellStyleEditPane; +import com.fr.design.mainframe.theme.edit.cell.NoBorderPaneCellStyleEditPane; +import com.fr.design.menu.ShortCut; +import com.fr.general.ComparatorUtils; +import com.fr.general.IOUtils; +import com.fr.general.NameObject; +import com.fr.stable.Nameable; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * Created by kerry on 2020-09-27 + */ +public class CellStyleListEditPane extends JListControlPane { + private boolean namePermitted = true; + private AttributeChangeListener attributeChangeListener; + + public CellStyleListEditPane() { + super(); + setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5)); + addModNameActionListener(new ModNameActionListener() { + public void nameModed(int index, String oldName, String newName) { + if (ComparatorUtils.equals(oldName, newName) || ComparatorUtils.equals(newName, NameInspector.ILLEGAL_NAME_HOLDER)) { + return; + } + namePermitted = true; + String[] allNames = nameableList.getAllNames(); + allNames[index] = StringUtils.EMPTY; + if (StringUtils.isEmpty(newName)) { + showTipDialogAndReset(i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Cell_Style_Empty_Name_Tip"), index); + nameableList.setNameAt(oldName, index); + return; + } + if (isNameRepeated(new List[]{Arrays.asList(allNames)}, newName)) { + showTipDialogAndReset(i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Cell_Style_Duplicated_Name_Tip", newName), index); + nameableList.setNameAt(oldName, index); + return; + } + populateSelectedValue(); + } + }); + } + + public void registerAttrChangeListener(AttributeChangeListener listener){ + this.attributeChangeListener = listener; + } + + + private void showTipDialogAndReset(String content, int index) { + nameableList.stopEditing(); + + FineJOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(CellStyleListEditPane.this), + content, + i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE); + setIllegalIndex(index); + namePermitted = false; + } + + @Override + public NameableCreator[] createNameableCreators() { + return new NameableCreator[]{ new DefaultCellStyleNameObjectCreator(), new CellStyleNameObjectCreator() }; + } + + @Override + protected JNameEdList createJNameList() { + JNameEdList nameEdList = super.createJNameList(); + nameEdList.setCellEditor(new DefaultListCellEditor(new UITextField()) { + @Override + public Component getListCellEditorComponent(JList list, Object value, boolean isSelected, int index) { + ListModelElement element = (ListModelElement) getModel().getElementAt(index); + if (element != null) { + NameObject selectNameObject = (NameObject) element.wrapper; + ThemedCellStyle cellStyle = (ThemedCellStyle) (selectNameObject.getObject()); + if (!cellStyle.isRemovable()) { + return null; + } + } + return super.getListCellEditorComponent(list, value, isSelected, index); + } + }); + return nameEdList; + } + + @Override + public BasicBeanPane createPaneByCreators(NameableCreator creator) { + CellStyleEditPane stylePane = (CellStyleEditPane) super.createPaneByCreators(creator); + stylePane.registerAttrChangeListener(attributeChangeListener); + return stylePane; + } + + @Override + protected String title4PopupWindow() { + return StringUtils.EMPTY; + } + + protected void initComponentPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setCreators(this.createNameableCreators()); + initCardPane(); + JPanel leftPane = getLeftPane(); + leftPane.setPreferredSize(new Dimension(90, 0)); + cardPane.setPreferredSize(new Dimension(270, 0)); + JPanel mainSplitPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + mainSplitPane.add(leftPane, BorderLayout.WEST); + mainSplitPane.add(cardPane, BorderLayout.CENTER); + + this.add(mainSplitPane, BorderLayout.CENTER); + this.checkButtonEnabled(); + } + + @Override + protected void initToolBar() { + super.initToolBar(); + UIToolbar toolbar = getToolBar(); + toolbar.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + } + + @Override + protected ShortCut4JControlPane[] createShortcuts() { + return new ShortCut4JControlPane[]{ + createAddItemShortCut4JControlPane(), + new RemoveItemShortCut4JControlPane(new RemoveItemAction()) + }; + } + + private ShortCut4JControlPane createAddItemShortCut4JControlPane (){ + ShortCut shortCut = shortCutFactory.createAddItemUpdateAction(new NameableCreator[]{new CellStyleNameObjectCreator()}); + return new AddItemShortCut4JControlPane(shortCut); + } + + public void populateBean(ThemedCellStyleList ob) { + if (ob == null) { + return; + } + + int oldSelectedIndex = getSelectedIndex(); + + List nameObjectList = new ArrayList<>(); + + List cellStyleList = ob.getCellStyleList(); + for (ThemedCellStyle cellStyle: cellStyleList) { + nameObjectList.add(new NameObject(cellStyle.getName(), cellStyle)); + } + + NameObject[] nameObjectArray = new NameObject[nameObjectList.size()]; + nameObjectList.toArray(nameObjectArray); + + populate(nameObjectArray); + + int newSelectedIndex = oldSelectedIndex; + if (newSelectedIndex >= nameObjectArray.length) { + newSelectedIndex = 0; + } + setSelectedIndex(newSelectedIndex); + } + + public ThemedCellStyleList updateBean() { + nameableList.stopEditing(); + + Nameable[] nameables = this.update(); + ThemedCellStyleList styleConfig = new ThemedCellStyleList(); + for (Nameable nameable : nameables) { + ThemedCellStyle tmpStyle = (ThemedCellStyle) ((NameObject) nameable).getObject(); + tmpStyle.setName(nameable.getName()); + styleConfig.addThemedCellStyle(tmpStyle); + } + return styleConfig; + } + + private static class AddItemShortCut4JControlPane extends ShortCut4JControlPane{ + AddItemShortCut4JControlPane(ShortCut shortCut) { + this.shortCut = shortCut; + } + + @Override + public void checkEnable() { + this.shortCut.setEnabled(true); + } + } + + private class RemoveItemShortCut4JControlPane extends ShortCut4JControlPane { + RemoveItemShortCut4JControlPane(ShortCut shortCut) { + this.shortCut = shortCut; + } + + @Override + public void checkEnable() { + ListModelElement selectModel = CellStyleListEditPane.this.getSelectedValue(); + if (selectModel != null) { + NameObject selectNameObject = (NameObject) selectModel.wrapper; + ThemedCellStyle cellStyle = (ThemedCellStyle) (selectNameObject.getObject()); + this.shortCut.setEnabled(cellStyle.isRemovable() && !cellStyle.isUse4Default()); + } else { + this.shortCut.setEnabled(false); + } + + } + } + + private class RemoveItemAction extends UpdateAction { + RemoveItemAction() { + setName(i18nText(("Fine-Design_Basic_Action_Remove"))); + setMnemonic('R'); + setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH)); + } + + @Override + public void actionPerformed(ActionEvent evt) { + CellStyleListEditPane.this.onRemoveItem(); + } + } + + private static class CellStyleNameObjectCreator extends NameObjectCreator { + + public CellStyleNameObjectCreator() { + this(CellStyleEditPane.class); + } + + public CellStyleNameObjectCreator(Class updatePane) { + super(i18nText("Fine-Design_Predefined_Cell_New_Style"), ThemedCellStyle.class, updatePane); + } + + @Override + public Nameable createNameable(UnrepeatedNameHelper helper) { + ThemedCellStyle cellStyle = new ThemedCellStyle(); + cellStyle.setName(menuName); + cellStyle.setStyle(Style.getInstance()); + cellStyle.setRemovable(true); + cellStyle.setUse4Default(false); + cellStyle.setUse4BigTitle(false); + cellStyle.setUse4SmallTitle(false); + cellStyle.setUse4Header(false); + cellStyle.setUse4MainText(false); + cellStyle.setUse4SupportInfo(false); + cellStyle.setUse4HighlightText(false); + return new NameObject(helper.createUnrepeatedName(this.menuName()), cellStyle); + } + + @Override + public Object acceptObject2Populate(Object ob) { + if (ob instanceof NameObject) { + ob = ((NameObject) ob).getObject(); + } + if (clazzOfObject != null && clazzOfObject.isInstance(ob) && acceptNameObject(ob)) { + doSthChanged4Icon(ob); + return ob; + } + return null; + } + + public boolean acceptNameObject(Object ob) { + return !((ThemedCellStyle) ob).isUse4Default(); + } + } + + private static class DefaultCellStyleNameObjectCreator extends CellStyleNameObjectCreator { + + public DefaultCellStyleNameObjectCreator() { + super(NoBorderPaneCellStyleEditPane.class); + } + + @Override + public boolean acceptNameObject(Object ob) { + return ((ThemedCellStyle) ob).isUse4Default(); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleEditPane.java new file mode 100644 index 000000000..3830f02f1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleEditPane.java @@ -0,0 +1,104 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.MultiTabPane; +import com.fr.design.mainframe.theme.edit.chart.ChartAxisStylePane; +import com.fr.design.mainframe.theme.edit.chart.ChartDataSheetStylePane; +import com.fr.design.mainframe.theme.edit.chart.ChartLabelStylePane; +import com.fr.design.mainframe.theme.edit.chart.ChartLegendStylePane; +import com.fr.design.mainframe.theme.edit.chart.ChartSeriesStylePane; +import com.fr.design.mainframe.theme.edit.chart.ChartTitleAndBackgroundStylePane; + +import javax.swing.BorderFactory; +import java.util.ArrayList; +import java.util.List; +import java.awt.Color; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-16 + */ +public class ChartStyleEditPane extends MultiTabPane { + + private ChartSeriesStylePane chartSeriesStylePane; + private ChartLegendStylePane chartLegendStylePane; + private ChartLabelStylePane chartLabelPane; + private ChartAxisStylePane chartAxisStylePane; + private ChartDataSheetStylePane chartDataSheetStylePane; + private ChartTitleAndBackgroundStylePane chartTitleAndBackgroundStylePane; + + public ChartStyleEditPane() { + } + + @Override + protected void initLayout() { + super.initLayout(); + setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + } + + @Override + protected List initPaneList() { + this.chartSeriesStylePane = new ChartSeriesStylePane(); + this.chartLegendStylePane = new ChartLegendStylePane(); + this.chartLabelPane = new ChartLabelStylePane(); + this.chartAxisStylePane = new ChartAxisStylePane(); + this.chartDataSheetStylePane = new ChartDataSheetStylePane(); + this.chartTitleAndBackgroundStylePane = createChartTitleAndBackgroundStylePane(); + paneList = new ArrayList<>(); + paneList.add(this.chartSeriesStylePane); + paneList.add(this.chartLegendStylePane); + paneList.add(this.chartLabelPane); + paneList.add(this.chartAxisStylePane); + paneList.add(this.chartDataSheetStylePane); + paneList.add(this.chartTitleAndBackgroundStylePane); + return paneList; + } + + protected ChartTitleAndBackgroundStylePane createChartTitleAndBackgroundStylePane() { + return new ChartTitleAndBackgroundStylePane(); + } + + @Override + public void populateBean(ThemedChartStyle ob) { + chartSeriesStylePane.populate(ob); + chartLegendStylePane.populate(ob); + chartLabelPane.populate(ob); + chartAxisStylePane.populate(ob); + chartDataSheetStylePane.populate(ob); + chartTitleAndBackgroundStylePane.populate(ob); + } + + @Override + public void updateBean(ThemedChartStyle ob) { + + } + + + @Override + public ThemedChartStyle updateBean() { + ThemedChartStyle chartStyle = new ThemedChartStyle(); + chartSeriesStylePane.update(chartStyle); + chartLegendStylePane.update(chartStyle); + chartLabelPane.update(chartStyle); + chartAxisStylePane.update(chartStyle); + chartDataSheetStylePane.update(chartStyle); + chartTitleAndBackgroundStylePane.update(chartStyle); + return chartStyle; + } + + public void populateGradientBar(List colors) { + chartSeriesStylePane.populateGradientBar(colors); + } + + @Override + public boolean accept(Object ob) { + return false; + } + + @Override + public void reset() { + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleFormEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleFormEditPane.java new file mode 100644 index 000000000..f0886804d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ChartStyleFormEditPane.java @@ -0,0 +1,16 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.design.mainframe.theme.edit.chart.ChartTitleAndBackgroundStyleFormPane; +import com.fr.design.mainframe.theme.edit.chart.ChartTitleAndBackgroundStylePane; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2021-08-30 + */ +public class ChartStyleFormEditPane extends ChartStyleEditPane { + + protected ChartTitleAndBackgroundStylePane createChartTitleAndBackgroundStylePane() { + return new ChartTitleAndBackgroundStyleFormPane(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ComponentStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ComponentStyleEditPane.java new file mode 100644 index 000000000..53e216b0d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ComponentStyleEditPane.java @@ -0,0 +1,137 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.base.theme.settings.ThemedComponentStyle; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.style.ComponentBodyStylePane; +import com.fr.design.gui.style.ComponentIntegralStylePane; +import com.fr.design.gui.style.ComponentTitleStylePane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.edit.component.ComponentMarginStylePane; +import com.fr.design.mainframe.theme.edit.ui.LabelUtils; +import com.fr.design.mainframe.theme.edit.ui.TabbedPane; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.general.act.BorderPacker; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/12 + */ +public class ComponentStyleEditPane extends JPanel { + public static final int LABEL_WIDTH = 60; + public static final int SETTING_WIDTH = 193; + + private final ComponentTitleStylePane componentTitleStylePane; + private final ComponentBodyStylePane componentBodyStylePane; + private final ExtendedComponentIntegralStylePane componentIntegralStylePane; + + public ComponentStyleEditPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + componentTitleStylePane = new ThemedComponentTitleStylePane(LABEL_WIDTH, SETTING_WIDTH); + componentBodyStylePane = new ComponentBodyStylePane(LABEL_WIDTH, SETTING_WIDTH); + componentIntegralStylePane = new ExtendedComponentIntegralStylePane(); + + JPanel content = new TabbedPane( + new String[] { + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Title"), + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Body"), + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Integral") + }, + new JComponent[] { createTabContainer(componentTitleStylePane), createTabContainer(componentBodyStylePane), createTabContainer(componentIntegralStylePane) } + ); + add(content, BorderLayout.NORTH); + } + + public void populateBean(ThemedComponentStyle style) { + componentTitleStylePane.populateBean(style.getStyle()); + componentBodyStylePane.populateBean(style.getStyle()); + componentIntegralStylePane.populateBean(style); + } + + public ThemedComponentStyle updateBean() { + ThemedComponentStyle style = new ThemedComponentStyle(); + + componentTitleStylePane.updateBean(style.getStyle()); + componentBodyStylePane.updateBean(style.getStyle()); + componentIntegralStylePane.updateBean(style); + return style; + } + + private static class ExtendedComponentIntegralStylePane extends JPanel { + private final ComponentIntegralStylePane integralStylePane; + private final ComponentMarginStylePane marginStylePane; + + public ExtendedComponentIntegralStylePane() { + setLayout(new BorderLayout(0, IntervalConstants.INTERVAL_L1)); + integralStylePane = new ComponentIntegralStylePane(LABEL_WIDTH, SETTING_WIDTH); + marginStylePane = new ComponentMarginStylePane(LABEL_WIDTH, SETTING_WIDTH); + + add(integralStylePane, BorderLayout.NORTH); + add(marginStylePane, BorderLayout.CENTER); + } + + public void populateBean(ThemedComponentStyle style) { + integralStylePane.populateBean(style.getStyle()); + marginStylePane.populate(style); + } + + public void updateBean(ThemedComponentStyle style) { + integralStylePane.updateBean(style.getStyle()); + marginStylePane.update(style); + } + } + + private static class ThemedComponentTitleStylePane extends ComponentTitleStylePane { + + public ThemedComponentTitleStylePane(int uiLabelWidth, int uiSettingWidth) { + super(uiLabelWidth, uiSettingWidth); + setSupportTitleVisible(false); + setSupportTitleContent(false); + setSupportOtherSetting(true); + } + + @Override + public void populateBean(BorderPacker style) { + style.setType(LayoutBorderStyle.TITLE); + super.populateBean(style); + } + + @Override + public void updateBean(BorderPacker style) { + super.updateBean(style); + style.setType(LayoutBorderStyle.TITLE); + } + } + + private JComponent createTabContainer(final JPanel component) { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.setPreferredSize(new Dimension(container.getPreferredSize().width, 220)); + + JPanel tipLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + tipLabelPane.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0)); + UILabel tipLabel = LabelUtils.createLabel(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Edit_Pane_Component_Style_Tip"), new Color(153, 153, 153)); + tipLabelPane.add(tipLabel); + container.add(tipLabelPane, BorderLayout.NORTH); + + container.add(new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return component; + } + }, BorderLayout.CENTER); + + return container; + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/FormBodyStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/FormBodyStyleEditPane.java new file mode 100644 index 000000000..1f2089e69 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/FormBodyStyleEditPane.java @@ -0,0 +1,44 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.base.theme.settings.ThemedFormBodyStyle; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.style.ComponentBodyStylePane; + +import javax.swing.BorderFactory; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/12 + */ +public class FormBodyStyleEditPane extends JScrollPane { + public static final int LABEL_WIDTH = 60; + public static final int SETTING_WIDTH = 193; + + private final ComponentBodyStylePane bodyStylePane; + + public FormBodyStyleEditPane() { + bodyStylePane = new ComponentBodyStylePane(LABEL_WIDTH, SETTING_WIDTH); + bodyStylePane.setBorder(BorderFactory.createEmptyBorder( + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1 + )); + setViewportView(bodyStylePane); + setBorder(BorderFactory.createEmptyBorder()); + setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + } + + public void populateBean(ThemedFormBodyStyle style) { + bodyStylePane.populateBean(style.getStyle()); + } + + public ThemedFormBodyStyle updateBean() { + ThemedFormBodyStyle formBodyStyle = new ThemedFormBodyStyle(); + bodyStylePane.updateBean(formBodyStyle.getStyle()); + return formBodyStyle; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ReportBodyStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ReportBodyStyleEditPane.java new file mode 100644 index 000000000..ec36c2970 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ReportBodyStyleEditPane.java @@ -0,0 +1,65 @@ +package com.fr.design.mainframe.theme.edit; + +import com.fr.base.theme.settings.ThemedReportBodyStyle; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.style.ReportBackgroundSpecialPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.predefined.ui.detail.background.BackgroundSettingPane; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Component; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/12 + */ +public class ReportBodyStyleEditPane extends JScrollPane { + public static final int LABEL_WIDTH = 60; + public static final int SETTING_WIDTH = 193; + + private final ReportBackgroundSpecialPane backgroundPane; + + public ReportBodyStyleEditPane() { + backgroundPane = new ReportBackgroundSpecialPane(); + + double p = TableLayout.PREFERRED; + + JPanel uiLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + uiLabelPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Report_Background_Fill")), BorderLayout.NORTH); + uiLabelPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + JPanel backgroundLabeledPane = TableLayoutHelper.createCommonTableLayoutPane( + new Component[][]{ new Component[] { uiLabelPane, backgroundPane } }, + new double[] { p }, new double[] { LABEL_WIDTH, SETTING_WIDTH}, IntervalConstants.INTERVAL_L1 + ); + backgroundLabeledPane.setBorder(BorderFactory.createEmptyBorder( + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1, + IntervalConstants.INTERVAL_L1 + )); + + setViewportView(backgroundLabeledPane); + setBorder(BorderFactory.createEmptyBorder()); + setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + } + + public void populateBean(ThemedReportBodyStyle style) { + backgroundPane.populateBean(style.getBackground()); + } + + public ThemedReportBodyStyle updateBean() { + ThemedReportBodyStyle style = new ThemedReportBodyStyle(); + style.setBackground(backgroundPane.update()); + return style; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/AbstractBackgroundDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/AbstractBackgroundDetailPane.java new file mode 100644 index 000000000..76f948ffd --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/AbstractBackgroundDetailPane.java @@ -0,0 +1,51 @@ +package com.fr.design.mainframe.theme.edit.background; + +import com.fr.design.event.UIObserverListener; +import com.fr.design.mainframe.backgroundpane.BackgroundQuickPane; +import com.fr.general.Background; + +import javax.swing.event.ChangeListener; + +/** + * Created by kerry on 2020-09-14 + */ +public abstract class AbstractBackgroundDetailPane extends BackgroundQuickPane { + @Override + public boolean accept(Background background) { + return false; + } + + @Override + public void populateBean(Background background) { + this.populate((T) background); + } + + @Override + public Background updateBean() { + return this.update(); + } + + @Override + public String title4PopupWindow() { + return null; + } + + @Override + public void reset() { + + } + + @Override + public void registerChangeListener(UIObserverListener listener) { + + } + + public abstract void populate(T background); + + public abstract T update(); + + public void addChangeListener(ChangeListener changeListener) { + + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/BackgroundSettingPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/BackgroundSettingPane.java new file mode 100644 index 000000000..667c60114 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/BackgroundSettingPane.java @@ -0,0 +1,136 @@ +package com.fr.design.mainframe.theme.edit.background; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.backgroundpane.BackgroundQuickPane; +import com.fr.general.Background; +import com.fr.log.FineLoggerFactory; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.ArrayList; + +/** + * Created by kerry on 2020-09-02 + */ +public class BackgroundSettingPane extends BasicBeanPane { + private ChangeListener changeListener = null; + private UIComboBox headCombobox; + private BackgroundQuickPane[] paneList; + + public BackgroundSettingPane() { + init(); + } + + private void init() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.add(createComboHeadPane(), BorderLayout.NORTH); + CardLayout cardlayout = new CardLayout(); + paneList = supportKindsOfBackgroundUI(); + final JPanel centerPane = new JPanel(cardlayout) { + @Override + public Dimension getPreferredSize() {// AUGUST:使用当前面板的的高度 + int index = headCombobox.getSelectedIndex(); + return new Dimension(super.getPreferredSize().width, paneList[index].getPreferredSize().height); + } + }; + centerPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); + for (BackgroundQuickPane pane : paneList) { + headCombobox.addItem(pane.title4PopupWindow()); + centerPane.add(pane, pane.title4PopupWindow()); + } + headCombobox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + cardlayout.show(centerPane, (String) headCombobox.getSelectedItem()); + } + }); + this.add(centerPane, BorderLayout.CENTER); + } + + public void addChangeListener(ChangeListener changeListener) { + this.changeListener = changeListener; + } + + + private JPanel createComboHeadPane() { + headCombobox = new UIComboBox(); + + JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Report_Fill")), headCombobox}}, + TableLayoutHelper.FILL_NONE, 33, 5); + headCombobox.setPreferredSize(new Dimension(160, 20)); + jPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); + return jPanel; + } + + protected BackgroundQuickPane[] supportKindsOfBackgroundUI() { + java.util.List kinds = new ArrayList<>(); + kinds.add(new EmptyBackgroundPane()); + kinds.add(new ColorDetailPane()); + kinds.add(new TextureDetailObservePane()); + kinds.add(new PatternDetailPane()); + kinds.add(createImageSelectPane()); + kinds.add(new GradientDetailPane()); + return kinds.toArray(new BackgroundQuickPane[kinds.size()]); + } + + protected ImageDetailPane createImageSelectPane() { + ImageDetailPane imageDetailPane = new ImageDetailPane(); + imageDetailPane.registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + fireChangeListener(); + } + }); + return imageDetailPane; + } + + protected void fireChangeListener() { + if (changeListener != null) { + changeListener.stateChanged(null); + } + } + + + @Override + public void populateBean(Background background) { + for (int i = 0; i < paneList.length; i++) { + BackgroundQuickPane pane = paneList[i]; + if (pane.accept(background)) { + pane.populateBean(background); + headCombobox.setSelectedIndex(i); + return; + } + } + } + + @Override + public Background updateBean() { + int selectIndex = this.headCombobox.getSelectedIndex(); + try { + return paneList[selectIndex].updateBean(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } + + @Override + protected String title4PopupWindow() { + return null; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ColorDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ColorDetailPane.java new file mode 100644 index 000000000..12eea2c52 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ColorDetailPane.java @@ -0,0 +1,105 @@ +package com.fr.design.mainframe.theme.edit.background; + +import com.fr.base.background.ColorBackground; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.style.color.ColorSelectPane; +import com.fr.general.Background; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; + +/** + * Created by kerry on 2020-08-31 + */ +public class ColorDetailPane extends AbstractBackgroundDetailPane { + public static final String SPACE_4 = " "; + private ColorBackgroundSelectPane selectPane; + + + public ColorDetailPane() { + this.selectPane = new ColorBackgroundSelectPane(); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.add(this.selectPane, BorderLayout.CENTER); + } + + @Override + public void populate(ColorBackground background) { + this.selectPane.setColor(background.getColor()); + } + + @Override + public ColorBackground update() { + return ColorBackground.getInstance(selectPane.getColor()); + } + + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Color"); + } + + @Override + public boolean accept(Background background) { + return background instanceof ColorBackground; + } + + class ColorBackgroundSelectPane extends ColorSelectPane implements UIObserver { + protected UIObserverListener uiObserverListener; + + protected void initialCompents(boolean isSupportTransparent) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder()); + if (isSupportTransparent) { + this.add(createNorthPane(), BorderLayout.NORTH); + } + JPanel centerPane = createCenterPane(); + this.add(centerPane, BorderLayout.CENTER); + this.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (uiObserverListener != null) { + uiObserverListener.doChange(); + } + } + }); + } + + private JPanel createNorthPane() { + UIButton transpanrentBtn = new UIButton(); + transpanrentBtn.setPreferredSize(new Dimension(160, 20)); + JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_Color")), + transpanrentBtn}}, TableLayoutHelper.FILL_NONE, 33, 5); + jPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 10)); + return jPanel; + } + + protected JPanel createCenterPane() { + JPanel centerPane = new JPanel(); + + JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{new Component[]{new UILabel(SPACE_4), centerPane}}, TableLayoutHelper.FILL_NONE, 33, 5); + jPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 10)); + return jPanel; + } + + @Override + public void registerChangeListener(UIObserverListener listener) { + this.uiObserverListener = listener; + } + + @Override + public boolean shouldResponseChangeListener() { + return true; + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/EmptyBackgroundPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/EmptyBackgroundPane.java new file mode 100644 index 000000000..b7b345c63 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/EmptyBackgroundPane.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.theme.edit.background; + +import com.fr.design.i18n.Toolkit; +import com.fr.general.Background; + +/** + * Created by kerry on 2020-09-01 + */ +public class EmptyBackgroundPane extends AbstractBackgroundDetailPane { + + @Override + public void populate(Background background) { + + } + + @Override + public Background update() { + return null; + } + + /** + * 名称 + * + * @return 名称 + */ + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Background_Null"); + } + + public boolean accept(Background background) { + return background == null; + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/GradientDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/GradientDetailPane.java new file mode 100644 index 000000000..042e8d4d3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/GradientDetailPane.java @@ -0,0 +1,160 @@ +package com.fr.design.mainframe.theme.edit.background; + +import com.fr.base.background.GradientBackground; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.style.background.gradient.GradientBar; +import com.fr.general.Background; + +import javax.swing.ButtonGroup; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * 渐变色的面板,不是很pp,面板应用显得繁琐,有写可以写成控件类型,比如色彩选择的。。,可以做得花哨点 + * + * @author ben + */ +public class GradientDetailPane extends AbstractBackgroundDetailPane implements UIObserver { + private static final long serialVersionUID = -6854603990673031897L; + private UIObserverListener listener; + private UIRadioButton left2right, top2bottom; + private GradientBar gradientBar; + private ChangeListener changeListener = null; + + public GradientDetailPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel gradientPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JPanel blankJp = new JPanel(); + gradientBar = new GradientBar(4, 140); + blankJp.add(gradientBar); + + gradientPanel.add(gradientBar, BorderLayout.SOUTH); + + JPanel jp = new JPanel(new GridLayout(2, 1, 15, 10)); + + + left2right = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Page_Setup_Horizontal")); + jp.add(left2right); + left2right.setSelected(true); + left2right.addActionListener(reviewListener); + + top2bottom = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Page_Setup_Vertical")); + jp.add(top2bottom); + top2bottom.addActionListener(reviewListener); + + ButtonGroup toggle = new ButtonGroup(); + toggle.add(left2right); + toggle.add(top2bottom); + + Component[][] components = new Component[][]{ + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_Gradient_Setting")), gradientPanel}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_Gradient_Color")), jp} + }; + JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_LASTCOLUMN, + IntervalConstants.INTERVAL_W4, IntervalConstants.INTERVAL_L1); + this.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (listener != null) { + listener.doChange(); + } + } + }); + + + this.add(contentPane); + } + + @Override + public boolean accept(Background background) { + return background instanceof GradientBackground; + } + + + + public void populate(GradientBackground bg) { + this.gradientBar.getSelectColorPointBtnP1().setColorInner(bg.getStartColor()); + this.gradientBar.getSelectColorPointBtnP2().setColorInner(bg.getEndColor()); + if (bg.getDirection() == GradientBackground.LEFT2RIGHT) { + left2right.setSelected(true); + } else { + top2bottom.setSelected(true); + } + if (bg.isUseCell()) { + return; + } + double startValue = (double) bg.getBeginPlace(); + double endValue = (double) bg.getFinishPlace(); + gradientBar.setStartValue(startValue); + gradientBar.setEndValue(endValue); + this.gradientBar.repaint(); + } + + public GradientBackground update() { + GradientBackground gb = new GradientBackground( + gradientBar.getSelectColorPointBtnP1().getColorInner(), + gradientBar.getSelectColorPointBtnP2().getColorInner()); + if (left2right.isSelected()) { + gb.setDirection(GradientBackground.LEFT2RIGHT); + } else { + gb.setDirection(GradientBackground.TOP2BOTTOM); + } + if (gradientBar.isOriginalPlace()) { + gb.setUseCell(true); + } else { + gb.setUseCell(false); + gb.setBeginPlace((float) gradientBar.getStartValue()); + gb.setFinishPlace((float) gradientBar.getEndValue()); + } + return gb; + } + + + ActionListener reviewListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + fireChagneListener(); + } + }; + + public void addChangeListener(ChangeListener changeListener) { + this.changeListener = changeListener; + gradientBar.addChangeListener(changeListener); + } + + public void fireChagneListener() { + if (this.changeListener != null) { + ChangeEvent evt = new ChangeEvent(this); + this.changeListener.stateChanged(evt); + } + } + + @Override + public void registerChangeListener(UIObserverListener listener) { + this.listener = listener; + } + + @Override + public boolean shouldResponseChangeListener() { + return true; + } + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Gradient_Color"); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ImageDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ImageDetailPane.java new file mode 100644 index 000000000..208c21045 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/ImageDetailPane.java @@ -0,0 +1,216 @@ +package com.fr.design.mainframe.theme.edit.background; + +import com.fr.base.Style; +import com.fr.base.background.ImageBackground; +import com.fr.base.background.ImageFileBackground; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.frpane.ImgChooseWrapper; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.style.background.image.ImageFileChooser; +import com.fr.design.style.background.image.ImagePreviewPane; +import com.fr.general.Background; +import com.fr.stable.Constants; + +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Image background pane. + */ +public class ImageDetailPane extends AbstractBackgroundDetailPane implements UIObserver { + private UIObserverListener listener; + protected ImagePreviewPane previewPane = null; + private Style imageStyle = null; + private ChangeListener changeListener = null; + private ImageFileChooser imageFileChooser = null; + + private UIRadioButton defaultRadioButton = null; + private UIRadioButton tiledRadioButton = null; + private UIRadioButton extendRadioButton = null; + private UIRadioButton adjustRadioButton = null; + + + public ImageDetailPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.add(initSelectFilePane(), BorderLayout.CENTER); + imageFileChooser = new ImageFileChooser(); + imageFileChooser.setMultiSelectionEnabled(false); + previewPane = new ImagePreviewPane(); + this.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (listener != null) { + listener.doChange(); + } + } + }); + } + + public JPanel initSelectFilePane() { + JPanel selectFilePane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + selectFilePane.setBorder(BorderFactory.createEmptyBorder()); + UIButton selectPictureButton = new UIButton( + Toolkit.i18nText("Fine-Design_Basic_Background_Image_Select")); + selectPictureButton.setMnemonic('S'); + selectPictureButton.addActionListener(selectPictureActionListener); + selectPictureButton.setPreferredSize(new Dimension(160, 20)); + //布局 + defaultRadioButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Default")); + tiledRadioButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Titled")); + extendRadioButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Extend")); + adjustRadioButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Layout_Image_Adjust")); + + defaultRadioButton.addActionListener(layoutActionListener); + tiledRadioButton.addActionListener(layoutActionListener); + extendRadioButton.addActionListener(layoutActionListener); + adjustRadioButton.addActionListener(layoutActionListener); + + JPanel jp = new JPanel(new GridLayout(4, 1, 15, 10)); + for (UIRadioButton button : imageLayoutButtons()) { + jp.add(button); + } + + ButtonGroup layoutBG = new ButtonGroup(); + layoutBG.add(defaultRadioButton); + layoutBG.add(tiledRadioButton); + layoutBG.add(extendRadioButton); + layoutBG.add(adjustRadioButton); + + defaultRadioButton.setSelected(true); + + Component[][] components = new Component[][]{ + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_Image")), selectPictureButton}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_Fill_Mode")), jp} + }; + JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_NONE, + IntervalConstants.INTERVAL_L4, IntervalConstants.INTERVAL_L1); + selectFilePane.add(centerPane, BorderLayout.CENTER); + return selectFilePane; + } + + protected UIRadioButton[] imageLayoutButtons() { + return new UIRadioButton[]{ + defaultRadioButton, + tiledRadioButton, + extendRadioButton, + adjustRadioButton + }; + } + + @Override + public boolean accept(Background background) { + return background instanceof ImageBackground; + } + + + /** + * Select picture. + */ + ActionListener selectPictureActionListener = new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + int returnVal = imageFileChooser.showOpenDialog(ImageDetailPane.this); + setImageStyle(); + ImgChooseWrapper.getInstance(previewPane, imageFileChooser, imageStyle, changeListener).dealWithImageFile(returnVal); + } + }; + + protected void setImageStyle() { + if (tiledRadioButton.isSelected()) { + imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_TILED); + } else if (adjustRadioButton.isSelected()) { + imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_ADJUST); + } else if (extendRadioButton.isSelected()) { + imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_EXTEND); + } else { + imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_CENTER); + } + } + + ActionListener layoutActionListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent evt) { + setImageStyle(); + changeImageStyle(); + } + + private void changeImageStyle() { + previewPane.setImageStyle(ImageDetailPane.this.imageStyle); + previewPane.repaint(); + } + }; + + @Override + public void populate(ImageBackground imageBackground) { + if (imageBackground.getLayout() == Constants.IMAGE_CENTER) { + defaultRadioButton.setSelected(true); + imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_CENTER); + } else if (imageBackground.getLayout() == Constants.IMAGE_EXTEND) { + extendRadioButton.setSelected(true); + imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_EXTEND); + } else if (imageBackground.getLayout() == Constants.IMAGE_ADJUST) { + adjustRadioButton.setSelected(true); + imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_ADJUST); + } else { + tiledRadioButton.setSelected(true); + imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_TILED); + } + previewPane.setImageStyle(ImageDetailPane.this.imageStyle); + if (imageBackground.getImage() != null) { + previewPane.setImageWithSuffix(imageBackground.getImageWithSuffix()); + previewPane.setImage(imageBackground.getImage()); + } + + fireChagneListener(); + } + + @Override + public ImageBackground update() { + ImageBackground imageBackground = new ImageFileBackground(previewPane.getImageWithSuffix()); + setImageStyle(); + imageBackground.setLayout(imageStyle.getImageLayout()); + return imageBackground; + } + + @Override + public void addChangeListener(ChangeListener changeListener) { + this.changeListener = changeListener; + } + + private void fireChagneListener() { + if (this.changeListener != null) { + ChangeEvent evt = new ChangeEvent(this); + this.changeListener.stateChanged(evt); + } + } + + @Override + public void registerChangeListener(UIObserverListener listener) { + this.listener = listener; + } + + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Background_Image"); + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/PatternDetailPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/PatternDetailPane.java new file mode 100644 index 000000000..7d5ee66a7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/PatternDetailPane.java @@ -0,0 +1,120 @@ +package com.fr.design.mainframe.theme.edit.background; + +import com.fr.base.background.PatternBackground; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.style.background.impl.PatternBackgroundPane; +import com.fr.design.style.color.ColorSelectBox; +import com.fr.general.Background; +import com.fr.log.FineLoggerFactory; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.GridLayout; +import java.awt.LayoutManager; + +/** + * Created by kerry on 2020-08-31 + */ +public class PatternDetailPane extends AbstractBackgroundDetailPane implements UIObserver { + + private UIObserverListener listener; + private PatternNewBackgroundPane patternNewBackgroundPane; + + public PatternDetailPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + patternNewBackgroundPane = new PatternNewBackgroundPane(6); + this.add(patternNewBackgroundPane, BorderLayout.CENTER); + } + + @Override + public void registerChangeListener(UIObserverListener listener) { + this.listener = listener; + } + + @Override + public void populate(PatternBackground background) { + this.patternNewBackgroundPane.populate(background); + } + + @Override + public PatternBackground update() { + try { + return (PatternBackground) this.patternNewBackgroundPane.update(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Background_Pattern"); + } + + + @Override + public boolean accept(Background background) { + return background instanceof PatternBackground; + } + + + @Override + public boolean shouldResponseChangeListener() { + return true; + } + + class PatternNewBackgroundPane extends PatternBackgroundPane { + private PatternNewBackgroundPane(int nColumn) { + super(nColumn); + } + + protected LayoutManager layoutOfTypePane(int nColumn) { + return new GridLayout(0, nColumn, 2, 2); + } + + protected void initComponents(int nColumn) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder()); + JPanel jPanel = new JPanel(); + jPanel.setLayout(layoutOfTypePane(nColumn)); + setChildrenOfTypePane(jPanel); + + foregroundColorPane = new ColorSelectBox(80); + backgroundColorPane = new ColorSelectBox(80); + foregroundColorPane.setSelectObject(Color.lightGray); + backgroundColorPane.setSelectObject(Color.black); + UILabel label = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_Pattern")); + label.setVerticalAlignment(SwingConstants.TOP); + Component[][] components = new Component[][]{ + new Component[]{label, jPanel}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_ForeBackground_Color")), foregroundColorPane}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_Pattern_Color")), backgroundColorPane} + }; + JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_LASTCOLUMN, + IntervalConstants.INTERVAL_W4, IntervalConstants.INTERVAL_L1); + JPanel jPanel1 = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + jPanel1.add(centerPane); + jPanel1.setBorder(BorderFactory.createEmptyBorder()); + this.add(jPanel1, BorderLayout.NORTH); + this.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (listener != null) { + listener.doChange(); + } + } + }); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/TextureDetailObservePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/TextureDetailObservePane.java new file mode 100644 index 000000000..a1d0fcb2c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/background/TextureDetailObservePane.java @@ -0,0 +1,98 @@ +package com.fr.design.mainframe.theme.edit.background; + +import com.fr.base.background.TextureBackground; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.style.background.texture.TextureDetailPane; +import com.fr.general.Background; +import com.fr.log.FineLoggerFactory; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; + +/** + * Created by kerry on 2020-09-02 + */ +public class TextureDetailObservePane extends AbstractBackgroundDetailPane implements UIObserver { + private TextureDetailPane detailPane; + + private UIObserverListener listener; + + public TextureDetailObservePane() { + + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + detailPane = TextureDetailPane.createMiniTextureDetailPane(6); + + detailPane.setPreferredSize(new Dimension(160, 108)); + UILabel label = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Background_Texture")); + label.setPreferredSize(new Dimension(24, 108)); + label.setVerticalAlignment(SwingConstants.TOP); + JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{new Component[]{label, detailPane}}, TableLayoutHelper.FILL_LASTCOLUMN, 33, 5); + jPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 10)); + + + detailPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (listener != null) { + listener.doChange(); + } + } + }); + this.add(jPanel, BorderLayout.CENTER); + } + + @Override + public void registerChangeListener(UIObserverListener listener) { + this.listener = listener; + + } + + @Override + public boolean shouldResponseChangeListener() { + return true; + } + + @Override + public void populate(TextureBackground background) { + this.detailPane.populate(background); + } + + @Override + public TextureBackground update() { + try { + return (TextureBackground) this.detailPane.update(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } + + + @Override + public String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Background_Texture"); + } + + @Override + public boolean accept(Background background) { + return background instanceof TextureBackground; + } + + + @Override + public void addChangeListener(ChangeListener changeListener) { + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/CellStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/CellStyleEditPane.java new file mode 100644 index 000000000..53e4d9a91 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/CellStyleEditPane.java @@ -0,0 +1,157 @@ +package com.fr.design.mainframe.theme.edit.cell; + +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.design.cell.CellStylePreviewPane; +import com.fr.design.constants.UIConstants; +import com.fr.design.dialog.AttrScrollPane; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.BasicScrollPane; +import com.fr.design.dialog.MultiTabPane; +import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; +import com.fr.design.gui.frpane.AttributeChangeListener; +import com.fr.design.gui.style.AbstractBasicStylePane; +import com.fr.design.gui.style.AlignmentPane; +import com.fr.design.gui.style.BorderPane; +import com.fr.design.gui.style.FormatPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.ui.BorderUtils; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.util.ArrayList; +import java.util.List; + +import static com.fr.design.i18n.Toolkit.i18nText; + + +/** + * 哎,复杂的原型图导致复杂的画法。非我所愿也 + * + * @author zhou + * @since 2012-5-24上午10:36:10 + */ +public class CellStyleEditPane extends MultiTabPane { + private ThemedCellStyle cellStyle; + private CellStylePreviewPane previewArea; + private boolean populating; + private AttributeChangeListener attributeChangeListener; + + public CellStyleEditPane() { + super(); + tabPane.setOneLineTab(true); + tabPane.setDrawLine(false); + tabPane.setBorder(BorderFactory.createLineBorder(UIConstants.SHADOW_GREY)); + tabPane.setLayout(new GridLayout(1, 3, 0, 0)); + } + + + + public void registerAttrChangeListener(AttributeChangeListener listener){ + this.attributeChangeListener = listener; + } + + private void fireAttrChangeListener() { + if (this.attributeChangeListener != null) { + this.attributeChangeListener.attributeChange(); + } + } + + public String title4PopupWindow() { + return i18nText("Fine-Design_Report_Custom_Style"); + } + + public void reset() { + populateBean(null); + } + + @Override + public void populateBean(ThemedCellStyle ob) { + this.populating = true; + this.cellStyle = ob; + + for (BasicPane basicPane : paneList) { + ((AbstractBasicStylePane) basicPane).populateBean(ob.getStyle()); + previewArea.setStyle(ob.getStyle()); + } + this.populating = false; + } + + @Override + public ThemedCellStyle updateBean() { + AbstractBasicStylePane basicStylePane = (AbstractBasicStylePane) paneList.get(tabPane.getSelectedIndex()); + this.cellStyle.setStyle(basicStylePane.update(this.cellStyle.getStyle())); + return this.cellStyle; + } + + @Override + public boolean accept(Object ob) { + return ob instanceof ThemedCellStyle; + } + + @Override + protected List initPaneList() { + paneList = new ArrayList<>(); + paneList.add(new FormatPane()); + paneList.add(new BorderPane()); + paneList.add(new AlignmentPane()); + return paneList; + } + + @Override + protected void initLayout() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel jPanel = new JPanel(); + jPanel.setLayout(new BorderLayout(0, 4)); + + JPanel previewPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + previewArea = new CellStylePreviewPane(); + previewArea.setPreferredSize(new Dimension(223, 30)); + previewPane.setBorder(BorderUtils.createTitleBorder(i18nText("Fine-Design_Basic_Preview"))); + previewPane.add(previewArea, BorderLayout.CENTER); + + this.add(previewPane, BorderLayout.NORTH); + + this.add(jPanel, BorderLayout.CENTER); + jPanel.add(tabPane, BorderLayout.NORTH); + JPanel attrListenerPane = new AbstractAttrNoScrollPane() { + + @Override + protected void initContentPane() { + leftContentPane = createContentPane(); + this.add(leftContentPane, BorderLayout.CENTER); + } + + @Override + protected JPanel createContentPane() { + this.addAttributeChangeListener(new AttributeChangeListener() { + @Override + public void attributeChange() { + if (populating) { + return; + } + ThemedCellStyle cellStyle = updateBean(); + if (cellStyle != null) { + previewArea.setStyle(cellStyle.getStyle()); + } + fireAttrChangeListener(); + } + }); + BasicScrollPane basicScrollPane = new AttrScrollPane() { + @Override + protected JPanel createContentPane() { + return centerPane; + } + }; + return basicScrollPane; + } + }; + jPanel.add(attrListenerPane, BorderLayout.CENTER); + } + + @Override + public void updateBean(ThemedCellStyle ob) {} +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/NoBorderPaneCellStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/NoBorderPaneCellStyleEditPane.java new file mode 100644 index 000000000..7104572da --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/NoBorderPaneCellStyleEditPane.java @@ -0,0 +1,19 @@ +package com.fr.design.mainframe.theme.edit.cell; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.style.AlignmentPane; +import com.fr.design.gui.style.FormatPane; + +import java.util.ArrayList; +import java.util.List; + +public class NoBorderPaneCellStyleEditPane extends CellStyleEditPane { + + @Override + protected List initPaneList() { + paneList = new ArrayList<>(); + paneList.add(new FormatPane()); + paneList.add(new AlignmentPane()); + return paneList; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/AbstractChartStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/AbstractChartStylePane.java new file mode 100644 index 000000000..e96bcd7bb --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/AbstractChartStylePane.java @@ -0,0 +1,50 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-17 + */ +public abstract class AbstractChartStylePane extends BasicPane { + + public AbstractChartStylePane() { + initComponents(); + initPane(); + } + + protected abstract void initComponents(); + + protected void initPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + double e1 = 75; + double e = 155; + double p = TableLayout.PREFERRED; + double[] columnSize = {e1, e}; + JPanel gapTableLayoutPane = TableLayoutHelper.createGapTableLayoutPane(getComponent(), getRows(p), columnSize, 20, LayoutConstants.VGAP_LARGE); + gapTableLayoutPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); + UIScrollPane rightTopPane = new UIScrollPane(gapTableLayoutPane); + rightTopPane.setBorder(BorderFactory.createEmptyBorder()); + this.add(rightTopPane, BorderLayout.CENTER); + } + + protected abstract Component[][] getComponent(); + + protected abstract double[] getRows(double p); + + public abstract void populate(ThemedChartStyle chartStyle); + + public abstract void update(ThemedChartStyle chartStyle); +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartAxisStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartAxisStylePane.java new file mode 100644 index 000000000..5a52bb28c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartAxisStylePane.java @@ -0,0 +1,69 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.style.color.ColorSelectBox; + +import java.awt.Component; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-16 + */ +public class ChartAxisStylePane extends AbstractChartStylePane { + + //轴标题字体样式 + private ChartFontPane titleFontPane; + + //轴标签字体样式 + private ChartFontPane labelFontPane; + + //轴线颜色 + private ColorSelectBox axisLineColor; + + protected void initComponents() { + titleFontPane = new ChartFontPane() { + public String getUILabelText() { + return Toolkit.i18nText("Fine-Design_Chart_Axis_Title_Character"); + } + }; + labelFontPane = new ChartFontPane() { + public String getUILabelText() { + return Toolkit.i18nText("Fine-Design_Chart_Axis_Label_Character"); + } + }; + axisLineColor = new ColorSelectBox(100); + } + + protected Component[][] getComponent() { + return new Component[][]{ + new Component[]{titleFontPane, null}, + new Component[]{labelFontPane, null}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Axis_Line_Color")), axisLineColor} + }; + } + + protected double[] getRows(double p) { + return new double[]{p, p, p}; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Chart_Axis"); + } + + public void populate(ThemedChartStyle chartStyle) { + titleFontPane.populate(chartStyle.getAxisTitleFont()); + labelFontPane.populate(chartStyle.getAxisLabelFont()); + axisLineColor.setSelectObject(chartStyle.getAxisLineColor()); + } + + + public void update(ThemedChartStyle chartStyle) { + chartStyle.setAxisTitleFont(titleFontPane.update()); + chartStyle.setAxisLabelFont(labelFontPane.update()); + chartStyle.setAxisLineColor(axisLineColor.getSelectObject()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartDataSheetStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartDataSheetStylePane.java new file mode 100644 index 000000000..07ec893f7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartDataSheetStylePane.java @@ -0,0 +1,58 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.style.color.ColorSelectBox; + +import java.awt.Component; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-17 + */ +public class ChartDataSheetStylePane extends AbstractChartStylePane { + + //字体样式 + private ChartFontPane fontPane; + + //边框颜色 + private ColorSelectBox borderColor; + + protected void initComponents() { + fontPane = new ChartFontPane() { + public String getUILabelText() { + return Toolkit.i18nText("Fine-Design_Chart_DataSheet_Character"); + } + }; + borderColor = new ColorSelectBox(100); + } + + protected Component[][] getComponent() { + return new Component[][]{ + new Component[]{fontPane, null}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Border_Color")), borderColor} + }; + } + + protected double[] getRows(double p) { + return new double[]{p, p, p}; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Chart_Data_Sheet"); + } + + public void populate(ThemedChartStyle chartStyle) { + fontPane.populate(chartStyle.getDataSheetFont()); + borderColor.setSelectObject(chartStyle.getDataSheetBorderColor()); + } + + + public void update(ThemedChartStyle chartStyle) { + chartStyle.setDataSheetFont(fontPane.update()); + chartStyle.setDataSheetBorderColor(borderColor.getSelectObject()); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartFontPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartFontPane.java new file mode 100644 index 000000000..ee04556c6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartFontPane.java @@ -0,0 +1,161 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.base.Utils; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.ibutton.UIToggleButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.FRFont; +import com.fr.general.GeneralUtils; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.Font; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-16 + */ +public class ChartFontPane extends BasicPane { + + public static final int FONT_START = 6; + public static final int FONT_END = 72; + private UIComboBox fontNameComboBox; + private UIComboBox fontSizeComboBox; + private UIToggleButton bold; + private UIToggleButton italic; + private UIColorButton fontColor; + private static Integer[] FONT_SIZES = new Integer[FONT_END - FONT_START + 1]; + + static { + for (int i = FONT_START; i <= FONT_END; i++) { + FONT_SIZES[i - FONT_START] = i; + } + } + + public ChartFontPane() { + initState(); + initComponents(); + } + + private void initState() { + fontNameComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); + fontSizeComboBox = new UIComboBox(FONT_SIZES); + bold = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); + italic = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); + fontColor = new UIColorButton(); + } + + protected void initComponents() { + Component[] components = new Component[]{ + fontColor, italic, bold + }; + JPanel buttonPane = new JPanel(new BorderLayout()); + buttonPane.add(fontSizeComboBox, BorderLayout.CENTER); + buttonPane.add(GUICoreUtils.createFlowPane(components, FlowLayout.LEFT, LayoutConstants.HGAP_LARGE), BorderLayout.EAST); + + this.setLayout(new BorderLayout()); + this.add(getContentPane(buttonPane), BorderLayout.CENTER); + + populate(FRContext.getDefaultValues().getFRFont()); + } + + protected JPanel getContentPane(JPanel buttonPane) { + double e1 = 75; + double e = 155; + double p = TableLayout.PREFERRED; + double[] rows = {p, p, p}; + double[] columnSize = {e1, e}; + UILabel text = new UILabel(getUILabelText(), SwingConstants.LEFT); + Component[][] components = { + new Component[]{null, null}, + new Component[]{text, fontNameComboBox}, + new Component[]{null, buttonPane} + }; + + return TableLayoutHelper.createGapTableLayoutPane(components, rows, columnSize, 20, LayoutConstants.VGAP_LARGE); + } + + public String getUILabelText() { + return Toolkit.i18nText("Fine-Design_Chart_Character"); + } + + public String title4PopupWindow() { + return null; + } + + public void populate(FRFont frFont) { + UIObserverListener listener = fontNameComboBox == null ? null : fontNameComboBox.getUiObserverListener(); + removeAllComboBoxListener(); + + if (frFont != null) { + fontNameComboBox.setSelectedItem(frFont.getFamily()); + bold.setSelected(frFont.isBold()); + italic.setSelected(frFont.isItalic()); + populateFontSize(frFont); + if (fontColor != null) { + fontColor.setColor(frFont.getForeground()); + } + } + + //更新结束后,注册监听器 + registerAllComboBoxListener(listener); + } + + private void populateFontSize(FRFont frFont) { + if (fontSizeComboBox != null) { + fontSizeComboBox.setSelectedItem(frFont.getSize()); + } + } + + private void removeAllComboBoxListener() { + fontNameComboBox.removeChangeListener(); + fontSizeComboBox.removeChangeListener(); + } + + private void registerAllComboBoxListener(UIObserverListener listener) { + fontNameComboBox.registerChangeListener(listener); + fontSizeComboBox.registerChangeListener(listener); + } + + /** + * 更新字 + * + * @return 更新字 + */ + public FRFont update() { + String name = GeneralUtils.objectToString(fontNameComboBox.getSelectedItem()); + + return FRFont.getInstance(name, updateFontStyle(), updateFontSize(), fontColor.getColor()); + } + + private int updateFontStyle() { + int style = Font.PLAIN; + if (bold.isSelected() && !italic.isSelected()) { + style = Font.BOLD; + } else if (!bold.isSelected() && italic.isSelected()) { + style = Font.ITALIC; + } else if (bold.isSelected() && italic.isSelected()) { + style = 3; + } + + return style; + } + + private float updateFontSize() { + return Float.parseFloat(GeneralUtils.objectToString(fontSizeComboBox.getSelectedItem())); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLabelStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLabelStylePane.java new file mode 100644 index 000000000..8eb736444 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLabelStylePane.java @@ -0,0 +1,78 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-16 + */ +public class ChartLabelStylePane extends AbstractChartStylePane { + + private UIButtonGroup autoButton; + //字体样式 + private ChartFontPane chartFontPane; + + protected void initComponents() { + autoButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Auto"), + Toolkit.i18nText("Fine-Design_Chart_Custom")}); + chartFontPane = new ChartFontPane() { + public String getUILabelText() { + return Toolkit.i18nText("Fine-Design_Chart_Label_Character"); + } + }; + initListener(); + } + + protected Component[][] getComponent() { + return new Component[][]{ + new Component[]{null, null}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Style_Setting")), autoButton}, + new Component[]{chartFontPane, null} + }; + } + + protected double[] getRows(double p) { + return new double[]{p, p, p}; + } + + private void initListener() { + autoButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + checkPreButton(); + } + }); + } + + private void checkPreButton() { + chartFontPane.setVisible(autoButton.getSelectedIndex() == 1); + chartFontPane.setPreferredSize(autoButton.getSelectedIndex() == 1 ? new Dimension(0, 60) : new Dimension(0, 0)); + } + + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Chart_Label"); + } + + public void populate(ThemedChartStyle chartStyle) { + autoButton.setSelectedIndex(chartStyle.isAutoLabelFont() ? 0 : 1); + chartFontPane.populate(chartStyle.getLabelFont()); + checkPreButton(); + } + + + public void update(ThemedChartStyle chartStyle) { + chartStyle.setAutoLabelFont(autoButton.getSelectedIndex() == 0); + chartStyle.setLabelFont(chartFontPane.update()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLegendStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLegendStylePane.java new file mode 100644 index 000000000..40f4652a0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartLegendStylePane.java @@ -0,0 +1,49 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.i18n.Toolkit; + +import java.awt.Component; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-16 + */ +public class ChartLegendStylePane extends AbstractChartStylePane { + + //字体样式 + private ChartFontPane chartFontPane; + + protected void initComponents() { + chartFontPane = new ChartFontPane() { + public String getUILabelText() { + return Toolkit.i18nText("Fine-Design_Chart_Legend_Character"); + } + }; + } + + protected Component[][] getComponent() { + return new Component[][]{ + new Component[]{chartFontPane, null} + }; + } + + protected double[] getRows(double p) { + return new double[]{p}; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Chart_Legend"); + } + + public void populate(ThemedChartStyle chartStyle) { + chartFontPane.populate(chartStyle.getLegendFont()); + } + + + public void update(ThemedChartStyle chartStyle) { + chartStyle.setLegendFont(chartFontPane.update()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartSeriesStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartSeriesStylePane.java new file mode 100644 index 000000000..fbb8f6489 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartSeriesStylePane.java @@ -0,0 +1,88 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog; +import com.fr.design.style.background.gradient.FixedGradientBar; + +import java.util.List; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-17 + */ +public class ChartSeriesStylePane extends AbstractChartStylePane { + + private UIButtonGroup colorTypeButton; + private FixedGradientBar gradientBar; + + protected void initComponents() { + colorTypeButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Custom_Color"), + Toolkit.i18nText("Fine-Design_Chart_Legend_Gradual")}); + gradientBar = new FixedGradientBar(4, 130); + initListener(); + } + + protected Component[][] getComponent() { + return new Component[][]{ + new Component[]{null, null}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Match_Color_Scheme")), colorTypeButton}, + new Component[]{null, gradientBar} + }; + } + + protected double[] getRows(double p) { + return new double[]{p, p, p}; + } + + private void initListener() { + colorTypeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + checkTypeButton(); + } + }); + } + + private void checkTypeButton() { + gradientBar.setVisible(colorTypeButton.getSelectedIndex() == 1); + gradientBar.setPreferredSize(colorTypeButton.getSelectedIndex() == 1 ? new Dimension(0, 60) : new Dimension(0, 0)); + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Chart_Series"); + } + + public void populate(ThemedChartStyle chartStyle) { + if (chartStyle.getThemedChartSeriesColor().isCombineColor()) { + List editingColorScheme = TemplateThemeProfileDialog.getEditingColorScheme(); + colorTypeButton.setSelectedIndex(0); + gradientBar.updateColor(editingColorScheme.get(0), editingColorScheme.get(1)); + } else { + colorTypeButton.setSelectedIndex(1); + gradientBar.updateColor(chartStyle.getThemedChartSeriesColor().getBeginColor(), chartStyle.getThemedChartSeriesColor().getEndColor()); + } + checkTypeButton(); + } + + + public void populateGradientBar(List colors) { + gradientBar.updateColor(colors.get(0), colors.get(1)); + this.repaint(); + } + + public void update(ThemedChartStyle chartStyle) { + chartStyle.getThemedChartSeriesColor().setCombineColor(colorTypeButton.getSelectedIndex() == 0); + chartStyle.getThemedChartSeriesColor().setBeginColor(gradientBar.getSelectColorPointBtnP1().getColorInner()); + chartStyle.getThemedChartSeriesColor().setEndColor(gradientBar.getSelectColorPointBtnP2().getColorInner()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStyleFormPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStyleFormPane.java new file mode 100644 index 000000000..204bde076 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStyleFormPane.java @@ -0,0 +1,36 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; + +import java.awt.Color; +import java.awt.Component; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2021-08-30 + */ +public class ChartTitleAndBackgroundStyleFormPane extends ChartTitleAndBackgroundStylePane { + + private UILabel tooltipLabel; + + protected void initComponents() { + super.initComponents(); + tooltipLabel = new UILabel("" + Toolkit.i18nText("Fine-Design_Chart_Title_Background_Tooltip") + ""); + tooltipLabel.setForeground(new Color(153, 153, 153)); + } + + protected Component[][] getComponent() { + Component[][] component = super.getComponent(); + Component[][] newComponent = new Component[component.length + 2][]; + System.arraycopy(component, 0, newComponent, 2, component.length); + newComponent[0] = new Component[]{null, null}; + newComponent[1] = new Component[]{tooltipLabel, null}; + return newComponent; + } + + protected double[] getRows(double p) { + return new double[]{p, p, p, p, p, p, p}; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStylePane.java new file mode 100644 index 000000000..6bac51876 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/chart/ChartTitleAndBackgroundStylePane.java @@ -0,0 +1,127 @@ +package com.fr.design.mainframe.theme.edit.chart; + +import com.fr.base.background.ImageBackground; +import com.fr.base.theme.settings.ThemedChartStyle; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.backgroundpane.BackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.ColorBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.ImageBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.NullBackgroundQuickPane; +import com.fr.design.mainframe.backgroundpane.VanChartGradientPane; +import com.fr.design.style.color.ColorSelectBox; +import com.fr.general.Background; +import com.fr.stable.Constants; + +import javax.swing.JPanel; +import java.util.ArrayList; +import java.util.List; +import java.awt.CardLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2020-09-16 + */ +public class ChartTitleAndBackgroundStylePane extends AbstractChartStylePane { + + //字体样式 + private ChartFontPane chartFontPane; + + private UIComboBox typeComboBox; + private List paneList; + private JPanel centerPane; + + //网格线颜色 + private ColorSelectBox mainGridColor; + + protected void initComponents() { + chartFontPane = new ChartFontPane() { + public String getUILabelText() { + return Toolkit.i18nText("Fine-Design_Chart_Title_Character"); + } + }; + + mainGridColor = new ColorSelectBox(100); + + typeComboBox = new UIComboBox(); + final CardLayout cardlayout = new CardLayout(); + initList(); + + centerPane = new JPanel(cardlayout) { + @Override + public Dimension getPreferredSize() {// AUGUST:使用当前面板的的高度 + int index = typeComboBox.getSelectedIndex(); + return new Dimension(super.getPreferredSize().width, paneList.get(index).getPreferredSize().height); + } + }; + for (int i = 0; i < paneList.size(); i++) { + BackgroundQuickPane pane = paneList.get(i); + typeComboBox.addItem(pane.title4PopupWindow()); + centerPane.add(pane, pane.title4PopupWindow()); + } + + typeComboBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + cardlayout.show(centerPane, (String) typeComboBox.getSelectedItem()); + } + }); + } + + private void initList() { + paneList = new ArrayList<>(); + paneList.add(new NullBackgroundQuickPane()); + paneList.add(new ColorBackgroundQuickPane()); + paneList.add(new ImageBackgroundQuickPane(false)); + paneList.add(new VanChartGradientPane()); + } + + protected Component[][] getComponent() { + return new Component[][]{ + new Component[]{chartFontPane, null}, + new Component[]{null, null}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Area_Background_Color")), typeComboBox}, + new Component[]{null, centerPane}, + new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Grid_Line_Color")), mainGridColor} + }; + } + + protected double[] getRows(double p) { + return new double[]{p, p, p, p, p}; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Chart_Title_Background"); + } + + public void populate(ThemedChartStyle chartStyle) { + chartFontPane.populate(chartStyle.getTitleFont()); + Background background = chartStyle.getChartBackground(); + for (int i = 0; i < paneList.size(); i++) { + BackgroundQuickPane pane = paneList.get(i); + if (pane.accept(background)) { + pane.populateBean(background); + typeComboBox.setSelectedIndex(i); + break; + } + } + mainGridColor.setSelectObject(chartStyle.getGridMainLineColor()); + } + + + public void update(ThemedChartStyle chartStyle) { + chartStyle.setTitleFont(chartFontPane.update()); + chartStyle.setChartBackground(paneList.get(typeComboBox.getSelectedIndex()).updateBean()); + if (chartStyle.getChartBackground() instanceof ImageBackground) { + ((ImageBackground) chartStyle.getChartBackground()).setLayout(Constants.IMAGE_EXTEND); + } + chartStyle.setGridMainLineColor(mainGridColor.getSelectObject()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/component/ComponentMarginStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/component/ComponentMarginStylePane.java new file mode 100644 index 000000000..643c1e960 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/component/ComponentMarginStylePane.java @@ -0,0 +1,101 @@ +package com.fr.design.mainframe.theme.edit.component; + +import com.fr.base.theme.settings.ThemedComponentStyle; +import com.fr.design.designer.IntervalConstants; +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 javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.Component; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * Created by kerry on 2020-09-01 + */ +public class ComponentMarginStylePane extends JPanel { + private final int uiLabelWidth; + private final int uiSettingWidth; + + protected UISpinner top; + protected UISpinner bottom; + protected UISpinner left; + protected UISpinner right; + + public ComponentMarginStylePane(int uiLabelWidth, int uiSettingWidth) { + this.uiLabelWidth = uiLabelWidth; + this.uiSettingWidth = uiSettingWidth; + initBoundPane(0, 0, 0, 0); + } + + public void initBoundPane(int t, int b, int l, int r) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + top = new UISpinner(0, Integer.MAX_VALUE, 1, t); + bottom = new UISpinner(0, Integer.MAX_VALUE, 1, b); + left = new UISpinner(0, Integer.MAX_VALUE, 1, l); + right = new UISpinner(0, Integer.MAX_VALUE, 1, r); + + top.setGlobalName(i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); + bottom.setGlobalName(i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); + left.setGlobalName(i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); + right.setGlobalName(i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); + + UILabel uiLabel = new UILabel(i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); + uiLabel.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); + uiLabel.setVerticalAlignment(SwingConstants.TOP); + + + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = { p }; + double[] columnSize = { this.uiLabelWidth, this.uiSettingWidth > 0 ? this.uiSettingWidth : f }; + + JPanel panel = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{new Component[]{uiLabel, createPaddingPane()}}, + rowSize, columnSize, + IntervalConstants.INTERVAL_L1, 0 + ); + this.add(panel); + } + + + public JPanel createPaddingPane() { + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p}; + double[] columnSize = {f, f}; + + Component[][] paddingPane = new Component[][]{ + new Component[]{top, bottom}, + new Component[]{createLabelByKey("Fine-Design_Report_Top"), createLabelByKey("Fine-Design_Report_Bottom")}, + new Component[]{left, right}, + new Component[]{createLabelByKey("Fine-Design_Report_Left"), createLabelByKey("Fine-Design_Basic_Right")} + }; + + return TableLayoutHelper.createGapTableLayoutPane(paddingPane, rowSize, columnSize, IntervalConstants.INTERVAL_L6, IntervalConstants.INTERVAL_L6); + } + + public void populate(ThemedComponentStyle componentStyle) { + this.top.setValue(componentStyle.getPaddingTop()); + this.bottom.setValue(componentStyle.getPaddingBottom()); + this.left.setValue(componentStyle.getPaddingLeft()); + this.right.setValue(componentStyle.getPaddingRight()); + } + + public void update(ThemedComponentStyle componentStyle) { + componentStyle.setPaddingTop((int) this.top.getValue()); + componentStyle.setPaddingBottom((int) this.bottom.getValue()); + componentStyle.setPaddingLeft((int) this.left.getValue()); + componentStyle.setPaddingRight((int) this.right.getValue()); + } + + private UILabel createLabelByKey(String key) { + return new UILabel(i18nText(key), SwingConstants.CENTER); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListExtendedPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListExtendedPane.java new file mode 100644 index 000000000..9d02180e7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListExtendedPane.java @@ -0,0 +1,144 @@ +package com.fr.design.mainframe.theme.edit.ui; + +import com.fr.base.theme.FineColorManager; +import com.fr.design.layout.FRGUIPaneFactory; + +import javax.swing.JPanel; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/7 + */ +public class ColorListExtendedPane extends JPanel implements MouseListener { + public static final int DEFAULT_COLOR_COUNT = 8; + public static final int DEFAULT_EXTENDED_COUNT = 5; + public static final int DEFAULT_COLOR_SIZE = 16; + public static final int DEFAULT_COLOR_GAP = 3; + + public static final ExtendedColorComputer DEFAULT_EXTENDED_COMPUTER = new ExtendedColorComputer() { + @Override + public Color computeExtendedColor(Color color, int index, int count) { + return FineColorManager.computeExtendedColor(color, index, count); + } + }; + + private final boolean selectable; + private final int colorCount; + private final int extendedCount; + private final int boxSize; + private final int boxGap; + + private final List colorList = new ArrayList<>(); + private ExtendedColorComputer extendedColorComputer = DEFAULT_EXTENDED_COMPUTER; + + private int selectedColorIndex = -1; + private int selectedExtendedIndex = -1; + + public ColorListExtendedPane() { + this(false, DEFAULT_COLOR_COUNT, DEFAULT_EXTENDED_COUNT, DEFAULT_COLOR_SIZE, DEFAULT_COLOR_GAP); + } + + public ColorListExtendedPane(boolean selectable, int colorCount, int extendedCount, int boxSize, int boxGap) { + setLayout(FRGUIPaneFactory.createBorderLayout()); + this.selectable = selectable; + this.colorCount = Math.max(1, colorCount); + this.extendedCount = extendedCount; + this.boxSize = boxSize; + this.boxGap = boxGap; + + for (int i = 0; i < colorCount; i++) { + colorList.add(Color.WHITE); + } + + int width = colorCount * boxSize + (colorCount - 1) * boxGap; + int height = extendedCount * boxSize + (extendedCount - 1) * boxGap; + setPreferredSize(new Dimension(width, height)); + } + + public void populate(List colors) { + if (colors.size() > 0) { + colorList.clear(); + colorList.addAll(colors); + repaint(); + } + } + + public List update() { + return new ArrayList<>(colorList); + } + + public void setExtendedColorComputer(ExtendedColorComputer extendedColorComputer) { + this.extendedColorComputer = extendedColorComputer; + } + + @Override + public void mouseClicked(MouseEvent e) { + int x = e.getX(); + int y = e.getY(); + + int colorIndex = x / (boxSize + boxGap); + int colorX = colorIndex * (boxSize + boxGap); + + int extendedIndex = y / boxSize; + int extendedY = extendedIndex * boxSize; + + if (colorX <= x && x <= colorX + boxSize && extendedY <= y && y <= extendedY + boxSize) { + selectedColorIndex = colorIndex; + selectedExtendedIndex = extendedIndex; + } else { + selectedColorIndex = -1; + selectedExtendedIndex = -1; + } + repaint(); + } + + @Override + public void mousePressed(MouseEvent e) { + + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + + } + + public interface ExtendedColorComputer { + Color computeExtendedColor(Color color, int index, int count); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + Color oldColor = g.getColor(); + + for (int i = 0; i < colorCount; i++) { + int x = i * (boxSize + boxGap); + for (int j = 0; j < extendedCount; j++) { + Color color = extendedColorComputer.computeExtendedColor(colorList.get(i), j, extendedCount); + g.setColor(color); + int y = j * (boxSize + boxGap); + g.fillRect(x, y, boxSize, boxSize); + } + } + + g.setColor(oldColor); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListPane.java new file mode 100644 index 000000000..adeca3d7a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/ColorListPane.java @@ -0,0 +1,206 @@ +package com.fr.design.mainframe.theme.edit.ui; + +import com.fr.base.FineColor; +import com.fr.base.background.ColorBackground; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.style.AbstractSelectBox; +import com.fr.design.style.color.NewColorSelectPane; + +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/7 + */ +public class ColorListPane extends JPanel implements UIObserver { + public static final int DEFAULT_COLOR_COUNT = 8; + public static final int DEFAULT_COLOR_SIZE = 16; + public static final int DEFAULT_COLOR_GAP = 3; + + private final int colorCount; + + private final List colorList = new ArrayList<>(); + private final List colorButtons = new ArrayList<>(); + + private final EventListenerList colorChangeListenerList = new EventListenerList(); + private UIObserverListener uiObserverListener; + + public ColorListPane() { + this(DEFAULT_COLOR_COUNT, DEFAULT_COLOR_SIZE, DEFAULT_COLOR_GAP); + } + + public ColorListPane(int colorCount, int boxSize, int boxGap) { + this.colorCount = Math.max(1, colorCount); + + for (int i = 0; i < colorCount; i++) { + colorList.add(Color.WHITE); + } + + setLayout(new GridLayout(1, 8, boxGap, 0)); + + for (int i = 0; i < colorCount; i++) { + ColorButton colorButton = new ColorButton(null); + colorButton.setPreferredSize(new Dimension(boxSize, boxSize)); + add(colorButton); + int index = i; + colorButton.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + colorList.set(index, colorButton.getSelectObject()); + fireColorStateChanged(); + } + }); + + colorButtons.add(colorButton); + } + + setPreferredSize(new Dimension(colorCount * boxSize + (colorCount - 1) * boxGap, boxSize)); + iniListener(); + } + + private void iniListener() { + if (shouldResponseChangeListener()) { + this.addColorChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (uiObserverListener == null) { + return; + } + uiObserverListener.doChange(); + } + }); + } + } + + public void populate(List colors) { + colorList.clear(); + for (int i = 0; i < colors.size(); i++) { + Color color = colors.get(i); + colorList.add(color); + if (i < colorCount) { + colorButtons.get(i).setSelectObject(color); + } + } + } + + public List update() { + return new ArrayList<>(colorList); + } + + public void addColorChangeListener(ChangeListener changeListener) { + colorChangeListenerList.add(ChangeListener.class, changeListener); + } + + public void removeColorChangeListener(ChangeListener changeListener) { + colorChangeListenerList.remove(ChangeListener.class, changeListener); + } + + public void fireColorStateChanged() { + Object[] listeners = colorChangeListenerList.getListenerList(); + ChangeEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + if (e == null) { + e = new ChangeEvent(this); + } + ((ChangeListener) listeners[i + 1]).stateChanged(e); + } + } + } + + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + public boolean shouldResponseChangeListener() { + return true; + } + + private static class ColorButton extends AbstractSelectBox { + private Color color; + private NewColorSelectPane colorPane; + private ChangeListener changeListener; + + public ColorButton(Color color) { + this.color = color; + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + showPopupMenu(); + } + }); + } + + @Override + public JPanel initWindowPane(double preferredWidth) { + colorPane = new NewColorSelectPane(false) { + @Override + public void setVisible(boolean b) { + super.setVisible(b); + } + + @Override + protected boolean selectRealTime() { + return false; + } + }; + colorPane.setColor(this.getSelectObject()); + colorPane.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + hidePopupMenu(); + FineColor fineColor = ((NewColorSelectPane) e.getSource()).getColor(); + // 不要直接使用原始的FineColor对象,它的值会变化,这里实际需要的内部的真实颜色 + color = fineColor.getColor(); + fireDisplayComponent(ColorBackground.getInstance(color)); + ColorListPane.ColorButton.this.fireStateChanged(); + } + }); + return colorPane; + } + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setPaint(color); + g2d.fill(new Rectangle2D.Double(0, 0, getWidth(), getHeight())); + } + + public void fireStateChanged() { + if (changeListener != null) { + changeListener.stateChanged(null); + } + } + + public void addChangeListener(ChangeListener changeListener) { + this.changeListener = changeListener; + } + + public Color getSelectObject() { + return this.color; + } + + public void setSelectObject(Color color) { + this.color = color; + if (this.colorPane != null) { + this.colorPane.setColor(color); + } + fireDisplayComponent(ColorBackground.getInstance(color)); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java new file mode 100644 index 000000000..2b099ed30 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java @@ -0,0 +1,29 @@ +package com.fr.design.mainframe.theme.edit.ui; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.general.FRFont; + +import java.awt.Color; +import java.awt.Font; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/15 + */ +public class LabelUtils { + public static UILabel createLabel(String title) { + return createLabel(title, new Color(51, 51, 52)); + } + + public static UILabel createLabel(String title, Color color) { + return createLabel(title, color, 12); + } + public static UILabel createLabel(String title, Color color, int size) { + UILabel uiLabel = new UILabel(title); + uiLabel.setForeground(color); + Font newFont = FRFont.getInstance(uiLabel.getFont().getFontName(), Font.PLAIN, size); + uiLabel.setFont(newFont); + return uiLabel; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/TabbedPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/TabbedPane.java new file mode 100644 index 000000000..3f4667e11 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/TabbedPane.java @@ -0,0 +1,73 @@ +package com.fr.design.mainframe.theme.edit.ui; + +import com.fr.design.gui.ibutton.UITabGroup; +import com.fr.design.layout.FRGUIPaneFactory; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Dimension; +import java.util.Arrays; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/12 + */ +public class TabbedPane extends JPanel { + protected UITabGroup buttonGroup; + public JPanel tabContentPane; + public CardLayout cardLayout; + private String[] names = new String[]{}; + private JComponent[] panes = new JComponent[]{}; + + public TabbedPane(String[] names, JComponent[] panes) { + setLayout(FRGUIPaneFactory.createBorderLayout()); + setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + for (JComponent pane :panes) { + pane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + } + + int count = Math.min(names.length, panes.length); + if (count > 0) { + this.names = names.length > count ? Arrays.copyOf(names, count) : names; + this.panes = panes.length > count ? Arrays.copyOf(panes, count) : panes; + initializeTabPane(); + } + } + + private void initializeTabPane() { + buttonGroup = new UITabGroup(this.names) { + @Override + public void tabChanged(int index) { + super.tabChanged(index); + cardLayout.show(tabContentPane, names[buttonGroup.getSelectedIndex()]); + } + }; + buttonGroup.setDrawLine(true); + + cardLayout = new CardLayout(); + tabContentPane = new JPanel(cardLayout) { + @Override + public Dimension getPreferredSize() { + int selectedIndex = buttonGroup.getSelectedIndex(); + if (selectedIndex < 0) { + return super.getPreferredSize(); + } else { + return panes[selectedIndex].getPreferredSize(); + } + } + }; + for (int i = 0; i < this.names.length; i++) { + tabContentPane.add(panes[i], names[i]); + } + buttonGroup.setSelectedIndex(0); + cardLayout.show(tabContentPane, names[0]); + + add(buttonGroup, BorderLayout.NORTH); + add(tabContentPane, BorderLayout.CENTER); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartComponentPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartComponentPreviewPane.java new file mode 100644 index 000000000..5c000749f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartComponentPreviewPane.java @@ -0,0 +1,34 @@ +package com.fr.design.mainframe.theme.preview; + +import com.fr.base.theme.FormTheme; + +import java.awt.Component; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ChartComponentPreviewPane extends ComponentPreviewPane implements ThemePreviewed { + private ChartPreviewPane contentPane; + + public ChartComponentPreviewPane(String title) { + super(title); + } + + @Override + protected Component createContentPane() { + contentPane = new ChartPreviewPane(); + return contentPane; + } + + @Override + public void refresh(FormTheme theme) { + super.refresh(theme); + contentPane.refresh(theme); + } + + public ChartPreviewPane getContentPane() { + return contentPane; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartPreviewPane.java new file mode 100644 index 000000000..2029539aa --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ChartPreviewPane.java @@ -0,0 +1,80 @@ +package com.fr.design.mainframe.theme.preview; + +import com.fr.base.chart.BaseChartCollection; +import com.fr.base.chart.BaseChartPainter; +import com.fr.base.chart.chartdata.CallbackEvent; +import com.fr.base.chart.result.WebChartIDInfo; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeCompatible; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.design.gui.chart.MiddleChartComponent; +import com.fr.script.Calculator; +import com.fr.stable.core.PropertyChangeListener; + +import javax.swing.BorderFactory; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ChartPreviewPane extends MiddleChartComponent implements ThemePreviewed { + + private ChartCollection chartCollection; + + private CallbackEvent callbackEvent; + + public ChartPreviewPane() { + this.setBorder(BorderFactory.createEmptyBorder(0, 1, 2, 1)); + } + + public void setCallbackEvent(CallbackEvent callbackEvent) { + this.callbackEvent = callbackEvent; + } + + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + super.paintComponent(g); + if (chartCollection != null) { + drawChart(g2d); + } + drawChart(g2d); + } + + private void drawChart(Graphics2D g2d) { + Dimension d = getBounds().getSize(); + int chartWidth = d.width; + int chartHeight = d.height; + BaseChartPainter painter = chartCollection.createResultChartPainterWithOutDealFormula(Calculator.createCalculator(), + WebChartIDInfo.createEmptyDesignerInfo(), chartWidth, chartHeight); + painter.paint(g2d, chartWidth, chartHeight, 0, null, callbackEvent); + } + + @Override + public void populate(BaseChartCollection cc) { + this.chartCollection = (ChartCollection) cc; + } + + @Override + public BaseChartCollection update() { + return this.chartCollection; + } + + @Override + public void reset() { + + } + + @Override + public void addStopEditingListener(PropertyChangeListener list) { + + } + + @Override + public void refresh(TemplateTheme style) { + chartCollection.onTemplateUsingThemeChange(style, TemplateThemeCompatible.NONE); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ComponentPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ComponentPreviewPane.java new file mode 100644 index 000000000..cb854a3f3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ComponentPreviewPane.java @@ -0,0 +1,205 @@ +package com.fr.design.mainframe.theme.preview; + +import com.fr.base.BaseUtils; +import com.fr.base.Style; +import com.fr.base.background.ImageBackground; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.settings.ThemedComponentStyle; +import com.fr.design.border.UIRoundedBorder; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.form.ui.Label; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.WidgetValue; +import com.fr.general.Background; +import com.fr.general.act.BorderPacker; +import com.fr.general.act.TitlePacker; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.border.LineBorder; +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public abstract class ComponentPreviewPane extends UINoOpaquePanel implements ThemePreviewed { + public static final int TITLE_HEIGHT = 46; + + private final JPanel container; + private TitleDemoPane titlePane; + private BorderPacker style = new LayoutBorderStyle(); + + public ComponentPreviewPane(){ + this(StringUtils.EMPTY); + } + + public ComponentPreviewPane(String title) { + container = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + setLayout(new BorderLayout()); + if (StringUtils.isNotEmpty(title)) { + titlePane = new TitleDemoPane(title); + titlePane.setPreferredSize(new Dimension(517, TITLE_HEIGHT)); + container.add(titlePane, BorderLayout.NORTH); + } + container.add(createContentPane(), BorderLayout.CENTER); + add(container, BorderLayout.CENTER); + } + + protected abstract Component createContentPane(); + + @Override + public void refresh(FormTheme theme) { + ThemedComponentStyle componentStyle = theme.getComponentStyle(); + + style = componentStyle.getStyle(); + if (style.getBorder() == 0) { + setBorder(null); + } else { + setBorder(new UIRoundedBorder(style.getBorder(), style.getColor(), style.getBorderRadius())); + } + + int paddingTop = componentStyle.getPaddingTop(); + int paddingBottom = componentStyle.getPaddingBottom(); + int paddingLeft = componentStyle.getPaddingLeft(); + int paddingRight = componentStyle.getPaddingRight(); + container.setBorder(BorderFactory.createEmptyBorder(paddingTop, paddingLeft, paddingBottom, paddingRight)); + if (titlePane != null) { + titlePane.refresh(componentStyle); + } + + } + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + + Border border = getBorder(); + if (border instanceof UIRoundedBorder) { + UIRoundedBorder roundedBorder = (UIRoundedBorder) border; + Utils.clipByRoundBorder(g2d, getWidth(), getHeight(), roundedBorder.getRoundedCorner(), roundedBorder.getThickness()); + } + + int titleHeight = titlePane == null ? 0 : titlePane.getHeight(); + Utils.paintBackground(g2d, style.getBackground(), new Rectangle2D.Double(0, titleHeight, getWidth(), getHeight() - titleHeight), style.getAlpha()); + + Utils.paintBackground(g2d, style.getBorderImage(), new Rectangle2D.Double(0, 0, getWidth(), getHeight()), style.getBorderImageOpacity()); + + super.paint(g); + } + + private static class TitleDemoPane extends UINoOpaquePanel { + private final Label data = new Label(); + private String title = StringUtils.EMPTY; + + public TitleDemoPane(String title){ + this.title = title; + } + + public void refresh(ThemedComponentStyle componentStyle) { + BorderPacker borderPacker = componentStyle.getStyle(); + TitlePacker titlePacker = componentStyle.getStyle().getTitle(); + + data.setColor(borderPacker.getColor()); + data.setWidgetValue(new WidgetValue(String.valueOf(titlePacker.getTextObject()))); + data.setFont(titlePacker.getFrFont()); + data.setTextalign(titlePacker.getPosition()); + data.setBackground(titlePacker.getBackground()); + data.setBackgroundOpacity(titlePacker.getBackgroundOpacity()); + + data.setInsetImage(titlePacker.getInsetImage()); + data.setInsetImagePadding(titlePacker.getInsetImagePadding()); + data.setInsetRelativeTextLeft(titlePacker.isInsetRelativeTextLeft()); + data.setInsetRelativeTextRight(titlePacker.isInsetRelativeTextRight()); + this.setBorder(new BottomLineBorder(componentStyle.getStyle().getColor(), componentStyle.getStyle().getBorder())); + } + + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Dimension size = getSize(); + Background background = data.getBackground(); + float opacity = data.getBackgroundOpacity(); + if (background != null) { + Utils.paintBackground((Graphics2D) g, background, new Rectangle2D.Double(0, 0, size.getWidth(), size.getHeight()), opacity); + } + + Graphics2D g2d = (Graphics2D) g.create(); + Background inset = data.getInsetImage(); + Image insetImage = inset instanceof ImageBackground ? ((ImageBackground) inset).getImage() : null; + + BaseUtils.drawStringStyleInRotation(g2d, + getWidth(), getHeight(), + title, + Style.getInstance(data.getFont()) + .deriveHorizontalAlignment(data.getTextalign()) + .deriveVerticalAlignment(data.isVerticalCenter() ? SwingConstants.CENTER : SwingConstants.TOP) + .deriveTextStyle(data.isWrap() ? Style.TEXTSTYLE_WRAPTEXT : Style.TEXTSTYLE_SINGLELINE), + insetImage, data.getInsetImagePadding(), data.isInsetRelativeTextLeft(), data.isInsetRelativeTextRight(), + Constants.FR_PAINT_RESOLUTION); + } + + } + + public static class BottomLineBorder extends LineBorder { + + private BottomLineBorder(Color color, int thickness) { + super(color, thickness); + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Graphics2D g2d = (Graphics2D) g; + + Color oldColor = g2d.getColor(); + Stroke oldStroke = g2d.getStroke(); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setColor(getLineColor()); + g2d.setStroke(new BasicStroke(getThickness() * 2)); + g2d.drawLine(0, height, width, height); + + g2d.setStroke(oldStroke); + g2d.setColor(oldColor); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + } + + + private static class Utils { + private static void paintBackground(Graphics2D g2d, Background background, Shape shape, float opacity) { + if (background != null) { + Composite oldComposite = g2d.getComposite(); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, opacity)); + background.paint(g2d, shape); + g2d.setComposite(oldComposite); + } + } + + private static void clipByRoundBorder(Graphics2D g2d, int width, int height, int radius, int borderThickness) { + int currentClipRadius = Math.max(radius - borderThickness, 0); + g2d.clip(new RoundRectangle2D.Double(0, 0, width, height, currentClipRadius, currentClipRadius)); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/FormThemePreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/FormThemePreviewPane.java new file mode 100644 index 000000000..18ac4b962 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/FormThemePreviewPane.java @@ -0,0 +1,201 @@ +package com.fr.design.mainframe.theme.preview; + +import com.fr.base.BaseFormula; +import com.fr.base.background.ColorBackground; +import com.fr.base.theme.FormTheme; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.chart.chartattr.Title; +import com.fr.chart.chartdata.NormalChartData; +import com.fr.chart.charttypes.ChartTypeManager; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.TemplateThemePreviewPane; +import com.fr.design.mainframe.theme.preview.ecpreview.ECComponentPreviewPane; +import com.fr.general.Background; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.chart.PiePlot4VanChart; +import com.fr.plugin.chart.attr.axis.VanChartAxis; +import com.fr.plugin.chart.base.AttrLabel; +import com.fr.plugin.chart.base.VanChartTools; +import com.fr.plugin.chart.column.VanChartColumnPlot; +import com.fr.plugin.chart.type.GradientType; +import com.fr.plugin.chart.type.RadiusType; +import com.fr.plugin.chart.vanchart.VanChart; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +import javax.swing.JPanel; +import java.awt.AlphaComposite; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class FormThemePreviewPane extends TemplateThemePreviewPane { + private ECComponentPreviewPane elementCasePane; + private Background background; + private ChartComponentPreviewPane columnChartPreviewPane; + private ChartComponentPreviewPane pieChartPreviewPane; + private float alpha = 1.0F; + + public FormThemePreviewPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel content = new UINoOpaquePanel(); + content.setLayout(new BorderLayout()); + content.add(createChartContent(), BorderLayout.CENTER); + content.add(elementCasePane = new ECComponentPreviewPane(), BorderLayout.SOUTH); + add(content, BorderLayout.CENTER); + } + + private JPanel createChartContent() { + JPanel chartContent = new UINoOpaquePanel(); + chartContent.setLayout(new BorderLayout()); + JPanel columnChartPanel = new UINoOpaquePanel() { + public Dimension getPreferredSize() { + return new Dimension(379, 314); + } + }; + columnChartPanel.setLayout(new BorderLayout()); + columnChartPreviewPane = createChartPreviewPane(initColumnChart(), i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Column_Title")); + columnChartPanel.add(columnChartPreviewPane, BorderLayout.CENTER); + + JPanel pieChartPanel = new UINoOpaquePanel() { + public Dimension getPreferredSize() { + return new Dimension(236, 314); + } + }; + pieChartPanel.setLayout(new BorderLayout()); + pieChartPreviewPane = createChartPreviewPane(initPieChart(), i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_Pie_Title")); + pieChartPanel.add(pieChartPreviewPane, BorderLayout.CENTER); + chartContent.add(columnChartPanel, BorderLayout.CENTER); + chartContent.add(pieChartPanel, BorderLayout.EAST); + return chartContent; + } + + private ChartComponentPreviewPane createChartPreviewPane(ChartCollection chartCollection, String title) { + ChartComponentPreviewPane chartComponentPreviewPane = new ChartComponentPreviewPane(title); + chartComponentPreviewPane.getContentPane().populate(chartCollection); + chartComponentPreviewPane.getContentPane().setCallbackEvent(this); + return chartComponentPreviewPane; + } + + @Override + public void refresh(FormTheme theme) { + background = theme.getBodyStyle().getStyle().getBackground(); + alpha = theme.getBodyStyle().getStyle().getAlpha(); + elementCasePane.refresh(theme); + columnChartPreviewPane.refresh(theme); + pieChartPreviewPane.refresh(theme); + repaint(); + } + + + protected void paintBackground(Graphics2D g2d) { + if (background == null) { + background = ColorBackground.getInstance(Color.WHITE); + } + Composite oldComposite = g2d.getComposite(); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); + background.paint(g2d, new Rectangle2D.Double(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT)); + g2d.setComposite(oldComposite); + } + + //柱形图 + private ChartCollection initColumnChart() { + try { + VanChart chart = (VanChart) ChartTypeManager.getInstance().getCharts(VanChartColumnPlot.VAN_CHART_COLUMN_PLOT_ID)[0].clone(); + chart.getTitle().setTitleVisible(false); + VanChartTools vanChartTools = chart.getVanChartTools(); + vanChartTools.setSort(false); + vanChartTools.setExport(false); + vanChartTools.setFullScreen(false); + + VanChartColumnPlot plot = chart.getPlot(); + AttrLabel defaultAttrLabel = plot.getDefaultAttrLabel(); + defaultAttrLabel.setEnable(true); + defaultAttrLabel.getAttrLabelDetail().getBorder().setBorderStyle(0); + defaultAttrLabel.getAttrLabelDetail().getBackground().setBackground(null); + plot.getConditionCollection().getDefaultAttr().addDataSeriesCondition(defaultAttrLabel); + + plot.getLegend().setPosition(Constants.TOP); + plot.getGradientStyle().setGradientType(GradientType.NONE); + plot.setSeriesOverlapPercent(30); + plot.setCategoryIntervalPercent(30); + + VanChartAxis defaultYAxis = plot.getDefaultYAxis(); + Title title = new Title(); + title.setTextObject(Toolkit.i18nText("Fine-Design_Chart_Axis_Title")); + title.getTextAttr().setRotation(-90); + title.getTextAttr().setThemed(true); + defaultYAxis.setTitle(title); + defaultYAxis.setShowAxisTitle(true); + defaultYAxis.setCustomMaxValue(true); + defaultYAxis.setCustomMinValue(true); + defaultYAxis.setCustomMainUnit(true); + defaultYAxis.setMaxValue(BaseFormula.createFormulaBuilder().build("=600")); + defaultYAxis.setMinValue(BaseFormula.createFormulaBuilder().build("=0")); + defaultYAxis.setMainUnit(BaseFormula.createFormulaBuilder().build("=200")); + + Object[] category = { + Toolkit.i18nText("Fine-Design_Chart_Category") + "1", + Toolkit.i18nText("Fine-Design_Chart_Category") + "2", + Toolkit.i18nText("Fine-Design_Chart_Category") + "3", + Toolkit.i18nText("Fine-Design_Chart_Category") + "4" + }; + Object[] series = { + Toolkit.i18nText("Fine-Design_Chart_Series") + "1", + Toolkit.i18nText("Fine-Design_Chart_Series") + "2" + }; + Object[][] value = { + {"250", "540", "300", "410"}, + {"180", "190", "170", "100"}, + }; + NormalChartData normalChartData = new NormalChartData(category, series, value); + chart.setPreViewChartData(normalChartData); + ChartCollection chartCollection = new ChartCollection(chart); + return chartCollection; + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return null; + } + + //饼图 + private ChartCollection initPieChart() { + try { + VanChart chart = (VanChart) ChartTypeManager.getInstance().getCharts(PiePlot4VanChart.VAN_CHART_PIE_PLOT)[0].clone(); + chart.getTitle().setTitleVisible(false); + VanChartTools vanChartTools = chart.getVanChartTools(); + vanChartTools.setSort(false); + vanChartTools.setExport(false); + vanChartTools.setFullScreen(false); + + PiePlot4VanChart plot = chart.getPlot(); + plot.getLegend().setPosition(Constants.BOTTOM); + plot.getGradientStyle().setGradientType(GradientType.NONE); + plot.setInnerRadiusPercent(75); + plot.getRadius().setRadiusType(RadiusType.FIXED); + plot.getRadius().setRadius(80); + + Object[] category = {StringUtils.EMPTY}; + Object[] series = {"A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1"}; + Object[][] value = {{45}, {24}, {12}, {8}, {5}, {3}, {2}, {1},}; + NormalChartData normalChartData = new NormalChartData(category, series, value); + chart.setPreViewChartData(normalChartData); + ChartCollection chartCollection = new ChartCollection(chart); + return chartCollection; + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ReportThemePreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ReportThemePreviewPane.java new file mode 100644 index 000000000..4ceec636d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ReportThemePreviewPane.java @@ -0,0 +1,128 @@ +package com.fr.design.mainframe.theme.preview; + +import com.fr.base.BaseFormula; +import com.fr.base.background.ColorBackground; +import com.fr.base.theme.ReportTheme; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.chart.chartattr.Title; +import com.fr.chart.chartdata.NormalChartData; +import com.fr.chart.charttypes.ChartTypeManager; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.TemplateThemePreviewPane; +import com.fr.design.mainframe.theme.preview.ecpreview.ECReportPreviewPane; +import com.fr.general.Background; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.chart.attr.axis.VanChartAxis; +import com.fr.plugin.chart.base.AttrLabel; +import com.fr.plugin.chart.base.VanChartTools; +import com.fr.plugin.chart.column.VanChartColumnPlot; +import com.fr.plugin.chart.type.GradientType; +import com.fr.plugin.chart.vanchart.VanChart; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ReportThemePreviewPane extends TemplateThemePreviewPane { + private Background background; + + private final ECReportPreviewPane reportPreviewPane; + + private final ChartPreviewPane chartPreviewPane; + + public ReportThemePreviewPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + chartPreviewPane = new ChartPreviewPane(); + chartPreviewPane.setPreferredSize(new Dimension(615, 237)); + chartPreviewPane.populate(initColumnChart()); + chartPreviewPane.setCallbackEvent(this); + reportPreviewPane = new ECReportPreviewPane(); + this.add(reportPreviewPane, BorderLayout.CENTER); + this.add(chartPreviewPane, BorderLayout.SOUTH); + } + + @Override + public void refresh(ReportTheme theme) { + background = theme.getBodyStyle().getBackground(); + reportPreviewPane.refresh(theme); + chartPreviewPane.refresh(theme); + repaint(); + } + + + protected void paintBackground(Graphics2D g2d) { + if (background == null) { + background = ColorBackground.getInstance(Color.WHITE); + } + background.paint(g2d, new Rectangle2D.Double(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT)); + } + + + //柱形图 + private ChartCollection initColumnChart() { + try { + VanChart chart = (VanChart) ChartTypeManager.getInstance().getCharts(VanChartColumnPlot.VAN_CHART_COLUMN_PLOT_ID)[0].clone(); + VanChartTools vanChartTools = chart.getVanChartTools(); + vanChartTools.setSort(false); + vanChartTools.setExport(false); + vanChartTools.setFullScreen(false); + + VanChartColumnPlot plot = chart.getPlot(); + AttrLabel defaultAttrLabel = plot.getDefaultAttrLabel(); + defaultAttrLabel.setEnable(true); + defaultAttrLabel.getAttrLabelDetail().getBorder().setBorderStyle(0); + defaultAttrLabel.getAttrLabelDetail().getBackground().setBackground(null); + plot.getConditionCollection().getDefaultAttr().addDataSeriesCondition(defaultAttrLabel); + + plot.getGradientStyle().setGradientType(GradientType.NONE); + plot.setSeriesOverlapPercent(30); + plot.setCategoryIntervalPercent(30); + + VanChartAxis defaultYAxis = plot.getDefaultYAxis(); + Title title = new Title(); + title.setTextObject(Toolkit.i18nText("Fine-Design_Chart_Axis_Title")); + title.getTextAttr().setRotation(-90); + title.getTextAttr().setThemed(true); + defaultYAxis.setTitle(title); + defaultYAxis.setShowAxisTitle(true); + defaultYAxis.setCustomMaxValue(true); + defaultYAxis.setCustomMinValue(true); + defaultYAxis.setCustomMainUnit(true); + defaultYAxis.setMaxValue(BaseFormula.createFormulaBuilder().build("=600")); + defaultYAxis.setMinValue(BaseFormula.createFormulaBuilder().build("=0")); + defaultYAxis.setMainUnit(BaseFormula.createFormulaBuilder().build("=200")); + + Object[] category = { + Toolkit.i18nText("Fine-Design_Chart_Category") + "1", + Toolkit.i18nText("Fine-Design_Chart_Category") + "2", + Toolkit.i18nText("Fine-Design_Chart_Category") + "3", + Toolkit.i18nText("Fine-Design_Chart_Category") + "4" + }; + Object[] series = { + Toolkit.i18nText("Fine-Design_Chart_Series") + "1", + Toolkit.i18nText("Fine-Design_Chart_Series") + "2", + Toolkit.i18nText("Fine-Design_Chart_Series") + "3" + }; + Object[][] value = { + {"340", "510", "300", "250"}, + {"180", "360", "170", "100"}, + {"210", "205", "405", "190"} + }; + NormalChartData normalChartData = new NormalChartData(category, series, value); + chart.setPreViewChartData(normalChartData); + ChartCollection chartCollection = new ChartCollection(chart); + return chartCollection; + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ThemePreviewed.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ThemePreviewed.java new file mode 100644 index 000000000..bb2aa05c2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ThemePreviewed.java @@ -0,0 +1,10 @@ +package com.fr.design.mainframe.theme.preview; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public interface ThemePreviewed { + void refresh(T style); +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/UINoOpaquePanel.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/UINoOpaquePanel.java new file mode 100644 index 000000000..16eb2d55e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/UINoOpaquePanel.java @@ -0,0 +1,19 @@ +package com.fr.design.mainframe.theme.preview; + +import javax.swing.JPanel; +import java.awt.LayoutManager; + +public class UINoOpaquePanel extends JPanel { + + public UINoOpaquePanel(){ + super(); + this.setOpaque(false); + this.setBackground(null); + } + + public UINoOpaquePanel(LayoutManager layout) { + super(layout, true); + this.setOpaque(false); + this.setBackground(null); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/AbstractECPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/AbstractECPreviewPane.java new file mode 100644 index 000000000..3d55153ab --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/AbstractECPreviewPane.java @@ -0,0 +1,47 @@ +package com.fr.design.mainframe.theme.preview.ecpreview; + +import com.fr.base.Style; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.design.mainframe.theme.preview.ThemePreviewed; +import com.fr.design.mainframe.theme.preview.UINoOpaquePanel; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.AbstractPreviewCell; + +import java.util.List; + +public abstract class AbstractECPreviewPane extends UINoOpaquePanel implements ThemePreviewed { + protected Style getReportBigTitleStyle(ThemedCellStyleList cellStyleList) { + return getCellStyle(cellStyleList.getUse4BigTitle()); + } + protected Style getReportHeaderStyle(ThemedCellStyleList cellStyleList) { + return getCellStyle(cellStyleList.getUse4Header()); + } + + protected Style getMainContentStyle(ThemedCellStyleList cellStyleList) { + return getCellStyle(cellStyleList.getUse4MainText()); + } + + protected Style getHighLightStyle(ThemedCellStyleList cellStyleList) { + return getCellStyle(cellStyleList.getUse4HighlightText()); + } + + protected Style getSmallTitleStyle(ThemedCellStyleList cellStyleList) { + return getCellStyle(cellStyleList.getUse4SmallTitle()); + } + + private Style getCellStyle(ThemedCellStyle themedCellStyle) { + if (themedCellStyle == null) { + return Style.DEFAULT_STYLE; + } + Style style = themedCellStyle.getStyle(); + return style != null ? style : Style.DEFAULT_STYLE; + } + + protected void refresh(List list, Style style) { + for (AbstractPreviewCell cell : list) { + cell.refresh(style); + } + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECComponentPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECComponentPreviewPane.java new file mode 100644 index 000000000..427b92cd5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECComponentPreviewPane.java @@ -0,0 +1,33 @@ +package com.fr.design.mainframe.theme.preview.ecpreview; + +import com.fr.base.theme.FormTheme; +import com.fr.design.mainframe.theme.preview.ComponentPreviewPane; + +import java.awt.Component; + +import static com.fr.design.i18n.Toolkit.i18nText; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ECComponentPreviewPane extends ComponentPreviewPane { + private ECPreviewPane contentPane; + + public ECComponentPreviewPane(){ + super(i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Title")); + } + + @Override + protected Component createContentPane() { + contentPane = new ECPreviewPane(); + return contentPane; + } + + @Override + public void refresh(FormTheme theme) { + super.refresh(theme); + contentPane.refresh(theme); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECPreviewPane.java new file mode 100644 index 000000000..4493ed263 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECPreviewPane.java @@ -0,0 +1,103 @@ +package com.fr.design.mainframe.theme.preview.ecpreview; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.preview.UINoOpaquePanel; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.AbstractPreviewCell; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.PreviewCell; +import com.fr.log.FineLoggerFactory; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.io.BufferedReader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/13 + */ +public class ECPreviewPane extends AbstractECPreviewPane { + private static String csv = + "城市 当月目标 当月完成 月完成率 年完成率\n" + + "合肥市 248,938 348,938 140% 140%\n" + + "邵阳市 248,938 348,938 140% 140%\n" + + "合计 1,071,460 1,371,460 128% 128%"; + private final List DATA_LIST = createDataList(); + private static final String BLANK_CHAR = " "; + private List headerCellList = new ArrayList<>(); + private List contentCellList = new ArrayList<>(); + private List hightLightCellList = new ArrayList<>(); + + private List createDataList() { + List data = new ArrayList<>(); + try (BufferedReader reader = new BufferedReader(new StringReader(csv))) { + String textLine; + while ((textLine = reader.readLine()) != null) { + String[] texts = textLine.split(BLANK_CHAR); + data.add(texts); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return data; + } + + + public ECPreviewPane() { + this.setPreferredSize(new Dimension(517, 147)); + this.setBorder(BorderFactory.createEmptyBorder(0, 1, 2, 1)); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + String[] titleArr = DATA_LIST.get(0); + String[] endArr = DATA_LIST.get(DATA_LIST.size() - 1); + JPanel titlePane = new UINoOpaquePanel(new GridLayout()); + this.add(titlePane, BorderLayout.NORTH); + for (String title : titleArr) { + PreviewCell cell = new PreviewCell(title); + cell.setPreferredSize(new Dimension(103, 36)); + titlePane.add(cell); + headerCellList.add(cell); + } + + JPanel contentPane = new UINoOpaquePanel(new GridLayout(2, 5, 0, 0)); + this.add(contentPane, BorderLayout.CENTER); + for (int i = 1; i < DATA_LIST.size() - 1; i++) { + String[] textLine = DATA_LIST.get(i); + for (int j = 0; j < textLine.length; j++) { + String text = textLine[j]; + PreviewCell cell = new PreviewCell(text); + cell.setPreferredSize(new Dimension(103, 33)); + contentPane.add(cell); + contentCellList.add(cell); + } + } + + JPanel endPane = new UINoOpaquePanel(new GridLayout()); + this.add(endPane, BorderLayout.SOUTH); + for (String text : endArr) { + PreviewCell cell = new PreviewCell(text); + cell.setPreferredSize(new Dimension(103, 33)); + endPane.add(cell); + hightLightCellList.add(cell); + } + + + } + + @Override + public void refresh(TemplateTheme theme) { + ThemedCellStyleList cellStyleConfig = theme.getCellStyleList(); + refresh(headerCellList, getReportHeaderStyle(cellStyleConfig)); + refresh(contentCellList, getMainContentStyle(cellStyleConfig)); + refresh(hightLightCellList, getHighLightStyle(cellStyleConfig)); + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECReportPreviewPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECReportPreviewPane.java new file mode 100644 index 000000000..231233196 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/ECReportPreviewPane.java @@ -0,0 +1,135 @@ +package com.fr.design.mainframe.theme.preview.ecpreview; + +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyleList; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.theme.preview.ThemePreviewed; +import com.fr.design.mainframe.theme.preview.UINoOpaquePanel; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.AbstractPreviewCell; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.CornerPreviewCell; +import com.fr.design.mainframe.theme.preview.ecpreview.cell.PreviewCell; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; + +public class ECReportPreviewPane extends UINoOpaquePanel implements ThemePreviewed { + private List headerTitleCellList = new ArrayList<>(); + private List headerCellList = new ArrayList<>(); + private List titleCellList = new ArrayList<>(); + private List contentCellList = new ArrayList<>(); + private List highLightCellList = new ArrayList<>(); + + private PreviewPane previewPane; + + public ECReportPreviewPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + previewPane = new PreviewPane(); + this.add(previewPane, BorderLayout.CENTER); + } + + @Override + public void refresh(ReportTheme theme) { + previewPane.refresh(theme); + } + + + class PreviewPane extends AbstractECPreviewPane { + + + public PreviewPane() { + this.setPreferredSize(new Dimension(517, 270)); + this.setBorder(BorderFactory.createEmptyBorder(7, 10, 5, 10)); + + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel northPane = createNorthPane(); + JPanel centerPane = createCenterPane(); + this.add(northPane, BorderLayout.NORTH); + this.add(centerPane, BorderLayout.CENTER); + } + + private JPanel createNorthPane() { + JPanel northPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + AbstractPreviewCell bigTitleCell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Big_Title")); + bigTitleCell.setPreferredSize(new Dimension(615, 46)); + headerTitleCellList.add(bigTitleCell); + northPane.add(bigTitleCell, BorderLayout.NORTH); + CornerPreviewCell cornerCell = new CornerPreviewCell(new String[]{Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Product"), + Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Data"), Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Statistical_Dimension")}, + new Point2D[]{new Point(159, 71), new Point(226, 49)}); + cornerCell.setPreferredSize(new Dimension(226, 71)); + headerCellList.add(cornerCell); + northPane.add(cornerCell, BorderLayout.WEST); + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + northPane.add(centerPane, BorderLayout.CENTER); + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Statistical_By_Area")); + titleCellList.add(cell); + cell.setPreferredSize(new Dimension(308, 38)); + centerPane.add(cell, BorderLayout.NORTH); + JPanel eastSouthPane = new UINoOpaquePanel(new GridLayout()); + PreviewCell cell1 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_East_China")); + PreviewCell cell2 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_South_China")); + PreviewCell cell3 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Subtotal")); + headerCellList.add(cell1); + headerCellList.add(cell2); + headerCellList.add(cell3); + eastSouthPane.add(cell1); + eastSouthPane.add(cell2); + eastSouthPane.add(cell3); + centerPane.add(eastSouthPane, BorderLayout.CENTER); + return northPane; + } + + private JPanel createCenterPane() { + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + JPanel westPane = FRGUIPaneFactory.createBorderLayout_NO_Opaque_Pane(); + centerPane.add(westPane, BorderLayout.WEST); + PreviewCell cell1 = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Drink")); + titleCellList.add(cell1); + cell1.setPreferredSize(new Dimension(112, 153)); + westPane.add(cell1, BorderLayout.WEST); + JPanel gridPane = new UINoOpaquePanel(new GridLayout(5, 1)); + for (int i = 0; i < 5; i++) { + PreviewCell cell = new PreviewCell(Toolkit.i18nText("Fine-Design_Basic_Template_Theme_Profile_Pane_EC_Apple_Juice")); + cell.setPreferredSize(new Dimension(114, 31)); + headerCellList.add(cell); + gridPane.add(cell); + } + westPane.add(gridPane, BorderLayout.CENTER); + + JPanel innerCenterPane = new UINoOpaquePanel(new GridLayout(5, 3)); + centerPane.add(innerCenterPane, BorderLayout.CENTER); + for (int i = 0; i < 15; i++) { + PreviewCell cell = new PreviewCell("35600"); + cell.setPreferredSize(new Dimension(123, 31)); + if ((i + 1) % 3 == 0) { + highLightCellList.add(cell); + } else { + contentCellList.add(cell); + } + innerCenterPane.add(cell); + } + + + return centerPane; + } + + @Override + public void refresh(TemplateTheme theme) { + ThemedCellStyleList cellStyleConfig = theme.getCellStyleList(); + refresh(headerTitleCellList, getReportBigTitleStyle(cellStyleConfig)); + refresh(headerCellList, getReportHeaderStyle(cellStyleConfig)); + refresh(contentCellList, getMainContentStyle(cellStyleConfig)); + refresh(titleCellList, getSmallTitleStyle(cellStyleConfig)); + refresh(highLightCellList, getHighLightStyle(cellStyleConfig)); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/AbstractPreviewCell.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/AbstractPreviewCell.java new file mode 100644 index 000000000..a8a5f1892 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/AbstractPreviewCell.java @@ -0,0 +1,31 @@ +package com.fr.design.mainframe.theme.preview.ecpreview.cell; + +import com.fr.base.Style; +import javax.swing.JComponent; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; + +public abstract class AbstractPreviewCell extends JComponent { + protected Style style = Style.DEFAULT_STYLE; + private static final int NO_SCALE_RESOLUTION = 100; + + + public void refresh(Style style) { + this.style = style; + } + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + Style.paintBackground(g2d, style, getWidth(), getHeight()); + paintContent(g2d, NO_SCALE_RESOLUTION); + Style.paintBorder(g2d, style, getWidth(), getHeight()); + } + + protected abstract void paintContent(Graphics2D g2d, int resolution); + + @Override + public Dimension getMinimumSize() { + return new Dimension(125, 30); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/CornerPreviewCell.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/CornerPreviewCell.java new file mode 100644 index 000000000..c82ea9fa9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/CornerPreviewCell.java @@ -0,0 +1,33 @@ +package com.fr.design.mainframe.theme.preview.ecpreview.cell; + +import com.fr.general.FRFont; +import com.fr.stable.GraphDrawHelper; + +import java.awt.Graphics2D; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; + +public class CornerPreviewCell extends AbstractPreviewCell { + private final String[] values; + private final Point2D[] point2DS; + + public CornerPreviewCell(String[] values, Point2D[] point2DS) { + this.values = values; + this.point2DS = point2DS; + } + + @Override + protected void paintContent(Graphics2D g2d, int resolution) { + FRFont frFont = style.getFRFont(); + g2d.setPaint(frFont.getForeground()); + g2d.drawString(values[0], 23, 53); + GraphDrawHelper.drawRotatedString(g2d, values[1], 128, 50, 30); + g2d.drawString(values[2], 150, 23); + //画分割线 + for (int i = 0; i < point2DS.length; i++) { + g2d.draw(new Line2D.Double(0, 0, point2DS[i].getX(), point2DS[i].getY())); //画线 + } + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/PreviewCell.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/PreviewCell.java new file mode 100644 index 000000000..a6a5836db --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/preview/ecpreview/cell/PreviewCell.java @@ -0,0 +1,25 @@ +package com.fr.design.mainframe.theme.preview.ecpreview.cell; + +import com.fr.base.Style; + +import java.awt.Dimension; +import java.awt.Graphics2D; + +public class PreviewCell extends AbstractPreviewCell { + + private final String value; + + public PreviewCell(String value) { + this.value = value; + } + + @Override + protected void paintContent(Graphics2D g2d, int resolution) { + Style.paintContent(g2d, value, style, getWidth() - 3, getHeight() - 3, resolution); + } + + @Override + public Dimension getMinimumSize() { + return new Dimension(125, 30); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeManageActionProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeManageActionProvider.java new file mode 100644 index 000000000..6d9744693 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeManageActionProvider.java @@ -0,0 +1,23 @@ +package com.fr.design.mainframe.theme.provider; + +import com.fr.stable.fun.impl.AbstractProvider; +import com.fr.stable.fun.mark.API; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/7 + */ +@API(level = ThemeManageActionProvider.CURRENT_LEVEL) +public abstract class AbstractThemeManageActionProvider extends AbstractProvider implements ThemeManageActionProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public String mark4Provider() { + return getClass().getName(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeProfileActionProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeProfileActionProvider.java new file mode 100644 index 000000000..0ff446e80 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/AbstractThemeProfileActionProvider.java @@ -0,0 +1,23 @@ +package com.fr.design.mainframe.theme.provider; + +import com.fr.stable.fun.impl.AbstractProvider; +import com.fr.stable.fun.mark.API; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/7 + */ +@API(level = ThemeProfileActionProvider.CURRENT_LEVEL) +public abstract class AbstractThemeProfileActionProvider extends AbstractProvider implements ThemeProfileActionProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public String mark4Provider() { + return getClass().getName(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeManageActionProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeManageActionProvider.java new file mode 100644 index 000000000..fd9f452f5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeManageActionProvider.java @@ -0,0 +1,28 @@ +package com.fr.design.mainframe.theme.provider; + +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.mainframe.theme.dialog.TemplateThemeDialog; +import com.fr.stable.fun.mark.Mutable; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/7 + */ +public interface ThemeManageActionProvider extends Mutable { + + String MARK_STRING = "ThemeManageActionProvider"; + + int CURRENT_LEVEL = 1; + + UIButton createButton(ThemeManageActionContext context); + + interface ThemeManageActionContext { + + TemplateThemeDialog getDialog(); + + TemplateThemeConfig getConfig(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeProfileActionProvider.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeProfileActionProvider.java new file mode 100644 index 000000000..cabf0a13a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/provider/ThemeProfileActionProvider.java @@ -0,0 +1,27 @@ +package com.fr.design.mainframe.theme.provider; + +import com.fr.base.theme.TemplateTheme; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.mainframe.theme.TemplateThemeProfilePane; +import com.fr.design.mainframe.theme.dialog.TemplateThemeDialog; +import com.fr.stable.fun.mark.Mutable; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/7 + */ +public interface ThemeProfileActionProvider extends Mutable { + + String MARK_STRING = "ThemeProfileActionProvider"; + + int CURRENT_LEVEL = 1; + + UIButton createButton(ThemeProfileActionContext context); + + interface ThemeProfileActionContext { + TemplateThemeDialog getDialog(); + + TemplateThemeProfilePane getProfilePane(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/BorderUtils.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/BorderUtils.java new file mode 100644 index 000000000..3b7a8b6c0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/BorderUtils.java @@ -0,0 +1,30 @@ +package com.fr.design.mainframe.theme.ui; + +import com.fr.design.border.UIRoundedBorder; +import com.fr.general.FRFont; + +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +import java.awt.Color; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/15 + */ +public class BorderUtils { + public static Border createTitleBorder(String title) { + return createTitleBorder(title, 12); + } + public static Border createTitleBorder(String title, int size) { + return new NoEdgeTitleBorder( + new UIRoundedBorder(new Color(0XE0E0E1), 1, 1), + title, + TitledBorder.LEADING, + TitledBorder.TOP, + FRFont.getInstance().applySize(size), + new Color(47, 142, 241) + ); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/NoEdgeTitleBorder.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/NoEdgeTitleBorder.java new file mode 100644 index 000000000..bf532b00f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/ui/NoEdgeTitleBorder.java @@ -0,0 +1,320 @@ +package com.fr.design.mainframe.theme.ui; + +import javax.swing.JLabel; +import javax.swing.UIManager; +import javax.swing.border.AbstractBorder; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +import javax.swing.plaf.basic.BasicHTML; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.geom.Path2D; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/16 + * 修正TitleBorder默认的行为,使得组件有多大,边框就有多大 + */ +public class NoEdgeTitleBorder extends TitledBorder { + + private final JLabel label; + + public NoEdgeTitleBorder(Border border, String title, int titleJustification, int titlePosition, Font titleFont, Color titleColor) { + super(border, title, titleJustification, titlePosition, titleFont, titleColor); + + this.label = new JLabel(); + this.label.setOpaque(false); + this.label.putClientProperty(BasicHTML.propertyKey, null); + } + + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Border border = getBorder(); + String title = getTitle(); + if ((title != null) && !title.isEmpty()) { + int edge = 0; //(border instanceof TitledBorder) ? 0 : EDGE_SPACING; + JLabel label = getLabel(c); + Dimension size = label.getPreferredSize(); + Insets insets = getBorderInsets(border, c, new Insets(0, 0, 0, 0)); + + int borderX = x + edge; + int borderY = y + edge; + int borderW = width - edge - edge; + int borderH = height - edge - edge; + + int labelY = y; + int labelH = size.height; + int position = getPosition(); + switch (position) { + case ABOVE_TOP: + insets.left = 0; + insets.right = 0; + borderY += labelH - edge; + borderH -= labelH - edge; + break; + case TOP: + insets.top = edge + insets.top/2 - labelH/2; + if (insets.top < edge) { + borderY -= insets.top; + borderH += insets.top; + } + else { + labelY += insets.top; + } + break; + case BELOW_TOP: + labelY += insets.top + edge; + break; + case ABOVE_BOTTOM: + labelY += height - labelH - insets.bottom - edge; + break; + case BOTTOM: + labelY += height - labelH; + insets.bottom = edge + (insets.bottom - labelH) / 2; + if (insets.bottom < edge) { + borderH += insets.bottom; + } + else { + labelY -= insets.bottom; + } + break; + case BELOW_BOTTOM: + insets.left = 0; + insets.right = 0; + labelY += height - labelH; + borderH -= labelH - edge; + break; + } + insets.left += edge + TEXT_INSET_H; + insets.right += edge + TEXT_INSET_H; + + int labelX = x; + int labelW = width - insets.left - insets.right; + if (labelW > size.width) { + labelW = size.width; + } + switch (getJustification(c)) { + case LEFT: + labelX += insets.left; + break; + case RIGHT: + labelX += width - insets.right - labelW; + break; + case CENTER: + labelX += (width - labelW) / 2; + break; + } + + if (border != null) { + if ((position != TOP) && (position != BOTTOM)) { + border.paintBorder(c, g, borderX, borderY, borderW, borderH); + } + else { + Graphics g2 = g.create(); + if (g2 instanceof Graphics2D) { + Graphics2D g2d = (Graphics2D) g2; + Path2D path = new Path2D.Float(); + path.append(new Rectangle(borderX, borderY, borderW, labelY - borderY), false); + path.append(new Rectangle(borderX, labelY, labelX - borderX - TEXT_SPACING, labelH), false); + path.append(new Rectangle(labelX + labelW + TEXT_SPACING, labelY, borderX - labelX + borderW - labelW - TEXT_SPACING, labelH), false); + path.append(new Rectangle(borderX, labelY + labelH, borderW, borderY - labelY + borderH - labelH), false); + g2d.clip(path); + } + border.paintBorder(c, g2, borderX, borderY, borderW, borderH); + g2.dispose(); + } + } + g.translate(labelX, labelY); + label.setSize(labelW, labelH); + label.paint(g); + g.translate(-labelX, -labelY); + } + else if (border != null) { + border.paintBorder(c, g, x, y, width, height); + } + } + + /** + * Reinitialize the insets parameter with this Border's current Insets. + * @param c the component for which this border insets value applies + * @param insets the object to be reinitialized + */ + public Insets getBorderInsets(Component c, Insets insets) { + Border border = getBorder(); + insets = getBorderInsets(border, c, insets); + + String title = getTitle(); + if ((title != null) && !title.isEmpty()) { + int edge = 0; //(border instanceof TitledBorder) ? 0 : EDGE_SPACING; + JLabel label = getLabel(c); + Dimension size = label.getPreferredSize(); + + switch (getPosition()) { + case ABOVE_TOP: + insets.top += size.height - edge; + break; + case TOP: { + if (insets.top < size.height) { + insets.top = size.height - edge; + } + break; + } + case BELOW_TOP: + insets.top += size.height; + break; + case ABOVE_BOTTOM: + insets.bottom += size.height; + break; + case BOTTOM: { + if (insets.bottom < size.height) { + insets.bottom = size.height - edge; + } + break; + } + case BELOW_BOTTOM: + insets.bottom += size.height - edge; + break; + } + insets.top += edge; //TEXT_SPACING; + insets.left += edge; //TEXT_SPACING; + insets.right += edge; //TEXT_SPACING; + insets.bottom += edge; //TEXT_SPACING; + } + return insets; + } + + public int getBaseline(Component c, int width, int height) { + if (c == null) { + throw new NullPointerException("Must supply non-null component"); + } + if (width < 0) { + throw new IllegalArgumentException("Width must be >= 0"); + } + if (height < 0) { + throw new IllegalArgumentException("Height must be >= 0"); + } + Border border = getBorder(); + String title = getTitle(); + if ((title != null) && !title.isEmpty()) { + int edge = 0; //(border instanceof TitledBorder) ? 0 : EDGE_SPACING; + JLabel label = getLabel(c); + Dimension size = label.getPreferredSize(); + Insets insets = getBorderInsets(border, c, new Insets(0, 0, 0, 0)); + + int baseline = label.getBaseline(size.width, size.height); + switch (getPosition()) { + case ABOVE_TOP: + return baseline; + case TOP: + insets.top = edge + (insets.top - size.height) / 2; + return (insets.top < edge) + ? baseline + : baseline + insets.top; + case BELOW_TOP: + return baseline + insets.top + edge; + case ABOVE_BOTTOM: + return baseline + height - size.height - insets.bottom - edge; + case BOTTOM: + insets.bottom = edge + (insets.bottom - size.height) / 2; + return (insets.bottom < edge) + ? baseline + height - size.height + : baseline + height - size.height + insets.bottom; + case BELOW_BOTTOM: + return baseline + height - size.height; + } + } + return -1; + } + + private int getPosition() { + int position = getTitlePosition(); + if (position != DEFAULT_POSITION) { + return position; + } + Object value = UIManager.get("TitledBorder.position"); + if (value instanceof Integer) { + int i = (Integer) value; + if ((0 < i) && (i <= 6)) { + return i; + } + } + else if (value instanceof String) { + String s = (String) value; + if (s.equalsIgnoreCase("ABOVE_TOP")) { + return ABOVE_TOP; + } + if (s.equalsIgnoreCase("TOP")) { + return TOP; + } + if (s.equalsIgnoreCase("BELOW_TOP")) { + return BELOW_TOP; + } + if (s.equalsIgnoreCase("ABOVE_BOTTOM")) { + return ABOVE_BOTTOM; + } + if (s.equalsIgnoreCase("BOTTOM")) { + return BOTTOM; + } + if (s.equalsIgnoreCase("BELOW_BOTTOM")) { + return BELOW_BOTTOM; + } + } + return TOP; + } + + private int getJustification(Component c) { + int justification = getTitleJustification(); + if ((justification == LEADING) || (justification == DEFAULT_JUSTIFICATION)) { + return c.getComponentOrientation().isLeftToRight() ? LEFT : RIGHT; + } + if (justification == TRAILING) { + return c.getComponentOrientation().isLeftToRight() ? RIGHT : LEFT; + } + return justification; + } + + private Color getColor(Component c) { + Color color = getTitleColor(); + if (color != null) { + return color; + } + return (c != null) + ? c.getForeground() + : null; + } + + private JLabel getLabel(Component c) { + this.label.setText(getTitle()); + Font font = getFont(c); + this.label.setFont(font); + this.label.setForeground(getColor(c)); + this.label.setComponentOrientation(c.getComponentOrientation()); + this.label.setEnabled(c.isEnabled()); + Dimension dimension = this.label.getPreferredSize(); + dimension.height = font.getSize(); + this.label.setPreferredSize(dimension); + return this.label; + } + + private static Insets getBorderInsets(Border border, Component c, Insets insets) { + if (border == null) { + insets.set(0, 0, 0, 0); + } + else if (border instanceof AbstractBorder) { + AbstractBorder ab = (AbstractBorder) border; + insets = ab.getBorderInsets(c, insets); + } + else { + Insets i = border.getBorderInsets(c); + insets.set(i.top, i.left, i.bottom, i.right); + } + return insets; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedFloatElement.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedFloatElement.java new file mode 100644 index 000000000..e1e2e4c15 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedFloatElement.java @@ -0,0 +1,41 @@ +package com.fr.design.mainframe.theme.utils; + +import com.fr.base.NameStyle; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.report.cell.FloatElement; +import com.fr.stable.unit.UNIT; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/9/9 + */ +public class DefaultThemedFloatElement { + public static FloatElement createInstance() { + return themingFloatElement(new FloatElement()); + } + + public static FloatElement createInstance(Object value) { + return themingFloatElement(new FloatElement(value)); + } + + public static FloatElement createInstance(UNIT leftDistance, UNIT topDistance, UNIT width, UNIT height, Object value) { + return themingFloatElement(new FloatElement(leftDistance, topDistance, width, height, value)); + } + + private static FloatElement themingFloatElement(FloatElement floatElement) { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateTheme theme = template.getTemplateTheme(); + ThemedCellStyle themedCellStyle = theme.getCellStyleList().getUse4Default(); + if (themedCellStyle != null) { + NameStyle nameStyle = NameStyle.getPassiveInstance(themedCellStyle.getName(), themedCellStyle.getStyle()); + floatElement.setStyle(nameStyle); + } + } + return floatElement; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedTemplateCellElementCase.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedTemplateCellElementCase.java new file mode 100644 index 000000000..67be5cc9a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/utils/DefaultThemedTemplateCellElementCase.java @@ -0,0 +1,45 @@ +package com.fr.design.mainframe.theme.utils; + +import com.fr.base.NameStyle; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyle; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.report.cell.DefaultTemplateCellElement; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/31 + */ +public class DefaultThemedTemplateCellElementCase { + + public static DefaultTemplateCellElement createInstance() { + return themingCellElement(new DefaultTemplateCellElement()); + } + + public static DefaultTemplateCellElement createInstance(int column, int row) { + return themingCellElement(new DefaultTemplateCellElement(column, row)); + } + + public static DefaultTemplateCellElement createInstance(int column, int row, Object value) { + return themingCellElement(new DefaultTemplateCellElement(column, row, value)); + } + + public static DefaultTemplateCellElement createInstance(int column, int row, int columnSpan, int rowSpan, Object value) { + return themingCellElement(new DefaultTemplateCellElement(column, row, columnSpan, rowSpan, value)); + } + + private static DefaultTemplateCellElement themingCellElement(DefaultTemplateCellElement cellElement) { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateTheme theme = template.getTemplateTheme(); + ThemedCellStyle themedCellStyle = theme.getCellStyleList().getUse4Default(); + if (themedCellStyle != null) { + NameStyle nameStyle = NameStyle.getPassiveInstance(themedCellStyle.getName(), themedCellStyle.getStyle()); + cellElement.setStyle(nameStyle); + } + } + return cellElement; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java index 8229c9f8d..0ec5b9c4f 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java @@ -1,5 +1,6 @@ package com.fr.design.mainframe.vcs.common; + import com.fr.concurrent.NamedThreadFactory; import com.fr.design.DesignerEnvManager; import com.fr.design.file.HistoryTemplateListCache; diff --git a/designer-base/src/main/java/com/fr/design/notification/SnapChatAllTypes.java b/designer-base/src/main/java/com/fr/design/notification/SnapChatAllTypes.java index d94da0c88..ae83a0bb9 100644 --- a/designer-base/src/main/java/com/fr/design/notification/SnapChatAllTypes.java +++ b/designer-base/src/main/java/com/fr/design/notification/SnapChatAllTypes.java @@ -12,7 +12,13 @@ public abstract class SnapChatAllTypes { /** * 社区按钮 */ - BBS("BBS"); + BBS("BBS"), + + /** + * 服务器按钮 + */ + SERVER("SERVER"); + private static final String SIGN = "0001"; @@ -35,4 +41,32 @@ public abstract class SnapChatAllTypes { } } + public enum UpdateAction implements SnapChatKey { + + /** + * 服务器模版主题管理 + */ + TEMPLATE_THEMES_MANAGER("TEMPLATE_THEMES_MANAGER"); + + private static final String SIGN = "0002"; + + private String key; + + UpdateAction(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + @Override + public String calc() { + + return CommonUtils.join( + new String[]{SIGN, getKey()}, "-" + ); + } + } + } diff --git a/designer-base/src/main/java/com/fr/design/preview/WriteEnhancePreview.java b/designer-base/src/main/java/com/fr/design/preview/PagePlusPreview.java similarity index 50% rename from designer-base/src/main/java/com/fr/design/preview/WriteEnhancePreview.java rename to designer-base/src/main/java/com/fr/design/preview/PagePlusPreview.java index 96e90d5a2..04fd6623c 100644 --- a/designer-base/src/main/java/com/fr/design/preview/WriteEnhancePreview.java +++ b/designer-base/src/main/java/com/fr/design/preview/PagePlusPreview.java @@ -1,40 +1,41 @@ package com.fr.design.preview; -import com.fr.base.io.IOFile; import com.fr.design.fun.impl.AbstractPreviewProvider; - +import com.fr.general.web.ParameterConstants; +import com.fr.locale.InterProviderFactory; import java.util.HashMap; import java.util.Map; -/** - * Created by loy on 2017/7/7. - */ -public class WriteEnhancePreview extends AbstractPreviewProvider { +import static com.fr.nx.app.web.v9.PagePlusActor.TYPE; + +public class PagePlusPreview extends AbstractPreviewProvider { + private static final int CODE = 100; + @Override public String nameForPopupItem() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Write_Enhance_Preview"); + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Page-Plus"); } @Override public String iconPathForPopupItem() { - return "com/fr/design/images/buttonicon/writes.png"; + return "com/fr/design/images/buttonicon/pages.png"; } @Override public String iconPathForLarge() { - return "com/fr/design/images/buttonicon/writeb24.png"; + return "com/fr/design/images/buttonicon/pageb24.png"; } @Override public int previewTypeCode() { - return IOFile.WRITE_ENHANCE_PREVIEW_TYPE; + return CODE; } @Override public Map parametersForPreview() { Map map = new HashMap(); - map.put("op", "write_plus"); + map.put(ParameterConstants.OP, TYPE); return map; } } diff --git a/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java b/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java index 26fc0c28a..da5817b85 100644 --- a/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java +++ b/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java @@ -38,7 +38,7 @@ public class AuthorityEditorPane extends BasicBeanPane { ) ) ); - IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{".cpt", ".class", ".frm", ".form"}); + IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{".cptx", ".cpt", ".class", ".frm", ".form"}); tree.setDigIn(true); tree.setFileNodeFilter(filter); UIScrollPane scrollPane = new UIScrollPane(tree); diff --git a/designer-base/src/main/java/com/fr/design/report/WatermarkPane.java b/designer-base/src/main/java/com/fr/design/report/WatermarkPane.java index 588e4601d..48e988a82 100644 --- a/designer-base/src/main/java/com/fr/design/report/WatermarkPane.java +++ b/designer-base/src/main/java/com/fr/design/report/WatermarkPane.java @@ -163,7 +163,7 @@ public class WatermarkPane extends BasicPane { tipsJp.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Direction_Vertical"), SwingConstants.CENTER)); watermarkGapTipsPane.add(tipsJp, BorderLayout.CENTER); - colorPane = new NewColorSelectPane(); + colorPane = new NewColorSelectPane(false); JPanel colorLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); colorLabelPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Text_Color")), BorderLayout.NORTH); diff --git a/designer-base/src/main/java/com/fr/design/style/AbstractSelectBox.java b/designer-base/src/main/java/com/fr/design/style/AbstractSelectBox.java index 1d66094f1..cd2b8e47a 100644 --- a/designer-base/src/main/java/com/fr/design/style/AbstractSelectBox.java +++ b/designer-base/src/main/java/com/fr/design/style/AbstractSelectBox.java @@ -40,7 +40,6 @@ public abstract class AbstractSelectBox extends AbstractPopBox implements Mou displayComponent = new BackgroundJComponent(); displayComponent.setEmptyBackground(); - displayComponent.setBorder(new TriggleLineBorder()); triggleButton = new UIButton(UIConstants.ARROW_DOWN_ICON) { public boolean shouldResponseChangeListener() { return false; diff --git a/designer-base/src/main/java/com/fr/design/style/AlignmentPane.java b/designer-base/src/main/java/com/fr/design/style/AlignmentPane.java index 136de486a..22f60b185 100644 --- a/designer-base/src/main/java/com/fr/design/style/AlignmentPane.java +++ b/designer-base/src/main/java/com/fr/design/style/AlignmentPane.java @@ -5,6 +5,7 @@ package com.fr.design.style; import com.fr.base.BaseUtils; import com.fr.base.Style; +import com.fr.design.border.UITitledBorder; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.ibutton.UIRadioButton; import com.fr.design.gui.icheckbox.UICheckBox; @@ -86,7 +87,7 @@ public class AlignmentPane extends BasicPane { //richer:文本控制和图片布局 JPanel textDirectionPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); contentPane.add(textDirectionPanel); - textDirectionPanel.setBorder(GUICoreUtils.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation"), null)); + textDirectionPanel.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_StyleAlignment_Text_Rotation"))); JPanel isVerticalTextPanel = FRGUIPaneFactory.createMediumHGapFlowInnerContainer_M_Pane(); textDirectionPanel.add(isVerticalTextPanel); initVerticalPane(isVerticalTextPanel); @@ -131,7 +132,7 @@ public class AlignmentPane extends BasicPane { private void initSpacingPane (JPanel spacingPane) { spacingPane.setLayout(new GridLayout(1, 3)); - spacingPane.setBorder(BorderFactory.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Spacing") + ":")); + spacingPane.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Spacing") + ":")); spacingBeforeSpinner = new UIBasicSpinner(new SpinnerNumberModel(new Integer(0), new Integer(0), null, new Integer(1))); spacingBeforeSpinner.addChangeListener(changeListener); @@ -153,7 +154,7 @@ public class AlignmentPane extends BasicPane { private JPanel getIndentPane() { JPanel indentPane = FRGUIPaneFactory.createMediumHGapFlowInnerContainer_M_Pane(); - indentPane.setBorder(GUICoreUtils.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Sytle_Indentation"), null)); + indentPane.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Sytle_Indentation"))); Comparable maximum = null; leftIndentSpinner = new UIBasicSpinner(new SpinnerNumberModel(new Integer(0), new Integer(0), maximum, new Integer(1))); leftIndentSpinner.addChangeListener(changeListener); diff --git a/designer-base/src/main/java/com/fr/design/style/BorderPane.java b/designer-base/src/main/java/com/fr/design/style/BorderPane.java index 442f30189..c9dff2c3d 100644 --- a/designer-base/src/main/java/com/fr/design/style/BorderPane.java +++ b/designer-base/src/main/java/com/fr/design/style/BorderPane.java @@ -7,6 +7,7 @@ import com.fr.base.BaseUtils; import com.fr.base.CellBorderStyle; import com.fr.base.GraphHelper; import com.fr.base.Style; +import com.fr.design.border.UITitledBorder; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icombobox.LineComboBox; @@ -96,7 +97,7 @@ public class BorderPane extends BasicPane { JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - centerPane.setBorder(GUICoreUtils.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"), null)); + centerPane.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"))); JPanel borderAllControlPane = FRGUIPaneFactory.createCenterFlowInnerContainer_S_Pane(); centerPane.add(borderAllControlPane, BorderLayout.NORTH); borderAllControlPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0)); @@ -147,7 +148,7 @@ public class BorderPane extends BasicPane { JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - northPane.setBorder(GUICoreUtils.createTitledBorder(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Line"), null)); + northPane.setBorder(UITitledBorder.createBorderWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Line"))); JPanel rightTopPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); northPane.add(rightTopPane, BorderLayout.NORTH); JPanel first = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); diff --git a/designer-base/src/main/java/com/fr/design/style/CustomSelectBox.java b/designer-base/src/main/java/com/fr/design/style/CustomSelectBox.java index cffe36373..3b8e1daa2 100644 --- a/designer-base/src/main/java/com/fr/design/style/CustomSelectBox.java +++ b/designer-base/src/main/java/com/fr/design/style/CustomSelectBox.java @@ -11,7 +11,7 @@ import javax.swing.event.ChangeListener; import com.fr.base.background.ColorBackground; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.style.background.BackgroundCustomJComponent; -import com.fr.design.style.color.ColorSelectPane; +import com.fr.design.style.color.NewColorSelectPane; /** @@ -40,11 +40,11 @@ public class CustomSelectBox extends AbstractPopBox { @Override public JPanel initWindowPane(double preferredWidth) { - ColorSelectPane colorPane = new ColorSelectPane(); + NewColorSelectPane colorPane = new NewColorSelectPane(); colorPane.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { - ColorSelectPane source = (ColorSelectPane)e.getSource(); + NewColorSelectPane source = (NewColorSelectPane)e.getSource(); setSelectObject(source.getColor()); hidePopupMenu(); } diff --git a/designer-base/src/main/java/com/fr/design/style/background/BackgroundJComponent.java b/designer-base/src/main/java/com/fr/design/style/background/BackgroundJComponent.java index 9d3c31bd4..611953a20 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/BackgroundJComponent.java +++ b/designer-base/src/main/java/com/fr/design/style/background/BackgroundJComponent.java @@ -1,10 +1,12 @@ package com.fr.design.style.background; +import java.awt.Color; import java.awt.Graphics; +import java.awt.Insets; import java.awt.geom.Rectangle2D; import javax.swing.JComponent; - +import com.fr.design.border.UIRoundedBorder; import com.fr.general.Background; /** @@ -18,7 +20,7 @@ public class BackgroundJComponent extends JComponent { protected Background background ; public BackgroundJComponent() { - + this.setBorder(new UIRoundedBorder(Color.decode("#999999"), 2, 2)); } public BackgroundJComponent(Background background) { @@ -29,16 +31,23 @@ public class BackgroundJComponent extends JComponent { super.paint(g); if(background != null && this.getSize().getWidth() > 0 && this.getSize().getHeight() > 0) { - background.paint(g, new Rectangle2D.Double(1, 1, this.getSize().getWidth() - 2, - this.getSize().getHeight() - 2)); - } + background.paint(g, new Rectangle2D.Double(2, 2, this.getSize().getWidth() - 4, + this.getSize().getHeight() - 4)); + } + } - - public void setEmptyBackground() { + + + public void setEmptyBackground() { this.background = null; } public void setSelfBackground(Background background) { this.background = background; } + + @Override + public Insets getInsets() { + return new Insets(0,0,0,0); + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/style/background/BackgroundPane.java b/designer-base/src/main/java/com/fr/design/style/background/BackgroundPane.java index 593250ca8..ebaf04e32 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/BackgroundPane.java +++ b/designer-base/src/main/java/com/fr/design/style/background/BackgroundPane.java @@ -8,6 +8,7 @@ import java.awt.Dimension; import java.util.HashMap; import java.util.Map; +import com.fr.base.background.ColorBackground; import com.fr.design.gui.frpane.UITabbedPane; import javax.swing.event.ChangeEvent; @@ -16,6 +17,9 @@ import javax.swing.event.EventListenerList; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.dialog.BasicPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.style.background.impl.ColorBackgroundPane; +import com.fr.design.style.background.impl.ColorNoThemeBackgroundPane; import com.fr.general.Background; import com.fr.log.FineLoggerFactory; @@ -27,14 +31,15 @@ public class BackgroundPane extends BasicPane { private EventListenerList eventChangeList = new EventListenerList(); protected Map cacheMap = new HashMap<>(); - + //需求说: 如果是浏览器背景, 隐藏掉几个button public BackgroundPane() { + BackgroundFactory.getWrapper(ColorBackground.class).setType( + DesignerContext.getDesignerFrame().isServerConfig() ? ColorNoThemeBackgroundPane.class : ColorBackgroundPane.class); this.initComponents(); this.setPreferredSize(new Dimension(400, 300)); } - protected void initComponents() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); diff --git a/designer-base/src/main/java/com/fr/design/style/background/gradient/AbstractComponentPopBox.java b/designer-base/src/main/java/com/fr/design/style/background/gradient/AbstractComponentPopBox.java new file mode 100644 index 000000000..ef647f2bd --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/style/background/gradient/AbstractComponentPopBox.java @@ -0,0 +1,243 @@ +package com.fr.design.style.background.gradient; + +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.style.background.BackgroundJComponent; +import com.fr.general.Background; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JWindow; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.util.ArrayList; +import java.util.List; +import java.awt.AWTEvent; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.AWTEventListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2021-08-24 + */ +public abstract class AbstractComponentPopBox extends JComponent { + + protected BackgroundJComponent displayComponent; + + private JWindow selectPopupWindow; + private boolean isWindowEventInit = false; + private static int GAP = 2; + private static int GAP2 = 20; + + private List changeListenerList = new ArrayList(); + + MouseAdapter mouseListener = new MouseAdapter() { + public void mousePressed(MouseEvent evt) { + showPopupMenu(); + } + + + }; + + AWTEventListener awt = new AWTEventListener() { + public void eventDispatched(AWTEvent event) { + if (event instanceof MouseEvent) { + MouseEvent evt = (MouseEvent) event; + if (evt.getClickCount() > 0) { + mouseClick(evt); + } + } + } + }; + + protected void showPopupMenu() { + if (selectPopupWindow != null && selectPopupWindow.isVisible()) { + hidePopupMenu(); + return; + } + + if (!this.isEnabled()) { + return; + } + Toolkit.getDefaultToolkit().addAWTEventListener(awt, AWTEvent.MOUSE_EVENT_MASK); + + selectPopupWindow = this.getControlWindow(); + + Point convertPoint = new Point(0, 0); + + // e: 将点(0,0)从ColorSelectionPane的坐标系统转换到屏幕坐标. + SwingUtilities.convertPointToScreen(convertPoint, this); + int y = convertPoint.y + this.getSize().height; + int x = convertPoint.x; + int h = y + selectPopupWindow.getHeight(); + int width = x + selectPopupWindow.getWidth(); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + if (h > screenSize.height) { + y = y - selectPopupWindow.getHeight() - GAP2;// 超过屏幕高度了 + } + + if (width > screenSize.width) { + x = screenSize.width - selectPopupWindow.getWidth(); + } + selectPopupWindow.setLocation(x, y); + + selectPopupWindow.setVisible(true); + + //wei : 为了点击别的地方下拉颜色窗口消失 + MouseAdapter parentMouseListener = new MouseAdapter() { + public void mousePressed(MouseEvent evt) { + mouseClick(evt); + } + }; + if (!this.isWindowEventInit && SwingUtilities.getAncestorOfClass(GradientBackgroundPane.class, this) != null) { + SwingUtilities.getAncestorOfClass(GradientBackgroundPane.class, this).addMouseListener(parentMouseListener); + this.isWindowEventInit = true; + } + } + + private void mouseClick(MouseEvent evt) { + Point point = new Point((int) (evt.getLocationOnScreen().getX()), (int) evt.getLocationOnScreen().getY()); + Dimension popBoxD = AbstractComponentPopBox.this.getSize(); + try { + Point popBoxP = AbstractComponentPopBox.this.getLocationOnScreen(); + Dimension popMenuD = this.getControlWindow().getSize(); + Point popMenuP = this.getControlWindow().getLocation(); + Rectangle popBoxRect = new Rectangle(popBoxP, popBoxD); + Rectangle popMenuRect = new Rectangle(popMenuP, popMenuD); + if (!popBoxRect.contains(point) && !popMenuRect.contains(point)) { + this.hidePopupMenu(); + } + } catch (Exception ignore) { + this.hidePopupMenu(); + } + } + + protected void hidePopupMenu() { + if (selectPopupWindow != null) { + selectPopupWindow.setVisible(false); + } + + selectPopupWindow = null; + Toolkit.getDefaultToolkit().removeAWTEventListener(awt); + } + + protected JWindow getControlWindow() { + //find parent. + if (this.selectPopupWindow == null) { + Window parentWindow = SwingUtilities.windowForComponent(this); + if (parentWindow != null) { + this.selectPopupWindow = new AbstractComponentPopBox.SelectControlWindow(parentWindow); + } + + selectPopupWindow.addMouseListener(new MouseAdapter() { + public void mouseExited(MouseEvent evt) { + int x = evt.getLocationOnScreen().x; + int y = evt.getLocationOnScreen().y; + + if (selectPopupWindow != null) { + double desValue = 2; + Rectangle rectangle = selectPopupWindow.getBounds(); + boolean b1 = x < rectangle.x + desValue || x >= rectangle.x + rectangle.width - desValue; + boolean b2 = y > rectangle.y + rectangle.height - desValue;//避免了鼠标下移刚进入selectPopupWindow的过程中弹出框隐藏,上移移出后由AbstractPopBox的mouseListener处理 + if (b1 || b2) { + hidePopupMenu(); + } + } + } + }); + } + + return selectPopupWindow; + } + + /** + * 添加事件 + * + * @param changeListener 事件 + */ + public void addSelectChangeListener(ChangeListener changeListener) { + this.changeListenerList.add(changeListener); + } + + /** + * 删除事件 + * + * @param changeListener 事件 + */ + public void removeSelectChangeListener(ChangeListener changeListener) { + this.changeListenerList.remove(changeListener); + } + + /** + * 响应事件 + */ + public void fireChangeListener() { + if (!changeListenerList.isEmpty()) { + ChangeEvent evt = new ChangeEvent(this); + for (int i = 0; i < changeListenerList.size(); i++) { + this.changeListenerList.get(i).stateChanged(evt); + } + } + } + + /** + * 待说明 + * + * @param background 背景 + */ + public void fireDisplayComponent(Background background) { + if (displayComponent != null) { + displayComponent.setSelfBackground(background); + } + fireChangeListener(); + this.repaint(); + } + + /** + * 初始化弹出框的面板 + * + * @param preWidth 宽度 + * @return 弹出面板 + */ + public abstract JPanel initWindowPane(double preWidth); + + private class SelectControlWindow extends JWindow { + private static final long serialVersionUID = -5776589767069105911L; + + public SelectControlWindow(Window paranet) { + super(paranet); + this.initComponents(); + } + + public void initComponents() { + JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.setContentPane(defaultPane); + +// defaultPane.setBorder(UIManager.getBorder("PopupMenu.border")); + + if (displayComponent != null) { + defaultPane.add(initWindowPane(displayComponent.getPreferredSize().getWidth())); + } else { + defaultPane.add(initWindowPane(20)); + } + this.pack(); + } + + @Override + public void setVisible(boolean b) { + super.setVisible(b); + AbstractComponentPopBox.this.repaint(); + } + } + + protected boolean isPopupVisible() { + return selectPopupWindow == null ? false : selectPopupWindow.isVisible(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/style/background/gradient/FixedGradientBarNoTheme.java b/designer-base/src/main/java/com/fr/design/style/background/gradient/FixedGradientBarNoTheme.java new file mode 100644 index 000000000..d45bd62f7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/style/background/gradient/FixedGradientBarNoTheme.java @@ -0,0 +1,39 @@ +package com.fr.design.style.background.gradient; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.style.color.ColorSelectDetailPane; +import com.fr.design.style.color.ColorSelectDialog; + +import javax.swing.JPanel; +import java.awt.Color; + +/** + * @author Bjorn + * @version 10.0 + * Created by Bjorn on 2021-08-19 + */ +public class FixedGradientBarNoTheme extends FixedGradientBar { + + + public FixedGradientBarNoTheme(int minvalue, int maxvalue) { + super(minvalue, maxvalue); + } + + protected void clickButton(int select) { + ColorSelectDetailPane pane = new ColorSelectDetailPane(Color.WHITE); + Color selectColor = getList().get(select).getColorInner() == null ? Color.WHITE : getList().get(select).getColorInner(); + ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, selectColor, FixedGradientBarNoTheme.this, true); + Color color = FixedGradientBarNoTheme.this.getColor(); + if (color != null) { + DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); + getList().get(select).setColorInner(color); + stateChanged(); + FixedGradientBarNoTheme.this.repaint(); + } + } + + public JPanel initWindowPane(double preWidth) { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/design/style/background/gradient/GradientBar.java b/designer-base/src/main/java/com/fr/design/style/background/gradient/GradientBar.java index b088864c0..97a19f464 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/gradient/GradientBar.java +++ b/designer-base/src/main/java/com/fr/design/style/background/gradient/GradientBar.java @@ -1,18 +1,16 @@ package com.fr.design.style.background.gradient; -import com.fr.design.DesignerEnvManager; +import com.fr.base.background.ColorBackground; import com.fr.design.event.UIObserver; import com.fr.design.event.UIObserverListener; import com.fr.design.gui.itextfield.UINumberField; -import com.fr.design.mainframe.DesignerContext; import com.fr.design.style.color.ColorCell; -import com.fr.design.style.color.ColorSelectDetailPane; -import com.fr.design.style.color.ColorSelectDialog; import com.fr.design.style.color.ColorSelectable; +import com.fr.design.style.color.NewColorSelectPane; import com.fr.stable.AssistUtils; - import com.fr.stable.os.OperatingSystem; -import javax.swing.JComponent; + +import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; @@ -33,8 +31,8 @@ import java.awt.geom.Point2D; /** * TODO:面板缩放的功能没有考虑(就是尾值过大,导致超过界面显示的情况),原来的那个实现完全是个BUG。要缩放的情况也比较少,就干脆以后弄吧 */ -public class GradientBar extends JComponent implements UIObserver, ColorSelectable { - +public class GradientBar extends AbstractComponentPopBox implements UIObserver, ColorSelectable { + private NewColorSelectPane colorPane; /** * */ @@ -88,6 +86,22 @@ public class GradientBar extends JComponent implements UIObserver, ColorSelectab iniListener(); } + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + public void updateColor(Color begin, Color end) { p1.setColorInner(begin); p2.setColorInner(end); @@ -106,15 +120,7 @@ public class GradientBar extends JComponent implements UIObserver, ColorSelectab } if (select >= 0) { - ColorSelectDetailPane pane = new ColorSelectDetailPane(Color.WHITE); - ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, Color.WHITE, GradientBar.this); - Color color = GradientBar.this.getColor(); - if (color != null) { - DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); - list.get(select).setColorInner(color); - stateChanged(); - GradientBar.this.repaint(); - } + clickButton(select); } GradientBar.this.repaint(); } @@ -122,6 +128,37 @@ public class GradientBar extends JComponent implements UIObserver, ColorSelectab }); } + protected void clickButton(int select) { + setIndex(select); + showPopupMenu(); + } + + public JPanel initWindowPane(double preferredWidth) { + // 下拉的时候重新生成面板,刷新最近使用颜色 + colorPane = new NewColorSelectPane(false) { + @Override + public void setVisible(boolean b) { + super.setVisible(b); + } + + @Override + protected boolean selectRealTime() { + return false; + } + }; + colorPane.setColor(getColor()); + colorPane.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + hidePopupMenu(); + setColor(((NewColorSelectPane) e.getSource()).getColor()); + getList().get(getIndex()).setColorInner(getColor()); + fireDisplayComponent(ColorBackground.getInstance(getColor())); + GradientBar.this.stateChanged(); + } + }); + return colorPane; + } + protected void addMouseDragListener() { this.addMouseMotionListener(new MouseAdapter() { public void mouseDragged(MouseEvent e) { @@ -132,10 +169,10 @@ public class GradientBar extends JComponent implements UIObserver, ColorSelectab break; } } - if(OperatingSystem.isLinux() && AssistUtils.equals(oldIndex,index)){ - if(Math.abs(p1.getX() - e.getX()) > Math.abs(p2.getX() - e.getX())){ + if (OperatingSystem.isLinux() && AssistUtils.equals(oldIndex, index)) { + if (Math.abs(p1.getX() - e.getX()) > Math.abs(p2.getX() - e.getX())) { index = 1; - }else{ + } else { index = 0; } } diff --git a/designer-base/src/main/java/com/fr/design/style/background/impl/ColorBackgroundPane.java b/designer-base/src/main/java/com/fr/design/style/background/impl/ColorBackgroundPane.java index 62a08a948..37fef6e61 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/impl/ColorBackgroundPane.java +++ b/designer-base/src/main/java/com/fr/design/style/background/impl/ColorBackgroundPane.java @@ -19,10 +19,14 @@ public class ColorBackgroundPane extends BackgroundDetailPane { public ColorBackgroundPane() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); - detailColorSelectPane = new DetailColorSelectPane(); + detailColorSelectPane = createColorSelectPane(); this.add(detailColorSelectPane, BorderLayout.CENTER); } + protected DetailColorSelectPane createColorSelectPane(){ + return new DetailColorSelectPane(); + } + public void populate(Background background) { if (background instanceof ColorBackground) { ColorBackground colorBackgroud = (ColorBackground) background; diff --git a/designer-base/src/main/java/com/fr/design/style/background/impl/ColorNoThemeBackgroundPane.java b/designer-base/src/main/java/com/fr/design/style/background/impl/ColorNoThemeBackgroundPane.java new file mode 100644 index 000000000..01ee19a67 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/style/background/impl/ColorNoThemeBackgroundPane.java @@ -0,0 +1,10 @@ +package com.fr.design.style.background.impl; + +import com.fr.design.style.color.DetailColorSelectPane; + +public class ColorNoThemeBackgroundPane extends ColorBackgroundPane{ + + protected DetailColorSelectPane createColorSelectPane(){ + return new DetailColorSelectPane(false); + } +} diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorAdjustPane.java b/designer-base/src/main/java/com/fr/design/style/color/ColorAdjustPane.java index fcdc594b5..ad99b9083 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorAdjustPane.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorAdjustPane.java @@ -1,13 +1,14 @@ package com.fr.design.style.color; import com.fr.base.BaseUtils; -import com.fr.base.background.ColorBackground; +import com.fr.design.DesignerEnvManager; import com.fr.design.event.UIObserver; import com.fr.design.event.UIObserverListener; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.VerticalFlowLayout; -import com.fr.design.style.AbstractSelectBox; +import com.fr.design.mainframe.DesignerContext; +import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -75,7 +76,7 @@ public class ColorAdjustPane extends JPanel implements UIObserver { int size = colorButtons.size(); Color[] colors = new Color[size]; for (int i = 0; i < size; i++) { - colors[i] = colorButtons.get(i).getSelectObject(); + colors[i] = colorButtons.get(i).getColor(); } return colors; } @@ -169,7 +170,7 @@ public class ColorAdjustPane extends JPanel implements UIObserver { } - private class AddColorButton extends AbstractSelectBox { + private class AddColorButton extends JComponent implements ColorSelectable { BufferedImage image = BaseUtils.readImageWithCache("/com/fr/design/images/buttonicon/add.png"); @@ -195,43 +196,38 @@ public class ColorAdjustPane extends JPanel implements UIObserver { return new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - showPopupMenu(); + //打开颜色选择面板 + showDialog(); } }; } - public JPanel initWindowPane(double preferredWidth) { - // 下拉的时候重新生成面板,刷新最近使用颜色 - ColorSelectPane colorPane = new ColorSelectPane(false) { - public void setVisible(boolean b) { - super.setVisible(b); - } + private void showDialog() { + ColorSelectDetailPane pane = new ColorSelectDetailPane(getColor()); + ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, getColor(), this, true); + Color color = this.getColor(); + if (color != null) { + DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); + } + } - protected boolean selectRealTime() { - return false; - } - }; - colorPane.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - hidePopupMenu(); - Color color = ((ColorSelectPane) e.getSource()).getColor(); - fireDisplayComponent(ColorBackground.getInstance(color)); - if(colorButtons.size() < MAX_BUTTON) { - colorButtons.add(createColorButton(color)); - } - ColorAdjustPane.this.stateChanged(); - relayout(); - } - }); - return colorPane; + @Override + public void setColor(Color color) { + if (colorButtons.size() < MAX_BUTTON) { + colorButtons.add(createColorButton(color)); + } + ColorAdjustPane.this.stateChanged(); + relayout(); } - public Color getSelectObject() { - return null; + @Override + public Color getColor() { + return Color.WHITE; } - public void setSelectObject(Color color) { + @Override + public void colorSetted(ColorCell colorCell) { } } -} +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorButton.java b/designer-base/src/main/java/com/fr/design/style/color/ColorButton.java index a052f99f1..5ad794c79 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorButton.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorButton.java @@ -1,11 +1,10 @@ package com.fr.design.style.color; import com.fr.base.BaseUtils; -import com.fr.base.background.ColorBackground; -import com.fr.design.style.AbstractSelectBox; +import com.fr.design.DesignerEnvManager; +import com.fr.design.mainframe.DesignerContext; -import javax.swing.JPanel; -import javax.swing.event.ChangeEvent; +import javax.swing.JComponent; import javax.swing.event.ChangeListener; import java.awt.Color; import java.awt.Dimension; @@ -22,7 +21,7 @@ import java.awt.image.BufferedImage; * @version 10.0 * Created by Bjorn on 2020-03-06 */ -public class ColorButton extends AbstractSelectBox { +public class ColorButton extends JComponent implements ColorSelectable { private static final double DEL_WIDTH = 7; @@ -34,8 +33,6 @@ public class ColorButton extends AbstractSelectBox { private boolean isMoveOn = false; - private ColorSelectPane colorPane; - private boolean lastButton; private ChangeListener changeListener; @@ -111,40 +108,24 @@ public class ColorButton extends AbstractSelectBox { } if (e.getX() >= bounds.getWidth() - DEL_WIDTH && e.getY() <= DEL_WIDTH) { deleteButton(); - hidePopupMenu(); return; } } //打开颜色选择面板 - showPopupMenu(); + showDialog(); } - public JPanel initWindowPane(double preferredWidth) { - // 下拉的时候重新生成面板,刷新最近使用颜色 - colorPane = new ColorSelectPane(false) { - @Override - public void setVisible(boolean b) { - super.setVisible(b); - } - - @Override - protected boolean selectRealTime() { - return false; - } - }; - colorPane.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - hidePopupMenu(); - color = ((ColorSelectPane) e.getSource()).getColor(); - fireDisplayComponent(ColorBackground.getInstance(color)); - ColorButton.this.stateChanged(); - } - }); - return colorPane; + private void showDialog() { + ColorSelectDetailPane pane = new ColorSelectDetailPane(getColor()); + ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, getColor(), this, true); + Color color = this.getColor(); + if (color != null) { + DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); + } } public void stateChanged() { - if (changeListener != null) { + if (changeListener != null) { changeListener.stateChanged(null); } } @@ -153,26 +134,18 @@ public class ColorButton extends AbstractSelectBox { this.changeListener = changeListener; } + @Override + public void setColor(Color color) { + this.color = color; + this.stateChanged(); + } - /** - * 获取当前选中的颜色 - * - * @return 当前选中的颜色 - */ - public Color getSelectObject() { + @Override + public Color getColor() { return this.color; } - /** - * 设置选中的颜色 - * - * @param color 颜色 - */ - public void setSelectObject(Color color) { - this.color = color; - colorPane.setColor(color); - - fireDisplayComponent(ColorBackground.getInstance(color)); + @Override + public void colorSetted(ColorCell colorCell) { } - -} +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorCell.java b/designer-base/src/main/java/com/fr/design/style/color/ColorCell.java index 06cca51d0..4cc3e41ce 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorCell.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorCell.java @@ -10,6 +10,7 @@ import java.awt.event.MouseEvent; import javax.swing.JComponent; +import com.fr.design.DesignerEnvManager; import com.fr.design.constants.UIConstants; import com.fr.general.ComparatorUtils; @@ -76,17 +77,21 @@ public class ColorCell extends JComponent implements ColorSelectable { g.fillRect(b.left, b.top, right, bottom); } - if (colorSelectable.getColor() != null - && ComparatorUtils.equals(colorSelectable.getColor(), this.getColor())) { + if (isColorSelected(colorSelectable)) { g.setColor(UIConstants.LINE_COLOR); g.drawRect(b.left, b.top, right - 1, bottom - 1); } } + protected boolean isColorSelected(ColorSelectable colorSelectable){ + return colorSelectable.getColor() != null + && ComparatorUtils.equals(colorSelectable.getColor(), this.getColor()); + } + /** * 鼠标事件处理 - * @param 鼠标事件 + * @param e 鼠标事件 */ public void processMouseEvent(MouseEvent e) { if (!isEnabled()) { @@ -96,6 +101,10 @@ public class ColorCell extends JComponent implements ColorSelectable { if (e == null || e.getID() == MouseEvent.MOUSE_RELEASED) { colorSelectable.setColor(this.getColor()); colorSelectable.colorSetted(this); + if (this.getColor() != null) { + int rgb = this.getColor().getRGB(); + DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(new Color(rgb)); + } } if (e != null) { diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindow.java b/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindow.java index 4ee3a119e..b84173f1d 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindow.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindow.java @@ -38,6 +38,10 @@ public abstract class ColorControlWindow extends JPopupMenu { return selectionPopupPane.getColor(); } + public void setColor(Color color) { + selectionPopupPane.setColor(color); + } + public PopupHider getPopupHider() { return popupHider; } @@ -58,15 +62,28 @@ public abstract class ColorControlWindow extends JPopupMenu { } protected void initSelectionPopupPane(boolean isSupportTransparent) { - selectionPopupPane = new ColorSelectionPopupPane(isSupportTransparent); + selectionPopupPane = createColorSelectionPopupPane(isSupportTransparent); this.add(selectionPopupPane, BorderLayout.CENTER); } - class ColorSelectionPopupPane extends NewColorSelectPane { + protected ColorSelectionPopupPane createColorSelectionPopupPane(boolean isSupportTransparent) { + return new ColorSelectionPopupPane(isSupportTransparent, supportThemeColor()); + } + + protected boolean supportThemeColor(){ + return true; + } + + protected class ColorSelectionPopupPane extends NewColorSelectPane { private static final long serialVersionUID = 7822856562329146354L; - public ColorSelectionPopupPane(boolean isSupportTransparent) { - super(isSupportTransparent); + public ColorSelectionPopupPane(boolean isSupportTransparent, boolean isSupportThemeColor) { + this(isSupportTransparent, isSupportThemeColor, null); + } + + public ColorSelectionPopupPane(boolean isSupportTransparent, boolean isSupportThemeColor, Color color) { + super(isSupportTransparent, isSupportThemeColor); + this.setColor(color); this.addChangeListener(new ChangeListener() { @Override @@ -77,7 +94,7 @@ public abstract class ColorControlWindow extends JPopupMenu { } @Override - protected void doTransparent() { + public void doTransparent() { popupHider.hidePopupMenu(); super.doTransparent(); } diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindowWithAuto.java b/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindowWithAuto.java index cbb0e97ea..01351bfed 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindowWithAuto.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorControlWindowWithAuto.java @@ -39,6 +39,11 @@ public abstract class ColorControlWindowWithAuto extends ColorControlWindow { return selectionPopupPaneWithAuto.getColor(); } + public void setColor(Color color) { + selectionPopupPaneWithAuto.setColor(color); + } + + protected void initSelectionPopupPane(boolean isSupportTransparent) { selectionPopupPaneWithAuto = new ColorSelectionPopupPaneWithAuto(isSupportTransparent); this.add(selectionPopupPaneWithAuto, BorderLayout.CENTER); @@ -61,7 +66,7 @@ public abstract class ColorControlWindowWithAuto extends ColorControlWindow { }); } - protected void doTransparent() { + public void doTransparent() { getPopupHider().hidePopupMenu(); setColor(null); } @@ -114,11 +119,10 @@ public abstract class ColorControlWindowWithAuto extends ColorControlWindow { } } + @Override public Dimension getPreferredSize() { - if (isSupportTransparent()) { - return new Dimension(super.getPreferredSize().width, TRANSPARENT_WINDOW_HEIGHT + BUTTON_HEIGHT); - } - return new Dimension(super.getPreferredSize().width, WINDOW_HEIGHT + BUTTON_HEIGHT); + Dimension dimension = super.getPreferredSize(); + return new Dimension(dimension.width, dimension.height + BUTTON_HEIGHT); } } diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorFactory.java b/designer-base/src/main/java/com/fr/design/style/color/ColorFactory.java index b22104f28..b643752b3 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorFactory.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorFactory.java @@ -71,5 +71,18 @@ public interface ColorFactory { new Color(0, 0, 255) }; + public static final Color STANDARD_COLORS[] = { + new Color(166, 89, 66), + new Color(166, 123, 66), + new Color(166, 66, 66), + new Color(103, 166, 66), + new Color(66, 121, 166), + new Color(68, 66, 166), + new Color(98, 66, 166), + new Color(146, 66, 166), + new Color(75, 18, 89), + new Color(89, 18, 51) + }; + } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectBox.java b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectBox.java index d2a824544..3ec124b13 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectBox.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectBox.java @@ -17,7 +17,7 @@ public class ColorSelectBox extends AbstractSelectBox implements UIObserv private static final long serialVersionUID = 2782150678943960557L; private Color color; - private ColorSelectPane colorPane; + private NewColorSelectPane colorPane; private UIObserverListener uiObserverListener; public ColorSelectBox(int preferredWidth) { @@ -40,12 +40,8 @@ public class ColorSelectBox extends AbstractSelectBox implements UIObserv } } - protected ColorSelectPane getColorSelectPane(){ - return new ColorSelectPane() { - public void setVisible(boolean b) { - super.setVisible(b); - } - }; + protected NewColorSelectPane getColorSelectPane(){ + return new NewColorSelectPane(); } /** @@ -56,14 +52,14 @@ public class ColorSelectBox extends AbstractSelectBox implements UIObserv public JPanel initWindowPane(double preferredWidth) { // 下拉的时候重新生成面板,刷新最近使用颜色 colorPane = getColorSelectPane(); + colorPane.setColor(color); colorPane.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { hidePopupMenu(); - color = ((ColorSelectPane) e.getSource()).getColor(); + color = ((NewColorSelectPane) e.getSource()).getColor(); fireDisplayComponent(ColorBackground.getInstance(color)); } }); - colorPane.setColor(color); return colorPane; } diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDetailPane.java b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDetailPane.java index 13d899822..3756fc627 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDetailPane.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDetailPane.java @@ -36,6 +36,10 @@ public class ColorSelectDetailPane extends BasicPane { return selectedPanel; } + private SwatchChooserPanel swatchChooserPanel; + + private CustomChooserPanel customChooserPanel; + public void setSelectedPanel(JColorChooser selectedPanel) { this.selectedPanel = selectedPanel; } @@ -69,9 +73,9 @@ public class ColorSelectDetailPane extends BasicPane { selectedPanel.setPreferredSize(new Dimension(selectedPanel.getWidth(), SELECT_PANEL_HEIGHT)); selectedPanel.setPreviewPanel(new JPanel()); - AbstractColorChooserPanel swatchChooserPanel = new SwatchChooserPanel(); - AbstractColorChooserPanel customChooserPanel = new CustomChooserPanel(); - selectedPanel.setChooserPanels(new AbstractColorChooserPanel[]{swatchChooserPanel, customChooserPanel}); + swatchChooserPanel = new SwatchChooserPanel(); + customChooserPanel = new CustomChooserPanel(); + selectedPanel.setChooserPanels(new AbstractColorChooserPanel[]{customChooserPanel, swatchChooserPanel}); this.add(selectedPanel, BorderLayout.NORTH); // 最近使用面板 @@ -98,4 +102,8 @@ public class ColorSelectDetailPane extends BasicPane { previewPanel.add(colorChooserPreview); this.add(previewPanel, BorderLayout.SOUTH); } + + public void populate(Color color){ + customChooserPanel.setColor(color); + } } diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDialog.java b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDialog.java index 33eb6dbf1..23dcf8cc3 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDialog.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectDialog.java @@ -1,6 +1,7 @@ package com.fr.design.style.color; import com.fr.base.chart.BaseChartCollection; +import com.fr.design.DesignerEnvManager; import com.fr.design.gui.chart.MiddleChartDialog; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.utils.gui.GUICoreUtils; @@ -77,6 +78,7 @@ public class ColorSelectDialog extends MiddleChartDialog{ this.okListener = (ColorTracker) okListener; this.seletePane = seletePane; initComponent(); + this.pane.populate(initialColor); } private void initComponent() { @@ -100,7 +102,9 @@ public class ColorSelectDialog extends MiddleChartDialog{ ok.setActionCommand("OK"); ok.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - seletePane.setColor(okListener.getColor()); + Color color = okListener.getColor(); + seletePane.setColor(color); + DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); doOK(); } }); diff --git a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectPane.java b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectPane.java index 68c1b2b99..452c5fe30 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/ColorSelectPane.java +++ b/designer-base/src/main/java/com/fr/design/style/color/ColorSelectPane.java @@ -30,6 +30,7 @@ import java.awt.event.MouseEvent; /** * The pane used to select color */ +@Deprecated public class ColorSelectPane extends TransparentPane implements ColorSelectable { private static final long serialVersionUID = -8634152305687249392L; diff --git a/designer-base/src/main/java/com/fr/design/style/color/DetailColorSelectPane.java b/designer-base/src/main/java/com/fr/design/style/color/DetailColorSelectPane.java index 4245c1293..5d7e81487 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/DetailColorSelectPane.java +++ b/designer-base/src/main/java/com/fr/design/style/color/DetailColorSelectPane.java @@ -29,10 +29,14 @@ import com.fr.design.dialog.BasicPane; * Often used for foreground selection. */ public class DetailColorSelectPane extends BasicPane { - private ColorSelectPane colorSelectPane; + private NewColorSelectPane colorSelectPane; private UILabel colorPreviewLabel; - public DetailColorSelectPane() { + public DetailColorSelectPane(){ + this(true); + } + + public DetailColorSelectPane(boolean supportTheme) { this.setBorder(BorderFactory.createEmptyBorder(4, 4, 0, 4)); this.setLayout(FRGUIPaneFactory.createBorderLayout()); @@ -44,7 +48,7 @@ public class DetailColorSelectPane extends BasicPane { defaultPane.add(Box.createHorizontalStrut(4)); JPanel colorSelectContainPane =FRGUIPaneFactory.createBorderLayout_L_Pane(); defaultPane.add(colorSelectContainPane); - colorSelectPane = new ColorSelectPane(); + colorSelectPane = NewColorSelectPane.createColorSelectPaneWithTheme(supportTheme); colorSelectContainPane.add(colorSelectPane, BorderLayout.NORTH); defaultPane.add(Box.createHorizontalStrut(8)); diff --git a/designer-base/src/main/java/com/fr/design/style/color/FineColorCell.java b/designer-base/src/main/java/com/fr/design/style/color/FineColorCell.java new file mode 100644 index 000000000..1007b3f84 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/style/color/FineColorCell.java @@ -0,0 +1,38 @@ +package com.fr.design.style.color; + +import com.fr.base.FineColor; +import com.fr.general.ComparatorUtils; + +import java.awt.Color; + +public class FineColorCell extends ColorCell { + private final int x; + private final int y; + + public FineColorCell(Color color, ColorSelectable colorSelectable) { + this(color, colorSelectable, -1, -1); + } + + public FineColorCell(Color color, ColorSelectable colorSelectable, int x, int y) { + super(color, colorSelectable); + this.x = x; + this.y = y; + } + + public Color getColor() { + Color color = super.getColor(); + FineColor fineColor = new FineColor(x, y, color); + return fineColor; + } + + + protected boolean isColorSelected(ColorSelectable colorSelectable) { + Color color = colorSelectable.getColor(); + if (color instanceof FineColor) { + return super.isColorSelected(colorSelectable) && (x == ((FineColor) color).getHor()) && (y == ((FineColor) color).getVer()); + } + return super.isColorSelected(colorSelectable); + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectBox.java b/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectBox.java index 4f291c639..04d368e6b 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectBox.java +++ b/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectBox.java @@ -20,7 +20,7 @@ public class NewColorSelectBox extends AbstractSelectBox implements UIObs private static final long serialVersionUID = 2782150678943960557L; private Color color; - private NewColorSelectPane colorPane = new NewColorSelectPane(); + private NewColorSelectPane colorPane = new NewColorSelectPane(false); private UIObserverListener uiObserverListener; private String newColorSelectBoxName = ""; private GlobalNameListener globalNameListener = null; @@ -58,7 +58,8 @@ public class NewColorSelectBox extends AbstractSelectBox implements UIObs */ public JPanel initWindowPane(double preferredWidth) { // 下拉的时候重新生成面板,以刷新最近使用颜色 - colorPane = new NewColorSelectPane(); + colorPane = new NewColorSelectPane(false); + colorPane.setColor(this.getSelectObject()); colorPane.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { hidePopupMenu(); diff --git a/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java b/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java index 6c21c10cb..f38e69a8b 100644 --- a/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java +++ b/designer-base/src/main/java/com/fr/design/style/color/NewColorSelectPane.java @@ -1,16 +1,23 @@ package com.fr.design.style.color; +import com.fr.base.FineColor; +import com.fr.base.theme.FineColorDeriveState; +import com.fr.base.theme.TemplateTheme; import com.fr.design.DesignerEnvManager; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.UIConstants; import com.fr.design.dialog.BasicPane; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.theme.dialog.TemplateThemeProfileDialog; import javax.swing.BorderFactory; -import javax.swing.Box; +import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -19,11 +26,10 @@ import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; +import java.util.List; /** @@ -33,56 +39,76 @@ import java.util.ArrayList; public class NewColorSelectPane extends BasicPane implements ColorSelectable { private static final long serialVersionUID = -8634152305687249392L; - private Color color = null; // color + private static final int WIDTH = 197; + private static final int HEIGHT = 250; + //颜色衍生的数量 + private static final int DEFAULT_DERIVE_COUNT = 5; + + private FineColor color = null; // color // color setting action. - private ArrayList colorChangeListenerList = new ArrayList(); + private final ArrayList colorChangeListenerList = new ArrayList<>(); // 是否支持透明 private boolean isSupportTransparent; - public final static int TRANSPARENT_WINDOW_HEIGHT = 165; - public final static int WINDOW_HEIGHT = 150; + private boolean isSupportThemeColor; // 最近使用颜色 - private UsedColorPane usedColorPane; + private final NewUsedColorPane usedColorPane; + private final JPanel menuColorPane; + private ColorCell[][] themeColorCellGrid; + + public static NewColorSelectPane createColorSelectPaneWithTheme(boolean supportTheme) { + return new NewColorSelectPane(true, supportTheme); + } /** * Constructor. */ public NewColorSelectPane() { - this(false); + this(true); + } + + public NewColorSelectPane(boolean isSupportTransparent) { + this(isSupportTransparent, true); } /** * Constructor. */ - NewColorSelectPane(boolean isSupportTransparent) { + public NewColorSelectPane(boolean isSupportTransparent, boolean isSupportThemeColor) { + this.isSupportThemeColor = isSupportThemeColor; initSelectButton(isSupportTransparent); - // center JPanel centerPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + centerPane.setBorder(BorderFactory.createEmptyBorder(10, 4, 0, 4)); this.add(centerPane, BorderLayout.CENTER); - // 第一行 - JPanel row1Pane = new JPanel(FRGUIPaneFactory.createBorderLayout()); - row1Pane.setBorder(BorderFactory.createEmptyBorder(8, 8, 0, 0)); - row1Pane.setPreferredSize(new Dimension(135, 16)); // 宽度为 16 * 8 + 7 - centerPane.add(row1Pane); - // 最近使用 - usedColorPane = new UsedColorPane(1, 8, 1, this, true, false); - usedColorPane.getPane().setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 8)); - row1Pane.add(usedColorPane.getPane()); + menuColorPane = getMenuColorPane(); - JPanel menuColorPane1 = new JPanel(); - centerPane.add(menuColorPane1); - - menuColorPane1.setLayout(new GridLayout(5, 8, 1, 1)); - menuColorPane1.setBorder(BorderFactory.createEmptyBorder(8, 8, 0, 8)); - for (int i = 0; i < ColorFactory.MenuColors.length; i++) { - menuColorPane1.add(new ColorCell(ColorFactory.MenuColors[i], this)); + if (isSupportThemeColor) { + JPanel themePane = initThemeColorPane(); + centerPane.add(themePane); + } else { + centerPane.add(menuColorPane); + initMenuColorPane(); } - centerPane.add(Box.createVerticalStrut(1)); + JPanel standardColorPane = new JPanel(new BorderLayout(0, 5)); + standardColorPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + standardColorPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Standard_Color")), BorderLayout.CENTER); + centerPane.add(standardColorPane); + JPanel colorSelectPane = createStandardColorPane(); + standardColorPane.add(colorSelectPane, BorderLayout.SOUTH); + + // 增加最近使用 pane + JPanel row1Pane = new JPanel(new BorderLayout(0, 5)); + row1Pane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + row1Pane.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Used")), BorderLayout.CENTER); + centerPane.add(row1Pane); + // 最近使用 + usedColorPane = new NewUsedColorPane(9, this, selectRealTime()); + row1Pane.add(usedColorPane.getPane(), BorderLayout.SOUTH); // mod by anchore 16/11/16 final UIButton customButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_More_Color")); @@ -99,12 +125,123 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { }); customButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); - JPanel centerPane1 = FRGUIPaneFactory.createBorderLayout_S_Pane(); - centerPane1.setBorder(BorderFactory.createEmptyBorder(2, 8, 0, 8)); - centerPane1.add(customButton, BorderLayout.NORTH); + JPanel centerPane1 = new JPanel(new BorderLayout(0, 0)); + centerPane1.setBorder(BorderFactory.createEmptyBorder(9, 0, 11, 0)); + centerPane1.add(customButton, BorderLayout.CENTER); + customButton.setPreferredSize(new Dimension(197, 20)); centerPane.add(centerPane1); } + private JPanel createStandardColorPane() { + JPanel jPanel = new JPanel(new GridLayout(1, 10, 3, 0)); + Color[] colorArray = ColorFactory.STANDARD_COLORS; + for (int i = 0; i < colorArray.length; i++) { + jPanel.add(new ColorCell(colorArray[i], this)); + } + return jPanel; + } + + private JPanel initThemeColorPane() { + menuColorPane.removeAll(); + JPanel themeColorPane = new JPanel(new BorderLayout(0, 5)); + themeColorPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + themeColorPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Theme_Color")), BorderLayout.CENTER); + + themeColorPane.add(menuColorPane, BorderLayout.SOUTH); + + menuColorPane.setLayout(new BorderLayout(0, 10)); + JPanel northPane = new JPanel(new GridLayout(1, 8, 3, 0)); + JPanel centerPane = new JPanel(new GridLayout(1, 8, 3, 0)); + menuColorPane.add(northPane, BorderLayout.NORTH); + menuColorPane.add(centerPane, BorderLayout.CENTER); + + Color[] colorArray = new Color[]{ + // 8列主题色 + Color.decode("#FFFFFF"), + Color.decode("#CCCCCC"), + Color.decode("#FFFFFF"), + Color.decode("#CCCCCC"), + Color.decode("#FFFFFF"), + Color.decode("#CCCCCC"), + Color.decode("#FFFFFF"), + Color.decode("#CCCCCC"), + + // 2列灰度色 + Color.decode("#333333"), + Color.decode("#FFFFFF"), + }; + + if (themeColorCellGrid == null) { + themeColorCellGrid = new ColorCell[colorArray.length][DEFAULT_DERIVE_COUNT]; + for (int i = 0; i < colorArray.length; i++) { + ColorCell[] colorCellColumn = new ColorCell[DEFAULT_DERIVE_COUNT]; + boolean isDefaultColor = (i == colorArray.length - 1 || i == colorArray.length - 2); + Color color = colorArray[i]; + Color[] deriveColorArr = FineColorDeriveState.getDeriveColorArr(color, isDefaultColor, DEFAULT_DERIVE_COUNT); + for (int j = 0; j < deriveColorArr.length; j++) { + colorCellColumn[j] = createFineColorCell(deriveColorArr[j], isDefaultColor, i, j); + } + themeColorCellGrid[i] = colorCellColumn; + } + } + + for (int i = 0; i < colorArray.length; i++) { + northPane.add(themeColorCellGrid[i][0]); + } + for (int i = 0; i < colorArray.length; i++) { + JPanel columnPane = new JPanel(new GridLayout(DEFAULT_DERIVE_COUNT - 1, 1, 0, 3)); + for (int j = 1; j < DEFAULT_DERIVE_COUNT; j++) { + columnPane.add(themeColorCellGrid[i][j]); + } + centerPane.add(columnPane); + } + + refreshThemeMenuColorPane(); + return themeColorPane; + } + + private void refreshThemeMenuColorPane() { + List standardColors = null; + if (TemplateThemeProfileDialog.isEditingTheme()) { + standardColors = TemplateThemeProfileDialog.getEditingColorScheme(); + } else { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null) { + TemplateTheme theme = template.getTemplateTheme(); + if (theme != null) { + standardColors = theme.getColorScheme().getColors(); + } + } + } + if (standardColors == null || standardColors.size() < 8) { + return; + } + + for (int i = 0; i < themeColorCellGrid.length - 2; i++) { + Color color = standardColors.get(i); + Color[] deriveColorArr = FineColorDeriveState.getDeriveColorArr(color, false, DEFAULT_DERIVE_COUNT); + for (int j = 0; j < deriveColorArr.length; j++) { + themeColorCellGrid[i][j].setColor(deriveColorArr[j]); + } + } + } + + + private FineColorCell createFineColorCell(Color color, boolean isDefaultColor, int x, int y) { + return isDefaultColor ? new FineColorCell(color, this) : new FineColorCell(color, this, x, y); + } + + + private void initMenuColorPane() { + menuColorPane.setLayout(new GridLayout(5, 8, 3, 3)); + Color[] colorArray = this.getColorArray(); + for (int i = 0; i < colorArray.length; i++) { + Color color = colorArray[i] == null ? UsedColorPane.DEFAULT_COLOR : colorArray[i]; + menuColorPane.add(new ColorCell(color, this)); + } + + } + public boolean isSupportTransparent() { return isSupportTransparent; } @@ -113,20 +250,18 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { isSupportTransparent = supportTransparent; } - protected void initSelectButton(boolean isSupportTransparent){ + protected boolean selectRealTime() { + return true; + } + + protected void initSelectButton(boolean isSupportTransparent) { this.isSupportTransparent = isSupportTransparent; this.setLayout(FRGUIPaneFactory.createBorderLayout()); this.setBorder(new UIRoundedBorder(UIConstants.TOOLBAR_BORDER_COLOR, 1, 5)); if (isSupportTransparent) { UIButton transparentButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_ChartF_Transparency")); this.add(transparentButton, BorderLayout.NORTH); - transparentButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - doTransparent(); - } - }); + transparentButton.addActionListener(e -> doTransparent()); } } @@ -134,7 +269,7 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { /** * 添加监听 * - * @param 监听列表 Add change listener. + * @param changeListener 监听 */ public void addChangeListener(ChangeListener changeListener) { this.colorChangeListenerList.add(changeListener); @@ -151,7 +286,7 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { * @return 颜色 * Return the color. */ - public Color getColor() { + public FineColor getColor() { return color; } @@ -163,7 +298,6 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { public Color getNotNoneColor() { if (color == null) { setColor(Color.WHITE); - return Color.WHITE; } return color; } @@ -175,27 +309,36 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { */ @Override public void setColor(Color color) { - this.color = color; + if (isSupportThemeColor) { + refreshThemeMenuColorPane(); + } + FineColor fineColor; + if (color == null) { + fineColor = null; + } else { + fineColor = color instanceof FineColor ? (FineColor) color : new FineColor(color); + } + setFineColor(fineColor); + } + + private void setFineColor(FineColor fineColor) { + this.color = fineColor; // fire color change. if (!colorChangeListenerList.isEmpty()) { ChangeEvent evt = new ChangeEvent(this); - for (int i = 0; i < colorChangeListenerList.size(); i++) { - this.colorChangeListenerList.get(i).stateChanged(evt); + for (ChangeListener changeListener : colorChangeListenerList) { + changeListener.stateChanged(evt); } } - DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); + this.repaint(); } - /** - * 设置颜色 - * - * @param 颜色位置 - */ @Override public void colorSetted(ColorCell colorCell) { + this.updateUsedColor(); colorCell.repaint(); } @@ -203,18 +346,32 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { setColor(null); } + protected Color[] getColorArray() { + return ColorFactory.MenuColors; + } + + protected JPanel getMenuColorPane() { + return new JPanel(); + } + + protected void customButtonPressed() { // 颜色选择器 ColorSelectDetailPane pane = new ColorSelectDetailPane(Color.WHITE); - ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, Color.WHITE, this); + Color color = getColor() == null ? Color.WHITE : getColor().getColor(); + ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, color, this); } @Override public Dimension getPreferredSize() { + int height = HEIGHT; if (isSupportTransparent) { - return new Dimension(super.getPreferredSize().width, TRANSPARENT_WINDOW_HEIGHT); + height += 15; + } + if (isSupportThemeColor) { + height += 25; } - return new Dimension(super.getPreferredSize().width, WINDOW_HEIGHT); + return new Dimension(WIDTH, height); } /** @@ -224,5 +381,69 @@ public class NewColorSelectPane extends BasicPane implements ColorSelectable { usedColorPane.updateUsedColor(); } + class NewUsedColorPane extends BasicPane { + + // 最近使用面板列数 + private int columns; + + // 最近使用面板 + private JPanel pane; + + private ColorSelectable selectable; + + private boolean setColorRealTime; + + public JPanel getPane() { + return this.pane; + } + + + public NewUsedColorPane(int columns, ColorSelectable selectable, boolean setColorRealTime) { + this.columns = columns; + this.selectable = selectable; + this.setColorRealTime = setColorRealTime; + initialComponents(); + } + + + private void initialComponents() { + int total = columns; + JPanel panel = new JPanel(); + panel.setLayout(new GridLayout(1, columns + 1, 3, 3)); + panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + //最近使用颜色 + Color[] colors = DesignerEnvManager.getEnvManager().getColorConfigManager().getColors(); + int size = colors.length; + for (int i = 0; i < total; i++) { + Color color = i < size ? colors[size - i - 1] : + UsedColorPane.DEFAULT_COLOR; + panel.add(new ColorCell(color == null ? UsedColorPane.DEFAULT_COLOR : color, selectable)); + } + // 取色按钮 + JButton pickColorButton = PickColorButtonFactory.getPickColorButton(selectable, PickColorButtonFactory.IconType.ICON16, setColorRealTime); + panel.add(pickColorButton); + this.pane = panel; + } + + /** + * 更新最近使用颜色 + */ + public void updateUsedColor() { + int total = columns; + Color[] colors = DesignerEnvManager.getEnvManager().getColorConfigManager().getColors(); + int size = colors.length; + for (int i = 0; i < total; i++) { + ColorCell cell = (ColorCell) this.pane.getComponent(i); + Color color = i < size ? colors[size - i - 1] : UsedColorPane.DEFAULT_COLOR; + cell.setColor(color == null ? UsedColorPane.DEFAULT_COLOR : color); + } + } + + @Override + protected String title4PopupWindow() { + return null; + } + } + } diff --git a/designer-base/src/main/java/com/fr/design/worker/save/SaveWorker.java b/designer-base/src/main/java/com/fr/design/worker/save/SaveWorker.java index f47a4f88e..51a79bbad 100644 --- a/designer-base/src/main/java/com/fr/design/worker/save/SaveWorker.java +++ b/designer-base/src/main/java/com/fr/design/worker/save/SaveWorker.java @@ -70,7 +70,6 @@ public class SaveWorker extends SwingWorker { this.template.setSaving(false); // 恢复界面 if (slowly && ComparatorUtils.equals(this.template.getName(), HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getName())) { - DesignerContext.getDesignerFrame().refreshUIToolBar(); DesignerContext.getDesignerFrame().getCenterTemplateCardPane().hideCover(); } DesignerFrameFileDealerPane.getInstance().stateChange(); diff --git a/designer-base/src/main/java/com/fr/file/FILEChooserPane.java b/designer-base/src/main/java/com/fr/file/FILEChooserPane.java index 4bacf9a85..5ea393ba6 100644 --- a/designer-base/src/main/java/com/fr/file/FILEChooserPane.java +++ b/designer-base/src/main/java/com/fr/file/FILEChooserPane.java @@ -770,6 +770,7 @@ public class FILEChooserPane extends BasicPane { // ben:filefilter设置初值为cpt过滤 this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPT, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); + this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPTX, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); // richer:form文件 daniel 改成三个字 this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.FRM, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/cptx/io/DesignReadWritableProvider.java b/designer-base/src/main/java/com/fr/nx/app/designer/cptx/io/DesignReadWritableProvider.java new file mode 100644 index 000000000..cfb7c4495 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/cptx/io/DesignReadWritableProvider.java @@ -0,0 +1,35 @@ +package com.fr.nx.app.designer.cptx.io; + +import com.fr.common.annotations.Negative; +import com.fr.file.FILE; +import com.fr.nx.cptx.io.handle.impl.CompileToPathCptxIOProvider; +import com.fr.nx.cptx.pack.util.CompiledReportOutputStream; +import com.fr.nx.cptx.utils.CptxFileUtils; + +/** + * 用于设计器保存编译后的结果并缓存可web预览模版 + * 没有可观的内存实现,内存实现方式复杂,赶发布,先提供简单的内存实现方式 + * + * @author: Maksim + * @Date: Created in 2020/4/10 + * @Description: 用于cptx写操作的Provider + */ +@Negative(until = "2020-05-10") +public class DesignReadWritableProvider extends CompileToPathCptxIOProvider { + /** + * 原文件 + */ + private final FILE file; + + public DesignReadWritableProvider(FILE file) { + super(CptxFileUtils.getFormatPath(file.getPath())); + this.file = file; + } + + + @Override + public CompiledReportOutputStream outputOpen() throws Exception { + return new CompiledReportOutputStream(file.asOutputStream(), getCompilePath()); + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/monitor/DesignerMetricRecorder.java b/designer-base/src/main/java/com/fr/nx/app/designer/monitor/DesignerMetricRecorder.java new file mode 100644 index 000000000..0644bd511 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/monitor/DesignerMetricRecorder.java @@ -0,0 +1,97 @@ +package com.fr.nx.app.designer.monitor; + +import com.fr.design.mainframe.errorinfo.ErrorInfo; +import com.fr.intelli.record.MetricRegistry; +import com.fr.json.JSON; +import com.fr.json.JSONFactory; +import com.fr.json.JSONObject; +import com.fr.message.ErrorMessage; +import com.fr.nx.app.designer.toolbar.TransformResult; + +/** + * Created by loy on 2021/1/18. + * + *

设计器埋点记录相关 + */ +public class DesignerMetricRecorder { + + private static final String ATTR_TEMPLATE_ID = "templateid"; + private static final String ATTR_USERNAME = "username"; + private static final String ATTR_UUID = "uuid"; + private static final String ATTR_ACTIVE_KEY = "activekey"; + private static final String ATTR_TEST_LOG = "testlog"; + private static final String ATTR_REPORT_CONTENT = "reportcontent"; + private static final String ATTR_ERROR_STACK = "errorstack"; + private static final String IDENTIFICATION = "view_plus"; + + private DesignerMetricRecorder() { + } + + /** + * 模板转换失败的埋点 + */ + public static void submitFailedTransform(TransformResult result, String templateID, String name, Exception e) { + if (isPressureTesting()) { + return; + } + saveAsJSON(result, templateID, name, e); + } + + /** + * 记录在设计器的错误信息收集中 + */ + private static void saveToErrorInfo(TransformResult result, String templateID, String name, Exception e, String unsupportMessage) { + JSONObject jo = JSONFactory.createJSON(JSON.OBJECT); + jo.put(ATTR_USERNAME, IDENTIFICATION); + jo.put(ATTR_UUID, IDENTIFICATION); + jo.put(ATTR_ACTIVE_KEY, IDENTIFICATION); + jo.put(ATTR_TEMPLATE_ID, templateID); + jo.put(ATTR_REPORT_CONTENT, name); + if (result == TransformResult.FAILED) { + jo.put(ATTR_TEST_LOG, e); + jo.put(ATTR_ERROR_STACK, e.getMessage()); + } else { + jo.put(ATTR_TEST_LOG, unsupportMessage); + } + new ErrorInfo().saveFileToCache(jo); + } + + /** + * 记录在fine_record_error表中 + */ + private static void saveToErrorMessage(TransformResult result, String templateID, String name, Exception e, String unsupportMessage) { + String errorMessage = unsupportMessage; + if (result == TransformResult.FAILED) { + errorMessage = e.getStackTrace()[0].toString(); + } + ErrorMessage message = ErrorMessage.build(e == null ? errorMessage : e.getMessage(), errorMessage); + message.setTname(name); + message.setDisplayName(name); + MetricRegistry.getMetric().submit(message); + } + + private static void saveAsJSON(TransformResult result, String templateID, String name, Exception e) { + saveToErrorInfo(result, templateID, name, e, null); + saveToErrorMessage(result, templateID, name, e, null); + } + + /** + * 预编译中不支持的功能的埋点 + */ + public static void submitUnSupportTransform(TransformResult result, String templateID, String name, String unsupportMessage) { + if (isPressureTesting()) { + return; + } + saveToErrorInfo(result, templateID, name, null, unsupportMessage); + saveToErrorMessage(result, templateID, name, null, unsupportMessage); + } + + /** + * 埋点对压测性能的影响控制参数 + * + * @return 是否压测 + */ + public static boolean isPressureTesting() { + return Boolean.parseBoolean(System.getProperty("monitorDebug")); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/CompileAction.java b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/CompileAction.java new file mode 100644 index 000000000..4496ecd9a --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/CompileAction.java @@ -0,0 +1,116 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.base.extension.FileExtension; +import com.fr.design.actions.UpdateAction; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.MenuKeySet; +import com.fr.file.FILE; +import com.fr.file.FileNodeFILE; +import com.fr.general.IOUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.utils.CompileTransformUtil; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import static com.fr.design.dialog.FineJOptionPane.showConfirmDialog; +import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER; +import static javax.swing.JOptionPane.OK_CANCEL_OPTION; +import static javax.swing.JOptionPane.OK_OPTION; +import static javax.swing.JOptionPane.WARNING_MESSAGE; + +/** + * Created by kerry on 2019-10-14 + */ +public class CompileAction extends UpdateAction { + public static final Icon TRANS_ICON = IOUtils.readIcon("/com/fr/nx/app/designer/transform.png"); + + private static final MenuKeySet COMPILE_ATTR = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'C'; + } + + @Override + public String getMenuName() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Tooltip"); + } + + @Override + public KeyStroke getKeyStroke() { + return KeyStroke.getKeyStroke(KeyEvent.VK_T, DEFAULT_MODIFIER); + } + }; + + public CompileAction() { + initMenuStyle(); + } + + private void initMenuStyle() { + this.setMenuKeySet(COMPILE_ATTR); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(TRANS_ICON); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + @Override + public void actionPerformed(ActionEvent e) { + JTemplate jtemplate = DesignerContext.getDesignerFrame().getSelectedJTemplate(); + if (jtemplate == null || jtemplate.getEditingFILE() == null) { + return; + } + FILE currentTemplate = jtemplate.getEditingFILE(); + if(currentTemplate instanceof FileNodeFILE){ + transformAndDisplay(jtemplate); + }else { + //模板不在报表环境下,提示保存 + int selVal = showConfirmDialog( + DesignerContext.getDesignerFrame(), + InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Preview_Message"), + InterProviderFactory.getProvider().getLocText("Fine-Plugin-Engine_Transformer_Tips"), + OK_CANCEL_OPTION, + WARNING_MESSAGE); + + if (OK_OPTION == selVal) { + //保存成功才会执行编译 + if (jtemplate.saveAsTemplate2Env()) { + transformAndDisplay(jtemplate); + } + } + } + + } + + //编译模板并展示 + private void transformAndDisplay(JTemplate jtemplate){ + String path = jtemplate.getEditingFILE().getPath(); + TemplateTransformer transformer = TemplateTransformer.parse(path); + FILE targetFile = CompileTransformUtil.getTargetFile(jtemplate, transformer); + TransformResult result = transformer.transform(jtemplate, targetFile); + jtemplate.fireJTemplateSaved(); + result.display(); + } + + @Override + public boolean isEnabled() { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + String path = jt.getEditingFILE().getPath(); + return FileExtension.CPTX.matchExtension(path) || FileExtension.CPT.matchExtension(path); + } + + @Override + public JComponent createToolBarComponent() { + UIButton transBtn = (UIButton) super.createToolBarComponent(); + transBtn.set4ToolbarButton(); + transBtn.setToolTipText(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Tooltip")); + return transBtn; + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TemplateTransformer.java b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TemplateTransformer.java new file mode 100644 index 000000000..42490fe7d --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TemplateTransformer.java @@ -0,0 +1,220 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.base.extension.FileExtension; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.MutilTempalteTabPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.file.FileNodeFILE; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.nx.app.designer.monitor.DesignerMetricRecorder; +import com.fr.nx.compile.CompileStatus; +import com.fr.nx.compile.ReportCompiler; +import com.fr.nx.compile.adapter.LegacyWorkBookAdapter; +import com.fr.nx.compile.util.ReportCompileUtils; +import com.fr.nx.cptx.CptxIOManager; +import com.fr.nx.cptx.cache.CptxTemplatePool; +import com.fr.nx.cptx.entry.CptxTemplate; +import com.fr.nx.cptx.io.handle.CptxTemplateHandle; +import com.fr.nx.app.designer.cptx.io.DesignReadWritableProvider; +import com.fr.nx.cptx.monitor.CompileMonitorHandler; +import com.fr.nx.cptx.utils.CptxFileUtils; +import com.fr.nx.data.layer.LayerItem; +import com.fr.nx.data.layer.LayerProps; +import com.fr.nx.template.compile.CompiledReport; +import com.fr.stable.StringUtils; +import org.jetbrains.annotations.NotNull; + +import java.io.OutputStream; + +import static com.fr.base.extension.FileExtension.ALL; +import static com.fr.base.extension.FileExtension.CPT; +import static com.fr.base.extension.FileExtension.CPTX; + +/** + * 模板转换器, 可以把cptx模板转为cpt, 或者cpt模板转为cptx. + * 以后可以扩展支持frm frmx互相转换 + */ + +public enum TemplateTransformer { + + TO_CPTX(CPT) { + @Override + public TransformResult transform(JTemplate jtemplate, FILE file) { + WorkBook workbook = (WorkBook) jtemplate.getTarget(); + TransformResultInfo resultInfo = compileCPTX(workbook, file); + if (needDoAfterTransformed(resultInfo.getResult())) { + doAfterTransformed(file, jtemplate); + } + return resultInfo.getResult(); + } + }, + TO_CPT(CPTX) { + @Override + public TransformResult transform(JTemplate jtemplate, FILE file) { + WorkBook workbook = (WorkBook) jtemplate.getTarget(); + try { + workbook.export(file.asOutputStream()); + doAfterTransformed(file, jtemplate); + return TransformResult.SUCCESS; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return TransformResult.FAILED; + } + } + }, + OTHER(ALL); + private FileExtension extension; + + TemplateTransformer(FileExtension extension) { + this.extension = extension; + } + + public TransformResult transform(JTemplate jtemplate) { + return transform(jtemplate, jtemplate.getEditingFILE()); + } + + public TransformResult transform(JTemplate jtemplate, FILE newFile) { + return TransformResult.UNSUPPORT; + } + + public static TemplateTransformer parse(String path) { + for (TemplateTransformer transformer : values()) { + if (transformer.extension.matchExtension(path)) { + return transformer; + } + } + return OTHER; + } + + private static boolean needDoAfterTransformed(TransformResult result) { + return ComparatorUtils.equals(TransformResult.SUCCESS, result) + || ComparatorUtils.equals(TransformResult.UNSUPPORT, result); + } + + private static void doAfterTransformed(FILE file, JTemplate jtemplate) { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (ComparatorUtils.equals(file.getPath(), jt.getPath())) { + HistoryTemplateListCache.getInstance().closeSelectedReport(jt); + DesignerContext.getDesignerFrame().openTemplate(file); + return; + } + MutilTempalteTabPane.getInstance().setIsCloseCurrent(true); + MutilTempalteTabPane.getInstance().closeFormat(jt); + MutilTempalteTabPane.getInstance().closeSpecifiedTemplate(jt); + DesignerContext.getDesignerFrame().openTemplate(file); + } + + + public static FILE createOutputFile(String oldPath, String oldSuffix, String newSuffix) { + String newPath = generateNewPath(oldPath, oldSuffix, newSuffix); + return new FileNodeFILE(new FileNode(newPath, false)); + } + + private static String generateNewPath(String oldPath, String oldSuffix, String newSuffix) { + if (StringUtils.isEmpty(oldPath) || StringUtils.isEmpty(oldSuffix) || StringUtils.isEmpty(newSuffix)) { + return oldPath; + } + + if (oldPath.endsWith(oldSuffix)) { + return StringUtils.cutStringEndWith(oldPath, oldSuffix) + newSuffix; + } + return oldPath; + } + + /** + * 编译和保存 + * + * @param workbook work + * @param file file + * @return 编译保存结果 + */ + @NotNull + public static TransformResultInfo compileCPTX(WorkBook workbook, FILE file) { + //对于非工作目录的cptx,修改无需执行编译 + if (!(file instanceof FileNodeFILE)) { + try { + OutputStream outputStream = file.asOutputStream(); + workbook.export(outputStream); + return TransformResultInfo.generateResult(TransformResult.SUCCESS).saved(true); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return TransformResultInfo.generateResult(TransformResult.FAILED).saved(false); + } + } + boolean saved; + CompiledReport report = null; + CompileStatus compileStatus = CompileStatus.SUCCEED; + if (workbook == null || file == null) { + return TransformResultInfo + .generateResult(TransformResult.FAILED, "work and file must not be null") + .saved(false); + } + String failMessage = null; + // 编译 + ReportCompiler compiler; + try { + compiler = new ReportCompiler(new LegacyWorkBookAdapter(workbook)); + long startTime = System.currentTimeMillis(); + compiler.compile(); + report = compiler.getCompiledReport(); + // 折叠树埋点 + LayerProps props = ReportCompileUtils.getLayerProps(report); + LayerItem[] items; + if (props != null && (items = props.getLayerItems()) != null) { + CompileMonitorHandler.submitTreeCompileFocusPoint( + startTime, file.getPath(), items.length, + props.getExpandLayer(), true + ); + } + compileStatus = compiler.getStatus(); + failMessage = compiler.getFailMessage(); + long endTime = System.currentTimeMillis(); + CompileMonitorHandler.submitCompileMessage(startTime, endTime, file.getPath(), ""); + if (compileStatus != CompileStatus.SUCCEED) { + DesignerMetricRecorder.submitUnSupportTransform( + TransformResult.UNSUPPORT, + workbook.getTemplateID(), + file.getName(), + compileStatus == CompileStatus.FAILED_UNSUPPORT ? failMessage : null + ); + } + } catch (Exception exception) { + String templateID = workbook.getTemplateID(); + String fileName = file.getName(); + DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, templateID, fileName, exception); + FineLoggerFactory.getLogger().error(exception.getMessage(), exception); + } + + // 构建编译结果,当前的 cptx template 是未经反序列化钩子处理过的 cptx 模版对象,不能直接用于模版预览 + CptxTemplate template = CptxIOManager.createCptxTemplate(workbook, report, compileStatus, failMessage); + // 保存 + DesignReadWritableProvider cptx = new DesignReadWritableProvider(file); + CptxTemplateHandle handle = CptxIOManager.create(template, cptx); + try { + saved = handle.save(); + } catch (Exception exception) { + // 存储cptx格式报错或者失败 + FineLoggerFactory.getLogger().error(exception.getMessage(), exception); + DesignerMetricRecorder.submitFailedTransform(TransformResult.FAILED, workbook.getTemplateID(), file.getName(), exception); + return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(false); + } + // 读取可 web 预览模版并缓存 + try { + // todo 是否考虑异步 + CptxTemplate previewCptxTemplate = CptxIOManager.open(cptx).getTemplate(); + CptxTemplatePool.getInstance().addCptxTemplate(CptxFileUtils.getFormatPath(file.getPath()), previewCptxTemplate); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + if (report == null) { + // 编译报错或者失败 + return TransformResultInfo.generateResult(TransformResult.FAILED, failMessage).saved(saved); + } + return TransformResultInfo.generateResult(TransformResult.parse(compileStatus), failMessage).saved(saved); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResult.java b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResult.java new file mode 100644 index 000000000..9668ec805 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResult.java @@ -0,0 +1,55 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.design.file.TemplateTreePane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.compile.CompileStatus; + +import javax.swing.JOptionPane; + +public enum TransformResult { + + SUCCESS(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Success")) { + @Override + public void display() { + // 转换成功后, 刷新下目录树 + TemplateTreePane.getInstance().refresh(); + super.display(); + } + }, + FAILED(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Failed")), + UNSUPPORT(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine-Transform-Unsupport")){ + @Override + public void display() { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), TransformResult.SUCCESS.toString()); + } + }; + + private String msg; + + private TransformResult(String msg) { + this.msg = msg; + } + + // 展示结果 + public void display() { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), this.toString()); + } + + @Override + public String toString() { + return this.msg; + } + + public static TransformResult parse(CompileStatus status) { + switch (status) { + case SUCCEED: + return TransformResult.SUCCESS; + case FAILED_UNSUPPORT: + return TransformResult.UNSUPPORT; + default: + return TransformResult.FAILED; + } + + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java new file mode 100644 index 000000000..e988e04e7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/toolbar/TransformResultInfo.java @@ -0,0 +1,64 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.locale.InterProviderFactory; +import com.fr.stable.StringUtils; + +/** + * Created by kerry on 2020-01-15 + */ +public class TransformResultInfo { + + private boolean saved; + private TransformResult result; + private final String transformLog; + + public static TransformResultInfo generateResult(TransformResult result, String transformLog) { + return new TransformResultInfo(result, transformLog); + } + + public static TransformResultInfo generateResult(TransformResult result) { + return new TransformResultInfo(result, StringUtils.EMPTY); + } + + + private TransformResultInfo(TransformResult result, String transformLog) { + this.result = result; + this.transformLog = transformLog; + this.saved = false; + } + + public boolean isSaved() { + return saved; + } + + public void setSaved(boolean saved) { + this.saved = saved; + } + + public TransformResultInfo saved(boolean saved) { + setSaved(saved); + return this; + } + + public TransformResult getResult() { + return result; + } + + public void setResult(TransformResult result) { + this.result = result; + } + + public String getTransformLog() { + switch (this.result) { + case FAILED: + return transformLog + "\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Failed_Tip"); + case SUCCESS: + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip"); + case UNSUPPORT: + return transformLog + "\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip"); + } + return transformLog; + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformProgress.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformProgress.java new file mode 100644 index 000000000..7b11cd34c --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformProgress.java @@ -0,0 +1,25 @@ +package com.fr.nx.app.designer.transform; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchTransformProgress { + private double progress = 0.0D; + private int total = 0; + private int complete = 0; + + public BatchTransformProgress(int total) { + this.total = total; + } + + + public double getProgress() { + return this.progress; + } + + + public void updateProgress() { + this.complete++; + this.progress = this.complete * 1D / this.total; + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformUtil.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformUtil.java new file mode 100644 index 000000000..aef4eed21 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformUtil.java @@ -0,0 +1,25 @@ +package com.fr.nx.app.designer.transform; + +import com.fr.file.filetree.FileNode; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by kerry on 2020-02-14 + */ +public class BatchTransformUtil { + private BatchTransformUtil() { + + } + + public static FileNode[] filterTransformedFile(FileNode[] fileNodes, List transformedList){ + List list = new ArrayList(); + for (FileNode fileNode : fileNodes) { + if (!transformedList.contains(fileNode)) { + list.add(fileNode); + } + } + return list.toArray(new FileNode[list.size()]); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformer.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformer.java new file mode 100644 index 000000000..8dee1ca30 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/BatchTransformer.java @@ -0,0 +1,71 @@ +package com.fr.nx.app.designer.transform; + +import com.fr.design.utils.concurrent.ThreadFactoryBuilder; +import com.fr.file.filetree.FileNode; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; +import com.fr.nx.app.designer.utils.CompileTransformUtil; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchTransformer { + private BatchTransformProgress progress = new BatchTransformProgress(0); + private Map transformResults = new ConcurrentHashMap(); + private UpdateCallBack updateCallBack; + private static final int MAXPOOLSIZE = 5; + private static final String THREAD_NAME_TEMPLATE = "batchtransform-thread-%s"; + private ExecutorService threadPoolExecutor = + Executors.newFixedThreadPool(MAXPOOLSIZE, + new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build()); + + public BatchTransformer(UpdateCallBack updateCallBack) { + this.updateCallBack = updateCallBack; + } + + + public void batchTransform(List fileNodes) { + //先清理下 + transformResults.clear(); + progress = new BatchTransformProgress(fileNodes.size()); + for (FileNode fileNode : fileNodes) { + transform(fileNode); + } + } + + private void transform(final FileNode fileNode) { + + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + TransformResultInfo transformResult = CompileTransformUtil.compileFile(fileNode); + transformResults.put(fileNode, transformResult); + updateTransformProgress(); + } + }); + } + + private synchronized void updateTransformProgress() { + progress.updateProgress(); + updateCallBack.updateProgress(progress.getProgress()); + } + + public void shutDown() { + if (threadPoolExecutor != null) { + threadPoolExecutor.shutdownNow(); + } + threadPoolExecutor = Executors.newFixedThreadPool(MAXPOOLSIZE, + new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build()); + updateCallBack.shutDown(); + } + + public Map getResults() { + return transformResults; + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/UpdateCallBack.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/UpdateCallBack.java new file mode 100644 index 000000000..85e1a1151 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/UpdateCallBack.java @@ -0,0 +1,22 @@ +package com.fr.nx.app.designer.transform; + +/** + * Created by kerry on 2019-12-10 + */ +public interface UpdateCallBack { + /** + * 更新进度 + * @param progress 进度 + */ + void updateProgress(double progress); + + /** + * 进度中断 + */ + void shutDown(); + + /** + * 进度重置 + */ + void reset(); +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformDialog.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformDialog.java new file mode 100644 index 000000000..75b32cb27 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformDialog.java @@ -0,0 +1,61 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.locale.InterProviderFactory; + +import javax.swing.JDialog; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * Created by kerry on 2019-12-19 + */ +public class BatchTransformDialog extends JDialog implements ActionListener { + private UIButton closeBtn; + + public BatchTransformDialog(Frame parent, JPanel contentPane) { + super(parent, true); + + this.setTitle(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform")); + this.setResizable(false); + JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + this.setContentPane(defaultPane); + + closeBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Close")); + closeBtn.addActionListener(this); + JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + buttonPanel.add(closeBtn); + + defaultPane.add(contentPane, BorderLayout.CENTER); + defaultPane.add(buttonPanel, BorderLayout.SOUTH); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + dialogExit(); + } + }); + + this.getRootPane().setDefaultButton(closeBtn); + + this.setSize(new Dimension(900, 600)); + GUICoreUtils.centerWindow(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + dialogExit(); + } + + + private void dialogExit() { + this.dispose(); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformPane.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformPane.java new file mode 100644 index 000000000..c11e4e4ad --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/BatchTransformPane.java @@ -0,0 +1,223 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.base.extension.FileExtension; +import com.fr.design.dialog.BasicPane; +import com.fr.design.file.NodeAuthProcessor; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.itree.filetree.FileNodeComparator; +import com.fr.design.gui.itree.filetree.FileNodeConstants; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.file.filetree.FileNode; +import com.fr.file.filetree.IOFileNodeFilter; +import com.fr.locale.InterProviderFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.tree.DefaultTreeModel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Created by kerry on 2019-12-10 + */ +public class BatchTransformPane extends BasicPane { + private UITextField searchField; + private TransformFileTree tree; + private Dialog showDialog; + private TransformPreparePane preparePane; + private TransformResultPane resultPane; + + + public BatchTransformPane() { + DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + this.showDialog = new BatchTransformDialog(designerFrame, this); + initPane(); + } + + private void initPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initNorthPane(); + initSouthPane(); + } + + private void initNorthPane() { + UILabel northTip = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Tip")); + northTip.setForeground(Color.decode("#8F8F92")); + northTip.setBorder(BorderFactory.createEmptyBorder(0, 550, 10, 10)); + this.add(northTip, BorderLayout.NORTH); + } + + private void initSouthPane() { + preparePane = new TransformPreparePane(this.showDialog, this); + tree = new TransformFileTree(preparePane); + this.add(preparePane, BorderLayout.CENTER); + initLeftPane(); + initRightPane(); + } + + private void initLeftPane() { + IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{FileExtension.CPT.getSuffix()}); + tree.setDigIn(true); + tree.setFileNodeFilter(filter); + UIScrollPane scrollPane = new UIScrollPane(tree); + scrollPane.setPreferredSize(new Dimension(320, 442)); + scrollPane.setBorder(BorderFactory.createEmptyBorder(12, 0, 0, 0)); + tree.refreshEnv(); + JPanel selectPane = FRGUIPaneFactory.createTitledBorderPaneCenter( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Select_Template")); + JPanel searchPane = initSearchPane(); + JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + jPanel.add(searchPane, BorderLayout.NORTH); + jPanel.add(scrollPane, BorderLayout.WEST); + jPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + selectPane.add(jPanel); + selectPane.setPreferredSize(new Dimension(330, 501)); + this.add(selectPane, BorderLayout.WEST); + } + + + private void initRightPane() { + resultPane = new TransformResultPane(); + this.add(resultPane, BorderLayout.EAST); + } + + private JPanel initSearchPane() { + JPanel jPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); + jPanel.setBorder(BorderFactory.createEmptyBorder()); + searchField = new UITextField(); + searchField.requestFocus(); + searchField.addKeyListener(keyFieldKeyListener); + searchField.setPreferredSize(new Dimension(261, 20)); + jPanel.add(searchField); + UIButton searchBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Search")); + searchBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + search(); + } + }); + searchBtn.setPreferredSize(new Dimension(44, 20)); + jPanel.add(searchBtn); + return jPanel; + } + + + private KeyAdapter keyFieldKeyListener = new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + search(); + e.consume(); + } + } + }; + + + + private void search() { + //重新构建TreeModel + filter(searchField.getText()); + ExpandMutableTreeNode rootNode = (ExpandMutableTreeNode) tree.getModel().getRoot(); + ((DefaultTreeModel) tree.getModel()).reload(rootNode); + // 展开所有isExpanded为true的TreeNode + rootNode.expandCurrentTreeNode(tree); + } + + public void filter(String filterString) { + NodeAuthProcessor.getInstance().refresh(); + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) tree.getModel(); + ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) defaultTreeModel.getRoot(); + NodeAuthProcessor.getInstance().fixTreeNodeAuth(rootTreeNode); + filter(rootTreeNode, filterString); + defaultTreeModel.reload(rootTreeNode); + } + + private void filter(ExpandMutableTreeNode rootTreeNode, String filterString) { + rootTreeNode.removeAllChildren(); + + FileNode[] fns; + fns = listFileNodes(rootTreeNode); + + ExpandMutableTreeNode[] subTreeNodes = NodeAuthProcessor.getInstance().parser2TreeNodeArray(fns); + + for (ExpandMutableTreeNode node : subTreeNodes) { + filter(node, filterString); + if (node.getChildCount() > 0 || (node.getChildCount() == 0 && node.toString().contains(filterString))) { + node.setExpanded(true); + rootTreeNode.add(node); + } + } + + } + + private FileNode[] listFileNodes(ExpandMutableTreeNode rootTreeNode) { + if (rootTreeNode == null) { + return new FileNode[0]; + } + + Object object = rootTreeNode.getUserObject(); + if (!(object instanceof FileNode)) { + return new FileNode[0]; + } + + FileNode[] fileNodes = null; + try { + fileNodes = tree.listFile(((FileNode) object).getEnvPath()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + if (fileNodes == null) { + fileNodes = new FileNode[0]; + } + Arrays.sort(fileNodes, new FileNodeComparator(FileNodeConstants.getSupportFileTypes())); + return fileNodes; + } + + public void resetFilePaths(Map resultMap) { + this.tree.resetSelectedPaths(); + Iterator iterator = resultMap.keySet().iterator(); + List list = new ArrayList(); + while (iterator.hasNext()){ + FileNode node = iterator.next(); + list.add(node); + } + this.tree.addTransformedList(list); + this.tree.refresh(); + resultPane.populate(resultMap); + } + + public void removeSelectedNode(FileNode fileNode) { + String path = fileNode.getEnvPath(); + this.tree.removeSelectedPath(path); + } + + + @Override + protected String title4PopupWindow() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Batch_Transform"); + } + + public Dialog showDialog() { + return this.showDialog; + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/PrepareTransformFileList.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/PrepareTransformFileList.java new file mode 100644 index 000000000..22d6afcfd --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/PrepareTransformFileList.java @@ -0,0 +1,79 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilist.UIList; +import com.fr.design.gui.itree.filetree.FileTreeIcon; +import com.fr.file.filetree.FileNode; + +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.JList; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +/** + * Created by kerry on 2020-01-13 + */ +public class PrepareTransformFileList extends UIList { + private TransformPreparePane transformingPane; + private static final int DELETE_RANGE = 20; + + + public PrepareTransformFileList(final TransformPreparePane transformingPane) { + super(); + this.transformingPane = transformingPane; + this.setBackground(UIConstants.TREE_BACKGROUND); + this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + DefaultListModel listModel = new DefaultListModel(); + this.setModel(listModel); + this.setCellRenderer(new UIListControlCellRenderer() { + @Override + protected Icon getLeftLabelIcon(Object value) { + if (value instanceof FileNode) { + return FileTreeIcon.getIcon((FileNode) value); + } + return null; + } + + @Override + protected Icon getRightLabelIcon(Object value) { + return BaseUtils.readIcon("/com/fr/nx/app/designer/transform/tab_close.png"); + } + }); + this.addMouseListener(getListMouseListener()); + } + + + private MouseListener getListMouseListener() { + return new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent evt) { + JList list = (JList) evt.getSource(); + int selectedIndex = list.getSelectedIndex(); + Rectangle rectangle = list.getCellBounds(selectedIndex, selectedIndex); + if (SwingUtilities.isLeftMouseButton(evt) + && pointInSelected(rectangle, evt.getX(), evt.getY())) { + Object value = PrepareTransformFileList.this.getSelectedValue(); + if (value != null) { + transformingPane.removeSelectedNode((FileNode) value); + } + } + } + }; + } + + private boolean pointInSelected(Rectangle rectangle, int x, int y) { + if (rectangle == null) { + return false; + } + return x >= rectangle.x + rectangle.width - DELETE_RANGE && + x <= rectangle.x + rectangle.width && + y >= rectangle.y && y <= rectangle.y + rectangle.height; + } +} + diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformFileTree.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformFileTree.java new file mode 100644 index 000000000..cbfcd253f --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformFileTree.java @@ -0,0 +1,204 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.base.FRContext; +import com.fr.base.extension.FileExtension; +import com.fr.design.gui.itree.checkboxtree.CheckBoxTree; +import com.fr.design.gui.itree.checkboxtree.CheckBoxTreeCellRenderer; +import com.fr.design.gui.itree.checkboxtree.CheckBoxTreeSelectionModel; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.remote.ui.tree.FileAuthorityTree; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.nx.app.designer.transform.BatchTransformUtil; + +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; +import java.awt.AlphaComposite; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Created by kerry on 2020-01-13 + */ +public class TransformFileTree extends FileAuthorityTree { + private TransformPreparePane preparePane; + private static final float CHECKBOX_ENABLE_OPACITY = 0.4f; + + private List transformedList = new ArrayList(); + + public TransformFileTree(TransformPreparePane preparePane) { + this.preparePane = preparePane; + } + + public void addTransformedList(List removeList) { + this.transformedList.addAll(removeList); + } + + @Override + protected CheckBoxTree.Handler createHandler() { + return new CheckBoxTree.Handler(this) { + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + TreePath treePath = this.getTreePathForMouseEvent(e); + if (treePath == null) { + return; + } + CheckBoxTreeSelectionModel selectionModel = _tree.getCheckBoxTreeSelectionModel(); + boolean selected = selectionModel.isPathSelected(treePath, selectionModel.isDigIn()); + ExpandMutableTreeNode lastPathComponent = (ExpandMutableTreeNode) treePath.getLastPathComponent(); + List selectedFileNodes = filterBatchFileNode(lastPathComponent); + preparePane.removeTransformNode(selectedFileNodes); + if (selected) { + preparePane.addTransformNode(selectedFileNodes); + } + + } + }; + } + + + private List filterBatchFileNode(ExpandMutableTreeNode treeNode) { + List fileNodeList = new ArrayList<>(); + int childCount = treeNode.getChildCount(); + if (childCount > 0) { + loadPendingChildTreeNode(treeNode); + int expandChildCount = treeNode.getChildCount(); + for (int i = 0; i < expandChildCount; i++) { + fileNodeList.addAll(filterBatchFileNode((ExpandMutableTreeNode) treeNode.getChildAt(i))); + } + } else { + FileNode fileNode = (FileNode) treeNode.getUserObject(); + boolean locked = fileNodeLocked(treeNode); + if (!fileNode.isDirectory() && !locked) { + fileNodeList.add((FileNode) treeNode.getUserObject()); + } + } + return fileNodeList; + } + + + private boolean fileNodeLocked(ExpandMutableTreeNode treeNode) { + Object userObj = treeNode.getUserObject(); + if (userObj instanceof FileNode) { + FileNode node = (FileNode) userObj; + String lock = node.getLock(); + if (lock != null && !node.getUserID().equals(lock)) { + return true; + } + } + return false; + } + + public void resetSelectedPaths() { + CheckBoxTreeSelectionModel selectionModel = this.getCheckBoxTreeSelectionModel(); + selectionModel.clearSelection(); + } + + @Override + public void selectCheckBoxPaths(String[] paths) { + if (paths == null || paths.length == 0) { + return; + } + + DefaultTreeModel model = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot(); + List res = new ArrayList<>(); + for (String path : paths) { + TreePath treePath = getSelectedPath(treeNode, path); + if (treePath != null) { + res.add(treePath); + } + } + // 勾选中这些结点 + this.getCheckBoxTreeSelectionModel().setSelectionPaths(res.toArray(new TreePath[0])); + } + + private TreePath getSelectedPath(ExpandMutableTreeNode treeNode, String path) { + //可以只在选中的path中选择 + for (int i = 0, len = treeNode.getChildCount(); i < len; i++) { + ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) treeNode.getChildAt(i); + if (childTreeNode.getChildCount() > 0) { + loadPendingChildTreeNode(childTreeNode); + TreePath treePath = getSelectedPath(childTreeNode, path); + if (treePath != null) { + return treePath; + } + } + if (!(childTreeNode.getUserObject() instanceof FileNode)) { + continue; + } + FileNode fileNode = (FileNode) childTreeNode.getUserObject(); + if (ComparatorUtils.equals(path, fileNode.getEnvPath())) { + DefaultTreeModel model = (DefaultTreeModel) this.getModel(); + return new TreePath(model.getPathToRoot(childTreeNode)); + } + } + return null; + } + + public void removeSelectedPath(String path) { + if (path == null) { + return; + } + DefaultTreeModel model = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) model.getRoot(); + TreePath selectedPath = getSelectedPath(treeNode, path); + if (selectedPath != null) { + this.getCheckBoxTreeSelectionModel().removeSelectionPath(selectedPath); + + } + } + + + @Override + public FileNode[] listFile(String path) { + // 支持插件扩展, 先从env的filter拿, 再从插件拿 + Set supportTypes = new HashSet(); + for (String temp : this.filter.getSupportedTypes()) { + supportTypes.add(FileExtension.parse(temp)); + } + FileNode[] fileNodes = FRContext.getFileNodes().list( + path, + supportTypes.toArray(new FileExtension[supportTypes.size()]) + ); + return BatchTransformUtil.filterTransformedFile(fileNodes, transformedList); + } + + @Override + public boolean isCheckBoxEnabled(TreePath path) { + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) path.getLastPathComponent(); + return !fileNodeLocked(treeNode); + } + + @Override + protected CheckBoxTreeCellRenderer createCellRenderer(TreeCellRenderer renderer) { + final CheckBoxTreeCellRenderer checkBoxTreeCellRenderer = new CheckBoxTreeCellRenderer(renderer) { + @Override + public void paint(Graphics g) { + if (!_checkBox.isEnabled()) { + AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, CHECKBOX_ENABLE_OPACITY); + ((Graphics2D) g).setComposite(composite); + } + super.paint(g); + } + }; + addPropertyChangeListener(CELL_RENDERER_PROPERTY, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + checkBoxTreeCellRenderer.setActualTreeRenderer((TreeCellRenderer) evt.getNewValue()); + } + }); + return checkBoxTreeCellRenderer; + } + + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformPreparePane.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformPreparePane.java new file mode 100644 index 000000000..efbded1b0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformPreparePane.java @@ -0,0 +1,130 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.file.filetree.FileNode; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; +import com.fr.nx.app.designer.transform.BatchTransformer; +import com.fr.nx.app.designer.transform.UpdateCallBack; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.DefaultListModel; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by kerry on 2020-01-13 + */ +public class TransformPreparePane extends JPanel { + private static final String INITIAL_DISPLAY_TEXT = "0"; + private PrepareTransformFileList fileList; + private List selectedFileNodes; + private UpdateProgressDialog dialog; + private BatchTransformer transformer; + private UpdateCallBack updateProgressPane; + private Dialog parentDialog; + private UILabel transCountLabel; + private BatchTransformPane batchTransformPane; + private UIButton startTransform; + + public TransformPreparePane(Dialog parentDialog, BatchTransformPane batchTransformPane) { + this.batchTransformPane = batchTransformPane; + this.parentDialog = parentDialog; + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + updateProgressPane = new UpdateProgressPane(this); + transformer = new BatchTransformer(updateProgressPane); + fileList = new PrepareTransformFileList(this); + selectedFileNodes = new ArrayList<>(); + initPane(); + } + + private void initPane() { + JPanel transformPane = FRGUIPaneFactory.createTitledBorderPaneCenter( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Template_To_Transform")); + transformPane.setPreferredSize(new Dimension(270, 501)); + startTransform = new UIButton(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Start")); + startTransform.setEnabled(false); + addStartTransformListener(startTransform); + transCountLabel = new UILabel(INITIAL_DISPLAY_TEXT); + JPanel northPane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + northPane.add(startTransform); + northPane.add(Box.createHorizontalStrut(160)); + northPane.add(transCountLabel); + transformPane.add(northPane, BorderLayout.NORTH); + UIScrollPane scrollPane = new UIScrollPane(fileList); + scrollPane.setPreferredSize(new Dimension(260, 442)); + scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + transformPane.add(scrollPane, BorderLayout.CENTER); + this.add(transformPane, BorderLayout.CENTER); + } + + private void addStartTransformListener(UIButton startTransform) { + startTransform.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + //开始转换 + transformer.batchTransform(selectedFileNodes); + displayProgressPane(); + } + + + private void displayProgressPane() { + dialog = new UpdateProgressDialog(transformer, parentDialog, (JPanel) updateProgressPane); + dialog.setVisible(true); + } + }); + } + + public void addTransformNode(List fileNodeList) { + selectedFileNodes.addAll(fileNodeList); + buildFileList(); + + } + + public void removeTransformNode(List fileNodeList) { + selectedFileNodes.removeAll(fileNodeList); + buildFileList(); + } + + public void removeSelectedNode(FileNode fileNode) { + selectedFileNodes.remove(fileNode); + buildFileList(); + this.batchTransformPane.removeSelectedNode(fileNode); + } + + private void buildFileList() { + DefaultListModel listModel = new DefaultListModel(); + int count = selectedFileNodes.size(); + for (int i = count - 1; i >= 0; i--) { + listModel.addElement(selectedFileNodes.get(i)); + } + this.fileList.setModel(listModel); + startTransform.setEnabled(selectedFileNodes.size() > 0); + transCountLabel.setText(String.valueOf(selectedFileNodes.size())); + } + + public void complete() { + dialog.dialogExit(); + updateProgressPane.reset(); + Map resultMap = transformer.getResults(); + resetFileNodeList(); + this.batchTransformPane.resetFilePaths(resultMap); + } + + private void resetFileNodeList(){ + this.selectedFileNodes.clear(); + buildFileList(); + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultList.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultList.java new file mode 100644 index 000000000..83eb53400 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultList.java @@ -0,0 +1,70 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilist.UIList; +import com.fr.design.gui.itree.filetree.FileTreeIcon; +import com.fr.file.filetree.FileNode; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; + +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.ListSelectionModel; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by kerry on 2020-01-13 + */ +public class TransformResultList extends UIList { + private Map resultMap; + private static final Icon FAILED_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_failed.png"); + private static final Icon SUCCESS_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_success.png"); + private static final Icon UNSUPPORT_ICON = BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transform_unsupport.png"); + + public TransformResultList() { + super(); + this.setBackground(UIConstants.TREE_BACKGROUND); + this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + DefaultListModel listModel = new DefaultListModel(); + this.setModel(listModel); + this.setCellRenderer(new UIListControlCellRenderer() { + @Override + protected Icon getLeftLabelIcon(Object value) { + if (value instanceof FileNode) { + return FileTreeIcon.getIcon((FileNode) value); + } + return null; + } + + @Override + protected Icon getRightLabelIcon(Object value) { + if (value != null) { + TransformResultInfo resultInfo = resultMap.get(value); + switch (resultInfo.getResult()) { + case FAILED: + return FAILED_ICON; + case SUCCESS: + return SUCCESS_ICON; + case UNSUPPORT: + return UNSUPPORT_ICON; + } + } + return null; + } + }); + } + + public void populate(Map resultMap) { + this.resultMap = resultMap; + DefaultListModel listModel = new DefaultListModel(); + Iterator> iterator = resultMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + FileNode key = entry.getKey(); + listModel.addElement(key); + } + this.setModel(listModel); + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultPane.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultPane.java new file mode 100644 index 000000000..6bed5aafc --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/TransformResultPane.java @@ -0,0 +1,110 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.toolbar.TransformResult; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.util.Iterator; +import java.util.Map; + +/** + * Created by kerry on 2020-01-10 + */ +public class TransformResultPane extends JPanel { + private TransformResultList resultList; + private UITextArea resultInfo; + private Map resultMap; + private UILabel successTip; + + public TransformResultPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initPane(); + } + + private void initPane() { + JPanel resultPane = FRGUIPaneFactory.createTitledBorderPaneCenter( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Result")); + JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + resultList = new TransformResultList(); + addValueChangeListener(); + UIScrollPane scrollPane = new UIScrollPane(resultList); + scrollPane.setPreferredSize(new Dimension(260, 260)); + scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + successTip = new UILabel(""); + successTip.setBorder(BorderFactory.createEmptyBorder(5, 150, 5, 10)); + northPane.add(successTip, BorderLayout.NORTH); + northPane.add(scrollPane, BorderLayout.CENTER); + resultPane.add(northPane); + + JPanel resultInfoPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + resultInfoPane.setPreferredSize(new Dimension(270, 165)); + resultInfoPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5)); + UILabel transformLogLabel = new UILabel( + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Logs")); + transformLogLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); + resultInfoPane.add(transformLogLabel, BorderLayout.NORTH); + resultInfo = new UITextArea(); + resultInfo.setBackground(Color.white); + resultInfo.setLineWrap(true); + resultInfo.setWrapStyleWord(true); + resultInfo.setEditable(false); + UIScrollPane resultScrollPane = new UIScrollPane(resultInfo); + resultInfoPane.add(resultScrollPane, BorderLayout.CENTER); + this.add(resultPane, BorderLayout.NORTH); + this.add(resultInfoPane, BorderLayout.CENTER); + } + + private void addValueChangeListener() { + resultList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + FileNode selectedValue = (FileNode) resultList.getSelectedValue(); + if (resultInfo != null && selectedValue != null) { + TransformResultInfo result = resultMap.get(selectedValue); + resultInfo.setText(result.getTransformLog()); + } + } + }); + } + + public void populate(Map resultMap) { + int count = getSuccessCount(resultMap); + String tip = InterProviderFactory.getProvider().getLocText( + "Fine-Plugin_Engine_Transform_Result_Tip", String.valueOf(count)); + successTip.setText(tip); + this.resultMap = resultMap; + resultList.populate(resultMap); + if (resultList.getModel().getSize() > 0) { + resultList.setSelectedIndex(0); + FileNode firstResult = (FileNode) resultList.getModel().getElementAt(0); + resultInfo.setText(resultMap.get(firstResult).getTransformLog()); + } + } + + private int getSuccessCount(Map resultMap) { + int count = 0; + Iterator> iterator = resultMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + TransformResultInfo resultInfo = entry.getValue(); + if (ComparatorUtils.equals(TransformResult.SUCCESS, resultInfo.getResult())) { + count++; + } + } + return count; + } + +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UIListControlCellRenderer.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UIListControlCellRenderer.java new file mode 100644 index 000000000..47f677238 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UIListControlCellRenderer.java @@ -0,0 +1,86 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.StringUtils; +import sun.swing.DefaultLookup; + +import javax.swing.Icon; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; + +/** + * Created by kerry on 2020-01-14 + */ +public class UIListControlCellRenderer extends JPanel implements ListCellRenderer { + private UILabel content; + private UILabel controlLabel; + private Color initialLabelForeground; + + public UIListControlCellRenderer() { + initPane(); + } + + private void initPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + content = new UILabel(); + initialLabelForeground = content.getForeground(); + controlLabel = new UILabel(); + controlLabel.setPreferredSize(new Dimension(16, 20)); + this.add(content, BorderLayout.CENTER); + this.add(controlLabel, BorderLayout.EAST); + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + setComponentOrientation(list.getComponentOrientation()); + Color bg = null; + Color fg = null; + + JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsert() + && dropLocation.getIndex() == index) { + + bg = DefaultLookup.getColor(this, ui, "List.dropCellBackground"); + fg = DefaultLookup.getColor(this, ui, "List.dropCellForeground"); + + isSelected = true; + } + + if (isSelected) { + setBackground(bg == null ? list.getSelectionBackground() : bg); + setForeground(fg == null ? list.getSelectionForeground() : fg); + content.setForeground(Color.WHITE); + + } else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + content.setForeground(initialLabelForeground); + } + + content.setText((value == null) ? StringUtils.EMPTY : value.toString()); + Icon leftLabelIcon = getLeftLabelIcon(value); + if (leftLabelIcon != null) { + content.setIcon(leftLabelIcon); + } + Icon rightLabelIcon = getRightLabelIcon(value); + if (rightLabelIcon != null) { + controlLabel.setIcon(rightLabelIcon); + } + return this; + } + + protected Icon getLeftLabelIcon(Object value) { + return null; + } + + protected Icon getRightLabelIcon(Object value) { + return null; + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressDialog.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressDialog.java new file mode 100644 index 000000000..6d9bb009b --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressDialog.java @@ -0,0 +1,70 @@ +package com.fr.nx.app.designer.transform.ui; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.transform.BatchTransformer; + +import javax.swing.JDialog; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * Created by kerry on 2019-12-19 + */ +public class UpdateProgressDialog extends JDialog implements ActionListener { + + private UIButton pauseBtn; + private BatchTransformer transformer; + + public UpdateProgressDialog(BatchTransformer transformer, Dialog parent, JPanel contentPane) { + super(parent, true); + this.transformer = transformer; + initPane(contentPane); + } + + private void initPane(JPanel contentPane) { + this.setTitle(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Format_Transform")); + this.setResizable(false); + JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + this.setContentPane(defaultPane); + + pauseBtn = new UIButton(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Suspend")); + pauseBtn.addActionListener(this); + JPanel buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + buttonPanel.add(pauseBtn); + + defaultPane.add(contentPane, BorderLayout.CENTER); + defaultPane.add(buttonPanel, BorderLayout.SOUTH); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + transformer.shutDown(); + dialogExit(); + } + }); + + this.getRootPane().setDefaultButton(pauseBtn); + + this.setSize(new Dimension(262, 122)); + GUICoreUtils.centerWindow(this); + } + + @Override + public void actionPerformed(ActionEvent e) { + transformer.shutDown(); + dialogExit(); + } + + public void dialogExit() { + this.dispose(); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressPane.java b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressPane.java new file mode 100644 index 000000000..5fb57c369 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/transform/ui/UpdateProgressPane.java @@ -0,0 +1,72 @@ +package com.fr.nx.app.designer.transform.ui; + + +import com.fr.base.BaseUtils; +import com.fr.decision.update.data.UpdateConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.ComparatorUtils; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.app.designer.transform.UpdateCallBack; +import com.sun.java.swing.plaf.motif.MotifProgressBarUI; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import java.awt.BorderLayout; +import java.awt.Dimension; + + +/** + * Created by kerry on 2019-12-11 + */ +public class UpdateProgressPane extends BasicPane implements UpdateCallBack { + private TransformPreparePane contentPane; + private JProgressBar progressBar; + + public UpdateProgressPane(TransformPreparePane contentPane) { + this.contentPane = contentPane; + initPane(); + } + + private void initPane() { + this.setPreferredSize(new Dimension(262, 60)); + UILabel icon = new UILabel(BaseUtils.readIcon("/com/fr/nx/app/designer/transform/transforming.png")); + icon.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); + this.add(icon, BorderLayout.WEST); + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + UILabel title = new UILabel(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transforming")); + title.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0)); + centerPane.add(title, BorderLayout.NORTH); + progressBar = new JProgressBar(); + progressBar.setUI(new MotifProgressBarUI()); + progressBar.setForeground(UpdateConstants.BAR_COLOR); + centerPane.add(progressBar, BorderLayout.CENTER); + this.add(centerPane, BorderLayout.CENTER); + } + + + @Override + public void updateProgress(double progress) { + progressBar.setValue((int) (progress * 100)); + if (ComparatorUtils.equals(progress, 1D)) { + contentPane.complete(); + } + } + + @Override + public void shutDown() { + contentPane.complete(); + } + + @Override + public void reset() { + progressBar.setValue(0); + } + + @Override + protected String title4PopupWindow() { + return InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Suspend"); + } +} diff --git a/designer-base/src/main/java/com/fr/nx/app/designer/utils/CompileTransformUtil.java b/designer-base/src/main/java/com/fr/nx/app/designer/utils/CompileTransformUtil.java new file mode 100644 index 000000000..3de788cd1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/nx/app/designer/utils/CompileTransformUtil.java @@ -0,0 +1,55 @@ +package com.fr.nx.app.designer.utils; + +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.nx.app.designer.toolbar.TemplateTransformer; +import com.fr.nx.app.designer.toolbar.TransformResult; +import com.fr.nx.app.designer.toolbar.TransformResultInfo; +import com.fr.workspace.WorkContext; + +import java.io.InputStream; + +import static com.fr.base.extension.FileExtension.CPT; +import static com.fr.base.extension.FileExtension.CPTX; + +/** + * Created by kerry on 2019-12-04 + */ +public class CompileTransformUtil { + + + public static TransformResultInfo compileFile(FileNode fileNode) { + long start = System.currentTimeMillis(); + InputStream in = WorkContext.getWorkResource().openStream(fileNode.getEnvPath()); + WorkBook workBook = new WorkBook(); + TransformResultInfo result = null; + try { + workBook.readStream(in); + FILE file = TemplateTransformer.createOutputFile(fileNode.getEnvPath(), CPT.getSuffix(), CPTX.getSuffix()); + result = TemplateTransformer.compileCPTX(workBook, file); + } catch (Exception ignore) { + result = TransformResultInfo.generateResult(TransformResult.FAILED); + } + long end = System.currentTimeMillis(); + FineLoggerFactory.getLogger().debug(fileNode.getName() + " compile cost : " + (end - start) +" ms "); + return result; + } + + + public static FILE getTargetFile(JTemplate jTemplate, TemplateTransformer transformer) { + FILE file = null; + if (ComparatorUtils.equals(TemplateTransformer.TO_CPTX, transformer)) { + file = TemplateTransformer.createOutputFile(jTemplate.getEditingFILE().getPath(), + CPT.getSuffix(), CPTX.getSuffix()); + + } else if (ComparatorUtils.equals(TemplateTransformer.TO_CPT, transformer)) { + file = TemplateTransformer.createOutputFile(jTemplate.getEditingFILE().getPath(), + CPTX.getSuffix(), CPT.getSuffix()); + } + return file; + } +} diff --git a/designer-base/src/main/java/com/fr/start/BaseDesigner.java b/designer-base/src/main/java/com/fr/start/BaseDesigner.java index b3945d0d7..1c4c61126 100644 --- a/designer-base/src/main/java/com/fr/start/BaseDesigner.java +++ b/designer-base/src/main/java/com/fr/start/BaseDesigner.java @@ -11,6 +11,7 @@ import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.MutilTempalteTabPane; import com.fr.design.file.TemplateTreePane; import com.fr.design.fun.DesignerStartOpenFileProcessor; +import com.fr.design.fun.impl.DesignerStartWithEmptyFile; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrame; import com.fr.design.mainframe.toolbar.ToolBarMenuDock; @@ -147,6 +148,10 @@ public abstract class BaseDesigner extends ToolBarMenuDock { //启动时打开指定文件的接口 DesignerStartOpenFileProcessor processor = ExtraDesignClassManager.getInstance().getSingle(DesignerStartOpenFileProcessor.XML_TAG); + // 如果插件没有,且又开启了启动时打开空文件,则使用启动时打开空文件 + if (processor == null && DesignerEnvManager.getEnvManager().isStartWithEmptyFile()) { + processor = DesignerStartWithEmptyFile.getInstance(); + } if (processor != null) { FILE f = processor.fileToShow(); if (f != null) { diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off.png b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off.png new file mode 100644 index 000000000..0e8dce8ef Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on.png b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on.png new file mode 100644 index 000000000..2f519cf39 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/transparent_background.png b/designer-base/src/main/resources/com/fr/design/images/transparent_background.png new file mode 100644 index 000000000..cfb233f46 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/transparent_background.png differ diff --git a/designer-base/src/main/resources/com/fr/env/jarVersion.properties b/designer-base/src/main/resources/com/fr/env/jarVersion.properties index 8619fca7c..7eff54deb 100644 --- a/designer-base/src/main/resources/com/fr/env/jarVersion.properties +++ b/designer-base/src/main/resources/com/fr/env/jarVersion.properties @@ -1 +1 @@ -report-engine-key=fine-report-engine-10.0.jar \ No newline at end of file +report-engine-key=fine-report-engine-11.0.jar \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerDebugTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerDebugTest.java new file mode 100644 index 000000000..6a8f8247b --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerDebugTest.java @@ -0,0 +1,239 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.base.Parameter; +import com.fr.base.chart.BaseChartCollection; +import com.fr.base.io.XMLEncryptKey; +import com.fr.base.io.XMLEncryptUtils; +import com.fr.base.iofile.IOFileAttrMarkManager; +import com.fr.base.parameter.ParameterUI; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.config.dao.DaoContext; +import com.fr.config.dao.impl.LocalClassHelperDao; +import com.fr.config.dao.impl.LocalEntityDao; +import com.fr.config.dao.impl.LocalXmlEntityDao; +import com.fr.file.MemFILE; +import com.fr.form.DefaultFormOperator; +import com.fr.form.FormOperator; +import com.fr.form.main.ExtraFormClassManager; +import com.fr.form.main.Form; +import com.fr.form.main.FormHyperlink; +import com.fr.form.main.parameter.FormParameterUI; +import com.fr.form.parameter.FormSubmitButton; +import com.fr.form.plugin.DefaultSwitcherImpl; +import com.fr.general.xml.GeneralXMLTools; +import com.fr.io.EncryptUtils; +import com.fr.js.FormHyperlinkProvider; +import com.fr.main.impl.WorkBook; +import com.fr.nx.calculable.Calculable; +import com.fr.nx.calculable.type.ConstantCalculable; +import com.fr.nx.cell.CellKey; +import com.fr.nx.cell.CellTemplate; +import com.fr.nx.cptx.cache.CptxTemplatePool; +import com.fr.nx.cptx.entry.CptxTemplate; +import com.fr.nx.cptx.resource.ImageResourceRef; +import com.fr.page.BaseSinglePagePrintable; +import com.fr.page.BaseSingleReportCache; +import com.fr.page.ClippedChartPage; +import com.fr.page.ClippedECPage; +import com.fr.page.ClippedPageProvider; +import com.fr.page.PDF2Painter; +import com.fr.page.PageGeneratorProvider; +import com.fr.page.PagePainter; +import com.fr.page.PagePainterProvider; +import com.fr.page.PageSetChainProvider; +import com.fr.page.PageSetProvider; +import com.fr.page.PageXmlOperator; +import com.fr.page.PageXmlProvider; +import com.fr.page.PaperSettingProvider; +import com.fr.page.ReportPage; +import com.fr.page.ReportPageAttrProvider; +import com.fr.page.ReportPageProvider; +import com.fr.page.SheetPage; +import com.fr.page.SinglePagePrintable; +import com.fr.page.SingleReportCache; +import com.fr.page.generator.PaginateReportPageGenerator; +import com.fr.page.generator.PolyReportPageGenerator; +import com.fr.page.generator.SheetPageGenerator; +import com.fr.page.pageset.ArrayPageSet; +import com.fr.page.pageset.PageSetChain; +import com.fr.page.stable.PaperSetting; +import com.fr.page.stable.ReportPageAttr; +import com.fr.plugin.attr.CalculatorAttrMark; +import com.fr.runtime.FineRuntime; +import com.fr.stable.EssentialUtils; +import com.fr.stable.bridge.BridgeMark; +import com.fr.stable.bridge.StableFactory; +import com.fr.stable.fun.WidgetSwitcher; +import com.fr.stable.module.Module; +import com.fr.stable.plugin.ExtraFormClassManagerProvider; +import com.fr.transaction.Configurations; +import com.fr.transaction.LocalConfigurationHelper; +import com.fr.xml.ReportXMLUtils; +import org.easymock.EasyMock; +import org.easymock.IArgumentMatcher; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import java.io.InputStream; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({CptxTemplatePool.class, XMLEncryptUtils.class}) +@SuppressStaticInitializationFor({"com.fr.nx.cptx.cache.CptxTemplatePool", "com.fr.base.io.XMLEncryptUtils"}) +@PowerMockIgnore({"com.sun.tools.attach.*", "sun.tools.attach.*"}) +public class TemplateTransformerDebugTest { + + @BeforeClass + public static void beforeClass() { + System.setProperty("apple.awt.UIElement", "true"); + StableFactory.registerXMLDescription(ReportPageAttrProvider.XML_TAG, new ReportPageAttr()); + StableFactory.registerMarkedClass(ReportPageProvider.XML_TAG, ReportPage.class); + StableFactory.registerMarkedClass(PaperSettingProvider.XML_TAG, PaperSetting.class); + StableFactory.registerMarkedClass(ReportPageProvider.XML_TAG_4_SHEET, SheetPage.class); + StableFactory.registerMarkedClass(PagePainterProvider.XML_TAG, PagePainter.class); + StableFactory.registerMarkedClass(PageSetChainProvider.XML_TAG, PageSetChain.class); + StableFactory.registerMarkedClass(PageXmlProvider.XML_TAG, PageXmlOperator.class); + StableFactory.registerMarkedClass(BaseSinglePagePrintable.XML_TAG, SinglePagePrintable.class); + StableFactory.registerMarkedClass(BaseSingleReportCache.XML_TAG, SingleReportCache.class); + StableFactory.registerMarkedClass(PageSetProvider.XML_TAG_4_ARRAY, ArrayPageSet.class); + StableFactory.registerMarkedClass(ClippedPageProvider.XML_TAG_EC, ClippedECPage.class); + StableFactory.registerMarkedClass(ClippedPageProvider.XML_TAG_CHART, ClippedChartPage.class); + StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_PAGE, PaginateReportPageGenerator.class); + StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_POLY, PolyReportPageGenerator.class); + StableFactory.registerMarkedClass(PageGeneratorProvider.XML_TAG_SHEET, SheetPageGenerator.class); + StableFactory.registerMarkedClass(PagePainterProvider.XML_TAG_4_PDF, PDF2Painter.class); + StableFactory.registerMarkedClass(BridgeMark.SUBMIT_BUTTON, FormSubmitButton.class); + StableFactory.registerMarkedClass(FormOperator.MARK_STRING, DefaultFormOperator.class); + StableFactory.registerMarkedClass(Module.FORM_MODULE, Form.class); + StableFactory.registerMarkedClass(ParameterUI.FORM_XML_TAG, FormParameterUI.class); + StableFactory.registerMarkedClass(FormHyperlinkProvider.XML_TAG, FormHyperlink.class); + StableFactory.registerMarkedObject(WidgetSwitcher.XML_TAG, new DefaultSwitcherImpl()); + StableFactory.registerMarkedClass(ExtraFormClassManagerProvider.XML_TAG, ExtraFormClassManager.class); + StableFactory.registerXMLDescription(BaseChartCollection.XML_TAG, new ChartCollection()); + StableFactory.registerXMLDescription(Parameter.XML_TAG, new Parameter()); + FineRuntime.start(); + GeneralXMLTools.Object_Tokenizer = new ReportXMLUtils.ReportObjectTokenizer(); + GeneralXMLTools.Object_XML_Writer_Finder = new ReportXMLUtils.ReportObjectXMLWriterFinder(); + DaoContext.setEntityDao(new LocalEntityDao()); + DaoContext.setClassHelperDao(new LocalClassHelperDao()); + DaoContext.setXmlEntityDao(new LocalXmlEntityDao()); + Configurations.setHelper(new LocalConfigurationHelper()); + + IOFileAttrMarkManager.register(new CalculatorAttrMark()); + } + + @Before + public void before() { + Whitebox.setInternalState(XMLEncryptUtils.class, "KEY", new XMLEncryptKey()); + } + + @Test + public void testUnsupportedCompile() { + WorkBook workbook = readCpt("read-write-expand-order.cpt"); + + CptxTemplatePool pool = EasyMock.mock(CptxTemplatePool.class); + PowerMock.mockStatic(CptxTemplatePool.class); + EasyMock.expect(CptxTemplatePool.getInstance()).andReturn(pool).anyTimes(); + + PowerMock.replay(CptxTemplatePool.class); + pool.addCptxTemplate(EasyMock.anyString(), matchUnsupportedWebPreviewCptxTemplate()); + EasyMock.expectLastCall().once(); + + EasyMock.replay(pool); + TemplateTransformer.compileCPTX(workbook, new MemFILE("read-write-expand-order.cpt")); + + EasyMock.verify(pool); + PowerMock.verify(CptxTemplatePool.class); + + } + + @Test + public void testImageRefCompile() { + WorkBook workbook = readCpt("read-write-image-ref.cpt"); + + CptxTemplatePool pool = EasyMock.mock(CptxTemplatePool.class); + PowerMock.mockStatic(CptxTemplatePool.class); + EasyMock.expect(CptxTemplatePool.getInstance()).andReturn(pool).anyTimes(); + + PowerMock.replay(CptxTemplatePool.class); + pool.addCptxTemplate(EasyMock.anyString(), matchImageRefWebPreviewCptxTemplate()); + EasyMock.expectLastCall().once(); + + EasyMock.replay(pool); + TemplateTransformer.compileCPTX(workbook, new MemFILE("read-write-image-ref.cpt")); + + EasyMock.verify(pool); + PowerMock.verify(CptxTemplatePool.class); + + } + + private CptxTemplate matchImageRefWebPreviewCptxTemplate() { + EasyMock.reportMatcher(new IArgumentMatcher() { + @Override + public boolean matches(Object argument) { + if (argument instanceof CptxTemplate) { + CptxTemplate cptxTemplate = (CptxTemplate) argument; + Assert.assertNotNull(cptxTemplate.getTemplate()); + Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult()); + Assert.assertEquals(1, cptxTemplate.getTemplate().getCompileResult().getCellBlocks().length); + Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure()); + Assert.assertNotNull(cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure().getCells()); + CellTemplate cellTemplate = cptxTemplate.getTemplate().getCompileResult().getCellBlocks()[0].getDataStructure().getCells().get(CellKey.fromString("A2")); + Assert.assertNotNull(cellTemplate); + Calculable calculable = cellTemplate.getCalculable(); + ConstantCalculable constantCalculable = calculable.unWrap(ConstantCalculable.KEY); + Assert.assertNotNull(constantCalculable); + Assert.assertTrue(constantCalculable.get() instanceof ImageResourceRef); + return true; + } + return false; + } + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("cptx template should be previewed on the web side but not."); + } + }); + return null; + } + + private CptxTemplate matchUnsupportedWebPreviewCptxTemplate() { + EasyMock.reportMatcher(new IArgumentMatcher() { + @Override + public boolean matches(Object argument) { + if (argument instanceof CptxTemplate) { + CptxTemplate cptxTemplate = (CptxTemplate) argument; + Assert.assertEquals("unsupported feature: sort after expand", + cptxTemplate.getMetadata().getFailMessage()); + return true; + } + return false; + } + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("should find unsupported error message but not"); + } + }); + return null; + } + + private static WorkBook readCpt(String subPath) { + InputStream is = TemplateTransformerDebugTest.class.getClassLoader().getResourceAsStream("cpt/" + subPath); + WorkBook wb = new WorkBook(); + try { + wb.readStream(EncryptUtils.decodeInputStream(is)); + } catch (Exception e) { + throw new RuntimeException(e); + } + return wb; + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerTest.java new file mode 100644 index 000000000..e0afe9313 --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TemplateTransformerTest.java @@ -0,0 +1,85 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.base.FRContext; +import com.fr.base.operator.common.CommonOperator; +import com.fr.file.FILE; +import com.fr.file.filetree.FileNodes; +import com.fr.invoke.Reflect; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static com.fr.nx.app.designer.toolbar.TemplateTransformer.OTHER; +import static com.fr.nx.app.designer.toolbar.TemplateTransformer.TO_CPT; +import static com.fr.nx.app.designer.toolbar.TemplateTransformer.TO_CPTX; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({FRContext.class}) +@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*", "com.fr.license.*"}) +public class TemplateTransformerTest { + + @Test + public void testParse() { + assertEquals(TO_CPTX, TemplateTransformer.parse("/sdf/abc.cpt")); + assertEquals(TO_CPT, TemplateTransformer.parse("/sdf/abc.cptx")); + assertEquals(OTHER, TemplateTransformer.parse("/sdf/abc.frm")); + assertEquals(OTHER, TemplateTransformer.parse(null)); + assertEquals(OTHER, TemplateTransformer.parse("abc")); + } + + @Test + public void testCompileFailed() { + TransformResultInfo result = TemplateTransformer.compileCPTX(null, null); + assertEquals(result.getResult(), TransformResult.FAILED); + } + + @Test + public void testGenerateNewPath() { + assertEquals(generateNewPath("/abc/dd.cpt", ".cpt", ".cptx"), "/abc/dd.cptx"); + assertEquals(generateNewPath("/abc/dd.cptx", ".cpt", ".cptx"), "/abc/dd.cptx"); + assertEquals(generateNewPath("/abc/dd.cptx", ".cptx", ".cpt"), "/abc/dd.cpt"); + assertEquals(generateNewPath("/abc/dd.frm", ".cpt", ".cptx"), "/abc/dd.frm"); + assertNull(generateNewPath(null, null, null)); + assertEquals(generateNewPath("abc", null, null), "abc"); + } + + private String generateNewPath(String oldPath, String oldSuffix, String newSuffix) { + return Reflect.on(TemplateTransformer.class).call("generateNewPath", oldPath, oldSuffix, newSuffix).get(); + } + + @Test + public void testCreateOutputFile() { + CommonOperator commonOperator = EasyMock.mock(CommonOperator.class); + FileNodes fileNodes = EasyMock.mock(FileNodes.class); + EasyMock.expect(fileNodes.getSupportedTypes()).andReturn(new String[]{"cptx"}).anyTimes(); + PowerMock.mockStatic(FRContext.class); + EasyMock.expect(FRContext.getCommonOperator()).andReturn(commonOperator).anyTimes(); + EasyMock.expect(FRContext.getFileNodes()).andReturn(fileNodes).anyTimes(); + EasyMock.expect(commonOperator.getWebRootPath()).andReturn("/WebInf/").anyTimes(); + EasyMock.replay(commonOperator, fileNodes); + PowerMock.replayAll(); + FILE file1 = TemplateTransformer.createOutputFile("WorkBook1.cpt", ".cpt", ".cptx"); + FILE file2 = TemplateTransformer.createOutputFile("WorkBook1.cpt", ".cptx", ".cpt"); + assertEquals("WorkBook1.cptx", file1.getPath()); + assertEquals("WorkBook1.cpt", file2.getPath()); + } + + + @Test + public void testNeedDoAfterTransformed() { + Assert.assertTrue(needDoAfterTransformed(TransformResult.SUCCESS)); + Assert.assertTrue(needDoAfterTransformed(TransformResult.UNSUPPORT)); + Assert.assertFalse(needDoAfterTransformed(TransformResult.FAILED)); + } + + private boolean needDoAfterTransformed(TransformResult result) { + return Reflect.on(TemplateTransformer.class).call("needDoAfterTransformed", result).get(); + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java new file mode 100644 index 000000000..66a32b95f --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/toolbar/TransformResultInfoTest.java @@ -0,0 +1,32 @@ +package com.fr.nx.app.designer.toolbar; + +import com.fr.locale.InterProviderFactory; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by kerry on 2020-01-15 + */ +public class TransformResultInfoTest { + @Test + public void testGetTransformLog() { + TransformResultInfo resultInfo1 = TransformResultInfo.generateResult(TransformResult.FAILED, "failed"); + Assert.assertEquals("failed\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Failed_Tip"), + resultInfo1.getTransformLog()); + TransformResultInfo resultInfo2 = TransformResultInfo.generateResult(TransformResult.SUCCESS); + Assert.assertEquals(InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Success_Tip"), + resultInfo2.getTransformLog()); + TransformResultInfo resultInfo3 = TransformResultInfo.generateResult(TransformResult.UNSUPPORT, "unsupport"); + Assert.assertEquals("unsupport\n" + + InterProviderFactory.getProvider().getLocText("Fine-Plugin_Engine_Transform_Unsupport_Tip"), + resultInfo3.getTransformLog()); + + } + + @Test + public void testSaved() { + TransformResultInfo resultInfo1 = TransformResultInfo.generateResult(TransformResult.FAILED, "failed").saved(false); + Assert.assertFalse(resultInfo1.isSaved()); + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformProgressTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformProgressTest.java new file mode 100644 index 000000000..c0b68c0ab --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformProgressTest.java @@ -0,0 +1,27 @@ +package com.fr.nx.app.designer.transform; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by kerry on 2020-01-15 + */ +public class BatchTransformProgressTest { + @Test + public void testGetProgress(){ + BatchTransformProgress batchTransformProgress = new BatchTransformProgress(100); + Assert.assertEquals(0.0D, batchTransformProgress.getProgress(), 0.0D); + } + + @Test + public void testUpdateProgress(){ + BatchTransformProgress batchTransformProgress = new BatchTransformProgress(100); + for (int i = 0; i < 80; i++) { + batchTransformProgress.updateProgress(); + } + Assert.assertEquals(0.8D, batchTransformProgress.getProgress(), 0.0D); + batchTransformProgress.updateProgress(); + Assert.assertEquals(0.81D, batchTransformProgress.getProgress(), 0.0D); + + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformUtilTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformUtilTest.java new file mode 100644 index 000000000..b3adc1246 --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformUtilTest.java @@ -0,0 +1,35 @@ +package com.fr.nx.app.designer.transform; + +import com.fr.file.filetree.FileNode; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by kerry on 2020-02-14 + */ +public class BatchTransformUtilTest { + @Test + public void testFilterTransformedFile(){ + FileNode[] fileNodes = new FileNode[]{ + new FileNode("test1", false), new FileNode("test2", false) + }; + List transformedFileNodes = new ArrayList(); + FileNode[] result1 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(2, result1.length); + + transformedFileNodes.add( new FileNode("test1", false)); + FileNode[] result2 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(1, result2.length); + + transformedFileNodes.add( new FileNode("test2", false)); + FileNode[] result3 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(0, result3.length); + + transformedFileNodes.add( new FileNode("test3", false)); + FileNode[] result4 = BatchTransformUtil.filterTransformedFile(fileNodes, transformedFileNodes); + Assert.assertEquals(0, result4.length); + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformerTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformerTest.java new file mode 100644 index 000000000..d29d3e742 --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/transform/BatchTransformerTest.java @@ -0,0 +1,124 @@ +package com.fr.nx.app.designer.transform; + +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; + +/** + * Created by kerry on 2020-01-15 + */ +// FIXME @kerry 打包失败,暂时先注释 +//@RunWith(value = PowerMockRunner.class) +//@PrepareForTest({CompileTransformUtil.class, PluginContexts.class}) +//@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*"}) +public class BatchTransformerTest { + + private static final int MAXPOOLSIZE = 5; + private static final int COREPOOLSIZE = 3; + private static final String THREAD_NAME_TEMPLATE = "batchtransform-thread-%s"; + + @Before + public void setUp() { +// FineRuntime.start(); +// ExecutorService threadPoolExecutor = new ThreadPoolExecutor(COREPOOLSIZE, MAXPOOLSIZE, +// 0L, TimeUnit.MILLISECONDS, +// new LinkedBlockingQueue(), +// new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_TEMPLATE).build()); +// PowerMock.mockStatic(PluginContexts.class); +// PluginContext pluginContext = EasyMock.mock(PluginContext.class); +// EasyMock.expect(pluginContext.newFixedThreadPool( +// EasyMock.anyInt(), EasyMock.anyObject(ThreadFactory.class))) +// .andReturn(threadPoolExecutor).anyTimes(); +// EasyMock.expect(PluginContexts.currentContext()).andReturn(pluginContext).anyTimes(); +// +// PowerMock.mockStatic(CompileTransformUtil.class); +// TransformResultInfo resultInfo = TransformResultInfo.generateResult(TransformResult.SUCCESS); +// EasyMock.expect(CompileTransformUtil.compileFile(EasyMock.anyObject(FileNode.class))) +// .andReturn(resultInfo).anyTimes(); +// EasyMock.replay(pluginContext); +// PowerMock.replayAll(); + } + + @Test + public void testBatchTransform() { +// final CountDownLatch countDownLatch = new CountDownLatch(2); +// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch)); +// List nodeList = new ArrayList<>(); +// FileNode test1 = new FileNode("path1", false); +// FileNode test2 = new FileNode("path2", false); +// nodeList.add(test1); +// nodeList.add(test2); +// transformer.batchTransform(nodeList); +// try { +// countDownLatch.await(5, TimeUnit.SECONDS); +// } catch (InterruptedException e) { +// Assert.fail(); +// } +// Map transformResults = transformer.getResults(); +// Assert.assertEquals(2, transformResults.size()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test1).getResult()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test2).getResult()); + + } + + @Test + public void testTransform() { +// final CountDownLatch countDownLatch = new CountDownLatch(1); +// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch)); +// FileNode test = new FileNode("path", false); +// Reflect.on(transformer).call("transform", test); +// try { +// countDownLatch.await(5, TimeUnit.SECONDS); +// } catch (InterruptedException e) { +// Assert.fail(); +// } +// Map transformResults = transformer.getResults(); +// Assert.assertEquals(1, transformResults.size()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test).getResult()); + } + + @Test + public void testShutDown() { +// final CountDownLatch countDownLatch = new CountDownLatch(1); +// BatchTransformer transformer = new BatchTransformer(new MockUpdateCallBack(countDownLatch)); +// List nodeList = new ArrayList<>(); +// FileNode test = new FileNode("path", false); +// nodeList.add(test); +// transformer.batchTransform(nodeList); +// transformer.shutDown(); +// try { +// countDownLatch.await(3, TimeUnit.SECONDS); +// } catch (InterruptedException e) { +// Assert.fail(); +// } +// Map transformResults = transformer.getResults(); +// Assert.assertEquals(1, transformResults.size()); +// Assert.assertEquals(TransformResult.SUCCESS, transformResults.get(test).getResult()); + } + + + private class MockUpdateCallBack implements UpdateCallBack { + private CountDownLatch countDownLatch; + + + public MockUpdateCallBack(CountDownLatch countDownLatch) { + this.countDownLatch = countDownLatch; + } + + @Override + public void updateProgress(double progress) { + countDownLatch.countDown(); + } + + @Override + public void shutDown() { + + } + + @Override + public void reset() { + + } + } +} diff --git a/designer-base/src/test/java/com/fr/nx/app/designer/utils/CompileTransformUtilTest.java b/designer-base/src/test/java/com/fr/nx/app/designer/utils/CompileTransformUtilTest.java new file mode 100644 index 000000000..653bbdef2 --- /dev/null +++ b/designer-base/src/test/java/com/fr/nx/app/designer/utils/CompileTransformUtilTest.java @@ -0,0 +1,58 @@ +package com.fr.nx.app.designer.utils; + +import com.fr.base.FRContext; +import com.fr.base.operator.common.CommonOperator; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.FILE; +import com.fr.file.filetree.FileNodes; +import com.fr.nx.app.designer.toolbar.TemplateTransformer; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +/** + * Created by kerry on 2019-12-04 + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({FRContext.class}) +@PowerMockIgnore({"sun.tools.attach.*", "com.sun.tools.*"}) +public class CompileTransformUtilTest { + @Test + public void testGetTargetFile() { + CommonOperator commonOperator = EasyMock.mock(CommonOperator.class); + FileNodes fileNodes = EasyMock.mock(FileNodes.class); + EasyMock.expect(fileNodes.getSupportedTypes()).andReturn(new String[]{"cptx"}).anyTimes(); + PowerMock.mockStatic(FRContext.class); + EasyMock.expect(FRContext.getCommonOperator()).andReturn(commonOperator).anyTimes(); + EasyMock.expect(FRContext.getFileNodes()).andReturn(fileNodes).anyTimes(); + EasyMock.expect(commonOperator.getWebRootPath()).andReturn("/WebInf/").anyTimes(); + EasyMock.replay(commonOperator, fileNodes); + PowerMock.replayAll(); + JTemplate jTemplate1 = EasyMock.mock(JTemplate.class); + FILE file1 = EasyMock.mock(FILE.class); + EasyMock.expect(jTemplate1.getEditingFILE()).andReturn(file1).anyTimes(); + EasyMock.expect(file1.getPath()).andReturn("WorkBook1.cpt").anyTimes(); + EasyMock.replay(jTemplate1, file1); + FILE targetFile = CompileTransformUtil.getTargetFile(jTemplate1, TemplateTransformer.TO_CPTX); + Assert.assertEquals("WorkBook1.cptx", targetFile.getPath()); + + targetFile = CompileTransformUtil.getTargetFile(jTemplate1, TemplateTransformer.TO_CPT); + Assert.assertEquals("WorkBook1.cpt", targetFile.getPath()); + + JTemplate jTemplate2 = EasyMock.mock(JTemplate.class); + FILE file2 = EasyMock.mock(FILE.class); + EasyMock.expect(jTemplate2.getEditingFILE()).andReturn(file2).anyTimes(); + EasyMock.expect(file2.getPath()).andReturn("WorkBook1.cpt").anyTimes(); + EasyMock.replay(jTemplate2, file2); + targetFile = CompileTransformUtil.getTargetFile(jTemplate2, TemplateTransformer.TO_CPTX); + Assert.assertEquals("WorkBook1.cptx", targetFile.getPath()); + + targetFile =CompileTransformUtil.getTargetFile(jTemplate2, TemplateTransformer.TO_CPT); + Assert.assertEquals("WorkBook1.cpt", targetFile.getPath()); + } +} diff --git a/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java b/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java index 4cd00e577..bce90aaae 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java +++ b/designer-chart/src/main/java/com/fr/design/chart/ChartDialog.java @@ -3,6 +3,7 @@ package com.fr.design.chart; import com.fr.base.chart.BaseChartCollection; import com.fr.chart.chartattr.ChartCollection; import com.fr.design.dialog.BasicDialog; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.chart.MiddleChartDialog; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.i18n.Toolkit; @@ -110,6 +111,7 @@ public class ChartDialog extends MiddleChartDialog { if (cc == null) { return; } + cc.setThemeStyle(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getTemplateTheme()); this.cc = cc; } diff --git a/designer-chart/src/main/java/com/fr/design/chart/gui/ChartComponent.java b/designer-chart/src/main/java/com/fr/design/chart/gui/ChartComponent.java index 1ce2fbffd..b251abc6a 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/gui/ChartComponent.java +++ b/designer-chart/src/main/java/com/fr/design/chart/gui/ChartComponent.java @@ -146,7 +146,6 @@ public class ChartComponent extends MiddleChartComponent implements MouseListene return; } - chartCollection4Design.setPredefinedStyleName(getGlobalPredefinedStyleName(), false); Graphics2D g2d = (Graphics2D) g; if (this.isOpaque()) { diff --git a/designer-chart/src/main/java/com/fr/design/chart/gui/ChartWidgetOption.java b/designer-chart/src/main/java/com/fr/design/chart/gui/ChartWidgetOption.java index 7e64f3d20..30d01cb55 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/gui/ChartWidgetOption.java +++ b/designer-chart/src/main/java/com/fr/design/chart/gui/ChartWidgetOption.java @@ -2,6 +2,7 @@ package com.fr.design.chart.gui; import com.fr.base.chart.BaseChartGetter; import com.fr.chart.chartattr.ChartCollection; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.core.WidgetOption; import com.fr.form.ui.ChartEditor; import com.fr.form.ui.Widget; @@ -40,6 +41,7 @@ public class ChartWidgetOption extends WidgetOption { try { ChartEditor widget = clz.newInstance(); ChartCollection chartCollection = (ChartCollection) BaseChartGetter.createChartCollection(this.chartID); + chartCollection.setThemeStyle(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getTemplateTheme()); VanChart vanChart = chartCollection.getSelectedChartProvider(VanChart.class); if (vanChart !=null) { vanChart.resetAttrInForm(); diff --git a/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/impl/ChartHyperPoplinkPane.java b/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/impl/ChartHyperPoplinkPane.java index ae3867220..3372880dd 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/impl/ChartHyperPoplinkPane.java +++ b/designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/impl/ChartHyperPoplinkPane.java @@ -7,6 +7,7 @@ import com.fr.chart.charttypes.ChartTypeManager; import com.fr.chart.web.ChartHyperPoplink; import com.fr.chartx.attr.ChartProvider; import com.fr.design.chart.gui.ChartComponent; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.hyperlink.AbstractHyperLinkPane; import com.fr.design.layout.FRGUIPaneFactory; @@ -14,9 +15,9 @@ import com.fr.design.mainframe.chart.ChartHyperEditPane; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.log.FineLoggerFactory; +import java.util.HashMap; import java.awt.BorderLayout; import java.awt.Dimension; -import java.util.HashMap; /** * 类说明: 图表超链 -- 弹出 悬浮窗. @@ -64,6 +65,7 @@ public class ChartHyperPoplinkPane extends AbstractHyperLinkPane preButton; private JPanel textFontPane; - public ChartTextAttrPaneWithPreStyle() { + public ChartTextAttrPaneWithThemeStyle() { initListener(); } protected JPanel getContentPane(JPanel buttonPane) { - preButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Predefined"), + JPanel panel = new JPanel(new BorderLayout(0, 10)); + + preButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Follow_Theme"), Toolkit.i18nText("Fine-Design_Chart_Custom")}); double f = TableLayout.FILL; double e = getEdithAreaWidth(); - double[] columnSize = {f, e}; double p = TableLayout.PREFERRED; - textFontPane = TableLayout4VanChartHelper.createGapTableLayoutPane(getComponents(buttonPane), getRowSize(), columnSize); - - double[] rowSize = {p, p, p}; + double[] columnSize = {f, e}; UILabel text = new UILabel(Toolkit.i18nText("Fine-Design_Chart_Character"), SwingConstants.LEFT); - Component[][] components = { - new Component[]{null, null}, - new Component[]{text, preButton}, - new Component[]{textFontPane, null}, - }; - return TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize); + JPanel preButtonPane = TableLayout4VanChartHelper.createGapTableLayoutPane(new Component[][]{new Component[]{text, preButton}}, new double[]{p}, columnSize); + textFontPane = TableLayout4VanChartHelper.createGapTableLayoutPane(getComponents(buttonPane), getRowSize(), columnSize); + panel.add(preButtonPane, BorderLayout.CENTER); + panel.add(textFontPane, BorderLayout.SOUTH); + panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + return panel; } protected double getEdithAreaWidth() { @@ -72,11 +72,19 @@ public class ChartTextAttrPaneWithPreStyle extends ChartTextAttrPane { private void checkPreButton() { textFontPane.setVisible(preButton.getSelectedIndex() == CUSTOM); - textFontPane.setPreferredSize(preButton.getSelectedIndex() == CUSTOM ? new Dimension(0, 60) : new Dimension(0, 0)); + } + + protected double[] getRowSize() { + double p = TableLayout.PREFERRED; + return new double[]{p, p}; } public void populate(TextAttr textAttr) { - if (textAttr.isPredefinedStyle()) { + populate(textAttr, false); + } + + public void populate(TextAttr textAttr, boolean autoFont) { + if (textAttr.isThemed() || autoFont) { preButton.setSelectedIndex(PREDEFINED_STYLE); } else { preButton.setSelectedIndex(CUSTOM); @@ -88,9 +96,9 @@ public class ChartTextAttrPaneWithPreStyle extends ChartTextAttrPane { public void update(TextAttr textAttr) { int selectedIndex = preButton.getSelectedIndex(); if (selectedIndex == PREDEFINED_STYLE) { - textAttr.setPredefinedStyle(true); + textAttr.setThemed(true); } else { - textAttr.setPredefinedStyle(false); + textAttr.setThemed(false); } super.update(textAttr); } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithPreStyle.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithThemeStyle.java similarity index 81% rename from designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithPreStyle.java rename to designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithThemeStyle.java index a4a0344fa..bee92e04c 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithPreStyle.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ColorSelectBoxWithThemeStyle.java @@ -1,6 +1,6 @@ package com.fr.design.mainframe.chart.gui.style; -import com.fr.chart.base.ColorWithPreStyle; +import com.fr.chart.base.ColorWithThemeStyle; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.ibutton.UIButtonGroup; import com.fr.design.gui.ilable.UILabel; @@ -22,7 +22,7 @@ import java.awt.event.ActionListener; * @version 10.0 * Created by Bjorn on 2020-09-07 */ -public class ColorSelectBoxWithPreStyle extends BasicPane { +public class ColorSelectBoxWithThemeStyle extends BasicPane { private static final int PREDEFINED_STYLE = 0; private static final int CUSTOM = 1; @@ -30,8 +30,8 @@ public class ColorSelectBoxWithPreStyle extends BasicPane { private UIButtonGroup preButton; private ColorSelectBox colorSelectBox; - public ColorSelectBoxWithPreStyle(int preferredWidth) { - preButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Predefined"), + public ColorSelectBoxWithThemeStyle(int preferredWidth) { + preButton = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Follow_Theme"), Toolkit.i18nText("Fine-Design_Chart_Custom")}); colorSelectBox = new ColorSelectBox(preferredWidth); initContent(); @@ -73,15 +73,15 @@ public class ColorSelectBoxWithPreStyle extends BasicPane { return null; } - public void populate(ColorWithPreStyle colorWithPreStyle) { - preButton.setSelectedIndex(colorWithPreStyle.isPredefinedStyle() ? PREDEFINED_STYLE : CUSTOM); + public void populate(ColorWithThemeStyle colorWithPreStyle) { + preButton.setSelectedIndex(colorWithPreStyle.isThemed() ? PREDEFINED_STYLE : CUSTOM); colorSelectBox.setSelectObject(colorWithPreStyle.getColor()); checkPreButton(); } - public ColorWithPreStyle update() { - ColorWithPreStyle colorWithPreStyle = new ColorWithPreStyle(); - colorWithPreStyle.setPredefinedStyle(preButton.getSelectedIndex() == PREDEFINED_STYLE); + public ColorWithThemeStyle update() { + ColorWithThemeStyle colorWithPreStyle = new ColorWithThemeStyle(); + colorWithPreStyle.setThemed(preButton.getSelectedIndex() == PREDEFINED_STYLE); colorWithPreStyle.setColor(colorSelectBox.getSelectObject()); return colorWithPreStyle; } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane.java index 6529efce0..736ae5b3f 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane.java @@ -370,6 +370,11 @@ public class UIColorPickerPane extends BasicPane implements UIObserver { ColorRecButton.this.repaint(); } + @Override + protected ColorSelectionPopupPane createColorSelectionPopupPane(boolean isSupportTransparent) { + return new ColorSelectionPopupPane(isSupportTransparent, supportThemeColor(), ColorRecButton.this.color); + } + }; } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane4Map.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane4Map.java index 8606ffab9..217b01d8b 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane4Map.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/series/UIColorPickerPane4Map.java @@ -2,15 +2,10 @@ package com.fr.design.mainframe.chart.gui.style.series; import com.fr.chart.base.ChartConstants; import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; -import com.fr.design.style.color.ColorCell; import com.fr.design.style.color.ColorSelectBox; -import com.fr.design.style.color.ColorSelectPane; +import com.fr.design.style.color.NewColorSelectPane; -import javax.swing.Box; -import javax.swing.JPanel; -import javax.swing.JSeparator; import java.awt.Color; -import java.awt.GridLayout; /** * Created by IntelliJ IDEA. @@ -27,23 +22,12 @@ public class UIColorPickerPane4Map extends UIColorPickerPane { return new ColorSelectBox4Map(100); } - private class ColorSelectPane4Map extends ColorSelectPane { + private class ColorSelectPane4Map extends NewColorSelectPane { public ColorSelectPane4Map(){ super(false); } - public void initCenterPaneChildren(JPanel centerPane) { - JPanel menuColorPane1 = new JPanel(); - centerPane.add(menuColorPane1); - menuColorPane1.setLayout(new GridLayout(5, 8, 5, 5)); - for (int i = 0; i < ChartConstants.MAP_COLOR_ARRAY.length; i++) { - menuColorPane1.add(new ColorCell(ChartConstants.MAP_COLOR_ARRAY[i], this)); - } - centerPane.add(Box.createVerticalStrut(5)); - centerPane.add(new JSeparator()); - } - protected Color[] getColorArray(){ return ChartConstants.MAP_COLOR_ARRAY; } @@ -54,7 +38,7 @@ public class UIColorPickerPane4Map extends UIColorPickerPane { super(preferredWidth); } - protected ColorSelectPane getColorSelectPane(){ + protected NewColorSelectPane getColorSelectPane(){ return new ColorSelectPane4Map(); } } diff --git a/designer-chart/src/main/java/com/fr/design/module/ChartPreFillStylePane.java b/designer-chart/src/main/java/com/fr/design/module/ChartPreFillStylePane.java index 8091a78eb..4cc8466fd 100644 --- a/designer-chart/src/main/java/com/fr/design/module/ChartPreFillStylePane.java +++ b/designer-chart/src/main/java/com/fr/design/module/ChartPreFillStylePane.java @@ -8,6 +8,7 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.style.background.gradient.FixedGradientBarNoTheme; import com.fr.design.style.color.ColorAdjustPane; import com.fr.design.style.background.gradient.FixedGradientBar; @@ -58,7 +59,7 @@ public class ChartPreFillStylePane extends BasicBeanPane { changeColorSetPane = new JPanel(cardLayout = new CardLayout()); changeColorSetPane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); - changeColorSetPane.add(colorGradient = new FixedGradientBar(4, 150), "gradient"); + changeColorSetPane.add(colorGradient = new FixedGradientBarNoTheme(4, 150), "gradient"); changeColorSetPane.add(colorAdjustPane = new ColorAdjustPane(), "acc"); cardLayout.show(changeColorSetPane, "acc"); customPane.add(changeColorSetPane, BorderLayout.CENTER); diff --git a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleAction.java b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleAction.java index 61b9a8c4f..e989e1a36 100644 --- a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleAction.java +++ b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleAction.java @@ -16,6 +16,8 @@ import com.fr.transaction.WorkerFacade; import com.fr.van.chart.designer.component.VanChartFillStylePane; import javax.swing.KeyStroke; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.util.concurrent.ExecutorService; import java.awt.event.ActionEvent; @@ -43,6 +45,7 @@ public class ChartPreStyleAction extends UpdateAction { */ public void actionPerformed(ActionEvent e) { DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + DesignerContext.getDesignerFrame().setServerConfig(true); final ChartPreStyleManagerPane pane = new ChartPreStyleManagerPane(); BasicDialog dialog = pane.showWindow(designerFrame); dialog.addDialogActionListener(new DialogActionAdapter() { @@ -79,7 +82,13 @@ public class ChartPreStyleAction extends UpdateAction { })); } }); - + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + super.windowClosed(e); + DesignerContext.getDesignerFrame().setServerConfig(false); + } + }); pane.populateBean(); dialog.setVisible(true); diff --git a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleListPane.java b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleListPane.java index 73914a320..99d048a81 100644 --- a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleListPane.java +++ b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleListPane.java @@ -10,7 +10,6 @@ import com.fr.design.gui.controlpane.NameObjectCreator; import com.fr.design.gui.controlpane.NameableCreator; import com.fr.design.gui.controlpane.ShortCut4JControlPane; import com.fr.design.gui.ilist.JNameEdList; -import com.fr.design.gui.ilist.ModNameActionListener; import com.fr.design.i18n.Toolkit; import com.fr.design.menu.ShortCut; import com.fr.general.ComparatorUtils; @@ -20,8 +19,6 @@ import com.fr.stable.StringUtils; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; @@ -34,12 +31,8 @@ import java.util.List; */ public class ChartPreStyleListPane extends JListControlPane { - ChartPreStyleManagerPane chartPreStyleManagerPane; - - public ChartPreStyleListPane(ChartPreStyleManagerPane chartPreStyleManagerPane) { + public ChartPreStyleListPane() { super(); - this.chartPreStyleManagerPane = chartPreStyleManagerPane; - initListener(); addModNameActionListener((int index, String oldName, String newName) -> { if (ComparatorUtils.equals(oldName, newName)) { return; @@ -94,13 +87,7 @@ public class ChartPreStyleListPane extends JListControlPane { @Override public BasicBeanPane createPaneByCreators(NameableCreator creator) { - return new ChartPreStylePane() { - @Override - protected void refreshWhenStyleChange(ChartColorMatching preStyle) { - super.refreshWhenStyleChange(preStyle); - chartPreStyleManagerPane.refreshDefaultColorBox(); - } - }; + return new ChartPreStylePane(); } @@ -123,21 +110,6 @@ public class ChartPreStyleListPane extends JListControlPane { return shortCut4JControlPane; } - public void initListener() { - nameableList.addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - chartPreStyleManagerPane.refreshDefaultColorBox(); - } - }); - nameableList.addModNameActionListener(new ModNameActionListener() { - @Override - public void nameModed(int index, String oldName, String newName) { - chartPreStyleManagerPane.refreshDefaultColorBox(oldName, newName); - } - }); - } - public void populateBean() { ChartPreStyleConfig config = ChartPreStyleConfig.getInstance().mirror(); ArrayList list = new ArrayList(); @@ -152,15 +124,10 @@ public class ChartPreStyleListPane extends JListControlPane { Nameable[] values = (Nameable[]) list.toArray(new Nameable[list.size()]); populate(values); - - if (config.containsName(config.getCurrentStyle())) { - this.setSelectedName(config.getCurrentStyle()); - } } public void updateBean() { ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); - Nameable[] values = update(); config.clearAllPreStyle(); @@ -180,4 +147,4 @@ public class ChartPreStyleListPane extends JListControlPane { this.shortCut.setEnabled(nameableList.getModel().getSize() > 1); } } -} +} \ No newline at end of file diff --git a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleManagerPane.java b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleManagerPane.java index 98f3862dc..26ee8f20e 100644 --- a/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleManagerPane.java +++ b/designer-chart/src/main/java/com/fr/design/module/ChartPreStyleManagerPane.java @@ -1,24 +1,10 @@ package com.fr.design.module; -import com.fr.base.ChartColorMatching; -import com.fr.base.ChartPreStyleConfig; -import com.fr.design.gui.icombobox.ColorSchemeComboBox; import com.fr.design.dialog.BasicPane; -import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.general.ComparatorUtils; -import com.fr.general.GeneralUtils; -import com.fr.general.NameObject; -import com.fr.stable.Nameable; -import com.fr.van.chart.designer.TableLayout4VanChartHelper; -import javax.swing.JPanel; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; import java.awt.BorderLayout; -import java.awt.Dimension; /** * 图表预定义管理 界面, 在工具栏-服务器管理中. @@ -28,8 +14,6 @@ import java.awt.Dimension; */ public class ChartPreStyleManagerPane extends BasicPane { - private ColorSchemeComboBox defaultColorBox; - private ChartPreStyleListPane chartPreStyleListPane; public ChartPreStyleManagerPane() { @@ -38,78 +22,20 @@ public class ChartPreStyleManagerPane extends BasicPane { private void initComponent() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); - JPanel colorBoxPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); - - chartPreStyleListPane = new ChartPreStyleListPane(this); - - initDefaultColorBox(); - colorBoxPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Chart_Match_Default_Color_Scheme") + ":")); - colorBoxPane.add(defaultColorBox); - - this.add(colorBoxPane, BorderLayout.NORTH); + chartPreStyleListPane = new ChartPreStyleListPane(); this.add(chartPreStyleListPane, BorderLayout.CENTER); } - private void initDefaultColorBox() { - Map colorSchemes = new LinkedHashMap<>(); - ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); - Iterator names = config.names(); - while (names.hasNext()) { - Object key = names.next(); - ColorSchemeComboBox.ColorInfo colorInfo = new ColorSchemeComboBox.ColorInfo(); - ChartColorMatching colorMatching = (ChartColorMatching) config.getPreStyle(key); - colorInfo.setGradient(colorMatching.getGradient()); - colorInfo.setColors(colorMatching.getColorList()); - colorSchemes.put(colorMatching.getId(), colorInfo); - } - defaultColorBox = new ColorSchemeComboBox(colorSchemes); - defaultColorBox.setPreferredSize(new Dimension(TableLayout4VanChartHelper.EDIT_AREA_WIDTH, 20)); - } - - private void refreshColorSchemes() { - Nameable[] nameables = chartPreStyleListPane.update(); - Map colorSchemes = new LinkedHashMap<>(); - for (Nameable value : nameables) { - String name = value.getName(); - ChartColorMatching colorMatching = (ChartColorMatching) ((NameObject) value).getObject(); - ColorSchemeComboBox.ColorInfo colorInfo = new ColorSchemeComboBox.ColorInfo(); - colorInfo.setGradient(colorMatching.getGradient()); - colorInfo.setColors(colorMatching.getColorList()); - colorSchemes.put(name, colorInfo); - } - defaultColorBox.refresh(colorSchemes); - } - - public void refreshDefaultColorBox() { - Object selectedItem = defaultColorBox.getSelectedItem(); - refreshColorSchemes(); - defaultColorBox.setSelectedItem(selectedItem); - } - - public void refreshDefaultColorBox(String oldName, String newName) { - Object selectedItem = defaultColorBox.getSelectedItem(); - if (ComparatorUtils.equals(selectedItem, oldName)) { - selectedItem = newName; - } - refreshColorSchemes(); - defaultColorBox.setSelectedItem(selectedItem); - } - @Override protected String title4PopupWindow() { return Toolkit.i18nText("Fine-Design_Report_ServerM_Predefined_Styles"); } public void populateBean() { - ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); - String currentStyle = config.getCurrentStyle(); - defaultColorBox.setSelectedItem(currentStyle); chartPreStyleListPane.populateBean(); } public void updateBean() { - ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); - config.setCurrentStyle(GeneralUtils.objectToString(defaultColorBox.getSelectedItem())); chartPreStyleListPane.updateBean(); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/column/VanChartColumnSeriesPane.java b/designer-chart/src/main/java/com/fr/van/chart/column/VanChartColumnSeriesPane.java index b83a20f61..27c588222 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/column/VanChartColumnSeriesPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/column/VanChartColumnSeriesPane.java @@ -71,9 +71,7 @@ public class VanChartColumnSeriesPane extends VanChartAbstractPlotSeriesPane { //边框(有圆角) protected VanChartBorderPane createDiffBorderPane() { - return new VanChartBorderWithRadiusPane(); - //TODO Bjorn 边框自动回退 - //return new VanChartBorderWithRadiusPane(true); + return new VanChartBorderWithRadiusPane(true); } private JPanel createSeriesStylePane(double[] row, double[] col) { diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartFillStylePane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartFillStylePane.java index 057675a0a..42e33b89c 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartFillStylePane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartFillStylePane.java @@ -26,16 +26,8 @@ public class VanChartFillStylePane extends ColorFillStylePane implements Designe DesignerContext.setDesignerBean(name, this); } - protected void styleSelectBoxChange() { - //TODO Bjorn 配色预定义回退 - //getCustomPane().setVisible(getStyleSelectBox().getSelectedIndex() != 0); - super.styleSelectBoxChange(); - } - protected ColorSchemeComboBox createColorSchemeComboBox() { - return new ColorSchemeComboBox(); - //TODO Bjorn 配色预定义回退 - //return new ColorSchemeComboBox(null, true); + return new ColorSchemeComboBox(null, true); } protected void initLayout() { @@ -63,21 +55,19 @@ public class VanChartFillStylePane extends ColorFillStylePane implements Designe } public void populateBean(AttrFillStyle condition) { - /* if (condition.isPredefinedStyle()) { + if (condition.isThemed()) { getStyleSelectBox().setSelectType(ColorSchemeComboBox.SelectType.DEFAULT); return; - }*/ - //TODO Bjorn 配色预定义回退 + } populateBean(condition.getColorFillStyle()); } public void updateBean(AttrFillStyle attrFillStyle) { - /* if (getStyleSelectBox().getSelectedIndex() == 0) { - attrFillStyle.setPredefinedStyle(true); + if (getStyleSelectBox().getSelectedIndex() == 0) { + attrFillStyle.setThemed(true); return; } - attrFillStyle.setPredefinedStyle(false);*/ - //TODO Bjorn 配色预定义回退 + attrFillStyle.setThemed(false); attrFillStyle.setColorFillStyle(updateBean()); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartLabelContentPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartLabelContentPane.java index e3bd8248f..8133771f9 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartLabelContentPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartLabelContentPane.java @@ -1,10 +1,12 @@ package com.fr.van.chart.designer.component; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithThemeStyle; import com.fr.plugin.chart.base.AttrTooltipContent; import com.fr.plugin.chart.type.TextAlign; import com.fr.van.chart.designer.style.VanChartStylePane; import javax.swing.JPanel; +import java.awt.BorderLayout; public class VanChartLabelContentPane extends VanChartTooltipContentPane { @@ -22,12 +24,11 @@ public class VanChartLabelContentPane extends VanChartTooltipContentPane { return new AttrTooltipContent(TextAlign.CENTER); } - //TODO Bjorn 标签面板回退 - /* public JPanel createCommonStylePane() { + public JPanel createCommonStylePane() { if (isInCondition()) { return super.createCommonStylePane(); } - setTextAttrPane(new ChartTextAttrPaneWithPreStyle()); + setTextAttrPane(new ChartTextAttrPaneWithThemeStyle()); JPanel stylePanel = new JPanel(new BorderLayout()); stylePanel.add(getTextAttrPane(), BorderLayout.CENTER); @@ -42,9 +43,9 @@ public class VanChartLabelContentPane extends VanChartTooltipContentPane { } if (hasTextStylePane()) { this.getTextAttrPane().update(attrTooltipContent.getTextAttr()); - if (!attrTooltipContent.getTextAttr().isPredefinedStyle()) { + if (!attrTooltipContent.getTextAttr().isThemed()) { attrTooltipContent.setCustom(true); } } - }*/ + } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartTooltipContentPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartTooltipContentPane.java index d7c590e64..12e242b73 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartTooltipContentPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartTooltipContentPane.java @@ -632,7 +632,7 @@ public class VanChartTooltipContentPane extends BasicBeanPane { private JPanel titlePane; private TinyFormulaPane titleContent; - private ChartTextAttrPane textAttrPane; + private ChartTextAttrPaneWithThemeStyle textAttrPane; private UIButtonGroup alignmentPane; private VanChartBackgroundWithOutShadowWithRadiusPane backgroundPane; private UIToggleButton useHtml; @@ -188,9 +188,7 @@ public class VanChartTitlePane extends AbstractVanChartScrollPane { } private JPanel createTitleStylePane() { - //TODO Bjorn 标题预定义逻辑 - //textAttrPane = new ChartTextAttrPaneWithPreStyle(); - textAttrPane = new ChartTextAttrPane(); + textAttrPane = new ChartTextAttrPaneWithThemeStyle(); return TableLayout4VanChartHelper.createExpandablePaneWithTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Widget_Style"), textAttrPane); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartTitleWithAutoBackground.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartTitleWithAutoBackground.java index e126c5359..eb87f4363 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartTitleWithAutoBackground.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/VanChartTitleWithAutoBackground.java @@ -14,8 +14,6 @@ public class VanChartTitleWithAutoBackground extends VanChartTitlePane { } protected VanChartBackgroundWithOutShadowWithRadiusPane createBackgroundPane() { - //TODO Bjorn 地图标题背景自动逻辑 - //return new VanChartBackgroundWithOutShadowWithRadiusPane(true); - return new VanChartBackgroundWithOutShadowWithRadiusPane(); + return new VanChartBackgroundWithOutShadowWithRadiusPane(true); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisScrollPaneWithTypeSelect.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisScrollPaneWithTypeSelect.java index ef042e0f2..15154de28 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisScrollPaneWithTypeSelect.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisScrollPaneWithTypeSelect.java @@ -1,9 +1,10 @@ package com.fr.van.chart.designer.style.axis; +import com.fr.chart.base.ColorWithThemeStyle; import com.fr.chart.chartattr.Axis; -import com.fr.design.i18n.Toolkit; import com.fr.design.beans.FurtherBasicBeanPane; import com.fr.design.gui.frpane.UIComboBoxPane; +import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.chart.PaneTitleConstants; import com.fr.general.ComparatorUtils; import com.fr.plugin.chart.attr.axis.VanChartAxis; @@ -16,9 +17,9 @@ import com.fr.van.chart.designer.style.VanChartStylePane; import javax.swing.BorderFactory; import javax.swing.JPanel; -import java.awt.BorderLayout; import java.util.ArrayList; import java.util.List; +import java.awt.BorderLayout; /** * 带有坐标轴类型选择控件。可选类型:分类、时间、数值 @@ -98,11 +99,13 @@ public class VanChartAxisScrollPaneWithTypeSelect extends AbstractVanChartScroll public VanChartAxis update(VanChartAxis axis) { int index = axisTypePane.getSelectedIndex(); + ColorWithThemeStyle mainGridColorWithPreStyle = axis.getMainGridColorWithPreStyle(); if(ComparatorUtils.equals(index, AxisType.AXIS_CATEGORY.ordinal())){ if(ComparatorUtils.equals(axis.getAxisType(), AxisType.AXIS_CATEGORY)){ textAxisPane.updateBean(axis); } else { axis = new VanChartAxis(axis.getAxisName(), axis.getPosition(), axis.getGridLineType(), axis.getMainGridColor()); + axis.setMainGridColorWithPreStyle(mainGridColorWithPreStyle); textAxisPane.updateBean(axis); } } else if(ComparatorUtils.equals(index, AxisType.AXIS_TIME.ordinal())){ @@ -110,6 +113,7 @@ public class VanChartAxisScrollPaneWithTypeSelect extends AbstractVanChartScroll timeAxisPane.updateBean(axis); } else { axis = new VanChartTimeAxis(axis.getAxisName(), axis.getPosition(), axis.getGridLineType(), axis.getMainGridColor()); + axis.setMainGridColorWithPreStyle(mainGridColorWithPreStyle); timeAxisPane.updateBean(axis); } } else if(ComparatorUtils.equals(index, AxisType.AXIS_VALUE.ordinal())){ @@ -117,6 +121,7 @@ public class VanChartAxisScrollPaneWithTypeSelect extends AbstractVanChartScroll valueAxisPane.updateBean(axis); } else { axis = new VanChartValueAxis(axis.getAxisName(), axis.getPosition(), axis.getGridLineType(), axis.getMainGridColor()); + axis.setMainGridColorWithPreStyle(mainGridColorWithPreStyle); valueAxisPane.updateBean(axis); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartBaseAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartBaseAxisPane.java index 9fb0c7e31..f945a1969 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartBaseAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartBaseAxisPane.java @@ -20,7 +20,8 @@ import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.chart.PaneTitleConstants; import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; -import com.fr.design.style.color.ColorSelectBox; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithThemeStyle; +import com.fr.design.mainframe.chart.gui.style.ColorSelectBoxWithThemeStyle; import com.fr.design.utils.gui.UIComponentUtils; import com.fr.design.widget.FRWidgetFactory; import com.fr.plugin.chart.attr.axis.VanChartAxis; @@ -85,9 +86,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { protected LineComboBox axisLineStyle; - //TODO Bjorn 坐标轴面板回退 - protected ColorSelectBox axisLineColor; - //protected ColorSelectBoxWithPreStyle axisLineColor; + protected ColorSelectBoxWithThemeStyle axisLineColor; protected UIButtonGroup mainTick; protected UIButtonGroup secondTick; @@ -381,31 +380,16 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { } protected ChartTextAttrPane getChartTextAttrPane() { - //TODO Bjorn 坐标轴面板回退 - /* return new ChartTextAttrPaneWithPreStyle() { + return new ChartTextAttrPaneWithThemeStyle() { protected double getEdithAreaWidth() { return TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH; } - };*/ - return new ChartTextAttrPane() { - @Override - protected JPanel getContentPane(JPanel buttonPane) { - double p = TableLayout.PREFERRED; - double f = TableLayout.FILL; - double e = TableLayout4VanChartHelper.SECOND_EDIT_AREA_WIDTH; - double[] columnSize = {f, e}; - double[] rowSize = {p, p, p}; - - return TableLayout4VanChartHelper.createGapTableLayoutPane(getComponents(buttonPane), rowSize, columnSize); - } }; } protected JPanel createLineStylePane(double[] row, double[] col) { axisLineStyle = createLineComboBox(); - //TODO Bjorn 坐标轴面板回退 - //axisLineColor = new ColorSelectBoxWithPreStyle(100); - axisLineColor = new ColorSelectBox(100); + axisLineColor = new ColorSelectBoxWithThemeStyle(100); String[] strings = new String[]{Toolkit.i18nText("Fine-Design_Chart_Open"), Toolkit.i18nText("Fine-Design_Chart_Close")}; AxisTickLineType[] values = new AxisTickLineType[]{AxisTickLineType.TICK_LINE_OUTSIDE, AxisTickLineType.TICK_LINE_NONE}; mainTick = new UIButtonGroup(strings, values); @@ -423,9 +407,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { return new Component[][]{ new Component[]{null, null}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Type")), axisLineStyle}, - //TODO Bjorn 坐标轴面板回退 - //new Component[]{axisLineColor, null}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color")), axisLineColor}, + new Component[]{axisLineColor, null}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Main_Graduation_Line")), mainTick}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Second_Graduation_Line")), secondTick}, }; @@ -735,9 +717,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { axisLineStyle.setSelectedLineStyle(axis.getAxisStyle()); } if (axisLineColor != null) { - axisLineColor.setSelectObject(axis.getAxisColor()); - //TODO Bjorn 坐标轴面板回退 - //axisLineColor.populate(axis.getLineColorWithPreStyle()); + axisLineColor.populate(axis.getLineColorWithPreStyle()); } if (mainTick != null) { mainTick.setSelectedItem(axis.getMainTickLine()); @@ -880,9 +860,7 @@ public class VanChartBaseAxisPane extends FurtherBasicBeanPane { axis.setAxisStyle(axisLineStyle.getSelectedLineStyle()); } if (axisLineColor != null) { - axis.setAxisColor(axisLineColor.getSelectObject()); - //TODO Bjorn 坐标轴面板回退 - //axis.setLineColorWithPreStyle(axisLineColor.update()); + axis.setLineColorWithPreStyle(axisLineColor.update()); } if (mainTick != null) { axis.setMainTickLine(mainTick.getSelectedItem()); diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/gauge/VanChartGaugeDetailAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/gauge/VanChartGaugeDetailAxisPane.java index cd6c4fcf6..18fadeb98 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/gauge/VanChartGaugeDetailAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/gauge/VanChartGaugeDetailAxisPane.java @@ -8,6 +8,7 @@ import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.chart.PaneTitleConstants; import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithAuto; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithThemeStyle; import com.fr.design.style.color.ColorSelectBox; import com.fr.plugin.chart.attr.axis.VanChartAxis; import com.fr.plugin.chart.attr.axis.VanChartGaugeAxis; @@ -102,9 +103,7 @@ public class VanChartGaugeDetailAxisPane extends VanChartValueAxisPane { if (isMulti(gaugeStyle)) { return new ChartTextAttrPaneWithAuto(FontAutoType.SIZE_AND_COLOR); } else { - return new ChartTextAttrPane(); - //TODO Bjorn 坐标轴面板回退 - //return new ChartTextAttrPaneWithPreStyle(); + return new ChartTextAttrPaneWithThemeStyle(); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarXAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarXAxisPane.java index 309a7daa6..3558443c4 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarXAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarXAxisPane.java @@ -46,9 +46,7 @@ public class VanChartRadarXAxisPane extends VanChartBaseAxisPane { return new Component[][]{ new Component[]{null,null} , new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Type")), axisLineStyle}, - //TODO Bjorn 坐标轴面板回退 - //new Component[]{axisLineColor, null}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color")), axisLineColor}, + new Component[]{axisLineColor, null}, }; } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarYAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarYAxisPane.java index cf4ffb386..001567688 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarYAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/radar/VanChartRadarYAxisPane.java @@ -90,9 +90,7 @@ public class VanChartRadarYAxisPane extends VanChartValueAxisPane { return new Component[][]{ new Component[]{null, null}, new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Type")), axisLineStyle}, - //TODO Bjorn 坐标轴面板回退 - //new Component[]{axisLineColor, null}, - new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color")), axisLineColor}, + new Component[]{axisLineColor, null}, }; } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartAreaBackgroundPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartAreaBackgroundPane.java index 19f5d4051..6f65af6e1 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartAreaBackgroundPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/VanChartAreaBackgroundPane.java @@ -11,6 +11,7 @@ import com.fr.design.mainframe.chart.PaneTitleConstants; import com.fr.van.chart.designer.AbstractVanChartScrollPane; import com.fr.van.chart.designer.TableLayout4VanChartHelper; import com.fr.van.chart.designer.component.background.VanChartBackgroundPane; +import com.fr.van.chart.designer.component.background.VanChartBackgroundPaneWithThemeStyle; import com.fr.van.chart.designer.component.border.VanChartBorderWithRadiusPane; import com.fr.van.chart.designer.style.background.radar.VanChartRadarAxisAreaPane; @@ -45,13 +46,11 @@ public class VanChartAreaBackgroundPane extends AbstractVanChartScrollPane { private LineTypeComboBox horizonLineType; private LineTypeComboBox verticalLineType; - private ColorSelectBox horizontalColorBox; - private ColorSelectBox verticalColorBox; - //TODO Bjorn 背景坐标轴面板回退 - /* private ColorSelectBoxWithPreStyle horizontalColorBox; - private ColorSelectBoxWithPreStyle verticalColorBox;*/ + private ColorSelectBoxWithThemeStyle horizontalColorBox; + private ColorSelectBoxWithThemeStyle verticalColorBox; private JPanel horizontalColorPane; private JPanel verticalColorPane; @@ -56,11 +54,8 @@ public class VanChartAxisAreaPane extends BasicBeanPane { } private void initComponents() { - horizontalColorBox = new ColorSelectBox(PREFERRED_WIDTH); - verticalColorBox = new ColorSelectBox(PREFERRED_WIDTH); - //TODO Bjorn 背景坐标轴面板回退 - /* horizontalColorBox = new ColorSelectBoxWithPreStyle(PREFERRED_WIDTH); - verticalColorBox = new ColorSelectBoxWithPreStyle(PREFERRED_WIDTH);*/ + horizontalColorBox = new ColorSelectBoxWithThemeStyle(PREFERRED_WIDTH); + verticalColorBox = new ColorSelectBoxWithThemeStyle(PREFERRED_WIDTH); horizonLineType = new LineTypeComboBox(new LineType[]{LineType.NONE, LineType.SOLID, LineType.DASHED}); verticalLineType = new LineTypeComboBox(new LineType[]{LineType.NONE, LineType.SOLID, LineType.DASHED}); @@ -93,18 +88,15 @@ public class VanChartAxisAreaPane extends BasicBeanPane { } protected void initGridLineComponents() { - //TODO Bjorn 背景坐标轴面板回退 Component[][] upComponent = new Component[][]{ new Component[]{null, null}, - new Component[]{null, horizontalColorBox} - //new Component[]{horizontalColorBox, null} + new Component[]{horizontalColorBox, null} }; horizontalColorPane = TableLayout4VanChartHelper.createGapTableLayoutPane(upComponent); Component[][] downComponent = new Component[][]{ new Component[]{null, null}, - new Component[]{null, verticalColorBox} - //new Component[]{verticalColorBox, null} + new Component[]{verticalColorBox, null} }; verticalColorPane = TableLayout4VanChartHelper.createGapTableLayoutPane(downComponent); @@ -228,16 +220,13 @@ public class VanChartAxisAreaPane extends BasicBeanPane { VanChartAxis defaultXAxis = rectanglePlot.getDefaultXAxis(); VanChartAxis defaultYAxis = rectanglePlot.getDefaultYAxis(); - //TODO Bjorn 背景坐标轴面板回退 if (defaultXAxis != null) { - //verticalColorBox.populate(defaultXAxis.getMainGridColorWithPreStyle()); - verticalColorBox.setSelectObject(defaultXAxis.getMainGridColor()); + verticalColorBox.populate(defaultXAxis.getMainGridColorWithPreStyle()); verticalLineType.setSelectedItem(defaultXAxis.getGridLineType()); } if (defaultYAxis != null) { - //horizontalColorBox.populate(defaultYAxis.getMainGridColorWithPreStyle()); - horizontalColorBox.setSelectObject(defaultYAxis.getMainGridColor()); + horizontalColorBox.populate(defaultYAxis.getMainGridColorWithPreStyle()); horizonLineType.setSelectedItem(defaultYAxis.getGridLineType()); } } @@ -264,16 +253,13 @@ public class VanChartAxisAreaPane extends BasicBeanPane { VanChartAxis defaultXAxis = rectanglePlot.getDefaultXAxis(); VanChartAxis defaultYAxis = rectanglePlot.getDefaultYAxis(); - //TODO Bjorn 背景坐标轴面板回退 if (defaultXAxis != null) { - //defaultXAxis.setMainGridColorWithPreStyle(verticalColorBox.update()); - defaultXAxis.setMainGridColor(verticalColorBox.getSelectObject()); + defaultXAxis.setMainGridColorWithPreStyle(verticalColorBox.update()); defaultXAxis.setGridLineType((LineType) verticalLineType.getSelectedItem()); } if (defaultYAxis != null) { - //defaultYAxis.setMainGridColorWithPreStyle(horizontalColorBox.update()); - defaultYAxis.setMainGridColor(horizontalColorBox.getSelectObject()); + defaultYAxis.setMainGridColorWithPreStyle(horizontalColorBox.update()); defaultYAxis.setGridLineType((LineType) horizonLineType.getSelectedItem()); } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/datasheet/VanChartDataSheetPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/datasheet/VanChartDataSheetPane.java index d6fa66bfb..83b65d01e 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/datasheet/VanChartDataSheetPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/datasheet/VanChartDataSheetPane.java @@ -10,6 +10,7 @@ import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.chart.PaneTitleConstants; import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithThemeStyle; import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.general.ComparatorUtils; import com.fr.plugin.chart.VanChartAttrHelper; @@ -19,6 +20,7 @@ import com.fr.plugin.chart.type.AxisType; import com.fr.van.chart.designer.AbstractVanChartScrollPane; import com.fr.van.chart.designer.TableLayout4VanChartHelper; import com.fr.van.chart.designer.component.border.VanChartBorderPane; +import com.fr.van.chart.designer.component.border.VanChartBorderPaneWithPreStyle; import com.fr.van.chart.designer.component.format.FormatPaneWithNormalType; import javax.swing.JPanel; @@ -103,15 +105,12 @@ public class VanChartDataSheetPane extends AbstractVanChartScrollPane { return TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize); } - //TODO Bjorn 数据表面板回退 protected VanChartBorderPane createBorderPanePane() { - return new VanChartBorderPane(); - //return new VanChartBorderPaneWithPreStyle(); + return new VanChartBorderPaneWithPreStyle(); } protected ChartTextAttrPane createChartTextAttrPane() { - return new ChartTextAttrPane(); - //return new ChartTextAttrPaneWithPreStyle(); + return new ChartTextAttrPaneWithThemeStyle(); } @Override diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeCateOrPercentLabelDetailPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeCateOrPercentLabelDetailPane.java index 3d6ad86e8..d8c321738 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeCateOrPercentLabelDetailPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeCateOrPercentLabelDetailPane.java @@ -49,11 +49,6 @@ public class VanChartGaugeCateOrPercentLabelDetailPane extends VanChartGaugeLabe return getGaugeStyle() == GaugeStyle.RING || getGaugeStyle() == GaugeStyle.SLOT; } - //TODO Bjorn 仪表盘自动逻辑 - protected boolean isFontColorAuto() { - return getGaugeStyle() == GaugeStyle.RING || getGaugeStyle() == GaugeStyle.SLOT; - } - protected boolean hasLabelPosition(Plot plot) { switch (getGaugeStyle()) { case RING: diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeLabelDetailPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeLabelDetailPane.java index 8c672bab6..0f9e84729 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeLabelDetailPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/label/VanChartGaugeLabelDetailPane.java @@ -79,10 +79,8 @@ public class VanChartGaugeLabelDetailPane extends VanChartPlotLabelDetailPane { return false; } - //TODO Bjorn 仪表盘自动逻辑 protected boolean isFontColorAuto() { - return false; - //return true; + return true; } private FontAutoType getFontAutoType() { diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/series/VanChartAbstractPlotSeriesPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/series/VanChartAbstractPlotSeriesPane.java index 849507e05..0a5f7b8fe 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/series/VanChartAbstractPlotSeriesPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/series/VanChartAbstractPlotSeriesPane.java @@ -271,9 +271,7 @@ public abstract class VanChartAbstractPlotSeriesPane extends AbstractPlotSeriesP } protected VanChartBorderPane createDiffBorderPane() { - return new VanChartBorderPane(); - //TODO Bjorn 边框自动回退 - //return new VanChartBorderPane(true); + return new VanChartBorderPane(true); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/drillmap/designer/other/VanChartDrillMapInteractivePane.java b/designer-chart/src/main/java/com/fr/van/chart/drillmap/designer/other/VanChartDrillMapInteractivePane.java index c439c4d4d..80962fd86 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/drillmap/designer/other/VanChartDrillMapInteractivePane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/drillmap/designer/other/VanChartDrillMapInteractivePane.java @@ -6,6 +6,7 @@ import com.fr.design.gui.ibutton.UIButtonGroup; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.backgroundpane.ColorBackgroundQuickPane; import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.plugin.chart.attr.plot.VanChartPlot; @@ -81,15 +82,13 @@ public class VanChartDrillMapInteractivePane extends VanChartInteractivePaneWith } }; - //TODO Bjorn 钻取地图钻取目录背景自动逻辑 - /*backgroundPane = new VanChartBackgroundPaneWithOutImageAndShadow(true) { + backgroundPane = new VanChartBackgroundPaneWithOutImageAndShadow(true) { @Override protected void initList() { paneList.add(new ColorBackgroundQuickPane()); } - };*/ + }; - backgroundPane = new VanChartBackgroundPaneWithOutImageAndShadow(); selectBackgroundPane = new VanChartBackgroundPaneWithOutImageAndShadow() { protected String labelName() { return Toolkit.i18nText("Fine-Design_Chart_Select_Color"); diff --git a/designer-chart/src/main/java/com/fr/van/chart/gauge/VanChartGaugeSeriesPane.java b/designer-chart/src/main/java/com/fr/van/chart/gauge/VanChartGaugeSeriesPane.java index d3f997295..49e4391b5 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/gauge/VanChartGaugeSeriesPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/gauge/VanChartGaugeSeriesPane.java @@ -78,8 +78,7 @@ public class VanChartGaugeSeriesPane extends VanChartMultiColorSeriesPane { double f = TableLayout.FILL; double e = TableLayout4VanChartHelper.EDIT_AREA_WIDTH; double[] columnSize = {f}; - //TODO Bjorn - double[] rowSize = {p, p, p, p, p, p, p}; + double[] rowSize = {p, p, p, p, p, p, p, p, p, p}; Component[][] components = new Component[][]{ new Component[]{createGaugeLayoutPane()}, new Component[]{createGaugeStylePane(rowSize, new double[]{f, e})}, @@ -225,14 +224,12 @@ public class VanChartGaugeSeriesPane extends VanChartMultiColorSeriesPane { private Component[][] getDiffComponentsWithGaugeStyle() { GaugeStyle style = getGaugeStyle(); switch (style) { - //TODO Bjorn 仪表盘样式自动逻辑 case RING: initRotate(); return new Component[][]{ new Component[]{null, null}, - getPaneBackgroundColor(), - /* getPaneBackgroundColorAuto(), - new Component[]{null, paneBackgroundColor},*/ + getPaneBackgroundColorAuto(), + new Component[]{null, paneBackgroundColor}, getInnerPaneBackgroundColor(), new Component[]{createRadiusPane(Toolkit.i18nText("Fine-Design_Chart_Radius_Set")), null}, getChutePercent() @@ -241,9 +238,8 @@ public class VanChartGaugeSeriesPane extends VanChartMultiColorSeriesPane { return new Component[][]{ new Component[]{null, null}, getNeedleColor(), - getSlotBackgroundColor(), - /* getSlotBackgroundColorAuto(), - new Component[]{null, slotBackgroundColor},*/ + getSlotBackgroundColorAuto(), + new Component[]{null, slotBackgroundColor}, new Component[]{createRadiusPane(Toolkit.i18nText("Fine-Design_Chart_Radius_Set")), null}, getChutePercent() }; @@ -251,33 +247,25 @@ public class VanChartGaugeSeriesPane extends VanChartMultiColorSeriesPane { return new Component[][]{ new Component[]{null, null}, getNeedleColor(), - getSlotBackgroundColor(), - /*getSlotBackgroundColorAuto(), - new Component[]{null, slotBackgroundColor},*/ + getSlotBackgroundColorAuto(), + new Component[]{null, slotBackgroundColor}, new Component[]{createRadiusPane(Toolkit.i18nText("Fine-Design_Chart_Length_Set")), null}, getThermometerWidth() }; default: return new Component[][]{ new Component[]{null, null}, - getHingeColor(), - /* getHingeColorAuto(), - new Component[]{null, hingeColor},*/ + getHingeColorAuto(), + new Component[]{null, hingeColor}, getHingeBackgroundColor(), getNeedleColor(), - getPaneBackgroundColor(), - /* getPaneBackgroundColorAuto(), - new Component[]{null, paneBackgroundColor},*/ + getPaneBackgroundColorAuto(), + new Component[]{null, paneBackgroundColor}, new Component[]{createRadiusPane(Toolkit.i18nText("Fine-Design_Chart_Radius_Set")), null} }; } } - private Component[] getHingeColor() { - hingeColor = new ColorSelectBox(120); - return new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Hinge")), hingeColor}; - } - private Component[] getHingeColorAuto() { hingeColor = new ColorSelectBox(120); hingeColorAuto = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Auto"), diff --git a/designer-chart/src/main/java/com/fr/van/chart/map/VanChartMapSeriesPane.java b/designer-chart/src/main/java/com/fr/van/chart/map/VanChartMapSeriesPane.java index a2adff77a..073002642 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/map/VanChartMapSeriesPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/map/VanChartMapSeriesPane.java @@ -337,9 +337,7 @@ public class VanChartMapSeriesPane extends VanChartColorValueSeriesPane { } protected JPanel createAreaPane() { - //TODO Bjorn 地图背景自动 - //borderWithAlphaPane = new VanChartBorderWithAlphaPane(true); - borderWithAlphaPane = new VanChartBorderWithAlphaPane(); + borderWithAlphaPane = new VanChartBorderWithAlphaPane(true); double p = TableLayout.PREFERRED; double f = TableLayout.FILL; @@ -355,8 +353,7 @@ public class VanChartMapSeriesPane extends VanChartColorValueSeriesPane { } protected JPanel createNullValueColorPane() { - //TODO Bjorn 地图空值背景自动 - /* nullValueAuto = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Auto"), + nullValueAuto = new UIButtonGroup<>(new String[]{Toolkit.i18nText("Fine-Design_Chart_Auto"), Toolkit.i18nText("Fine-Design_Chart_Custom")}); initNullValueListener(); nullValueColorBox = new ColorSelectBox(80); @@ -373,10 +370,7 @@ public class VanChartMapSeriesPane extends VanChartColorValueSeriesPane { new Component[]{text, nullValueAuto}, new Component[]{null, nullValueColorBox}, }; - return TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize);*/ - - nullValueColorBox = new ColorSelectBox(80); - return TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Chart_NULL_Value_Color"), nullValueColorBox); + return TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize); } @@ -593,15 +587,13 @@ public class VanChartMapSeriesPane extends VanChartColorValueSeriesPane { markerTypeCom.setSelectedItem(mapPlot.getMapMarkerType().toLocalString()); } if (nullValueColorBox != null) { - //TODO Bjorn 地图空值背景自动 - /* if (((VanChartMapPlot) plot).isAutoNullValue()) { + if (((VanChartMapPlot) plot).isAutoNullValue()) { nullValueAuto.setSelectedIndex(0); } else { nullValueAuto.setSelectedIndex(1); } nullValueColorBox.setSelectObject(((VanChartMapPlot) plot).getNullValueColor()); - checkNullValueButton();*/ - nullValueColorBox.setSelectObject(mapPlot.getNullValueColor()); + checkNullValueButton(); } //大数据模式 恢复用注释。下面3行删除。 if (lineMapLargeDataModelGroup != null) { @@ -623,8 +615,7 @@ public class VanChartMapSeriesPane extends VanChartColorValueSeriesPane { } } if (nullValueColorBox != null) { - //TODO Bjorn 地图空值背景自动 - //((VanChartMapPlot) plot).setAutoNullValue(nullValueAuto.getSelectedIndex() == 0); + ((VanChartMapPlot) plot).setAutoNullValue(nullValueAuto.getSelectedIndex() == 0); mapPlot.setNullValueColor(nullValueColorBox.getSelectObject()); } //大数据模式 恢复用注释。下面3行删除。 diff --git a/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java b/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java index 4a43d7619..580144ce5 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/map/designer/type/GisLayerPane.java @@ -73,12 +73,17 @@ public class GisLayerPane extends JPanel implements UIObserver { } private boolean isStandardGis() { + return gisButton.getSelectedIndex() == 1; + } + + private boolean isAuto() { return gisButton.getSelectedIndex() == 0; } private JPanel createGISLayerPane() { - gisButton = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Form_Widget_Style_Standard"), Toolkit.i18nText("Fine-Design_Chart_Custom")}); + gisButton = new UIButtonGroup(new String[]{Toolkit.i18nText("Fine-Design_Chart_Mode_Auto"), + Toolkit.i18nText("Fine-Design_Form_Widget_Style_Standard"), Toolkit.i18nText("Fine-Design_Chart_Custom")}); gisButton.setSelectedIndex(0); gisGaoDeLayer = new UIComboBox(MapLayerConfigManager.getGaoDeLayerItems()); gisButton.addActionListener(event -> { @@ -94,6 +99,9 @@ public class GisLayerPane extends JPanel implements UIObserver { layerPaneCheckPane = new JPanel(new CardLayout()) { @Override public Dimension getPreferredSize() { + if (isAuto()) { + return new Dimension(0, 0); + } if (isStandardGis()) { return gisGaoDeLayer.getPreferredSize(); } else { @@ -101,6 +109,7 @@ public class GisLayerPane extends JPanel implements UIObserver { } } }; + layerPaneCheckPane.add(new JPanel(), "auto"); layerPaneCheckPane.add(gisGaoDeLayer, "standard"); layerPaneCheckPane.add(gisLayer, "custom"); @@ -129,7 +138,7 @@ public class GisLayerPane extends JPanel implements UIObserver { layerCardPane = new JPanel(new CardLayout()) { @Override public Dimension getPreferredSize() { - if (isStandardGis()) { + if (isStandardGis() || isAuto()) { return new Dimension(0, 0); } String itemName = Utils.objectToString(gisLayer.getSelectedItem()); @@ -188,7 +197,9 @@ public class GisLayerPane extends JPanel implements UIObserver { private void refreshZoomLevel() { //gis图层不同,对应的缩放等级不同。 ZoomLevel[] levels; - if (isStandardGis()) { + if (isAuto()) { + levels = MapStatusPane.ZOOM_LEVELS; + } else if (isStandardGis()) { if (gisGaoDeLayer.getSelectedIndex() == gisGaoDeLayer.getItemCount() - 1) { levels = MapStatusPane.ZOOM_LEVELS; } else { @@ -209,7 +220,14 @@ public class GisLayerPane extends JPanel implements UIObserver { private void checkLayerCardPane() { CardLayout cardLayout = (CardLayout) layerPaneCheckPane.getLayout(); - cardLayout.show(layerPaneCheckPane, isStandardGis() ? "standard" : "custom"); + if (isAuto()) { + cardLayout.show(layerPaneCheckPane, "auto"); + } else if (isStandardGis()) { + cardLayout.show(layerPaneCheckPane, "standard"); + } else { + cardLayout.show(layerPaneCheckPane, "custom"); + } + } private void checkCustomLayerCardPane() { @@ -218,10 +236,6 @@ public class GisLayerPane extends JPanel implements UIObserver { } public void resetGisLayer(VanChartMapPlot mapPlot) { - //TODO Bjorn 地图gis图层自动逻辑 - /* mapPlot.getGisLayer().setGisLayerType(GISLayerType.AUTO); - mapPlot.getGisLayer().setLayerName(GISLayerType.getLocString(GISLayerType.AUTO));*/ - GisLayer defaultGisLayer = mapPlot.getDefaultGisLayer(); mapPlot.setGisLayer(defaultGisLayer); populate(defaultGisLayer); @@ -229,6 +243,9 @@ public class GisLayerPane extends JPanel implements UIObserver { public void populate(GisLayer layer) { switch (layer.getGisLayerType()) { + case AUTO: + gisButton.setSelectedIndex(0); + break; case GAO_DE_API: case LAYER_NULL: populateStandardGis(layer); @@ -243,7 +260,7 @@ public class GisLayerPane extends JPanel implements UIObserver { } private void populateStandardGis(GisLayer layer) { - gisButton.setSelectedIndex(0); + gisButton.setSelectedIndex(1); if (layer.getGisLayerType() == GISLayerType.LAYER_NULL) { gisGaoDeLayer.setSelectedIndex(gisGaoDeLayer.getItemCount() - 1); } else { @@ -252,7 +269,7 @@ public class GisLayerPane extends JPanel implements UIObserver { } private void populateCustomGis(GisLayer layer) { - gisButton.setSelectedIndex(1); + gisButton.setSelectedIndex(2); gisLayer.setSelectedItem(layer.getShowItemName()); switch (layer.getGisLayerType()) { @@ -266,7 +283,10 @@ public class GisLayerPane extends JPanel implements UIObserver { } public void update(GisLayer layer) { - if (isStandardGis()) { + if (isAuto()) { + layer.setGisLayerType(GISLayerType.AUTO); + layer.setLayerName(GISLayerType.getLocString(GISLayerType.AUTO)); + } else if (isStandardGis()) { updateStandardGis(layer); } else { updateCustomGis(layer); diff --git a/designer-chart/src/main/java/com/fr/van/chart/range/component/LegendGradientBar.java b/designer-chart/src/main/java/com/fr/van/chart/range/component/LegendGradientBar.java index 8401f86a9..6096056a4 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/range/component/LegendGradientBar.java +++ b/designer-chart/src/main/java/com/fr/van/chart/range/component/LegendGradientBar.java @@ -274,7 +274,8 @@ public class LegendGradientBar extends JComponent implements ColorSelectable, UI private void dealClick(SelectColorPointBtn selectColorPointBtn) { ColorSelectDetailPane pane = new ColorSelectDetailPane(Color.WHITE); this.setColor(selectColorPointBtn.getColorInner()); - ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, Color.WHITE, LegendGradientBar.this); + Color selectColor = selectColorPointBtn.getColorInner() == null ? Color.WHITE : selectColorPointBtn.getColorInner(); + ColorSelectDialog.showDialog(DesignerContext.getDesignerFrame(), pane, selectColor, LegendGradientBar.this); Color color = this.getColor(); if (color != null) { DesignerEnvManager.getEnvManager().getColorConfigManager().addToColorQueue(color); diff --git a/designer-chart/src/main/java/com/fr/van/chart/scatter/VanChartScatterLabelContentPane.java b/designer-chart/src/main/java/com/fr/van/chart/scatter/VanChartScatterLabelContentPane.java index 9c79f9b8c..364b3d1fe 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/scatter/VanChartScatterLabelContentPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/scatter/VanChartScatterLabelContentPane.java @@ -1,10 +1,13 @@ package com.fr.van.chart.scatter; +import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPaneWithThemeStyle; +import com.fr.plugin.chart.base.AttrTooltipContent; import com.fr.van.chart.designer.component.VanChartHtmlLabelPane; import com.fr.van.chart.designer.component.VanChartHtmlLabelPaneWithBackGroundLabel; import com.fr.van.chart.designer.style.VanChartStylePane; import javax.swing.JPanel; +import java.awt.BorderLayout; /** * 散点图标签界面 @@ -21,12 +24,11 @@ public class VanChartScatterLabelContentPane extends VanChartScatterTooltipCont return new VanChartHtmlLabelPaneWithBackGroundLabel(); } - //TODO Bjorn 散点图标签预定义样式 - /* public JPanel createCommonStylePane() { + public JPanel createCommonStylePane() { if (isInCondition()) { return super.createCommonStylePane(); } - setTextAttrPane(new ChartTextAttrPaneWithPreStyle()); + setTextAttrPane(new ChartTextAttrPaneWithThemeStyle()); JPanel stylePanel = new JPanel(new BorderLayout()); stylePanel.add(getTextAttrPane(), BorderLayout.CENTER); @@ -41,9 +43,9 @@ public class VanChartScatterLabelContentPane extends VanChartScatterTooltipCont } if (hasTextStylePane()) { this.getTextAttrPane().update(attrTooltipContent.getTextAttr()); - if (!attrTooltipContent.getTextAttr().isPredefinedStyle()) { + if (!attrTooltipContent.getTextAttr().isThemed()) { attrTooltipContent.setCustom(true); } } - }*/ + } } 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/beans/LayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java index e2aa7f152..f10b877e2 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java @@ -54,7 +54,7 @@ public interface LayoutAdapter { * @return 是否添加成功,成功返回true,否则false */ boolean addBean(XCreator creator, int x, int y, boolean accept); - + /** * 返回该布局管理适配器的Painter,为容器提供放置位置的标识。 */ diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/location/AccessDirection.java b/designer-form/src/main/java/com/fr/design/designer/beans/location/AccessDirection.java index eae04d998..5650c45f1 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/location/AccessDirection.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/location/AccessDirection.java @@ -16,6 +16,7 @@ import com.fr.design.utils.ComponentUtils; import com.fr.env.utils.DesignerInteractionHistory; import com.fr.form.ui.container.WAbsoluteLayout; import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget; +import com.fr.form.ui.container.WBorderLayout; import java.awt.*; @@ -29,7 +30,7 @@ public abstract class AccessDirection implements Direction { private int ymin; private int xmin; - abstract int getCursor(); + abstract int getCursor(); protected abstract Rectangle getDraggedBounds(int dx, int dy, Rectangle currentBounds, FormDesigner designer, Rectangle oldBounds); @@ -56,14 +57,14 @@ public abstract class AccessDirection implements Direction { x = designer.getRootComponent().getWidth(); } //参数面板可以无下限拉长 - if (y < 0) { - y = 0; - } else if (y > designer.getRootComponent().getHeight() + designer.getParaHeight() && designer.getSelectionModel().hasSelectionComponent() + if (y < 0) { + y = 0; + } else if (y > designer.getRootComponent().getHeight() + designer.getParaHeight() && designer.getSelectionModel().hasSelectionComponent() && !designer.getSelectionModel().getSelection().getSelectedCreator().acceptType(XWParameterLayout.class)) { - y = designer.getRootComponent().getHeight() + designer.getParaHeight(); - } - return new Point(x, y); - } + y = designer.getRootComponent().getHeight() + designer.getParaHeight(); + } + return new Point(x, y); + } protected void sorptionPoint(Point point, Rectangle currentBounds, FormDesigner designer) { boolean findInX = currentBounds.getWidth() <= MoveUtils.SORPTION_UNIT; @@ -100,10 +101,10 @@ public abstract class AccessDirection implements Direction { findInY = true; } - } - if (findInX && findInY) { - break; - } + } + if (findInX && findInY) { + break; + } } setDesignerStateModelProperties(designer, findInX, findInY, currentBounds, point); @@ -129,11 +130,10 @@ public abstract class AccessDirection implements Direction { } - private WAbsoluteLayout getLayout(final FormDesigner designer){ - XLayoutContainer formLayoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator( - designer.getTarget().getContainer()); + private WAbsoluteLayout getLayout(final FormDesigner designer) { WAbsoluteLayout layout; - if (formLayoutContainer.acceptType(XWBorderLayout.class)) {//看起来这边的作用应该是为了区别cpt(得到XWParameterLayout)还是frm(得到XWBorderLayout)的参数界面 + //看起来这边的作用应该是为了区别cpt(得到XWParameterLayout)还是frm(得到XWBorderLayout)的参数界面 + if (designer.getTarget().getContainer().acceptType(WBorderLayout.class)) { Container container = designer.getSelectionModel().getSelection().getSelectedCreator().getParent(); if (container instanceof XWAbsoluteLayout) { layout = ((XWAbsoluteLayout) container).toData(); @@ -161,49 +161,49 @@ public abstract class AccessDirection implements Direction { return; } //设定控件最小高度21,因每次拖曳至少移动1,防止控件高度等于21时,拖曳导致rec.y的变化使得控件不停的向上或向下移动。 - if(rec.height == MINHEIGHT){ + if (rec.height == MINHEIGHT) { ymin = rec.y; } - if(rec.height == MINHEIGHT - 1){ + if (rec.height == MINHEIGHT - 1) { ymin = ymin == rec.y ? rec.y : rec.y - 1; } - if(rec.height < MINHEIGHT){ + if (rec.height < MINHEIGHT) { rec.height = MINHEIGHT; rec.y = ymin; } // 增加下宽度也设最小为21 if (rec.width == MINWIDTH) { - xmin = rec.x; + xmin = rec.x; } - if(rec.width == MINWIDTH - 1){ - xmin = xmin == rec.x ? rec.x : rec.x - 1; + if (rec.width == MINWIDTH - 1) { + xmin = xmin == rec.x ? rec.x : rec.x - 1; } if (rec.width < MINWIDTH) { - rec.width = MINWIDTH; - rec.x = xmin; + rec.width = MINWIDTH; + rec.x = xmin; } } - /** - * 更新鼠标指针形状 - * @param formEditor 设计界面组件 - */ - public void updateCursor(FormDesigner formEditor) { + /** + * 更新鼠标指针形状 + * @param formEditor 设计界面组件 + */ + public void updateCursor(FormDesigner formEditor) { - // 调用位置枚举的多态方法getCursor获取鼠标形状 - int type = getCursor(); + // 调用位置枚举的多态方法getCursor获取鼠标形状 + int type = getCursor(); - if (type != formEditor.getCursor().getType()) { - // 设置当前形状 - formEditor.setCursor(Cursor.getPredefinedCursor(type)); + if (type != formEditor.getCursor().getType()) { + // 设置当前形状 + formEditor.setCursor(Cursor.getPredefinedCursor(type)); - // 显示/改变Tooltip + // 显示/改变Tooltip showTooltip(formEditor); - } - } + } + } - private void showTooltip(FormDesigner formEditor) { + private void showTooltip(FormDesigner formEditor) { // 显示拖拽改变组件尺寸相关的提示信息 int cursorType = formEditor.getCursor().getType(); if (Cursor.SW_RESIZE_CURSOR <= cursorType && cursorType <= Cursor.E_RESIZE_CURSOR) { @@ -217,15 +217,15 @@ public abstract class AccessDirection implements Direction { } } - public String getTooltip() { - return null; + public String getTooltip() { + return null; + } + + /** + * 生成组件备用的bound + * @param formEditor 设计界面组件 + */ + public void backupBounds(FormDesigner formEditor) { + formEditor.getSelectionModel().getSelection().backupBounds(); } - - /** - * 生成组件备用的bound - * @param formEditor 设计界面组件 - */ - public void backupBounds(FormDesigner formEditor) { - formEditor.getSelectionModel().getSelection().backupBounds(); - } } \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XChartEditor.java b/designer-form/src/main/java/com/fr/design/designer/creator/XChartEditor.java index 3d1550af6..ee166d27e 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XChartEditor.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XChartEditor.java @@ -284,6 +284,9 @@ public class XChartEditor extends XBorderStyleWidgetCreator { if (editingMouseListener.stopEditing()) { if (this != (XCreator) designer.getRootComponent()) { ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, this); + if (isEditing) { + EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_SETTINGS); + } editingMouseListener.startEditing(this, isEditing ? adapter.getDesignerEditor() : null, adapter); if (isEditing) { EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_SETTINGS); diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XCreatorUtils.java b/designer-form/src/main/java/com/fr/design/designer/creator/XCreatorUtils.java index 945d3bfdd..b7fd34df9 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XCreatorUtils.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XCreatorUtils.java @@ -3,6 +3,13 @@ */ package com.fr.design.designer.creator; +import com.fr.base.theme.FineColorFlushUtils; +import com.fr.base.theme.FineColorGather; +import com.fr.base.theme.FineColorManager; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeAware; +import com.fr.base.theme.TemplateThemeCompatible; import com.fr.design.ExtraDesignClassManager; import com.fr.design.designer.creator.cardlayout.XCardAddButton; import com.fr.design.designer.creator.cardlayout.XCardSwitchButton; @@ -11,12 +18,17 @@ import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; import com.fr.design.designer.creator.cardlayout.XWCardTagLayout; import com.fr.design.designer.creator.cardlayout.XWCardTitleLayout; import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fun.ChartWidgetOptionProvider; import com.fr.design.fun.FormWidgetOptionProvider; import com.fr.design.fun.ParameterWidgetOptionProvider; +import com.fr.design.mainframe.JTemplate; import com.fr.design.module.DesignModuleFactory; import com.fr.design.utils.gui.LayoutUtils; +import com.fr.form.main.Form; +import com.fr.form.main.WidgetGather; import com.fr.form.parameter.FormSubmitButton; +import com.fr.form.ui.AbstractBorderStyleWidget; import com.fr.form.ui.Button; import com.fr.form.ui.CardAddButton; import com.fr.form.ui.CardSwitchButton; @@ -216,6 +228,16 @@ public class XCreatorUtils { return xClazz; } + public static XCreator createThemedXCreator(Widget widget) { + XCreator creator = createXCreator(widget); + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + TemplateTheme theme = template.getTemplateTheme(); + if (theme instanceof FormTheme) { + setupTemplateTheme(creator, true, (FormTheme) theme, TemplateThemeCompatible.NONE); + } + return creator; + } + /** * 创建creator * @@ -356,4 +378,26 @@ public class XCreatorUtils { } return null; } + + + public static void setupTemplateTheme(XCreator container, final boolean forceFollowingTheme, final FormTheme currentTemplateUsingTheme, TemplateThemeCompatible compatible) { + FineColorGather colorGather = new FineColorManager.FineColorReplaceByTheme(currentTemplateUsingTheme, compatible); + Form.traversalWidget(container.toData(), new WidgetGather() { + @Override + public void dealWith(Widget widget) { + TemplateThemeAware themedWidget = (TemplateThemeAware) widget; + if (forceFollowingTheme && widget instanceof AbstractBorderStyleWidget) { + ((AbstractBorderStyleWidget) widget).setBorderStyleFollowingTheme(true); + } + themedWidget.onTemplateUsingThemeChange(currentTemplateUsingTheme, compatible); + } + + @Override + public boolean dealWithAllCards() { + return true; + } + }, TemplateThemeAware.class); + FineColorFlushUtils.replaceCacheObject(container.toData(), colorGather); + FineColorManager.traverse(container.toData(), colorGather); + } } \ No newline at end of file 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 fe27467f4..e222b4486 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 @@ -12,6 +12,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.fun.WidgetPropertyUIProvider; @@ -25,7 +26,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.stable.AssistUtils; import com.fr.stable.Constants; @@ -91,7 +91,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); } @@ -232,7 +232,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 cd0919d59..191add9b8 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/designer/creator/XWTitleLayout.java b/designer-form/src/main/java/com/fr/design/designer/creator/XWTitleLayout.java index 6e67c9ff8..b2ef84edc 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XWTitleLayout.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XWTitleLayout.java @@ -76,7 +76,7 @@ public class XWTitleLayout extends DedicateLayoutContainer { // 初始化后(如打开旧模版),需要重新调整组件/标题/边框的显示效果 XCreator xCreator = getBodyCreator(); if (xCreator instanceof XBorderStyleWidgetCreator) { - ((XBorderStyleWidgetCreator) xCreator).reshuffleBorderAndBackgroundPaintingEffectIfTitleExists(); + ((XBorderStyleWidgetCreator) xCreator).refreshStylePreviewEffect(); } } @@ -219,17 +219,26 @@ public class XWTitleLayout extends DedicateLayoutContainer { public void convert() { isRefreshing = true; WTitleLayout layout = this.toData(); + XBorderStyleWidgetCreator bodyCreator = null; this.removeAll(); for (int i = 0, num = layout.getWidgetCount(); i < num; i++) { BoundsWidget bw = (BoundsWidget) layout.getWidget(i); if (bw != null) { Rectangle bounds = bw.getBounds(); XWidgetCreator comp = (XWidgetCreator) XCreatorUtils.createXCreator(bw.getWidget()); - String constraint = bw.getWidget().acceptType(Label.class) ? WTitleLayout.TITLE : WTitleLayout.BODY; + boolean isTitleWidget = bw.getWidget().acceptType(Label.class); + String constraint = isTitleWidget ? WTitleLayout.TITLE : WTitleLayout.BODY; this.add(comp, constraint); comp.setBounds(bounds); + if (!isTitleWidget && comp instanceof XBorderStyleWidgetCreator) { + bodyCreator = (XBorderStyleWidgetCreator) comp; + } } } + // 刷新时重置下样式 + if (bodyCreator != null) { + bodyCreator.refreshStylePreviewEffect(); + } isRefreshing = false; } diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardLayout.java b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardLayout.java index e1d4a416e..b784187e7 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardLayout.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardLayout.java @@ -406,15 +406,10 @@ public class XWCardLayout extends XLayoutContainer { private void initBorderTitleStyle(BorderPacker style) { //初始化默认标题样式 - if (!initFlag) { - return; - } - style.setType(LayoutBorderStyle.TITLE); style.setBorder(Constants.LINE_THIN); TitlePacker widgetTitle = style.getTitle(); widgetTitle.setBackground(ColorBackground.getInstance(TITLE_COLOR)); - initFlag = false; } //隐藏或显示标题部分 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..f2d1c4ad9 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/JFormType.java @@ -0,0 +1,141 @@ +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 defaultPreviewType; + + JFormType(int type, PreviewProvider defaultPreviewType) { + this.type = type; + this.newType = (type == 1); + this.defaultPreviewType = defaultPreviewType; + } + + public int getType() { + return type; + } + + public boolean isNewType() { + return newType; + } + + public PreviewProvider getDefaultPreviewType() { + return defaultPreviewType; + } + + 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) { + if (jTemplate.getPreviewType() != null) { + PreviewProvider[] previewProviders = jTemplate.supportPreview(); + for (PreviewProvider previewProvider : previewProviders) { + if (previewProvider.getClass() == jTemplate.getPreviewType().getClass()) { + return; + } + } + } + jTemplate.setPreviewType(this.getDefaultPreviewType()); + } +} 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..fe192b59b --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/NewJForm.java @@ -0,0 +1,291 @@ +package com.fr.design.fit; + +import com.fr.base.DynamicUnitList; +import com.fr.base.Parameter; +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, Parameter[] parameters) { + this(form, file); + } + + 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() { + 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(); + return addAdaptiveSwitchButton(extraButtons); + } + + private UIButton[] addAdaptiveSwitchButton(UIButton[] extraButtons) { + 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..20351165e --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/attrpane/ElementEditorExtendDefinePane.java @@ -0,0 +1,114 @@ +package com.fr.design.fit.attrpane; + +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedComponentStyle; +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.gui.style.FollowingThemePane; +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.main.Form; +import com.fr.form.ui.ElementCaseEditor; +import com.fr.form.ui.PaddingMargin; +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 final 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); + paddingBoundPane = new PaddingBoundPane(); + themePane.addFollowThemePane(paddingBoundPane, new FollowingThemePane.FollowingThemeActionChangeListener() { + @Override + public void onFollowingTheme(boolean following) { + paddingBoundPane.setVisible(!following); + + if (following) { + TemplateTheme theme = themePane.getUsingTheme(); + if (theme instanceof FormTheme) { + ThemedComponentStyle style = ((FormTheme) theme).getComponentStyle(); + int top = style.getPaddingTop(); + int bottom = style.getPaddingBottom(); + int left = style.getPaddingLeft(); + int right = style.getPaddingRight(); + paddingBoundPane.populateBean(new PaddingMargin(top, left, bottom, right)); + } + } + } + }); + } + + protected JPanel createCenterPane() { + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + elementCaseToolBarEditor = new AccessibleElementCaseToolBarEditor(); + Component[][] components = new Component[][]{ + 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 (themePane.isFollowingTheme() || 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..563ed16aa --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/attrpane/FRAbsoluteBodyLayoutExtendDefinePane.java @@ -0,0 +1,198 @@ +package com.fr.design.fit.attrpane; + +import com.fr.base.io.IOFile; +import com.fr.base.iofile.attr.WatermarkAttr; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateTheme; +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.gui.style.FollowingThemePane; +import com.fr.design.gui.xpane.LayoutStylePane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.WidgetPropertyPane; +import com.fr.design.mainframe.widget.accessibles.AccessibleBodyWatermarkEditor; +import com.fr.design.utils.gui.UIComponentUtils; +import com.fr.design.widget.FRWidgetFactory; +import com.fr.design.widget.ui.designer.component.WidgetBoundPane; +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.general.act.BorderPacker; +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; + + protected FollowingThemePane themePane; + private LayoutStylePane stylePane; + private AccessibleBodyWatermarkEditor watermarkEditor; + + private UIComboBox layoutCombox; + private WBodyLayoutType layoutType = WBodyLayoutType.ABSOLUTE; + + public FRAbsoluteBodyLayoutExtendDefinePane(XCreator xCreator) { + super(xCreator); + } + + + public void initComponent() { + initUIComboBox(); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel panel1 = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(panel1, BorderLayout.CENTER); + + UIExpandablePane scalePane = new UIExpandablePane( + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Area_Scaling"), + 280, 20, + createAreaScalePane() + ); + panel1.add(scalePane, BorderLayout.NORTH); + + UIExpandablePane advancedPane = new UIExpandablePane( + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Advanced"), + 280, 20, + this.createAdvancePane()); + panel1.add(advancedPane, BorderLayout.CENTER); + + } + + public JPanel createAdvancePane() { + JPanel advancedContentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + themePane = new FollowingThemePane(Toolkit.i18nText("Fine-Design_Form_Body_Style_Setting")); + stylePane = new LayoutStylePane(); + themePane.addFollowThemePane(stylePane, new FollowingThemePane.FollowingThemeActionChangeListener() { + @Override + public void onFollowingTheme(boolean following) { + stylePane.supportBodyStyle(!following); + + BorderPacker style = stylePane.updateBean(); + if (following) { + TemplateTheme theme = themePane.getUsingTheme(); + if (theme instanceof FormTheme) { + style = ((FormTheme) theme).getBodyStyle().merge(style); + } + } + stylePane.populateBean((LayoutBorderStyle) style); + } + }); + advancedContentPane.add(themePane, BorderLayout.NORTH); + + watermarkEditor = new AccessibleBodyWatermarkEditor(); + JPanel watermarkPane = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{ + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_WaterMark")), watermarkEditor} + }, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W3, IntervalConstants.INTERVAL_L1); + watermarkPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0)); + advancedContentPane.add(watermarkPane, BorderLayout.CENTER); + + return advancedContentPane; + } + + public JPanel createAreaScalePane() { + initLayoutComboBox(); + + UILabel layoutTypeLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Layout_Type")); + + JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{ + {layoutTypeLabel, layoutCombox} + }, + TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1); + + contentPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0)); + + JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + containerPane.add(contentPane, BorderLayout.CENTER); + containerPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + + return containerPane; + } + + 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); + themePane.supportFollowingTheme(ob.supportThemed()); + themePane.setFollowingTheme(ob.isBorderStyleFollowingTheme()); + stylePane.populateBean((LayoutBorderStyle) 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.setBorderStyleFollowingTheme(themePane.isFollowingTheme()); + layout.setBorderStyle(stylePane.updateBean()); + 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..78e2c5c3a --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/attrpane/FRFitLayoutExtendDefinePane.java @@ -0,0 +1,282 @@ +package com.fr.design.fit.attrpane; + + +import com.fr.base.io.IOFile; +import com.fr.base.iofile.attr.WatermarkAttr; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateTheme; +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.gui.style.FollowingThemePane; +import com.fr.design.gui.xpane.LayoutStylePane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; +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.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.general.act.BorderPacker; +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 FollowingThemePane themePane; + private LayoutStylePane 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()); + UIExpandablePane layoutExpandablePane = new UIExpandablePane( + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout"), + 280, 20, + createLayoutPane() + ); + this.add(layoutExpandablePane, BorderLayout.NORTH); + + JPanel advancePane = createAdvancePane(); + UIExpandablePane advanceExpandablePane = new UIExpandablePane( + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Advanced"), + 280, 20, + advancePane + ); + this.add(advanceExpandablePane, BorderLayout.CENTER); + } + + public JPanel createAdvancePane() { + JPanel contentPane0 = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + themePane = new FollowingThemePane(Toolkit.i18nText("Fine-Design_Form_Body_Style_Setting")); + stylePane = new LayoutStylePane(); + themePane.addFollowThemePane(stylePane, new FollowingThemePane.FollowingThemeActionChangeListener() { + @Override + public void onFollowingTheme(boolean following) { + stylePane.supportBodyStyle(!following); + + BorderPacker style = stylePane.updateBean(); + if (following) { + TemplateTheme theme = themePane.getUsingTheme(); + if (theme instanceof FormTheme) { + style = ((FormTheme) theme).getBodyStyle().merge(style); + } + } + stylePane.populateBean((LayoutBorderStyle) style); + } + }); + contentPane0.add(themePane, BorderLayout.NORTH); + + JPanel contentPane1 = FRGUIPaneFactory.createBorderLayout_S_Pane(); + contentPane0.add(contentPane1, BorderLayout.CENTER); + + watermarkEditor = new AccessibleBodyWatermarkEditor(); + JPanel waterMarkPane = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{ + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_WaterMark")), watermarkEditor} + }, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W3, IntervalConstants.INTERVAL_L1); + waterMarkPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + contentPane1.add(waterMarkPane, BorderLayout.NORTH); + + paddingBound = new PaddingBoundPane(); + contentPane1.add(paddingBound, BorderLayout.CENTER); + + return contentPane0; + } + + public JPanel createLayoutPane() { + JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + 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")); + + JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{ + {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Layout_Type")), layoutComboBox}, + {intervalLabel, componentIntervelPane} + }, + TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1); + contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + containerPane.add(contentPane, BorderLayout.CENTER); + + return containerPane; + } + + + 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()); + themePane.supportFollowingTheme(ob.supportThemed()); + themePane.setFollowingTheme(ob.isBorderStyleFollowingTheme()); + stylePane.populateBean((LayoutBorderStyle) 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); + } + layout.setBorderStyleFollowingTheme(themePane.isFollowingTheme()); + LayoutBorderStyle borderStyle = stylePane.updateBean(); + 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..81ae07762 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/attrpane/PcFitExpandablePane.java @@ -0,0 +1,128 @@ +package com.fr.design.fit.attrpane; + +import com.finebi.cbb.utils.CompareUtils; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.fun.PcFitProvider; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +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; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + +/** + * Created by kerry on 2020-04-22 + */ +public class PcFitExpandablePane extends JPanel { + Item[] defaultItems = new Item[]{new Item(Toolkit.i18nText("Fine-Designer_Fit_Ec_Double_Fit"), 2, Toolkit.i18nText("Fine-Designer_Fit_Ec_Double_Fit_Tip")), + new Item(Toolkit.i18nText("Fine-Designer_Fit_Ec_Hor_Fit"), 1, Toolkit.i18nText("Fine-Designer_Fit_Ec_Hor_Fit_Tip")), + new Item(Toolkit.i18nText("Fine-Designer_Fit_Ec_No_Fit"), 3, Toolkit.i18nText("Fine-Designer_Fit_Ec_No_Fit_Tip"))}; + UIComboBox comboBox = new UIComboBox(); + UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine-Designer_Fit_Ec_No_Fit_Tip")); + + Map contentDisplayType = new HashMap<>(); + Map contentDisplayTip = new HashMap<>(); + + public PcFitExpandablePane(DataModify attrPane) { + init(attrPane); + } + + public void init(final DataModify attrPane) { + initComboBox(); + 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(contentDisplayTip.get(comboBox.getSelectedItem())); + } + }); + Component[][] components = new Component[][]{ + new Component[]{new UILabel(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); + } + + private void initComboBox() { + for (Item item : defaultItems) { + comboBox.addItem(item.value); + contentDisplayType.put(item.key, item.value); + contentDisplayTip.put(item.value, item.tip); + } + + Set pcFitProviders = ExtraDesignClassManager.getInstance().getArray(PcFitProvider.XML_TAG); + + for (PcFitProvider pcFitProvider : pcFitProviders) { + comboBox.addItem(pcFitProvider.getContentDisplayValue()); + contentDisplayType.put(pcFitProvider.getContentDisplayKey(), pcFitProvider.getContentDisplayValue()); + contentDisplayTip.put(pcFitProvider.getContentDisplayValue(), pcFitProvider.getContentDisplayTip()); + } + } + + public ReportFitAttr update() { + ReportFitAttr fitAttr = getDefaultReportFitAttr(); + String selectType = (String) comboBox.getSelectedItem(); + for (Integer key : contentDisplayType.keySet()) { + if (CompareUtils.isEqual(contentDisplayType.get(key), selectType)) { + fitAttr.setFitStateInPC(key); + } + } + return fitAttr; + } + + public void populate(ReportFitAttr fitAttr) { + if (fitAttr == null || !contentDisplayType.keySet().contains(fitAttr.fitStateInPC())) { + fitAttr = getDefaultReportFitAttr(); + } + String selectType = contentDisplayType.get(fitAttr.fitStateInPC()); + for (int i = 0; i < comboBox.getItemCount(); i++) { + if (CompareUtils.isEqual(selectType, comboBox.getItemAt(i))) { + comboBox.setSelectedIndex(i); + tipLabel.setText(contentDisplayTip.get(selectType)); + } + } + } + + private ReportFitAttr getDefaultReportFitAttr() { + ReportFitAttr fitAttr = new ReportFitAttr(); + fitAttr.setFitStateInPC(FitAttrState.NOT_FIT.getState()); + return fitAttr; + } + + class Item { + public String value; + public int key; + public String tip; + + Item(String value, int key, String tip) { + this.value = value; + this.key = key; + this.tip = tip; + } + } +} 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..8c55e8ab0 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/common/AdaptiveSwitchUtil.java @@ -0,0 +1,259 @@ +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.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.main.Form; +import com.fr.form.main.WidgetGather; +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; +import java.util.Set; + +/** + * 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())); + } + processAbsoluteLayoutCompatible(jForm.getTarget()); + TemplateTool.saveForm(jForm); + } + return template; + } + + + private static void processAbsoluteLayoutCompatible(Form form){ + Form.traversalWidget(form.getContainer(), new WidgetGather() { + @Override + public void dealWith(Widget widget) { + if (widget.acceptType(WAbsoluteBodyLayout.class)) { + return; + } + WAbsoluteLayout absoluteLayout = (WAbsoluteLayout) widget; + //切换到新模板后,内部的绝对画布块都要设置成适应缩放的逻辑 + absoluteLayout.setCompState(0); + } + + @Override + public boolean dealWithAllCards() { + return true; + } + }, WAbsoluteLayout.class); + } + + + + /** + * @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); + } + if (old.getTarget() instanceof Form) { + try { + return new NewJForm((Form) (old.getTarget()).clone(), old.getEditingFILE()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + return null; + } + } else { + return null; + } + } + + /** + * @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..cb415df59 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fit/common/TemplateTool.java @@ -0,0 +1,222 @@ +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.JForm; +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) { + if (!(jTemplate instanceof JForm)) { + JFormType.OLD_TYPE.switchUIMode(); + return; + } + JFormType currentType = JFormType.OLD_TYPE; + if (AdaptiveSwitchUtil.isSwitchJFromIng()) { + currentType = DesignerUIModeConfig.getInstance().newUIMode() ? JFormType.NEW_TYPE : JFormType.OLD_TYPE; + } else if (isNewJForm(jTemplate)) { + currentType = JFormType.NEW_TYPE; + } + //UI转换 + currentType.switchUIMode(); + //标志位转换 + currentType.updateJFromTemplateType(jTemplate); + //预览方式转换 + currentType.updatePreviewType(jTemplate); + } + }; + + private static boolean isNewJForm(JTemplate jTemplate) { + if (jTemplate instanceof NewJForm) { + NewJForm newJForm = (NewJForm) jTemplate; + if (LightTool.containNewFormFlag(newJForm.getTarget()) || newJForm.getTarget().getTemplateID() == null) { + return true; + } + } + return false; + } + + 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..32fe81ded --- /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 = jFormType.obtainFitAttr(); + 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/gui/xpane/CardTagLayoutStylePane.java b/designer-form/src/main/java/com/fr/design/gui/xpane/CardTagLayoutStylePane.java index 37db55102..98fe066e2 100644 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/CardTagLayoutStylePane.java +++ b/designer-form/src/main/java/com/fr/design/gui/xpane/CardTagLayoutStylePane.java @@ -10,15 +10,14 @@ import javax.swing.JPanel; */ public class CardTagLayoutStylePane extends LayoutStylePane { + @Override - protected JPanel createTitleStylePane(){ - JPanel panel = super.createTitleStylePane(); - panel.setVisible(false); - return panel; + protected JPanel createNamedTitleStylePane(boolean isRootLayout) { + return null; } @Override - protected JPanel createBackgroundStylePane(boolean supportCornerRadius) { - return super.createBackgroundStylePane(false); + protected JPanel createNamedIntegralStylePane(boolean isRootLayout, boolean supportCornerRadius) { + return super.createNamedIntegralStylePane(isRootLayout, false); } } diff --git a/designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java b/designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java index 453bd5e0d..09170b8c3 100644 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java +++ b/designer-form/src/main/java/com/fr/design/gui/xpane/LayoutStylePane.java @@ -1,40 +1,35 @@ package com.fr.design.gui.xpane; -import com.fr.base.Utils; -import com.fr.base.svg.IconUtils; import com.fr.design.beans.BasicBeanPane; import com.fr.design.designer.IntervalConstants; import com.fr.design.file.HistoryTemplateListCache; -import com.fr.design.formula.TinyFormulaPane; -import com.fr.design.gui.frpane.UIPercentDragPane; -import com.fr.design.gui.ibutton.UIButtonGroup; -import com.fr.design.gui.ibutton.UIColorButton; -import com.fr.design.gui.ibutton.UIToggleButton; -import com.fr.design.gui.icheckbox.UICheckBox; -import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.ispinner.UISpinner; import com.fr.design.gui.style.BackgroundSpecialPane; -import com.fr.design.gui.style.FRFontPane; +import com.fr.design.gui.style.ComponentBodyStylePane; +import com.fr.design.gui.style.ComponentIntegralStylePane; +import com.fr.design.gui.style.ComponentTitleStylePane; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.JForm; import com.fr.design.mainframe.JTemplate; import com.fr.design.mainframe.backgroundpane.GradientBackgroundQuickPane; import com.fr.form.ui.LayoutBorderStyle; -import com.fr.form.ui.WidgetTitle; -import com.fr.general.Background; -import com.fr.general.FRFont; -import com.fr.general.IOUtils; -import com.fr.general.act.TitlePacker; -import com.fr.stable.Constants; - -import javax.swing.*; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; import javax.swing.border.LineBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.awt.*; +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Stroke; + +import static com.fr.design.i18n.Toolkit.i18nText; /** * @author Starryi @@ -44,51 +39,19 @@ import java.awt.*; * 可配置图片类型边框的样式设置面板 */ public class LayoutStylePane extends BasicBeanPane { - public static final String[] BORDER_STYLE = new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Common"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Shadow") - }; - private static final Dimension BUTTON_SIZE = new Dimension(20, 20); public static final int SETTING_LABEL_WIDTH = 60; protected LayoutBorderStyle style = new LayoutBorderStyle(); - //渲染风格:有无阴影 - protected UIComboBox borderStyleCombo; - // 含图片类型边框的边框配置面板(图片类型边框 + 阴影时存在默认的阴影颜色) - protected BorderLineAndImagePane borderLineAndImagePane; - //边框圆角或圆角裁剪 - protected UISpinner cornerSpinner; - //主体背景 - protected BackgroundSpecialPane backgroundPane; - //主体背景透明度 - protected UIPercentDragPane backgroundOpacityPane; - - // 标题可见 - protected UICheckBox titleVisibleCheckbox; - //标题文字内容 - protected TinyFormulaPane titleTextPane; - //标题字体格式 - protected UIComboBox titleFontFamilyComboBox; - //标题字体大小 - protected UIComboBox titleFontSizeComboBox; - //标题字体颜色 - protected UIColorButton titleFontColorSelectPane; - //标题字体特殊效果:粗体、斜体、下划线 - private UIToggleButton titleFontBoldButton; - private UIToggleButton titleFontItalicButton; - private UIToggleButton titleFontUnderlineButton; -// private LineComboBox titleFontUnderlineCombo; // 目前前端仅支持短横线类型的下划线,因此设计器端暂时就不展示线型选择框了,待后续优化 - // 标题图文混排 - protected TitleInsetImagePane titleInsetImagePane; - //对齐方式 - protected UIButtonGroup titleAlignPane; - //标题整体背景 - protected BackgroundSpecialPane titleBackgroundPane; - //标题背景透明度 - protected UIPercentDragPane titleBackgroundOpacityPane; - - private boolean supportBorderImage = false; + public JPanel namedTitleStylePane; + public JPanel namedBodyStylePane; + public JPanel namedIntegralStylePane; + + protected ComponentTitleStylePane titleStylePane; + protected ComponentBodyStylePane bodyStylePane; + protected ComponentIntegralStylePane integralStylePane; + + private final boolean supportBorderImage; public LayoutStylePane() { this(false); @@ -96,344 +59,92 @@ public class LayoutStylePane extends BasicBeanPane { public LayoutStylePane(boolean supportBorderImage) { this.supportBorderImage = supportBorderImage; - this.initLayout(); + this.initializePane(); } - protected void initLayout() { + protected void initializePane() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); this.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); - JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); - JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - boolean currentIsRootLayout = currentEditingTemplate != null && !currentEditingTemplate.isJWorkBook() && ((JForm)currentEditingTemplate).isSelectRootPane(); + boolean isRootLayout = currentEditingTemplate != null && !currentEditingTemplate.isJWorkBook() && ((JForm)currentEditingTemplate).isSelectRootPane(); - JPanel titlePane = createTitleStylePane(); - JPanel bodyContentPane = currentIsRootLayout ? createBodyContentPane4RootLayout() : createBodyContentPane(); - JPanel backgroundPane = createBackgroundStylePane(true); + namedTitleStylePane = createNamedTitleStylePane(isRootLayout); + namedBodyStylePane = createNamedBodyStylePane(isRootLayout); + namedIntegralStylePane = createNamedIntegralStylePane(isRootLayout, true); - if (titlePane != null) { - container.add(titlePane, BorderLayout.NORTH); - if (currentIsRootLayout) { - titlePane.setVisible(false); - } - } - JPanel nextContainerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - container.add(nextContainerPane, BorderLayout.CENTER); + addComponents(new JComponent[] { namedTitleStylePane, namedBodyStylePane, namedIntegralStylePane }); + } - if (bodyContentPane != null) { - //界面上表单主体只有背景和透明度可以设置 - nextContainerPane.add(bodyContentPane, BorderLayout.NORTH); + protected JPanel createNamedTitleStylePane(boolean isRootLayout) { + if (isRootLayout) { + return null; } - if (backgroundPane != null) { - nextContainerPane.add(backgroundPane, BorderLayout.CENTER); - if (currentIsRootLayout) { - backgroundPane.setVisible(false); - } - } - - this.add(container, BorderLayout.CENTER); + this.titleStylePane = new ComponentTitleStylePane(SETTING_LABEL_WIDTH); + return this.createNamedSubStylePane(i18nText("Fine-Design_Form_Widget_Style_Title"), this.titleStylePane); } - protected JPanel createBackgroundStylePane(boolean supportCornerRadius) { - borderStyleCombo = new UIComboBox(BORDER_STYLE); - borderLineAndImagePane = new BorderLineAndImagePane(this.supportBorderImage); - cornerSpinner = new UISpinner(0,1000,1,0); - - double p = TableLayout.PREFERRED; - double f = TableLayout.FILL; - double[] rowSize = supportCornerRadius ? new double[] {p, p, p, p} : new double[]{p, p, p}; - double[] columnSize = {SETTING_LABEL_WIDTH, f}; - - UILabel uiLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Background_Style")); - Font font = uiLabel.getFont().deriveFont(Font.BOLD); - uiLabel.setFont(font); - uiLabel.setForeground(new Color(143, 143, 146)); - - JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ - {uiLabel, null}, - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Render_Style")), borderStyleCombo}, - {this.borderLineAndImagePane, null}, - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Radius")), cornerSpinner}, - }, - rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); - contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); - - JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); - container.setBorder(new BottomLineBorder()); - container.add(contentPane, BorderLayout.NORTH); - - return container; + protected JPanel createNamedBodyStylePane(boolean isRootLayout) { + this.bodyStylePane = new ComponentBodyStylePane(SETTING_LABEL_WIDTH); + if (isRootLayout) { + return this.bodyStylePane; + } + return this.createNamedSubStylePane(i18nText("Fine-Design_Form_Widget-Style_Body_Content"), this.bodyStylePane); } - protected JPanel createBodyContentPane() { - backgroundPane = new LayoutBackgroundSpecialPane(); - backgroundOpacityPane = new UIPercentDragPane(); - - double p = TableLayout.PREFERRED; - double f = TableLayout.FILL; - double[] rowSize = {p, p}; - double[] columnSize = {SETTING_LABEL_WIDTH, f}; - - JPanel bodyBackground = createBackgroundAndOpacityPane( - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Fill"), - this.backgroundPane, - this.backgroundOpacityPane); + protected JPanel createNamedIntegralStylePane(boolean isRootLayout, boolean supportCornerRadius) { + if (isRootLayout) { + return null; + } + this.integralStylePane = new ComponentIntegralStylePane(SETTING_LABEL_WIDTH, supportBorderImage, supportCornerRadius); + return this.createNamedSubStylePane(i18nText("Fine-Design_Form_Widget-Style_Integral_Style"), this.integralStylePane); + } - UILabel uiLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Content")); + protected JPanel createNamedSubStylePane(String name, JPanel stylePane) { + UILabel uiLabel = new UILabel(name); Font font = uiLabel.getFont().deriveFont(Font.BOLD); uiLabel.setFont(font); uiLabel.setForeground(new Color(143, 143, 146)); - JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ - {uiLabel, null}, - {bodyBackground, null}, - }, - rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); - contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); - - JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); - container.setBorder(new BottomLineBorder()); - container.add(contentPane, BorderLayout.NORTH); - - return container; - } - protected JPanel createBodyContentPane4RootLayout() { - backgroundPane = new LayoutBackgroundSpecialPane(); - backgroundOpacityPane = new UIPercentDragPane(); - - double p = TableLayout.PREFERRED; - double f = TableLayout.FILL; - double[] rowSize = {p}; - double[] columnSize = {SETTING_LABEL_WIDTH, f}; - - JPanel bodyBackground = createBackgroundAndOpacityPane( - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Fill"), - this.backgroundPane, - this.backgroundOpacityPane); - - JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(new JComponent[][]{ - {bodyBackground, null}, - }, - rowSize, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); - contentPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + JPanel content = TableLayoutHelper.createGapTableLayoutPane( new JComponent[][] { + {uiLabel}, + {stylePane} + }, TableLayoutHelper.FILL_LASTCOLUMN, 0, IntervalConstants.INTERVAL_L1); + content.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0)); JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.add(content, BorderLayout.NORTH); container.setBorder(new BottomLineBorder()); - container.add(contentPane, BorderLayout.NORTH); return container; } - protected void initTitleComponents() { - titleVisibleCheckbox = new UICheckBox(); - - titleTextPane = new TinyFormulaPane(); - - titleFontFamilyComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report()); - TitlePacker title = style.getTitle(); - if (title != null) { - FRFont frFont = title.getFrFont(); - if (frFont != null) { - String fontFamily = frFont.getFamily(); - // 使用style中默认的字体初始化titleFontFamilyComboBox,保证UI和数据的一致性 - this.titleFontFamilyComboBox.setSelectedItem(fontFamily); + private void addComponents(JComponent[] components) { + JPanel container = this; + for (JComponent component: components) { + if (component != null) { + container.add(component, BorderLayout.NORTH); + JPanel nextContainer = new JPanel(FRGUIPaneFactory.createBorderLayout()); + container.add(nextContainer, BorderLayout.CENTER); + container = nextContainer; } } - titleFontFamilyComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Family")); - - titleFontSizeComboBox = new UIComboBox(FRFontPane.FONT_SIZES); - titleFontSizeComboBox.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Size")); - - titleFontColorSelectPane = new UIColorButton(); - titleFontColorSelectPane.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); - titleFontColorSelectPane.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Foreground")); - - titleFontBoldButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png")); - titleFontBoldButton.setPreferredSize(BUTTON_SIZE); - titleFontBoldButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); - titleFontBoldButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Bold")); - - titleFontItalicButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png")); - titleFontItalicButton.setPreferredSize(BUTTON_SIZE); - titleFontItalicButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); - titleFontItalicButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Italic")); - - titleFontUnderlineButton = new UIToggleButton(IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png")); - titleFontUnderlineButton.setPreferredSize(BUTTON_SIZE); - titleFontUnderlineButton.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); - titleFontUnderlineButton.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Underline")); - -// titleFontUnderlineCombo = new LineComboBox(UIConstants.BORDER_LINE_STYLE_ARRAY); -// titleFontUnderlineCombo.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_FRFont_Line_Style")); - - titleInsetImagePane = new TitleInsetImagePane(); - - titleAlignPane = new UIButtonGroup( - new Icon[] { - IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), - IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), - IconUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png") - }, - new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT}); - titleAlignPane.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") - }); - - titleBackgroundPane = new LayoutBackgroundSpecialPane(); - - titleBackgroundOpacityPane = new UIPercentDragPane(); - } - - protected JPanel createTitleStylePane() { - initTitleComponents(); - - double p = TableLayout.PREFERRED; - double f = TableLayout.FILL; - double[] rowSize = {p,p,p,p,p,p}; - double[] columnSize = {SETTING_LABEL_WIDTH, f}; - - final JPanel bottomPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][]{ - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Content")), titleTextPane}, - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Format")), titleFontFamilyComboBox}, - {null, createTitleFontButtonPane()}, - {titleInsetImagePane, null}, - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Text_Align")), titleAlignPane}, - {this.createTitleBackgroundAndOpacityPane(), null}, - }, - rowSize, columnSize, IntervalConstants.INTERVAL_L1); - bottomPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); - bottomPane.setVisible(false); - - JPanel visibleComposedPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - - titleVisibleCheckbox.setSelected(false); - visibleComposedPane.add(titleVisibleCheckbox, BorderLayout.WEST); - visibleComposedPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Visible")), BorderLayout.CENTER); - - UILabel uiLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title")); - Font font = uiLabel.getFont().deriveFont(Font.BOLD); - uiLabel.setFont(font); - uiLabel.setForeground(new Color(143, 143, 146)); - JPanel topPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] { - {uiLabel, null}, - {visibleComposedPane, null} - }, new double[]{p, p}, new double[]{SETTING_LABEL_WIDTH, p}, IntervalConstants.INTERVAL_L1); - topPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); - - JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); - container.setBorder(new BottomLineBorder()); - container.add(topPane, BorderLayout.NORTH); - container.add(bottomPane, BorderLayout.CENTER); - - titleVisibleCheckbox.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - bottomPane.setVisible(titleVisibleCheckbox.isSelected()); - } - }); - - return container; - } - - protected JPanel createTitleFontButtonPane(){ - double p = TableLayout.PREFERRED; - double f = TableLayout.FILL; - double[] rowSize = {p}; - double[] columnSize = {f, p, p, p, p}; - - JPanel buttonPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][] { - {titleFontSizeComboBox, titleFontColorSelectPane, titleFontItalicButton, titleFontBoldButton, titleFontUnderlineButton}, - }, rowSize, columnSize, IntervalConstants.INTERVAL_W0); - - JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - containerPane.add(buttonPane, BorderLayout.NORTH); -// containerPane.add(titleFontUnderlineCombo, BorderLayout.CENTER); - -// titleFontUnderlineCombo.setVisible(false); -// titleFontUnderlineButton.addChangeListener(new ChangeListener() { -// @Override -// public void stateChanged(ChangeEvent e) { -// titleFontUnderlineCombo.setVisible(titleFontUnderlineButton.isSelected()); -// } -// }); - - return containerPane; - } - - protected JPanel createTitleBackgroundAndOpacityPane() { - return createBackgroundAndOpacityPane( - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Background"), - titleBackgroundPane, - titleBackgroundOpacityPane); } @Override public LayoutBorderStyle updateBean() { LayoutBorderStyle style = new LayoutBorderStyle(); - updateMain(style); - updateTitle(style); - return style; - } - protected void updateMain(LayoutBorderStyle style) { - if (borderStyleCombo != null) { - style.setBorderStyle(borderStyleCombo.getSelectedIndex()); - } - if (cornerSpinner != null) { - style.setBorderRadius((int) cornerSpinner.getValue()); + if (this.titleStylePane != null) { + this.titleStylePane.updateBean(style); } - if (borderLineAndImagePane != null) { - borderLineAndImagePane.updateBean(style); + if (this.bodyStylePane != null) { + this.bodyStylePane.updateBean(style); } - if (backgroundPane != null) { - style.setBackground(backgroundPane.update()); + if (this.integralStylePane != null) { + this.integralStylePane.updateBean(style); } - if (backgroundOpacityPane != null) { - style.setAlpha((float)backgroundOpacityPane.updateBean()); - } - } - - protected void updateTitle(LayoutBorderStyle style) { - style.setType(titleVisibleCheckbox != null && titleVisibleCheckbox.isSelected() ? LayoutBorderStyle.TITLE : LayoutBorderStyle.STANDARD); - TitlePacker title = style.getTitle() == null ? new WidgetTitle() : style.getTitle(); - title.setTextObject(titleTextPane.updateBean()); - FRFont frFont = title.getFrFont(); - frFont = frFont.applySize((Integer) titleFontSizeComboBox.getSelectedItem()); - frFont = frFont.applyName(titleFontFamilyComboBox.getSelectedItem().toString()); - frFont = frFont.applyForeground(titleFontColorSelectPane.getColor()); - frFont = updateTitleFontItalicBold(frFont); -// int line = titleFontUnderlineButton.isSelected() ? this.titleFontUnderlineCombo.getSelectedLineStyle() : Constants.LINE_NONE; - int line = titleFontUnderlineButton.isSelected() ? Constants.LINE_THIN : Constants.LINE_NONE; - frFont = frFont.applyUnderline(line); - title.setFrFont(frFont); - title.setPosition((Integer) titleAlignPane.getSelectedItem()); - titleInsetImagePane.updateBean(title); - title.setBackground(titleBackgroundPane.update()); - title.setBackgroundOpacity((float)titleBackgroundOpacityPane.updateBean()); - style.setTitle(title); - } - - private FRFont updateTitleFontItalicBold(FRFont frFont) { - int italic_bold = frFont.getStyle(); - boolean isItalic = italic_bold == Font.ITALIC || italic_bold == (Font.BOLD + Font.ITALIC); - boolean isBold = italic_bold == Font.BOLD || italic_bold == (Font.BOLD + Font.ITALIC); - if (titleFontItalicButton.isSelected() && !isItalic) { - italic_bold += Font.ITALIC; - } else if (!titleFontItalicButton.isSelected() && isItalic) { - italic_bold -= Font.ITALIC; - } - frFont = frFont.applyStyle(italic_bold); - if (titleFontBoldButton.isSelected() && !isBold) { - italic_bold += Font.BOLD; - } else if (!titleFontBoldButton.isSelected() && isBold) { - italic_bold -= Font.BOLD; - } - frFont = frFont.applyStyle(italic_bold); - return frFont; + return style; } @Override @@ -443,104 +154,20 @@ public class LayoutStylePane extends BasicBeanPane { } this.style.setStyle(style); - populateMain(); - populateTitle(); - } - - protected void populateMain() { - if (this.borderStyleCombo != null) { - this.borderStyleCombo.setSelectedIndex(style.getBorderStyle()); - } - if (this.borderLineAndImagePane != null) { - this.borderLineAndImagePane.populateBean(style); + if (this.titleStylePane != null) { + this.titleStylePane.populateBean(this.style); } - if (this.backgroundPane != null) { - this.backgroundPane.populateBean(style.getBackground()); - if (this.backgroundOpacityPane != null) { - this.backgroundOpacityPane.populateBean(style.getAlpha()); - } + if (this.bodyStylePane != null) { + this.bodyStylePane.populateBean(this.style); } - if (this.cornerSpinner != null) { - this.cornerSpinner.setValue(style.getBorderRadius()); + if (this.integralStylePane != null) { + this.integralStylePane.populateBean(this.style); } } - protected void populateTitle() { - TitlePacker widgetTitle = style == null ? new WidgetTitle() : style.getTitle(); - widgetTitle = widgetTitle == null ? new WidgetTitle() : widgetTitle; - titleVisibleCheckbox.setSelected(style.getType() != LayoutBorderStyle.STANDARD); - - this.titleTextPane.populateBean(widgetTitle.getTextObject().toString()); - - FRFont frFont = widgetTitle.getFrFont(); - this.titleFontSizeComboBox.setSelectedItem(frFont.getSize()); - this.titleFontFamilyComboBox.setSelectedItem(frFont.getFamily()); - this.titleFontColorSelectPane.setColor(frFont.getForeground()); - this.titleFontColorSelectPane.repaint(); - titleFontBoldButton.setSelected(frFont.isBold()); - titleFontItalicButton.setSelected(frFont.isItalic()); - - int line = frFont.getUnderline(); - if (line == Constants.LINE_NONE) { - titleFontUnderlineButton.setSelected(false); -// titleFontUnderlineCombo.setVisible(false); - } else { - titleFontUnderlineButton.setSelected(true); -// titleFontUnderlineCombo.setVisible(true); -// this.titleFontUnderlineCombo.setSelectedLineStyle(line); - } - - titleAlignPane.setSelectedItem(widgetTitle.getPosition()); - titleInsetImagePane.populateBean(widgetTitle); - titleBackgroundPane.populateBean(widgetTitle.getBackground()); - titleBackgroundOpacityPane.populateBean(widgetTitle.getBackgroundOpacity()); - } - @Override protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style"); - } - - private static JPanel createBackgroundAndOpacityPane(String name, BackgroundSpecialPane backgroundPane, UIPercentDragPane opacityPane) { - JPanel container = new JPanel(); - container.setLayout(new BorderLayout(0, 6)); - - double p = TableLayout.PREFERRED; - double f = TableLayout.FILL; - double[] columnSize = {SETTING_LABEL_WIDTH, f}; - - // 确保BackgroundSpecialPane高度变化时,Label依然保持与其顶部对齐 - JPanel backgroundLabelPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - backgroundLabelPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); - backgroundLabelPane.add(new UILabel(name), BorderLayout.NORTH); - - JPanel backgroundComposedPane = TableLayoutHelper.createGapTableLayoutPane( - new JComponent[][]{ - {backgroundLabelPane, backgroundPane} - }, - new double[]{p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); - - JPanel opacityComposedPane = TableLayoutHelper.createGapTableLayoutPane( - new JComponent[][]{ - {new UILabel(""), new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))}, - {new UILabel(""), opacityPane} - }, - new double[]{p, p}, columnSize, IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L1); - - container.add(backgroundComposedPane, BorderLayout.NORTH, 0); - container.add(opacityComposedPane, BorderLayout.CENTER, 1); - - opacityComposedPane.setVisible(false); - - backgroundPane.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - Background background = backgroundPane.update(); - opacityComposedPane.setVisible(background != null); - } - }); - - return container; + return i18nText("Fine-Design_Form_Widget_Style"); } protected static class BottomLineBorder extends LineBorder { @@ -574,4 +201,23 @@ public class LayoutStylePane extends BasicBeanPane { return new GradientBackgroundQuickPane(140); } } + + public void supportTitleStyle(boolean supportTitleVisible, boolean supportTitleContent, boolean supportOtherSetting) { + if (titleStylePane != null) { + titleStylePane.setSupportTitleVisible(supportTitleVisible); + titleStylePane.setSupportTitleContent(supportTitleContent); + titleStylePane.setSupportOtherSetting(supportOtherSetting); + } + } + + public void supportBodyStyle(boolean supporting) { + if (namedBodyStylePane != null) { + namedBodyStylePane.setVisible(supporting); + } + } + public void supportIntegralStyle(boolean supporting) { + if (namedIntegralStylePane != null) { + namedIntegralStylePane.setVisible(supporting); + } + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java b/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java index ca621984b..a7244c0f2 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java @@ -201,7 +201,7 @@ public class EditingMouseListener extends MouseInputAdapter { e.translatePoint(oldX - e.getX(), oldY - e.getY()); } - private void offsetEventPoint(MouseEvent e){ + private void offsetEventPoint(MouseEvent e) { int x = designer.getRelativeX(e.getX()); int y = designer.getRelativeY(e.getY()); e.translatePoint(x - e.getX(), y - e.getY()); @@ -213,8 +213,8 @@ public class EditingMouseListener extends MouseInputAdapter { * @param e 鼠标事件 */ public void mouseReleased(MouseEvent e) { - MouseEvent transEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton()); - MouseEvent clickEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton()); + MouseEvent transEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton()); + MouseEvent clickEvent = new MouseEvent(e.getComponent(), MouseEvent.MOUSE_CLICKED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), e.getButton()); int oldX = e.getX(); int oldY = e.getY(); offsetEventPoint(e); @@ -248,7 +248,7 @@ public class EditingMouseListener extends MouseInputAdapter { } } - private boolean isAutoFire(MouseEvent transEvent, MouseEvent clickEvent ) { + private boolean isAutoFire(MouseEvent transEvent, MouseEvent clickEvent) { offsetEventPoint(transEvent); XCreator xCreator = designer.getComponentAt(transEvent); return (pressX != clickEvent.getX() || pressY != clickEvent.getY()) @@ -797,15 +797,15 @@ public class EditingMouseListener extends MouseInputAdapter { /** * 刷新顶层组件 - * */ - public void refreshTopXCreator(boolean isEditing){ + */ + public void refreshTopXCreator(boolean isEditing) { designer.refreshTopXCreator(isEditing); } /** * 刷新顶层组件 - * */ - public void refreshTopXCreator(){ + */ + public void refreshTopXCreator() { refreshTopXCreator(false); } 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 23e08e5cf..16dc8593e 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; @@ -80,7 +79,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; @@ -252,7 +250,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); @@ -302,10 +300,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()) { @@ -320,6 +327,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( @@ -332,6 +340,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()) { @@ -400,7 +416,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/FormCreatorDropTarget.java b/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java index 7a6a73f4b..7db972e9b 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java @@ -27,19 +27,16 @@ import com.fr.design.mod.bean.ContentChangeItem; import com.fr.design.mod.event.TableDataModifyEvent; import com.fr.design.utils.ComponentUtils; import com.fr.event.EventDispatcher; -import com.fr.form.share.editor.SharableEditorProvider; import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.ShareLoader; +import com.fr.form.share.editor.SharableEditorProvider; import com.fr.form.ui.Widget; import com.fr.stable.Constants; import com.fr.stable.StringUtils; -import java.util.Collections; -import java.util.HashMap; import javax.swing.BorderFactory; import javax.swing.JWindow; -import java.util.List; -import java.util.Map; +import javax.swing.SwingUtilities; import java.awt.Color; import java.awt.Component; import java.awt.Point; @@ -49,7 +46,10 @@ import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; -import javax.swing.SwingUtilities; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * 添加模式下鼠标事件处理器。 @@ -139,6 +139,7 @@ public class FormCreatorDropTarget extends DropTarget { } EventDispatcher.fire(TableDataModifyEvent.INSTANCE, new ContentChangeItem(tdNameMap, widget, ChangeItem.TABLE_DATA_NAME)); } + designer.getSelectionModel().setSelectedCreators( FormSelectionUtils.rebuildSelection(xCreator, new Widget[]{widget})); designer.getEditListenerTable().fireCreatorModified(addingModel.getXCreator(), DesignerEvent.CREATOR_ADDED); 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 73085231a..cbe9e87e6 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 @@ -2,6 +2,9 @@ package com.fr.design.mainframe; import com.fr.base.Parameter; import com.fr.base.ScreenResolution; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeCompatible; import com.fr.base.vcs.DesignerMode; import com.fr.design.DesignModelAdapter; import com.fr.design.DesignState; @@ -41,7 +44,9 @@ import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.event.DesignerOpenedListener; +import com.fr.design.file.HistoryTemplateListCache; 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; @@ -56,7 +61,9 @@ import com.fr.design.utils.gui.LayoutUtils; import com.fr.form.FormElementCaseContainerProvider; import com.fr.form.FormElementCaseProvider; import com.fr.form.main.Form; +import com.fr.form.main.WidgetGather; import com.fr.form.parameter.FormSubmitButton; +import com.fr.form.ui.AbstractBorderStyleWidget; import com.fr.form.ui.EditorHolder; import com.fr.form.ui.PaddingMargin; import com.fr.form.ui.Widget; @@ -149,7 +156,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/mainframe/FormSelection.java b/designer-form/src/main/java/com/fr/design/mainframe/FormSelection.java index 308eba774..ee7918e50 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormSelection.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormSelection.java @@ -109,7 +109,7 @@ public class FormSelection { } /** - * 是否是可以增加的 + * 是否是可以增加组件到已选中的组件里面 * * @param creator 组件 * @return 是则返回true diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormSpacingLineDrawer.java b/designer-form/src/main/java/com/fr/design/mainframe/FormSpacingLineDrawer.java index 540c707d4..005a750c4 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormSpacingLineDrawer.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormSpacingLineDrawer.java @@ -31,6 +31,7 @@ public class FormSpacingLineDrawer { private FormDesigner designer; private XCreator hoverCreator = null; + private XCreator selectedCreator = null; private Rectangle selectedRec; private Rectangle hoveredRec; private boolean isMouseMoveEvent = false; @@ -40,19 +41,19 @@ public class FormSpacingLineDrawer { } public void updateMouseEvent(MouseEvent e, boolean isMouseMoveEvent) { - XCreator creator = designer.getSelectionModel().getSelection().getSelectedCreator(); - if (creator != null) { + selectedCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); + if (selectedCreator != null) { this.hoverCreator = getHoverComponentAt(e.getX(), e.getY()); } this.isMouseMoveEvent = isMouseMoveEvent; } public void draw(Graphics g) { - if (!isDrawSpacingLine()) { + if (!isMouseMoveEvent || selectedCreator == null || hoverCreator == null) { return; } - if (!hoverCreator.isParentAbsolute()) { + if (!isDrawSpacingLine()) { return; } @@ -136,55 +137,34 @@ public class FormSpacingLineDrawer { GraphDrawHelper.drawString(g2d, text, labelX, labelY); } - private boolean isSelectedParaComponent() { - return designer.getParaComponent() == designer.getSelectionModel().getSelection().getSelectedCreator(); - } - - private boolean isSelectedRootComponent() { - return designer.isRoot(designer.getSelectionModel().getSelection().getSelectedCreator()); - } - - private boolean isSelectedForm() { - return designer.getSelectionModel().getSelection().getSelectedCreator().getParent() == null; - } - private boolean isNeedExtendedLine(AbstractFormParallelLine[] nearestSides) { return nearestSides[0].isVerticalCenterLineBeforeTheParallelLine(nearestSides[1]) || nearestSides[0].isVerticalCenterLineBehindTheParallelLine(nearestSides[1]); } - private boolean isSelectedRootPane() { - // form、body、para这三个选中了,都不要画任何间距线 - return isSelectedForm() || isSelectedRootComponent() || isSelectedParaComponent(); - } - // 当前组件是否在参数面板里面 - private boolean isCompInPara(XCreator creator) { + private boolean isComponentInBody(XCreator creator) { XLayoutContainer container = XCreatorUtils.getHotspotContainer(creator); - - boolean xCreatorAccept = creator.acceptType(XWParameterLayout.class); - boolean containerAccept = container != null && container.acceptType(XWParameterLayout.class); - - return xCreatorAccept || containerAccept; + return container != null && !container.acceptType(XWParameterLayout.class); } - private boolean isBodyAbsoluteLayout() { - return !(designer instanceof FormParaDesigner) && FormDesignerUtils.isBodyAbsolute(designer); + private boolean isSelectedComponentInBody() { + return isComponentInBody(selectedCreator); } - private boolean isSelectedCompInPara() { - return isCompInPara(designer.getSelectionModel().getSelection().getSelectedCreator()); + private boolean isHoveredComponentInBody() { + return isComponentInBody(hoverCreator); } - private boolean isHoveredCompInPara() { - return isCompInPara(hoverCreator); + private boolean isBodyAbsoluteLayout() { + return !(designer instanceof FormParaDesigner) && FormDesignerUtils.isBodyAbsolute(designer); } - private boolean isSelectedCompOrHoveredCompInPara() { - return isSelectedCompInPara() || isHoveredCompInPara(); + private boolean isInAbsoluteLayout() { + return isBodyAbsoluteLayout() && hoverCreator.isParentAbsolute() && selectedCreator.isParentAbsolute(); } private boolean isDrawSpacingLine() { - return isBodyAbsoluteLayout() && !isSelectedRootPane() && hoverCreator != null && !isSelectedCompOrHoveredCompInPara() && isMouseMoveEvent; + return isInAbsoluteLayout() && isSelectedComponentInBody() && isHoveredComponentInBody(); } private AbstractFormParallelLine[] getNearestHorizontalSide() { diff --git a/designer-form/src/main/java/com/fr/design/mainframe/JForm.java b/designer-form/src/main/java/com/fr/design/mainframe/JForm.java index 0bee88e90..784a3b690 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/JForm.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/JForm.java @@ -6,7 +6,12 @@ import com.fr.base.Parameter; import com.fr.base.Releasable; import com.fr.base.extension.FileExtension; import com.fr.base.iofile.attr.ExtendSharableAttrMark; +import com.fr.base.theme.TemplateThemeCompatible; import com.fr.base.vcs.DesignerMode; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.FormThemeConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; import com.fr.design.DesignModelAdapter; import com.fr.design.DesignState; import com.fr.design.ExtraDesignClassManager; @@ -34,11 +39,13 @@ import com.fr.design.designer.creator.XWParameterLayout; import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; import com.fr.design.event.TargetModifiedEvent; import com.fr.design.event.TargetModifiedListener; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fun.FormAdaptiveConfigUIProcessor; import com.fr.design.fun.PreviewProvider; import com.fr.design.fun.PropertyItemPaneProvider; import com.fr.design.gui.frpane.HyperlinkGroupPane; import com.fr.design.gui.frpane.HyperlinkGroupPaneActionProvider; +import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.gui.xpane.FormHyperlinkGroupPane; @@ -49,6 +56,7 @@ import com.fr.design.mainframe.form.FormECCompositeProvider; import com.fr.design.mainframe.form.FormECDesignerProvider; import com.fr.design.mainframe.template.info.JFormProcessInfo; import com.fr.design.mainframe.template.info.TemplateProcessInfo; +import com.fr.design.mainframe.theme.dialog.TemplateThemeUsingDialog; import com.fr.design.mainframe.toolbar.ToolBarMenuDock; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.menu.KeySetUtils; @@ -94,6 +102,7 @@ import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.SwingConstants; +import javax.swing.tree.TreePath; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; @@ -107,7 +116,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; -import javax.swing.tree.TreePath; public class JForm extends JTemplate implements BaseJForm, Releasable { private static final String FORM_CARD = "FORM"; @@ -234,6 +242,20 @@ public class JForm extends JTemplate implements BaseJForm dialog = new TemplateThemeUsingDialog<>(designerFrame, JForm.this, FormThemeConfig.getInstance()); + dialog.setVisible(true); + } + }); + return button; + } + //表单返回 FORM_TAB or ELEMENTCASE_TAB public int getEditingReportIndex() { return this.index; @@ -643,9 +665,11 @@ public class JForm extends JTemplate implements BaseJForm implements BaseJForm implements BaseJForm implements BaseJForm getUsingTemplateThemeConfig() { + return getTarget().getUsingTemplateThemeConfig(); + } + + @Override + public FormTheme getTemplateTheme() { + return getTarget().getTemplateTheme(); + } + + @Override + public void setTemplateTheme(TemplateTheme newTheme, TemplateThemeCompatible compatible) { + FormTheme oldTheme = getTarget().getTemplateTheme(); + boolean shouldCreateUndoState = compatible == TemplateThemeCompatible.NONE && !StringUtils.equals(oldTheme.getName(), newTheme.getName()); + + FormArea formArea = formDesign.getArea(); + int horizontalValue = formArea.getHorizontalValue(); + int verticalValue= formArea.getVerticalValue(); + Dimension areaSize = formArea.getAreaSize(); + double widthValue = formArea.getWidthPaneValue(); + double heightValue = formArea.getHeightPaneValue(); + double slideValue = formArea.getSlideValue(); + + getTarget().setTemplateTheme(newTheme, compatible); + + if (HistoryTemplateListCache.getInstance().getCurrentEditingTemplate() == this) { + fireTargetModified(shouldCreateUndoState); + formDesign.refreshRoot(); + // 刷新界面后恢复原来的尺寸 + formDesign.getArea().setAreaSize(areaSize, horizontalValue, verticalValue, widthValue, heightValue, slideValue); + if (this.index != FORM_TAB) { + refreshToolArea(); + } else { + // CHART-20568: 当图表块处于编辑状态时,任何界面内容的修改都会导致其进行截图操作,进而引起设计器界面再次重绘,导致死循环,因而需要停止编辑 恢复浮层展示 + TreePath[] treePaths = FormHierarchyTreePane.getInstance(formDesign).getComponentTree().getSelectedTreePath(); + if (treePaths != null) { + for (TreePath path : treePaths) { + if (path != null) { + formDesign.stopEditing(path); + } + } + } + } + FormHierarchyTreePane.getInstance().refreshRoot(); + } + + super.setTemplateTheme(newTheme, compatible); + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/ToolBarButton.java b/designer-form/src/main/java/com/fr/design/mainframe/ToolBarButton.java index 4c18ba475..53b9c5291 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/ToolBarButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/ToolBarButton.java @@ -99,7 +99,7 @@ public class ToolBarButton extends UIButton implements MouseListener, MouseMotio creatorSource = no.getNameOption().createWidget(); } if (creatorSource != null) { - XCreator xCreator = XCreatorUtils.createXCreator(creatorSource); + XCreator xCreator = XCreatorUtils.createThemedXCreator(creatorSource); WidgetToolBarPane.getTarget().startDraggingBean(xCreator); FormDesignerUtils.addWidgetProcessInfo(xCreator.toData()); lastPressEvent = null; diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/action/CreateComponentAction.java b/designer-form/src/main/java/com/fr/design/mainframe/share/action/CreateComponentAction.java index 1baac868f..476afe8b6 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/action/CreateComponentAction.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/action/CreateComponentAction.java @@ -252,6 +252,9 @@ public class CreateComponentAction extends UpdateAction { private Image componentToImage(Component comp, Rectangle rect) { BufferedImage im = new BufferedImage((int) rect.getWidth(), (int) rect.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = (Graphics2D)im.getGraphics(); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0 , rect.width, rect.height); comp.paint(im.getGraphics()); return im; } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/action/InstallComponentAction.java b/designer-form/src/main/java/com/fr/design/mainframe/share/action/InstallComponentAction.java index a845759f7..6cb00b6ff 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/action/InstallComponentAction.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/action/InstallComponentAction.java @@ -95,7 +95,9 @@ public class InstallComponentAction extends UpdateAction { } ShareWidgetInfoManager.getInstance().saveXmlInfo(); - boolean needShowMessage = (chosenFiles.length > 1 && chosenFiles.length != failureList.size()) || containRues(chosenFiles); + boolean reuNeedShowMessage = chosenFiles.length > 1 && chosenFiles.length != failureList.size(); + boolean reusNeedShowMessage = containRues(chosenFiles) && !failureList.isEmpty(); + boolean needShowMessage = reuNeedShowMessage || reusNeedShowMessage; return new InstallBackInfo(installStatus, needShowMessage, failureList); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/generate/task/ComponentCreator.java b/designer-form/src/main/java/com/fr/design/mainframe/share/generate/task/ComponentCreator.java index b14229df6..126660665 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/generate/task/ComponentCreator.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/generate/task/ComponentCreator.java @@ -3,6 +3,7 @@ package com.fr.design.mainframe.share.generate.task; import com.fr.base.TableData; import com.fr.base.iofile.attr.ExtendSharableAttrMark; import com.fr.base.iofile.attr.SharableAttrMark; +import com.fr.base.theme.TemplateTheme; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.JTemplate; import com.fr.design.mainframe.share.generate.impl.AbstractComponentCreatorProcessor; @@ -39,6 +40,8 @@ public class ComponentCreator extends AbstractComponentCreatorProcessor { @Override public ComponentReuBean create(JTemplate jt, Map paraMap, Widget widget, DefaultSharableWidget info) throws Exception { + // 适用于共享组件的模版主题 + setSuitableTemplateThemeName(jt, info); // 遍历判断是否存在共享组件 checkOriginStatus(widget, info); @@ -56,6 +59,13 @@ public class ComponentCreator extends AbstractComponentCreatorProcessor { return new ComponentReuBean(generatePath, editor, info); } + private void setSuitableTemplateThemeName(JTemplate jt, DefaultSharableWidget info) { + TemplateTheme theme = jt.getTemplateTheme(); + if (theme != null) { + info.setSuitableTemplateThemeName(theme.getName()); + } + } + protected void checkOriginStatus(Widget widget, final DefaultSharableWidget info) { Form.traversalWidget(widget, new WidgetGatherAdapter() { diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java index 911ff7b77..d92755502 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java @@ -211,7 +211,8 @@ public class LocalWidgetBlock extends PreviewWidgetBlock creatorSource.setWidgetID(UUID.randomUUID().toString()); ((AbstractBorderStyleWidget) creatorSource).addWidgetAttrMark(new SharableAttrMark(true)); //tab布局WCardMainBorderLayout通过反射出来的大小是960*480 - XCreator xCreator = ShareComponentUtils.createXCreator(creatorSource, shareId, no.getBindInfo()); + String suitableTemplateThemeName = no.getWidget().getSuitableTemplateThemeName(); + XCreator xCreator = ShareComponentUtils.createThemedXCreator(creatorSource, suitableTemplateThemeName, shareId, no.getBindInfo()); WidgetToolBarPane.getTarget().startDraggingBean(xCreator); lastPressEvent = null; this.setBorder(null); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java index b8cb0e678..8ad419b03 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java @@ -12,6 +12,7 @@ import com.fr.design.login.DesignerLoginHelper; import com.fr.design.login.DesignerLoginSource; import com.fr.design.mainframe.WidgetToolBarPane; import com.fr.design.mainframe.share.collect.ComponentCollector; +import com.fr.form.share.DefaultSharableWidget; import com.fr.form.share.group.DefaultShareGroup; import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane; @@ -143,7 +144,13 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock { ((AbstractBorderStyleWidget) creatorSource).addWidgetAttrMark(new SharableAttrMark(true)); SharableWidgetProvider bindInfo = ShareUtils.getElCaseBindInfoById(shareId); //tab布局WCardMainBorderLayout通过反射出来的大小是960*480 - XCreator xCreator = ShareComponentUtils.createXCreator(creatorSource, shareId, bindInfo); + XCreator xCreator; + if (bindInfo instanceof DefaultSharableWidget) { + String suitableTemplateThemeName = ((DefaultSharableWidget) bindInfo).getSuitableTemplateThemeName(); + xCreator = ShareComponentUtils.createThemedXCreator(creatorSource, suitableTemplateThemeName, shareId, bindInfo); + } else { + xCreator = ShareComponentUtils.createXCreator(creatorSource, shareId, bindInfo); + } WidgetToolBarPane.getTarget().startDraggingBean(xCreator); lastPressEvent = null; this.setBorder(null); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/AbstractOnlineWidgetShowPane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/AbstractOnlineWidgetShowPane.java index 7c090cac3..117ac0ab8 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/AbstractOnlineWidgetShowPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/AbstractOnlineWidgetShowPane.java @@ -47,14 +47,11 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel { private OnlineShareWidget[] sharableWidgetProviders; - //缓存一份用于搜索 - private final OnlineShareWidget[] sharableWidgetCache; //主面板和搜索面板的cardLayout private CardLayout mainCardLayout; public AbstractOnlineWidgetShowPane(OnlineShareWidget[] sharableWidgetProviders) { - this.sharableWidgetCache = sharableWidgetProviders; this.sharableWidgetProviders = sharableWidgetProviders; this.setLayout(FRGUIPaneFactory.createBorderLayout()); JPanel contentPane = initContentPane(); @@ -119,7 +116,7 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel { } List widgets = new ArrayList<>(); if (StringUtils.isNotEmpty(text)) { - for (OnlineShareWidget provider : sharableWidgetCache) { + for (OnlineShareWidget provider : sharableWidgetProviders) { if (provider.getName().toLowerCase().contains(text)) { widgets.add(provider); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallUtils.java b/designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallUtils.java index 610f688a4..cd3e8c1ad 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallUtils.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallUtils.java @@ -30,9 +30,14 @@ public class InstallUtils { * 安装组件包 */ public static boolean installReusFile(File chosenFile, long installTime, List list) { - return installReusFile(chosenFile, installTime, list, o -> { + InstallResult installResult = installReusFile(chosenFile, installTime, list, o -> { //do nothing - }).installStatus; + }); + Group group = installResult.group; + if (group.getAllBindInfoList().length == 0) { + DefaultShareGroupManager.getInstance().removeGroup(group); + } + return installResult.installStatus; } /** diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/util/ShareComponentUtils.java b/designer-form/src/main/java/com/fr/design/mainframe/share/util/ShareComponentUtils.java index 80162a406..0dd613975 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/util/ShareComponentUtils.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/util/ShareComponentUtils.java @@ -2,6 +2,9 @@ package com.fr.design.mainframe.share.util; import com.fr.base.io.IOFile; import com.fr.base.iofile.attr.ExtendSharableAttrMark; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeCompatible; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreatorUtils; import com.fr.design.designer.creator.XLayoutContainer; @@ -50,6 +53,19 @@ public class ShareComponentUtils { return xCreator; } + public static XCreator createThemedXCreator(Widget creatorSource, String suitableTemplateThemeName, String shareId, SharableWidgetProvider provider) { + XCreator creator = createXCreator(creatorSource, shareId, provider); + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + TemplateTheme theme = template.getTemplateTheme(); + if (theme instanceof FormTheme) { + boolean isCurrentUsingThemeSuitSharedComponent = StringUtils.isNotEmpty(theme.getName()) && + StringUtils.isNotEmpty(suitableTemplateThemeName) && + StringUtils.equals(theme.getName(), suitableTemplateThemeName); + XCreatorUtils.setupTemplateTheme(creator, false, (FormTheme) theme, isCurrentUsingThemeSuitSharedComponent ? TemplateThemeCompatible.NONE : TemplateThemeCompatible.ABSENT); + } + return creator; + } + /** * 检查readme.txt文件 */ 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..908defcbb --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/preview/DeveloperPreview.java @@ -0,0 +1,65 @@ +package com.fr.design.preview; + +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.MutilTempalteTabPane; +import com.fr.design.fun.impl.AbstractPreviewProvider; +import com.fr.design.i18n.Toolkit; +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 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; + } + + public String tooltipForPopItem() { + return Toolkit.i18nText("Fine-Designer_Fit_Developer_Preview_Menu_Hint"); + } + + @Override + public void onClick(JTemplate jt) { + MutilTempalteTabPane.getInstance().closeCurrentTpl(); + super.onClick(jt); + } + + + @Override + public Map parametersForPreview() { + Map map = new HashMap(); + map.put(ParameterConstants.OP, "editable_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..b77d86620 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/preview/FormAdaptivePreview.java @@ -0,0 +1,41 @@ +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; + +/** + * Created by kerry on 2020-04-23 + */ +public class FormAdaptivePreview extends AbstractPreviewProvider { + private static final int PREVIEW_TYPE = 6; + + @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 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/widget/ui/designer/layout/ChartEditorDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ChartEditorDefinePane.java index fdb3efc9d..a4daf4acf 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ChartEditorDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ChartEditorDefinePane.java @@ -1,49 +1,56 @@ package com.fr.design.widget.ui.designer.layout; -import com.fr.design.designer.IntervalConstants; -import com.fr.design.designer.creator.CRPropertyDescriptor; -import com.fr.design.designer.creator.PropertyGroupPane; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedComponentStyle; 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.gui.style.FollowingThemePane; 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.form.ui.ChartEditor; -import com.fr.form.ui.ElementCaseEditor; -import com.fr.form.web.FormToolBarManager; +import com.fr.form.ui.PaddingMargin; import com.fr.general.ComparatorUtils; -import javax.swing.*; -import java.awt.*; +import javax.swing.JPanel; /** * Created by ibm on 2017/8/7. */ public class ChartEditorDefinePane extends WTitleLayoutDefinePane { - private PaddingBoundPane paddingBoundPane; + private final PaddingBoundPane paddingBoundPane; public ChartEditorDefinePane(XCreator xCreator) { super(xCreator); + paddingBoundPane = new PaddingBoundPane(); + themePane.addFollowThemePane(paddingBoundPane, new FollowingThemePane.FollowingThemeActionChangeListener() { + @Override + public void onFollowingTheme(boolean following) { + paddingBoundPane.setVisible(!following); + + if (following) { + TemplateTheme theme = themePane.getUsingTheme(); + if (theme instanceof FormTheme) { + ThemedComponentStyle style = ((FormTheme) theme).getComponentStyle(); + int top = style.getPaddingTop(); + int bottom = style.getPaddingBottom(); + int left = style.getPaddingLeft(); + int right = style.getPaddingRight(); + paddingBoundPane.populateBean(new PaddingMargin(top, left, bottom, right)); + } + } + + } + }); } protected JPanel createCenterPane() { - JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - paddingBoundPane = new PaddingBoundPane(); - Component[][] components = new Component[][]{ - new Component[]{paddingBoundPane, null}, - }; - JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W0, IntervalConstants.INTERVAL_L1); - panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0)); - centerPane.add(panel, BorderLayout.NORTH); - return centerPane; + return FRGUIPaneFactory.createBorderLayout_S_Pane(); } protected ChartEditor updateSubBean() { ChartEditor chartEditor = (ChartEditor) creator.toData(); - if (ComparatorUtils.equals(getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate"))) { + if (themePane.isFollowingTheme() || ComparatorUtils.equals(getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate"))) { paddingBoundPane.update(chartEditor); } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ElementEditorDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ElementEditorDefinePane.java index d8b0060e7..87c89f3cb 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ElementEditorDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/layout/ElementEditorDefinePane.java @@ -1,13 +1,18 @@ package com.fr.design.widget.ui.designer.layout; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedComponentStyle; import com.fr.design.designer.IntervalConstants; import com.fr.design.designer.creator.*; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.style.FollowingThemePane; 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.form.ui.ElementCaseEditor; +import com.fr.form.ui.PaddingMargin; import com.fr.form.web.FormToolBarManager; import com.fr.general.ComparatorUtils; @@ -21,21 +26,37 @@ import java.awt.Component; * Created by ibm on 2017/8/7. */ public class ElementEditorDefinePane extends WTitleLayoutDefinePane { - private PaddingBoundPane paddingBoundPane; + private final PaddingBoundPane paddingBoundPane; private AccessibleElementCaseToolBarEditor elementCaseToolBarEditor; private PropertyGroupPane extraPropertyGroupPane; public ElementEditorDefinePane(XCreator xCreator) { super(xCreator); + paddingBoundPane = new PaddingBoundPane(); + themePane.addFollowThemePane(paddingBoundPane, new FollowingThemePane.FollowingThemeActionChangeListener() { + @Override + public void onFollowingTheme(boolean following) { + paddingBoundPane.setVisible(!following); + if (following) { + TemplateTheme theme = themePane.getUsingTheme(); + if (theme instanceof FormTheme) { + ThemedComponentStyle style = ((FormTheme) theme).getComponentStyle(); + int top = style.getPaddingTop(); + int bottom = style.getPaddingBottom(); + int left = style.getPaddingLeft(); + int right = style.getPaddingRight(); + paddingBoundPane.populateBean(new PaddingMargin(top, left, bottom, right)); + } + } + } + }); } 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); @@ -49,7 +70,7 @@ public class ElementEditorDefinePane extends WTitleLayoutDefinePane extends AbstractDataModify { + protected FollowingThemePane themePane; private LayoutStylePane stylePane; public WTitleLayoutDefinePane(XCreator xCreator) { @@ -27,8 +33,29 @@ public abstract class WTitleLayoutDefinePane").append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Properties_Mobile_Tip")) - .append("").append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Properties_Mobile_Install_Parameter_Pane_Plugin")) - .append("").append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Properties_Mobile_To_Get_More_Style")) - .append(""); - tipLabel.setText(text.toString()); - tipLabel.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - try { - Desktop.getDesktop().browse(new URI(CloudCenter.getInstance().acquireUrlByKind("plugin.mobile.style"))); - } catch (Exception exp) { - FineLoggerFactory.getLogger().error(exp.getMessage(), exp); - } - } - @Override - public void mouseEntered(MouseEvent e) { - Object source = e.getSource(); - if (source instanceof UILabel) { - ((UILabel) source).setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - } - @Override - public void mouseExited(MouseEvent e) { - Object source = e.getSource(); - if (source instanceof UILabel) { - ((UILabel) source).setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - } - } - @Override - public void mouseMoved(MouseEvent e) { - Object source = e.getSource(); - if (source instanceof UILabel) { - ((UILabel) source).setCursor(new Cursor(Cursor.HAND_CURSOR)); - } - } - }); - return tipLabel; - } - // 控件顺序 private UIExpandablePane getMobileWidgetListPane() { mobileWidgetListPane = new MobileWidgetListPane(designer, (WSortLayout) paraCreator.toData()); diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/TabMobileWidgetDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/TabMobileWidgetDefinePane.java index af591abdd..93e2ee172 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/TabMobileWidgetDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/TabMobileWidgetDefinePane.java @@ -46,7 +46,7 @@ public class TabMobileWidgetDefinePane extends MobileWidgetDefinePane { public TabMobileWidgetDefinePane(XCreator xCreator) { this.xCreator = xCreator; - contentJPanel = FRGUIPaneFactory.createCenterFlowZeroGapBorderPane(); + contentJPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); scrollPane = new AttrScrollPane() { @Override protected JPanel createContentPane() { @@ -117,7 +117,7 @@ public class TabMobileWidgetDefinePane extends MobileWidgetDefinePane { //高级 holder.add(advancePane, BorderLayout.CENTER); - contentJPanel.add(holder, BorderLayout.CENTER); + contentJPanel.add(holder, BorderLayout.NORTH); this.add(scrollPane, BorderLayout.CENTER); } 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 000000000..7d7e064d1 Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/developer_preview.png differ 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 000000000..fc3d3d347 Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/developer_preview24.png differ diff --git a/designer-form/src/main/resources/com/fr/design/form/images/icon_form_tab.png b/designer-form/src/main/resources/com/fr/design/form/images/icon_form_tab.png new file mode 100755 index 000000000..a6ad9f86c Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/icon_form_tab.png differ 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 000000000..3730b3b79 Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/icon_switch.png differ 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 000000000..daee74b51 Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/icon_switch_disable.png differ diff --git a/designer-form/src/main/resources/com/fr/design/form/images/icon_switch_new_ui.png b/designer-form/src/main/resources/com/fr/design/form/images/icon_switch_new_ui.png new file mode 100755 index 000000000..f7a2a86f6 Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/icon_switch_new_ui.png differ 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 000000000..08217d411 Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/icon_switch_old_ui.png differ 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 000000000..d479fb376 Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/loading.png differ diff --git a/designer-form/src/main/resources/com/fr/design/form/images/theme4currentTemplate.png b/designer-form/src/main/resources/com/fr/design/form/images/theme4currentTemplate.png new file mode 100644 index 000000000..e022f1cfb Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/theme4currentTemplate.png differ diff --git a/designer-form/src/main/resources/com/fr/design/form/images/theme4newTemplate.png b/designer-form/src/main/resources/com/fr/design/form/images/theme4newTemplate.png new file mode 100644 index 000000000..457721834 Binary files /dev/null and b/designer-form/src/main/resources/com/fr/design/form/images/theme4newTemplate.png differ diff --git a/designer-form/src/test/java/com/fr/design/fit/FitStateCompatibleTest.java b/designer-form/src/test/java/com/fr/design/fit/FitStateCompatibleTest.java new file mode 100644 index 000000000..a826cb4b2 --- /dev/null +++ b/designer-form/src/test/java/com/fr/design/fit/FitStateCompatibleTest.java @@ -0,0 +1,24 @@ +package com.fr.design.fit; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by kerry on 2020-04-27 + */ +public class FitStateCompatibleTest { + @Test + public void testGetNewTypeFromOld() { + Assert.assertEquals(0, FitStateCompatible.getNewTypeFromOld(0)); + Assert.assertEquals(1, FitStateCompatible.getNewTypeFromOld(1)); + Assert.assertEquals(0, FitStateCompatible.getNewTypeFromOld(2)); + Assert.assertEquals(2, FitStateCompatible.getNewTypeFromOld(3)); + } + + @Test + public void testGetOldTypeFromNew() { + Assert.assertEquals(2, FitStateCompatible.getOldTypeFromNew(0)); + Assert.assertEquals(1, FitStateCompatible.getOldTypeFromNew(1)); + Assert.assertEquals(3, FitStateCompatible.getOldTypeFromNew(2)); + } +} diff --git a/designer-form/src/test/java/com/fr/design/fit/FormUIModeConfigTest.java b/designer-form/src/test/java/com/fr/design/fit/FormUIModeConfigTest.java new file mode 100644 index 000000000..12c57280c --- /dev/null +++ b/designer-form/src/test/java/com/fr/design/fit/FormUIModeConfigTest.java @@ -0,0 +1,22 @@ +package com.fr.design.fit; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by kerry on 2020-06-05 + */ +public class FormUIModeConfigTest { + @Test + public void testSetNewUIMode(){ + DesignerUIModeConfig.getInstance().setNewUIMode(); + Assert.assertTrue(DesignerUIModeConfig.getInstance().newUIMode()); + } + + @Test + public void testSetOldUIMode(){ + Assert.assertTrue(DesignerUIModeConfig.getInstance().newUIMode()); + DesignerUIModeConfig.getInstance().setOldUIMode(); + Assert.assertFalse(DesignerUIModeConfig.getInstance().newUIMode()); + } +} diff --git a/designer-form/src/test/java/com/fr/design/fit/PXReportLengthUNITTest.java b/designer-form/src/test/java/com/fr/design/fit/PXReportLengthUNITTest.java new file mode 100644 index 000000000..eef7eece9 --- /dev/null +++ b/designer-form/src/test/java/com/fr/design/fit/PXReportLengthUNITTest.java @@ -0,0 +1,49 @@ +package com.fr.design.fit; + +import com.fr.base.ScreenResolution; +import com.fr.stable.unit.FU; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +/** + * Created by kerry on 2020-04-24 + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest(ScreenResolution.class) +public class PXReportLengthUNITTest { + + @Test + public void testUnitText() { + PXReportLengthUNIT pxReportLengthUNIT = new PXReportLengthUNIT(); + Assert.assertEquals(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Px"), pxReportLengthUNIT.unitText()); + } + + @Test + public void testUnitType() { + PXReportLengthUNIT pxReportLengthUNIT = new PXReportLengthUNIT(); + Assert.assertEquals(4, pxReportLengthUNIT.unitType()); + } + + @Test + public void testUnit2Value4Scale() { + PXReportLengthUNIT pxReportLengthUNIT = new PXReportLengthUNIT(); + PowerMock.mockStatic(ScreenResolution.class); + EasyMock.expect(ScreenResolution.getScreenResolution()).andReturn(96).once(); + PowerMock.replayAll(); + Assert.assertEquals(12, (int) pxReportLengthUNIT.unit2Value4Scale(FU.getInstance(457200L))); + } + + @Test + public void testFloat2UNIT() { + PowerMock.mockStatic(ScreenResolution.class); + EasyMock.expect(ScreenResolution.getScreenResolution()).andReturn(96).once(); + PowerMock.replayAll(); + PXReportLengthUNIT pxReportLengthUNIT = new PXReportLengthUNIT(); + Assert.assertEquals(457200L, pxReportLengthUNIT.float2UNIT(12.0F).toFU()); + } +} diff --git a/designer-form/src/test/java/com/fr/design/fit/PXTest.java b/designer-form/src/test/java/com/fr/design/fit/PXTest.java new file mode 100644 index 000000000..4db3e5e0a --- /dev/null +++ b/designer-form/src/test/java/com/fr/design/fit/PXTest.java @@ -0,0 +1,64 @@ +package com.fr.design.fit; + +import com.fr.base.ScreenResolution; +import com.fr.invoke.Reflect; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.math.BigDecimal; + +/** + * Created by kerry on 2020-04-26 + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest(ScreenResolution.class) +public class PXTest { + + @Test + public void testGetScaleNumber(){ + PowerMock.mockStatic(ScreenResolution.class); + EasyMock.expect(ScreenResolution.getScreenResolution()).andReturn(96).once(); + PowerMock.replayAll(); + PX px = new PX(100F); + BigDecimal scaleNumber = Reflect.on(px).call("getScaleNumber").get(); + Assert.assertEquals(100L, scaleNumber.longValue()); + } + + @Test + public void testGetMoreFUScale() { + PowerMock.mockStatic(ScreenResolution.class); + EasyMock.expect(ScreenResolution.getScreenResolution()).andReturn(96).times(2); + PowerMock.replayAll(); + PX px = new PX(100F); + long fuScale = Reflect.on(px).call("getMoreFUScale").get(); + Assert.assertEquals(381L, fuScale); + } + + @Test + public void testToPixI(){ + PowerMock.mockStatic(ScreenResolution.class); + EasyMock.expect(ScreenResolution.getScreenResolution()).andReturn(96).times(2); + PowerMock.replayAll(); + PX px = new PX(100F); + Assert.assertEquals(100, px.toPixI(96)); + + px = new PX(19.5F); + Assert.assertEquals(19.5F, px.toPixF(96), 0.0F); + } + + @Test + public void testToPixWithResolution(){ + Assert.assertEquals(100D, PX.toPixWithResolution(100D, 96), 0.0D); + + Assert.assertEquals(19.5D, PX.toPixWithResolution(19.5D, 96), 0.0D); + + Assert.assertEquals(150D, PX.toPixWithResolution(100D, 144), 0.0D); + + Assert.assertEquals(29.25D, PX.toPixWithResolution(19.5D, 144), 0.0D); + } +} diff --git a/designer-form/src/test/java/com/fr/design/fit/common/FormDesignerUtilTest.java b/designer-form/src/test/java/com/fr/design/fit/common/FormDesignerUtilTest.java new file mode 100644 index 000000000..786d45d91 --- /dev/null +++ b/designer-form/src/test/java/com/fr/design/fit/common/FormDesignerUtilTest.java @@ -0,0 +1,38 @@ +package com.fr.design.fit.common; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by kerry on 2020-06-12 + */ +public class FormDesignerUtilTest { + + @Test + public void testRemoveDeletedEC(){ + List list1 = new ArrayList(); + List list2 = new ArrayList(); + list2.add("test2"); + list2.add("test3"); + list2.add("test4"); + FormDesignerUtil.removeDeletedEC(list1, list2); + Assert.assertEquals(0, list2.size()); + + list1.add("test1"); + list1.add("test3"); + list2.add("test2"); + list2.add("test3"); + list2.add("test4"); + FormDesignerUtil.removeDeletedEC(list1, list2); + Assert.assertEquals(1, list2.size()); + Assert.assertEquals("test3", list2.get(0)); + + list1.remove("test3"); + FormDesignerUtil.removeDeletedEC(list1, list2); + Assert.assertEquals(0, list2.size()); + + } +} diff --git a/designer-form/src/test/java/com/fr/design/mainframe/template/info/JFormProcessInfoTest.java b/designer-form/src/test/java/com/fr/design/mainframe/template/info/JFormProcessInfoTest.java index 04327d354..be4c9cd7a 100644 --- a/designer-form/src/test/java/com/fr/design/mainframe/template/info/JFormProcessInfoTest.java +++ b/designer-form/src/test/java/com/fr/design/mainframe/template/info/JFormProcessInfoTest.java @@ -2,6 +2,7 @@ package com.fr.design.mainframe.template.info; import com.fr.base.background.ColorBackground; import com.fr.chart.chartattr.ChartCollection; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.form.main.Form; import com.fr.form.ui.CardSwitchButton; import com.fr.form.ui.ChartEditor; @@ -41,11 +42,11 @@ public class JFormProcessInfoTest { boolean result = Reflect.on(jFormProcessInfo).call("hasTestECReport").get(); Assert.assertTrue(result); - elementCase.addCellElement(new DefaultTemplateCellElement()); + elementCase.addCellElement(DefaultThemedTemplateCellElementCase.createInstance()); result = Reflect.on(jFormProcessInfo).call("hasTestECReport").get(); Assert.assertTrue(result); - DefaultTemplateCellElement templateCellElement = new DefaultTemplateCellElement(); + DefaultTemplateCellElement templateCellElement = DefaultThemedTemplateCellElementCase.createInstance(); templateCellElement.setValue(123); elementCase.addCellElement(templateCellElement); diff --git a/designer-form/src/test/java/com/fr/design/preview/DeveloperPreviewTest.java b/designer-form/src/test/java/com/fr/design/preview/DeveloperPreviewTest.java new file mode 100644 index 000000000..624e34e59 --- /dev/null +++ b/designer-form/src/test/java/com/fr/design/preview/DeveloperPreviewTest.java @@ -0,0 +1,28 @@ +package com.fr.design.preview; + +import com.fr.design.mainframe.JForm; +import com.fr.general.web.ParameterConstants; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Map; + +/** + * Created by kerry on 2020-04-24 + */ +public class DeveloperPreviewTest { + @Test + public void testParametersForPreview() { + DeveloperPreview formPreview = new DeveloperPreview(); + Map map = formPreview.parametersForPreview(); + Assert.assertEquals(1, map.size()); + Assert.assertEquals("developer_preview", map.get(ParameterConstants.OP)); + } + + @Test + public void testAccept() { + DeveloperPreview formPreview = new DeveloperPreview(); + Assert.assertTrue(formPreview.accept(EasyMock.mock(JForm.class))); + } +} diff --git a/designer-form/src/test/java/com/fr/design/preview/FormAdaptivePreviewTest.java b/designer-form/src/test/java/com/fr/design/preview/FormAdaptivePreviewTest.java new file mode 100644 index 000000000..4972568b4 --- /dev/null +++ b/designer-form/src/test/java/com/fr/design/preview/FormAdaptivePreviewTest.java @@ -0,0 +1,28 @@ +package com.fr.design.preview; + +import com.fr.design.mainframe.JForm; +import com.fr.general.web.ParameterConstants; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Map; + +/** + * Created by kerry on 2020-04-24 + */ +public class FormAdaptivePreviewTest { + @Test + public void testParametersForPreview() { + FormAdaptivePreview formPreview = new FormAdaptivePreview(); + Map map = formPreview.parametersForPreview(); + Assert.assertEquals(1, map.size()); + Assert.assertEquals("form_adaptive", map.get(ParameterConstants.OP)); + } + + @Test + public void testAccept() { + FormAdaptivePreview formPreview = new FormAdaptivePreview(); + Assert.assertTrue(formPreview.accept(EasyMock.mock(JForm.class))); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/actions/cell/AbstractCellElementAction.java b/designer-realize/src/main/java/com/fr/design/actions/cell/AbstractCellElementAction.java index 87c423d99..e4108e6d2 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/cell/AbstractCellElementAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/cell/AbstractCellElementAction.java @@ -6,9 +6,9 @@ import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.grid.GridUtils; import com.fr.grid.selection.CellSelection; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.core.SheetUtils; import com.fr.report.elementcase.TemplateElementCase; @@ -35,7 +35,7 @@ public abstract class AbstractCellElementAction extends CellSelectionAction { final TemplateElementCase tplEC = ePane.getEditingElementCase(); TemplateCellElement editCellElement = tplEC.getTemplateCellElement(cs.getColumn(), cs.getRow()); if (editCellElement == null) { - editCellElement = new DefaultTemplateCellElement(cs.getColumn(), cs.getRow()); + editCellElement = DefaultThemedTemplateCellElementCase.createInstance(cs.getColumn(), cs.getRow()); tplEC.addCellElement(editCellElement); } SheetUtils.calculateDefaultParent(tplEC); @@ -52,7 +52,7 @@ public abstract class AbstractCellElementAction extends CellSelectionAction { int row = j + finalCS.getRow(); TemplateCellElement editCellElement = tplEC.getTemplateCellElement(column, row); if (editCellElement == null) { - editCellElement = new DefaultTemplateCellElement(column, row); + editCellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); tplEC.addCellElement(editCellElement); } // alex:不加这一句话会导致跨行跨列的格子被多次update diff --git a/designer-realize/src/main/java/com/fr/design/actions/cell/CellStyleAttrAction.java b/designer-realize/src/main/java/com/fr/design/actions/cell/CellStyleAttrAction.java new file mode 100644 index 000000000..a257ea95d --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/actions/cell/CellStyleAttrAction.java @@ -0,0 +1,26 @@ +package com.fr.design.actions.cell; + +import com.fr.base.BaseUtils; +import com.fr.design.i18n.Toolkit; +import com.fr.design.menu.KeySetUtils; +import com.fr.general.IOUtils; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/26 + */ +public class CellStyleAttrAction extends CellAttributeTableAction { + + public CellStyleAttrAction() { + this.setMenuKeySet(KeySetUtils.GLOBAL_STYLE); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(IOUtils.readIcon("/com/fr/design/images/m_format/cell.png")); + } + + @Override + protected String getID() { + return Toolkit.i18nText("Fine-Design_Form_Widget_Style"); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/actions/cell/CustomCellStyleAction.java b/designer-realize/src/main/java/com/fr/design/actions/cell/CustomCellStyleAction.java new file mode 100644 index 000000000..db34cea32 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/actions/cell/CustomCellStyleAction.java @@ -0,0 +1,22 @@ +package com.fr.design.actions.cell; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.CellElementPropertyPane; + +import java.awt.event.ActionEvent; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/8/26 + */ +public class CustomCellStyleAction extends CellStyleAttrAction { + + @Override + public void actionPerformed(ActionEvent e) { + CellElementPropertyPane.getInstance().GoToPane( + Toolkit.i18nText("Fine-Design_Report_Engine_Style"), + Toolkit.i18nText("Fine-Design_Report_Engine_Custom") + ); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/actions/cell/GlobalStyleMenuDef.java b/designer-realize/src/main/java/com/fr/design/actions/cell/GlobalStyleMenuDef.java index 4699ab886..f72e708d3 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/cell/GlobalStyleMenuDef.java +++ b/designer-realize/src/main/java/com/fr/design/actions/cell/GlobalStyleMenuDef.java @@ -6,24 +6,35 @@ package com.fr.design.actions.cell; import com.fr.base.BaseUtils; import com.fr.base.NameStyle; -import com.fr.config.ServerPreferenceConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.settings.ThemedCellStyle; import com.fr.design.actions.SelectionListenerAction; import com.fr.design.actions.UpdateAction; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.imenu.UIMenu; import com.fr.design.mainframe.CellElementPropertyPane; import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.JTemplate; import com.fr.design.menu.KeySetUtils; import com.fr.design.menu.MenuDef; import com.fr.design.selection.SelectionListener; import com.fr.design.style.StylePane; - import com.fr.stable.StringUtils; import com.fr.stable.pinyin.PinyinHelper; -import java.awt.*; -import java.awt.event.*; -import java.util.Iterator; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.util.List; +/** + * 11.beta.1 + * REPORT-51919 主题切换 + * REPORT-58062 【主题切换】细节定制-单元格样式-样式数量较多,菜单栏中选择时没有滚动条 + * 模版主题化后,该菜单列表废弃,点击工具栏-单元格-样式菜单将直接跳转到右侧栏单元格样式面板 + * @deprecated + */ public class GlobalStyleMenuDef extends MenuDef { private static final int MAX_LENTH = 12; private ElementCasePane ePane; @@ -72,10 +83,12 @@ public class GlobalStyleMenuDef extends MenuDef { public void updateMenu() { UIMenu createdMenu = this.createJMenu(); createdMenu.removeAll(); - Iterator iterator = ServerPreferenceConfig.getInstance().getStyleNameIterator(); - while (iterator.hasNext()) { - String name = (String) iterator.next(); - NameStyle nameStyle = NameStyle.getInstance(name); + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + TemplateTheme theme = template.getTemplateTheme(); + List themedCellStyleList = theme.getCellStyleList().getCellStyleList(); + for (ThemedCellStyle themedCellStyle: themedCellStyleList) { + String name = themedCellStyle.getName(); + NameStyle nameStyle = NameStyle.getPassiveInstance(name, themedCellStyle.getStyle()); UpdateAction.UseMenuItem useMenuItem =new GlobalStyleSelection(ePane, nameStyle).createUseMenuItem(); useMenuItem.setNameStyle(nameStyle); createdMenu.add(useMenuItem); diff --git a/designer-realize/src/main/java/com/fr/design/actions/cell/NewPresentAction.java b/designer-realize/src/main/java/com/fr/design/actions/cell/NewPresentAction.java index 66870ff6f..786910a02 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/cell/NewPresentAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/cell/NewPresentAction.java @@ -4,12 +4,12 @@ import com.fr.base.present.Present; import com.fr.design.actions.PresentCheckBoxAction; import com.fr.design.mainframe.CellElementPropertyPane; import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralUtils; import com.fr.grid.selection.CellSelection; import com.fr.grid.selection.Selection; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.elementcase.TemplateElementCase; import com.fr.stable.StableUtils; @@ -46,7 +46,7 @@ public class NewPresentAction extends PresentCheckBoxAction { int row = j + cellRectangle.y; TemplateCellElement cellElement = elementCase.getTemplateCellElement(column, row); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(column, row); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); elementCase.addCellElement(cellElement); } else if (cellElement.getPresent() != null) { cellElement.setPresent(null); diff --git a/designer-realize/src/main/java/com/fr/design/actions/cell/StyleAction.java b/designer-realize/src/main/java/com/fr/design/actions/cell/StyleAction.java index 1f77f9b93..707779c82 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/cell/StyleAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/cell/StyleAction.java @@ -12,6 +12,11 @@ import com.fr.design.mainframe.CellElementPropertyPane; import com.fr.design.menu.KeySetUtils; +/** + * 11.beta.1 + * REPORT-51919 主题切换 + * @deprecated + */ public class StyleAction extends UpdateAction { public StyleAction() { diff --git a/designer-realize/src/main/java/com/fr/design/actions/columnrow/ColumnRowSizingAction.java b/designer-realize/src/main/java/com/fr/design/actions/columnrow/ColumnRowSizingAction.java index 0903323b8..794f1febb 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/columnrow/ColumnRowSizingAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/columnrow/ColumnRowSizingAction.java @@ -4,6 +4,7 @@ package com.fr.design.actions.columnrow; import com.fr.design.DesignerEnvManager; +import com.fr.design.fit.DesignerUIModeConfig; import com.fr.design.fun.ReportLengthUNITProvider; import com.fr.design.gui.frpane.UnitInputPane; import com.fr.design.gui.frpane.UnitInputPane.ValueNotChangeException; @@ -11,8 +12,6 @@ import com.fr.design.mainframe.DesignerContext; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.mainframe.ElementCasePane; -import com.fr.design.fun.ReportLengthUNITProvider; -import com.fr.design.unit.UnitConvertUtil; import com.fr.general.ComparatorUtils; import com.fr.grid.selection.CellSelection; import com.fr.report.elementcase.ElementCase; @@ -51,7 +50,7 @@ public abstract class ColumnRowSizingAction extends AbstractColumnRowIndexAction try { float newHeight = (float) uPane.update(); int unitType = DesignerEnvManager.getEnvManager().getReportLengthUnit(); - ReportLengthUNITProvider lengthUNIT = UnitConvertUtil.parseLengthUNIT(unitType); + ReportLengthUNITProvider lengthUNIT = DesignerUIModeConfig.getInstance().parseLengthUNIT(unitType); UNIT newLen = lengthUNIT.float2UNIT(newHeight); if (!ComparatorUtils.equals(oldLen, newLen)) { updateAction(report, newLen, finalCS); @@ -68,7 +67,7 @@ public abstract class ColumnRowSizingAction extends AbstractColumnRowIndexAction protected void populateNumberDialog(final UnitInputPane uPane, UNIT unit) { int unitType = DesignerEnvManager.getEnvManager().getReportLengthUnit(); - ReportLengthUNITProvider lengthUNIT = UnitConvertUtil.parseLengthUNIT(unitType); + ReportLengthUNITProvider lengthUNIT = DesignerUIModeConfig.getInstance().parseLengthUNIT(unitType); float va = lengthUNIT.unit2Value4Scale(unit); uPane.setUnitText(lengthUNIT.unitText()); uPane.populate(va); diff --git a/designer-realize/src/main/java/com/fr/design/actions/columnrow/DSColumnBasicAction.java b/designer-realize/src/main/java/com/fr/design/actions/columnrow/DSColumnBasicAction.java index ddd10ad55..dda5faa86 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/columnrow/DSColumnBasicAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/columnrow/DSColumnBasicAction.java @@ -9,8 +9,8 @@ import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.grid.selection.CellSelection; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.core.SheetUtils; import com.fr.report.elementcase.TemplateElementCase; @@ -61,7 +61,7 @@ public class DSColumnBasicAction extends CellSelectionAction { editCellElement = report.getTemplateCellElement(column, row); if (editCellElement == null) { - editCellElement = new DefaultTemplateCellElement(column, row); + editCellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); report.addCellElement(editCellElement); } // update cell attributes diff --git a/designer-realize/src/main/java/com/fr/design/actions/insert/cell/GeneralCellAction.java b/designer-realize/src/main/java/com/fr/design/actions/insert/cell/GeneralCellAction.java index ae805e027..758c4e335 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/insert/cell/GeneralCellAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/insert/cell/GeneralCellAction.java @@ -10,6 +10,7 @@ import com.fr.design.menu.MenuKeySet; import javax.swing.*; +import java.awt.event.ActionEvent; /** * @@ -52,4 +53,11 @@ public class GeneralCellAction extends AbstractCellAction implements WorkBookSup public Class getCellValueClass() { return String.class; } + + @Override + public void actionPerformed(ActionEvent evt) { + super.actionPerformed(evt); + this.getEditingComponent().getGrid().getCellEditor().stopCellEditing(); + } + } diff --git a/designer-realize/src/main/java/com/fr/design/actions/insert/flot/ChartFloatAction.java b/designer-realize/src/main/java/com/fr/design/actions/insert/flot/ChartFloatAction.java index 67fcaae59..58292bbf2 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/insert/flot/ChartFloatAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/insert/flot/ChartFloatAction.java @@ -13,6 +13,7 @@ import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.gui.chart.MiddleChartDialog; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.theme.utils.DefaultThemedFloatElement; import com.fr.design.menu.MenuKeySet; import com.fr.design.module.DesignModuleFactory; import com.fr.grid.Grid; @@ -90,7 +91,7 @@ public class ChartFloatAction extends ElementCaseAction { public void doOk() { isRecordNeeded = true; FloatElement newFloatElement; - newFloatElement = new FloatElement(chartDialog.getChartCollection()); + newFloatElement = DefaultThemedFloatElement.createInstance(chartDialog.getChartCollection()); newFloatElement.setWidth(new OLDPIX(BaseChartCollection.CHART_DEFAULT_WIDTH)); newFloatElement.setHeight(new OLDPIX(BaseChartCollection.CHART_DEFAULT_HEIGHT)); diff --git a/designer-realize/src/main/java/com/fr/design/actions/insert/flot/FormulaFloatAction.java b/designer-realize/src/main/java/com/fr/design/actions/insert/flot/FormulaFloatAction.java index e61494581..0251bf3d8 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/insert/flot/FormulaFloatAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/insert/flot/FormulaFloatAction.java @@ -13,6 +13,7 @@ import com.fr.design.formula.FormulaFactory; import com.fr.design.formula.UIFormula; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.theme.utils.DefaultThemedFloatElement; import com.fr.design.menu.MenuKeySet; import com.fr.design.utils.gui.AdjustWorkBookDefaultStyleUtils; import com.fr.grid.Grid; @@ -98,7 +99,7 @@ public class FormulaFloatAction extends ElementCaseAction { } reportPane.stopEditing(); - final FloatElement floatElement = new FloatElement(); + final FloatElement floatElement = DefaultThemedFloatElement.createInstance(); AdjustWorkBookDefaultStyleUtils.adjustFloatElement(floatElement); final UIFormula formulaPane = FormulaFactory.createFormulaPane(); formulaPane.populate(BaseFormula.createFormulaBuilder().build()); diff --git a/designer-realize/src/main/java/com/fr/design/actions/insert/flot/ImageFloatAction.java b/designer-realize/src/main/java/com/fr/design/actions/insert/flot/ImageFloatAction.java index e514c88df..7eb9146ea 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/insert/flot/ImageFloatAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/insert/flot/ImageFloatAction.java @@ -12,6 +12,7 @@ import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.ElementCasePane; import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.theme.utils.DefaultThemedFloatElement; import com.fr.design.menu.MenuKeySet; import com.fr.design.report.SelectImagePane; @@ -73,7 +74,7 @@ public class ImageFloatAction extends ElementCaseAction { reportPane.stopEditing(); - final FloatElement floatElement = new FloatElement(); + final FloatElement floatElement = DefaultThemedFloatElement.createInstance(); final SelectImagePane selectImagePane = new SelectImagePane(); selectImagePane.populate(floatElement); diff --git a/designer-realize/src/main/java/com/fr/design/actions/insert/flot/TextBoxFloatAction.java b/designer-realize/src/main/java/com/fr/design/actions/insert/flot/TextBoxFloatAction.java index 4496aeb25..32723cffa 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/insert/flot/TextBoxFloatAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/insert/flot/TextBoxFloatAction.java @@ -6,6 +6,7 @@ package com.fr.design.actions.insert.flot; import com.fr.base.DynamicUnitList; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.theme.utils.DefaultThemedFloatElement; import com.fr.design.menu.MenuKeySet; import com.fr.design.utils.gui.AdjustWorkBookDefaultStyleUtils; import com.fr.grid.Grid; @@ -59,7 +60,7 @@ public class TextBoxFloatAction extends AbstractShapeAction { if (jws == null) { return; } - FloatElement floatElement = new FloatElement("Text"); + FloatElement floatElement = DefaultThemedFloatElement.createInstance("Text"); AdjustWorkBookDefaultStyleUtils.adjustFloatElement(floatElement); this.startDraw(floatElement); doWithDrawingFloatElement(); diff --git a/designer-realize/src/main/java/com/fr/design/actions/report/ReportBackgroundAction.java b/designer-realize/src/main/java/com/fr/design/actions/report/ReportBackgroundAction.java index fa4055807..481d2e094 100644 --- a/designer-realize/src/main/java/com/fr/design/actions/report/ReportBackgroundAction.java +++ b/designer-realize/src/main/java/com/fr/design/actions/report/ReportBackgroundAction.java @@ -4,14 +4,15 @@ package com.fr.design.actions.report; -import com.fr.base.svg.IconUtils; import com.fr.design.actions.ReportComponentAction; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.ReportComponent; import com.fr.design.menu.KeySetUtils; -import com.fr.design.report.ReportBackgroundPane; -import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.report.NewReportBackgroundPane; import com.fr.report.core.ReportUtils; +import com.fr.report.report.Report; /** * Background action. @@ -35,16 +36,16 @@ public class ReportBackgroundAction extends ReportComponentAction= 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..9a2601aee --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/fit/grid/NewFormDesignerGridUI.java @@ -0,0 +1,201 @@ +package com.fr.design.fit.grid; + +import com.fr.design.designer.creator.XElementCase; +import com.fr.design.fit.AdaptiveCellElementPainter; +import com.fr.design.fit.DesignerUIModeConfig; +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 = getScaleWidth(rectangle.width) - columnWidthList.getRangeValue(0, horizontalValue).toPixI(resolution); + int height = getScaleHeight(rectangle.height) - rowHeightList.getRangeValue(0, verticalValue).toPixI(resolution); + drawBoundsLine(g2d, width, height); + addListener(grid, elementCasePane, width, height, rectangle.width, rectangle.height); + } + + private int getScaleWidth(int width) { + return width * resolution / DesignerUIModeConfig.getInstance().getScreenResolution(); + + } + + private int getScaleHeight(int height) { + return height * resolution / DesignerUIModeConfig.getInstance().getScreenResolution(); + } + + + /** + * 获取需要画线的矩形大小 + */ + 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/javascript/ListenerEditPane.java b/designer-realize/src/main/java/com/fr/design/javascript/ListenerEditPane.java index 914b389a5..095d011f7 100644 --- a/designer-realize/src/main/java/com/fr/design/javascript/ListenerEditPane.java +++ b/designer-realize/src/main/java/com/fr/design/javascript/ListenerEditPane.java @@ -7,6 +7,7 @@ import com.fr.design.fun.JavaScriptActionProvider; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.hyperlink.popup.MobilePopupPane; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; @@ -43,6 +44,7 @@ public class ListenerEditPane extends BasicBeanPane { private static final String CUSTOMACTION = Toolkit.i18nText("Fine-Design_Report_Submit_Type_Custom"); private static final String EMAIL = Toolkit.i18nText("Fine-Design_Report_Email_Sent_Email"); private static final String EXPORT = Toolkit.i18nText("Fine-Design_Basic_Export_JS_Event"); + private static final String MOBILEPOPUP = Toolkit.i18nText("FR-Plugin-Designer_Mobile_Popup"); private Listener listener; @@ -68,7 +70,8 @@ public class ListenerEditPane extends BasicBeanPane { nameText = new UITextField(8); nameText.setEditable(false); namePane.add(nameText, BorderLayout.WEST); - final List style = new ArrayList<>(Arrays.asList(JS, DBCOMMIT, CUSTOMACTION, EMAIL)); + final List style = new ArrayList<>(Arrays.asList(JS, DBCOMMIT, CUSTOMACTION, EMAIL, MOBILEPOPUP)); + styleBox = new UIComboBox(style.toArray()); boolean workbook = DesignerContext.getDesignerFrame().getSelectedJTemplate().isJWorkBook(); if (workbook) { style.add(EXPORT); @@ -101,10 +104,14 @@ public class ListenerEditPane extends BasicBeanPane { // 发送邮件 EmailPane emailPane = new EmailPane(); hyperlinkPane.add(EMAIL, emailPane); + // 移动端弹窗 + MobilePopupPane mobilePopupPane = new MobilePopupPane(); + hyperlinkPane.add(MOBILEPOPUP, mobilePopupPane); cards.add(javaScriptPane); cards.add(commit2DBJavaScriptPane); cards.add(customActionPane); cards.add(emailPane); + cards.add(mobilePopupPane); // 导出事件 这里要按顺序添加 if (workbook) { ExportJavaScriptPane exportJavaScriptPane = new ExportJavaScriptPane(); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/CellElementPropertyPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/CellElementPropertyPane.java index 1716fb476..9fd6027fb 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/CellElementPropertyPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/CellElementPropertyPane.java @@ -15,6 +15,7 @@ import com.fr.design.gui.frpane.UITitlePanel; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itabpane.TitleChangeListener; import com.fr.design.mainframe.cell.CellElementEditPane; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.general.GeneralContext; import com.fr.grid.selection.CellSelection; @@ -25,7 +26,6 @@ import com.fr.plugin.injectable.PluginModule; import com.fr.plugin.manage.PluginFilter; import com.fr.plugin.observer.PluginEvent; import com.fr.plugin.observer.PluginEventListener; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.Elem; import com.fr.report.elementcase.TemplateElementCase; @@ -138,7 +138,7 @@ public class CellElementPropertyPane extends DockingView { } if (element == null) { - element = new DefaultTemplateCellElement(0, 0); + element = DefaultThemedTemplateCellElementCase.createInstance(0, 0); } return element; } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/CellWidgetPropertyPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/CellWidgetPropertyPane.java index 120c2fe3b..f0ff751f1 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/CellWidgetPropertyPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/CellWidgetPropertyPane.java @@ -4,6 +4,7 @@ import com.fr.design.actions.utils.ReportActionUtils; import com.fr.design.dialog.BasicPane; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.AdjustWorkBookDefaultStyleUtils; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.design.widget.WidgetPane; import com.fr.form.ui.NoneWidget; import com.fr.form.ui.Widget; @@ -12,7 +13,6 @@ import com.fr.grid.selection.Selection; import com.fr.log.FineLoggerFactory; import com.fr.privilege.finegrain.WidgetPrivilegeControl; import com.fr.report.cell.CellElement; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.elementcase.TemplateElementCase; @@ -60,7 +60,7 @@ public class CellWidgetPropertyPane extends BasicPane { public void populate(TemplateCellElement cellElement) { if (cellElement == null) {// 利用默认的CellElement. - cellElement = new DefaultTemplateCellElement(0, 0, null); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(0, 0, null); } Widget cellWidget = cellElement.getWidget(); @@ -89,7 +89,7 @@ public class CellWidgetPropertyPane extends BasicPane { final TemplateElementCase tplEC = ePane.getEditingElementCase(); TemplateCellElement editCellElement = tplEC.getTemplateCellElement(cs.getColumn(), cs.getRow()); if (editCellElement == null) { - editCellElement = new DefaultTemplateCellElement(cs.getColumn(), cs.getRow()); + editCellElement = DefaultThemedTemplateCellElementCase.createInstance(cs.getColumn(), cs.getRow()); AdjustWorkBookDefaultStyleUtils.adjustCellElement(editCellElement); } this.cellElement = editCellElement; 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 306aaf4ed..dbc4269d6 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,10 +67,12 @@ 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; import com.fr.design.mainframe.cell.QuickEditorRegion; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.design.menu.KeySetUtils; import com.fr.design.menu.MenuDef; import com.fr.design.menu.NameSeparator; @@ -95,7 +97,6 @@ import com.fr.page.PageAttributeGetter; import com.fr.page.ReportPageAttrProvider; import com.fr.poly.creator.PolyElementCasePane; import com.fr.report.ReportHelper; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.FloatElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.cell.cellattr.core.RichText; @@ -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(); @@ -354,10 +355,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(); @@ -568,7 +569,7 @@ public abstract class ElementCasePane extends Tar int row = j + cellRectangle.y; TemplateCellElement cellElement = elementCase.getTemplateCellElement(column, row); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(column, row); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); elementCase.addCellElement(cellElement); } Style style = cellElement.getStyle(); @@ -1378,7 +1379,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/ElementCasePaneAuthorityEditPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePaneAuthorityEditPane.java index 58b778065..54ba90ea9 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePaneAuthorityEditPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePaneAuthorityEditPane.java @@ -11,6 +11,7 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.design.mainframe.toolbar.AuthorityEditToolBarComponent; import com.fr.design.roleAuthority.ReportAndFSManagePane; import com.fr.design.roleAuthority.RolesAlreadyEditedPane; @@ -291,7 +292,7 @@ public class ElementCasePaneAuthorityEditPane extends AuthorityEditPane { int row = j + cellRectangle.y; TemplateCellElement editCellElement = elementCase.getTemplateCellElement(column, row); if (editCellElement == null) { - editCellElement = new DefaultTemplateCellElement(column, row); + editCellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); elementCase.addCellElement(editCellElement); } else { // 对于合并的格子,我们不多次计算的权限. @@ -371,7 +372,7 @@ public class ElementCasePaneAuthorityEditPane extends AuthorityEditPane { Rectangle cellRectangle = cellSelection.getCellRectangle(0); DefaultTemplateCellElement cellElement = (DefaultTemplateCellElement) elementCase.getCellElement(cellRectangle.x, cellRectangle.y); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(cellRectangle.x, cellRectangle.y); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(cellRectangle.x, cellRectangle.y); } boolean firstCellDoneaAuthority = cellElement.isDoneAuthority( ReportAndFSManagePane.getInstance().getRoleTree().getSelectedRoleName()); @@ -507,7 +508,7 @@ public class ElementCasePaneAuthorityEditPane extends AuthorityEditPane { int row = j + cellRectangle.y; DefaultTemplateCellElement cellElement = (DefaultTemplateCellElement) elementCase.getCellElement(column, row); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(cellSelection.getColumn(), cellSelection.getRow()); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(cellSelection.getColumn(), cellSelection.getRow()); } if (cellElement.getCellWidgetAttr() == null) { isAllHasWidget = false; @@ -562,7 +563,7 @@ public class ElementCasePaneAuthorityEditPane extends AuthorityEditPane { final TemplateElementCase elementCase = elementCasePane.getEditingElementCase(); DefaultTemplateCellElement cellElement = (DefaultTemplateCellElement) elementCase.getCellElement(cellSelection.getColumn(), cellSelection.getRow()); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(cellSelection.getColumn(), cellSelection.getRow()); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(cellSelection.getColumn(), cellSelection.getRow()); } //单元格带控件 if (cellElement.getCellWidgetAttr() != null) { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePaneDelegate.java b/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePaneDelegate.java index 79b5c8dc5..5cc095cfa 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePaneDelegate.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePaneDelegate.java @@ -5,9 +5,9 @@ import com.fr.design.DesignState; import com.fr.design.actions.UpdateAction; import com.fr.design.actions.cell.CellAttributeAction; import com.fr.design.actions.cell.CellExpandAttrAction; +import com.fr.design.actions.cell.CellStyleAttrAction; import com.fr.design.actions.cell.CellWidgetAttrAction; import com.fr.design.actions.cell.ConditionAttributesAction; -import com.fr.design.actions.cell.GlobalStyleMenuDef; import com.fr.design.actions.columnrow.InsertColumnAction; import com.fr.design.actions.columnrow.InsertRowAction; import com.fr.design.actions.core.ActionFactory; @@ -201,7 +201,7 @@ public class ElementCasePaneDelegate extends ElementCasePane { MenuDef menuDef = new MenuDef(KeySetUtils.CELL.getMenuKeySetName(), KeySetUtils.CELL.getMnemonic()); menuDef.addShortCut(new CellExpandAttrAction()); - menuDef.addShortCut(new GlobalStyleMenuDef(this)); + menuDef.addShortCut(new CellStyleAttrAction()); // 单元格形态 menuDef.addShortCut(DeprecatedActionManager.getPresentMenu(this)); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/FormatBrushAction.java b/designer-realize/src/main/java/com/fr/design/mainframe/FormatBrushAction.java index 9b89864b6..1256c7664 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/FormatBrushAction.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/FormatBrushAction.java @@ -4,9 +4,9 @@ import com.fr.base.Style; import com.fr.design.actions.ElementCaseAction; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.grid.selection.CellSelection; import com.fr.grid.selection.Selection; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.elementcase.TemplateElementCase; @@ -129,7 +129,7 @@ public class FormatBrushAction extends ElementCaseAction { int row = j + cs.getRow(); TemplateCellElement cellElement = elementCase.getTemplateCellElement(column, row); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(column, row); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); elementCase.addCellElement(cellElement); } cellElement.setStyle(referencedStyle[i % columnSpan][j % rowSpan]); @@ -152,7 +152,7 @@ public class FormatBrushAction extends ElementCaseAction { int row = j + cellRectangle.y; TemplateCellElement cellElement = elementCase.getTemplateCellElement(column, row); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(column, row); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); elementCase.addCellElement(cellElement); } Style style = cellElement.getStyle(); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java b/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java index c901562eb..faf5e6d14 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java @@ -5,7 +5,13 @@ import com.fr.base.DynamicUnitList; import com.fr.base.Parameter; import com.fr.base.ScreenResolution; import com.fr.base.extension.FileExtension; +import com.fr.base.theme.FormTheme; +import com.fr.base.theme.TemplateThemeCompatible; import com.fr.base.vcs.DesignerMode; +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.ReportThemeConfig; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeConfig; import com.fr.design.DesignModelAdapter; import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.AllowAuthorityEditAction; @@ -31,6 +37,7 @@ import com.fr.design.constants.UIConstants; import com.fr.design.data.datapane.TableDataTreePane; import com.fr.design.designer.TargetComponent; import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.MutilTempalteTabPane; import com.fr.design.fun.PreviewProvider; @@ -45,6 +52,7 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.cell.QuickEditorRegion; import com.fr.design.mainframe.template.info.JWorkBookProcessInfo; import com.fr.design.mainframe.template.info.TemplateProcessInfo; +import com.fr.design.mainframe.theme.dialog.TemplateThemeUsingDialog; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.menu.KeySetUtils; import com.fr.design.menu.MenuDef; @@ -57,7 +65,6 @@ import com.fr.design.parameter.ParameterInputPane; import com.fr.design.preview.MobilePreview; import com.fr.design.preview.PagePreview; import com.fr.design.preview.ViewPreview; -import com.fr.design.preview.WriteEnhancePreview; import com.fr.design.preview.WritePreview; import com.fr.design.report.fit.menupane.ReportFitAttrAction; import com.fr.design.roleAuthority.ReportAndFSManagePane; @@ -145,6 +152,7 @@ public class JWorkBook extends JTemplate { super(workBook, fileName); populateReportParameterAttr(); } + public JWorkBook(WorkBook workBook, FILE file, Parameter[] parameters) { super(workBook, file, parameters); populateReportParameterAttr(); @@ -217,6 +225,20 @@ public class JWorkBook extends JTemplate { return DesignModeContext.isDuchampMode() ? reportComposite : centerPane; } + @Override + protected UIButton createTemplateThemeButton() { + UIButton button = super.createTemplateThemeButton(); + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + TemplateThemeUsingDialog dialog = new TemplateThemeUsingDialog<>(designerFrame, JWorkBook.this, ReportThemeConfig.getInstance()); + dialog.setVisible(true); + } + }); + return button; + } + @Override public TemplateProcessInfo getProcessInfo() { if (processInfo == null) { @@ -489,7 +511,7 @@ public class JWorkBook extends JTemplate { double creatorWidth = blockCreator.getEditorBounds().width; double areaHeight = polyDezi.polyArea.getHeight(); double areaWidth = polyDezi.polyArea.getWidth(); - if(AssistUtils.equals(creatorWidth,0) || AssistUtils.equals(creatorHeight,0)){ + if (AssistUtils.equals(creatorWidth, 0) || AssistUtils.equals(creatorHeight, 0)) { return resolution; } double time = (areaHeight / creatorHeight) < (areaWidth / creatorWidth) ? (areaHeight / creatorHeight) : (areaWidth / creatorWidth); @@ -506,7 +528,7 @@ public class JWorkBook extends JTemplate { int row = reportPane.getSelection().getSelectedRows()[0]; double rowLength = reportPane.getSelection().getSelectedRows().length; double rowExtent = reportPane.getGrid().getVerticalExtent(); - if(AssistUtils.equals(columnLength,0) || AssistUtils.equals(rowLength,0)){ + if (AssistUtils.equals(columnLength, 0) || AssistUtils.equals(rowLength, 0)) { return resolution; } double time = (columnExtent / columnLength) < (rowExtent / rowLength) ? (columnExtent / columnLength) : (rowExtent / rowLength); @@ -753,7 +775,9 @@ public class JWorkBook extends JTemplate { @Override protected void applyUndoState(WorkBookUndoState u) { try { - this.setTarget((WorkBook) u.getWorkBook().clone()); + WorkBook undoWorkBook = (WorkBook) u.getWorkBook().clone(); + undoWorkBook.checkAndResetTheme(); + this.setTarget(undoWorkBook); if (!DesignerMode.isAuthorityEditing()) { if (u.getAuthorityType() != BaseUndoState.NORMAL_STATE) { applyAll(u); @@ -929,7 +953,7 @@ public class JWorkBook extends JTemplate { public PreviewProvider[] supportPreview() { PreviewProvider[] templatePreviews = super.supportPreview(); return ArrayUtils.addAll(new PreviewProvider[]{ - new PagePreview(), new WritePreview(), new ViewPreview(), new WriteEnhancePreview(), new MobilePreview() + new PagePreview(), new WritePreview(), new ViewPreview(), new MobilePreview() }, templatePreviews); } @@ -1208,10 +1232,11 @@ public class JWorkBook extends JTemplate { protected void addChooseFILEFilter(FILEChooserPane fileChooser) { String appName = ProductConstants.APP_NAME; fileChooser.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPT, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); + fileChooser.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPTX, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); addExtraChooseFILEFilter(fileChooser); } - protected void addExtraChooseFILEFilter(FILEChooserPane fileChooser){ + protected void addExtraChooseFILEFilter(FILEChooserPane fileChooser) { Set providers = ExtraDesignClassManager.getInstance().getArray(ReportSupportedFileUIProvider.XML_TAG); for (ReportSupportedFileUIProvider provider : providers) { provider.addChooseFileFilter(fileChooser, this.suffix()); @@ -1246,4 +1271,38 @@ public class JWorkBook extends JTemplate { designer.repaint(); } } + + @Override + protected void setUpTheme4NewTemplate() { + super.setUpTheme4NewTemplate(); + getTarget().setTemplateTheme(getTarget().getTemplateTheme()); + } + + + @Override + public TemplateThemeConfig getUsingTemplateThemeConfig() { + return getTarget().getUsingTemplateThemeConfig(); + } + + @Override + public ReportTheme getTemplateTheme() { + return getTarget().getTemplateTheme(); + } + + @Override + public void setTemplateTheme(TemplateTheme newTheme, TemplateThemeCompatible compatible) { + ReportTheme oldTheme = getTarget().getTemplateTheme(); + boolean shouldCreateUndoState = compatible == TemplateThemeCompatible.NONE && !StringUtils.equals(oldTheme.getName(), newTheme.getName()); + + getTarget().setTemplateTheme(newTheme, compatible); + + if (HistoryTemplateListCache.getInstance().getCurrentEditingTemplate() == this) { + fireTargetModified(shouldCreateUndoState); + reportComposite.setSelectedIndex(reportComposite.getSelectedIndex()); + TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).refreshDockingView(); + DesignerContext.getDesignerFrame().resetToolkitByPlus(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate()); + } + + super.setTemplateTheme(newTheme, compatible); + } } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/SheetNameTabPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/SheetNameTabPane.java index 7b6fbff6f..f2bf5e585 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/SheetNameTabPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/SheetNameTabPane.java @@ -26,6 +26,9 @@ import com.fr.base.BaseUtils; import com.fr.base.GraphHelper; import com.fr.base.svg.IconUtils; +import com.fr.base.theme.ReportTheme; +import com.fr.base.theme.TemplateTheme; +import com.fr.base.theme.TemplateThemeCompatible; import com.fr.base.vcs.DesignerMode; import com.fr.design.actions.UpdateAction; import com.fr.design.constants.UIConstants; @@ -807,7 +810,15 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse scrollIndex++; } - reportComposite.getEditingWorkBook().addReport(insertPos, newTemplateReport()); + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + TemplateTheme theme = template.getTemplateTheme(); + + TemplateReport templateReport = newTemplateReport(); + if (theme instanceof ReportTheme) { + templateReport.onTemplateUsingThemeChange((ReportTheme) theme, TemplateThemeCompatible.NONE); + } + + reportComposite.getEditingWorkBook().addReport(insertPos, templateReport); setSelectedIndex(insertPos); // sheet名字的公式也需要做相应的变化. diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/app/CptApp.java b/designer-realize/src/main/java/com/fr/design/mainframe/app/CptApp.java index 431b401fc..62134c121 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/app/CptApp.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/app/CptApp.java @@ -45,7 +45,12 @@ class CptApp extends AbstractWorkBookApp { @Override public WorkBook asIOFile(FILE file) { - return asIOFile(file, true); + // 11.beta.1 + // REPORT-51919 主题切换 + // REPORT-57943 【主题切换】10.0自定义的预定义样式,模板放11.0上,配置丢失 + // 11.beta.1 模版主题功能后,预定义单元格样式功能废弃,所有预定义单元格样式将被统一放置到"兼容主题"中, + // 对于本地不存在的预定义单元格样式,将会被设置为兼容主题中默认单元格样式,因此这里不需要再执行检查 + return asIOFile(file, false); } @Override diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppActivator.java b/designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppActivator.java index e4038ab42..e09796201 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppActivator.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppActivator.java @@ -4,6 +4,7 @@ import com.fr.design.mainframe.App; import com.fr.design.mainframe.JTemplateFactory; import com.fr.module.Activator; import com.fr.module.extension.Prepare; +import com.fr.nx.app.designer.CptxApp; import java.util.List; @@ -35,7 +36,7 @@ public class DesignerAppActivator extends Activator implements Prepare { @Override public void prepare() { - addMutable(App.KEY, new CptApp(), new FormApp(), new XlsApp(), new XlsxApp()); + addMutable(App.KEY, new CptApp(), new CptxApp(), new FormApp(), new XlsApp(), new XlsxApp()); } } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppUtils.java b/designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppUtils.java index 437458c9a..218ee4728 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppUtils.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppUtils.java @@ -27,6 +27,7 @@ import com.fr.third.guava.cache.CacheBuilder; import com.fr.third.guava.collect.Multimap; import com.fr.workspace.WorkContext; +import javax.swing.SwingUtilities; import java.time.Duration; import java.util.Collection; import java.util.Map; @@ -183,7 +184,7 @@ public class DesignerAppUtils { // 试图获取多行读取错误提示并缓存待处理列表 String detail = dealWithErrorDetailMultiLineAndCache(path); if (detail.length() > 0) { - UIUtil.invokeLaterIfNeeded(() -> { + SwingUtilities.invokeLater(() -> { if (WorkContext.getCurrent().isLocal()) { UIExpandDialog.Builder() .owner(DesignerContext.getDesignerFrame()) diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/CellElementEditPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/CellElementEditPane.java index 1792cbe02..4205ea152 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/CellElementEditPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/CellElementEditPane.java @@ -12,13 +12,14 @@ import com.fr.design.mainframe.cell.settingpane.CellExpandAttrPane; import com.fr.design.mainframe.cell.settingpane.CellOtherSetPane; import com.fr.design.mainframe.cell.settingpane.CellPresentPane; import com.fr.design.mainframe.cell.settingpane.CellStylePane; +import com.fr.design.mainframe.cell.settingpane.*; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.design.utils.DesignUtils; import com.fr.design.utils.gui.AdjustWorkBookDefaultStyleUtils; import com.fr.general.ComparatorUtils; import com.fr.grid.selection.CellSelection; import com.fr.grid.selection.Selection; import com.fr.report.cell.CellElement; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.elementcase.TemplateElementCase; @@ -119,7 +120,7 @@ public class CellElementEditPane extends BasicPane { CellElement cellElement = elementCase.getCellElement(cs.getColumn(), cs.getRow()); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(cs.getColumn(), cs.getRow()); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(cs.getColumn(), cs.getRow()); AdjustWorkBookDefaultStyleUtils.adjustCellElement(cellElement); //默认选中的是A1单元格,所以若是A1单元格没有加到列表时要加上,否则在聚合报表时会出错 if (cs.isSelectedOneCell(elementCasePane) && (cs.getColumn() + cs.getRow() == 0)) { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/AbstractCellAttrPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/AbstractCellAttrPane.java index 83ef31eaa..d9f8ed633 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/AbstractCellAttrPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/AbstractCellAttrPane.java @@ -2,9 +2,9 @@ package com.fr.design.mainframe.cell.settingpane; import com.fr.design.mainframe.AbstractAttrPane; import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.grid.selection.CellSelection; import com.fr.grid.selection.FloatSelection; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.elementcase.TemplateElementCase; @@ -52,7 +52,7 @@ public abstract class AbstractCellAttrPane extends AbstractAttrPane { TemplateElementCase elementCase = elementCasePane.getEditingElementCase(); TemplateCellElement cellElement = elementCase.getTemplateCellElement(cs.getColumn(), cs.getRow()); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(cs.getColumn(), cs.getRow()); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(cs.getColumn(), cs.getRow()); } this.cellElement = cellElement; elementCase.addCellElement(this.cellElement); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandAttrPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandAttrPane.java index 0f7466af0..cd454660d 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandAttrPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandAttrPane.java @@ -12,9 +12,9 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.general.ComparatorUtils; import com.fr.general.IOUtils; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.cell.cellattr.CellExpandAttr; import com.fr.report.elementcase.TemplateElementCase; @@ -239,7 +239,7 @@ public class CellExpandAttrPane extends AbstractCellAttrPane { int row = j + cellRectangle.y; TemplateCellElement cellElement = elementCase.getTemplateCellElement(column, row); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(column, row); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); elementCase.addCellElement(cellElement); } updateBean(cellElement); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandExtraAttrPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandExtraAttrPane.java index 13c288f92..e9af09a4e 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandExtraAttrPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellExpandExtraAttrPane.java @@ -7,6 +7,7 @@ import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.ui.util.UIUtil; import com.fr.event.EventDispatcher; +import com.fr.nx.app.designer.cell.CellTreeAttrPanelProvider; import com.fr.plugin.context.PluginContext; import com.fr.plugin.injectable.PluginModule; import com.fr.plugin.manage.PluginFilter; @@ -19,7 +20,10 @@ import java.awt.BorderLayout; import java.awt.Component; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import static com.fr.plugin.observer.PluginEventType.AfterRun; @@ -114,14 +118,14 @@ public class CellExpandExtraAttrPane extends JPanel { extras = new ArrayList<>(); } extras.clear(); - Set attrProviders = ExtraDesignClassManager.getInstance().getArray(CellExpandAttrPanelProvider.MARK_STRING); - if (attrProviders != null) { - for (CellExpandAttrPanelProvider attrProvider : attrProviders) { - if (attrProvider.isDisplayable()) { - BasicBeanPane extra = attrProvider.createPanel(); - if (extra != null) { - extras.add(extra); - } + Set attrProviders = new LinkedHashSet<>(Collections.singletonList(new CellTreeAttrPanelProvider())); + Optional.>of(ExtraDesignClassManager.getInstance().getArray(CellExpandAttrPanelProvider.MARK_STRING)) + .ifPresent(attrProviders::addAll); + for (CellExpandAttrPanelProvider attrProvider : attrProviders) { + if (attrProvider.isDisplayable()) { + BasicBeanPane extra = attrProvider.createPanel(); + if (extra != null) { + extras.add(extra); } } } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java index 1f0ebd779..1d02fde9c 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java @@ -17,10 +17,10 @@ import com.fr.design.layout.TableLayoutHelper; import com.fr.design.layout.VerticalFlowLayout; import com.fr.design.mainframe.EastRegionContainerPane; import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.design.utils.gui.UIComponentUtils; import com.fr.design.widget.FRWidgetFactory; import com.fr.general.ComparatorUtils; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.cell.cellattr.CellGUIAttr; import com.fr.report.cell.cellattr.CellInsertPolicyAttr; @@ -570,7 +570,7 @@ public class CellOtherSetPane extends AbstractCellAttrPane { int row = j + cellRectangle.y; TemplateCellElement cellElement = elementCase.getTemplateCellElement(column, row); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(column, row); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); elementCase.addCellElement(cellElement); } updateBean(cellElement); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellPresentPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellPresentPane.java index 960e93eec..881b8b083 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellPresentPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellPresentPane.java @@ -2,9 +2,9 @@ package com.fr.design.mainframe.cell.settingpane; import com.fr.base.present.Present; import com.fr.design.constants.UIConstants; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.design.present.PresentPane; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.elementcase.TemplateElementCase; @@ -67,7 +67,7 @@ public class CellPresentPane extends AbstractCellAttrPane { int row = j + cellRectangle.y; TemplateCellElement cellElement = elementCase.getTemplateCellElement(column, row); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(column, row); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); elementCase.addCellElement(cellElement); } cellElement.setPresent(present); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellStylePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellStylePane.java index 049b0111a..a678c501a 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellStylePane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellStylePane.java @@ -4,10 +4,10 @@ import com.fr.base.Style; import com.fr.design.actions.utils.ReportActionUtils; import com.fr.design.constants.UIConstants; import com.fr.design.mainframe.cell.settingpane.style.StylePane; +import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase; import com.fr.design.style.BorderUtils; import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.report.cell.DefaultTemplateCellElement; import com.fr.report.cell.TemplateCellElement; import com.fr.report.elementcase.TemplateElementCase; @@ -70,7 +70,7 @@ public class CellStylePane extends AbstractCellAttrPane { @Override public void updateBeans() { Object[] selectionCellBorderObjects = BorderUtils.createCellBorderObject(elementCasePane); - if (stylePane.getSelectedIndex() == 1) { + if (stylePane.getSelectedIndex() == 0) { Style s = stylePane.updateBean(); TemplateElementCase elementCase = elementCasePane.getEditingElementCase(); int cellRectangleCount = cs.getCellRectangleCount(); @@ -82,7 +82,7 @@ public class CellStylePane extends AbstractCellAttrPane { int row = j + cellRectangle.y; TemplateCellElement cellElement = elementCase.getTemplateCellElement(column, row); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(column, row); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); elementCase.addCellElement(cellElement); } cellElement.setStyle(s); @@ -100,7 +100,7 @@ public class CellStylePane extends AbstractCellAttrPane { int row = j + cellRectangle.y; TemplateCellElement cellElement = elementCase.getTemplateCellElement(column, row); if (cellElement == null) { - cellElement = new DefaultTemplateCellElement(column, row); + cellElement = DefaultThemedTemplateCellElementCase.createInstance(column, row); elementCase.addCellElement(cellElement); } Style style = cellElement.getStyle(); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java index e2d824757..e559cfaa4 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java @@ -1,37 +1,162 @@ package com.fr.design.mainframe.cell.settingpane.style; +import com.fr.base.NameStyle; +import com.fr.base.Style; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.dialog.BasicPane; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.ElementCasePane; +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; -import javax.swing.event.ChangeListener; +public class StylePane extends BasicPane implements UIObserver { + public static final String[] FOLLOWING_THEME_STRING_ARRAYS = new String[]{ + Toolkit.i18nText("Fine-Design_Style_Follow_Theme"), + Toolkit.i18nText("Fine-Design_Style_Not_Follow_Theme"), + }; + public static final int DEFAULT_SELECTED_INDEX = 0; -import com.fr.base.Style; -import com.fr.design.beans.FurtherBasicBeanPane; -import com.fr.design.gui.frpane.UIComboBoxPane; -import com.fr.general.ComparatorUtils; + private final UIButtonGroup followingThemeButtonGroup; + private final CustomStylePane customStylePane; + private final ThemedCellStyleListPane themedCellStyleListPane; + private final CardLayout cardLayout; + private final JComponent[] panes = new JComponent[2]; -import com.fr.design.mainframe.ElementCasePane; + private JPanel contentPane; + + private final List observerListeners = new ArrayList<>(); + + public StylePane() { + followingThemeButtonGroup = new UIButtonGroup<>(FOLLOWING_THEME_STRING_ARRAYS); + customStylePane = new CustomStylePane(); + themedCellStyleListPane = new ThemedCellStyleListPane(); + panes[0] = createThemedStylePane(); + panes[1] = createCustomStylePane(); + cardLayout = new CardLayout(); + + initializePane(); + } + + private void initializePane() { + setLayout(new BorderLayout(0, IntervalConstants.INTERVAL_L1)); + + add(createFollowingThemePane(), BorderLayout.NORTH); + contentPane = createTabbedContentPane(); + add(contentPane, BorderLayout.CENTER); + } + + private JPanel createFollowingThemePane() { + followingThemeButtonGroup.setSelectedIndex(DEFAULT_SELECTED_INDEX); + followingThemeButtonGroup.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + int selectedIndex = followingThemeButtonGroup.getSelectedIndex(); + cardLayout.show(contentPane, FOLLOWING_THEME_STRING_ARRAYS[selectedIndex]); + if (selectedIndex == 1) { + // 对于同一个单元格,跟随主题切换到自定义,自定义中的配置与其保持一致 + NameStyle lastSelectedNameStyle = themedCellStyleListPane.updateBean(); + if (lastSelectedNameStyle != null) { + Style lastSelectedRealStyle = lastSelectedNameStyle.getRealStyle(); + try { + lastSelectedRealStyle = (Style) lastSelectedRealStyle.clone(); + if (lastSelectedRealStyle != null) { + customStylePane.populateBean(lastSelectedRealStyle); + } + } catch (CloneNotSupportedException ex) { + FineLoggerFactory.getLogger().error(ex.getMessage(), ex); + } + } + } else { + // 对于同一个单元格,自定义切换到跟随主题,跟随主题选中"默认"样式,并使用默认样式设置选中的单元格 + themedCellStyleListPane.reset(); + } + + fireStateChanged(); + } + }); + + UILabel uiLabel = new UILabel(Toolkit.i18nText("Fine-Design_Style_Setting")); + + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + + return TableLayoutHelper.createGapTableLayoutPane( + new Component[][]{ new Component[] { uiLabel, followingThemeButtonGroup} }, + new double[] { p }, new double[] { p, f}, + IntervalConstants.INTERVAL_L1, 0); + } + + protected JPanel createTabbedContentPane() { + JPanel contentPane = new JPanel(cardLayout) { + @Override + public Dimension getPreferredSize() { + int selectedIndex = followingThemeButtonGroup.getSelectedIndex(); + if (selectedIndex < 0) { + return super.getPreferredSize(); + } else { + return panes[selectedIndex].getPreferredSize(); + } + } + }; + for (int i = 0; i < FOLLOWING_THEME_STRING_ARRAYS.length; i++) { + contentPane.add(panes[i], FOLLOWING_THEME_STRING_ARRAYS[i]); + } + cardLayout.show(contentPane, FOLLOWING_THEME_STRING_ARRAYS[DEFAULT_SELECTED_INDEX]); -public class StylePane extends UIComboBoxPane