diff --git a/build.gradle b/build.gradle index da6b0daf88..bf1616759c 100644 --- a/build.gradle +++ b/build.gradle @@ -68,7 +68,7 @@ allprojects { implementation 'org.swingexplorer:swexpl:2.0.1' implementation 'org.swingexplorer:swag:1.0' implementation 'net.java.dev.jna:jna:5.4.0' - implementation 'org.apache.tomcat:tomcat-catalina:8.5.69' + implementation 'org.apache.tomcat:tomcat-catalina:8.5.72' implementation 'io.socket:socket.io-client:0.7.0' implementation 'com.fr.third:fine-third:' + frVersion implementation 'com.fr.core:fine-core:' + frDevVersion diff --git a/designer-base/src/main/java/com/fr/common/exception/ThrowableHandler.java b/designer-base/src/main/java/com/fr/common/exception/ThrowableHandler.java new file mode 100644 index 0000000000..225d90e791 --- /dev/null +++ b/designer-base/src/main/java/com/fr/common/exception/ThrowableHandler.java @@ -0,0 +1,12 @@ +package com.fr.common.exception; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2021/12/27 + */ +public interface ThrowableHandler { + + boolean process(Throwable e); + +} diff --git a/designer-base/src/main/java/com/fr/common/listener/ManageDsListenerRegisterListener.java b/designer-base/src/main/java/com/fr/common/listener/ManageDsListenerRegisterListener.java new file mode 100644 index 0000000000..966f3daf1c --- /dev/null +++ b/designer-base/src/main/java/com/fr/common/listener/ManageDsListenerRegisterListener.java @@ -0,0 +1,51 @@ +package com.fr.common.listener; + +import com.fr.design.data.DesignTableDataManager; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import javax.swing.event.ChangeListener; + +/** + * 管理数据集相关监听的注册 + * + * 原本的监听生命周期注册与销毁: + * + * 创建时组件时进行注册,在模板关闭时进行销毁 + * 但是在模板未关闭的这段时间,如果不断的打开和关闭某些弹窗,次数达到一定程度,会导致出现大量内存占用,除非此时关闭模板 + * + * 改成以下模式: + * + * 当组件可见或者被添加到某个大组件 注册相关监听 + * 当组件不可见或者被移除时 立即移除相关监听 + * 及时清理无效监听,减少实时内存占用 + * + * + * @author hades + * @version 11.0 + * Created by hades on 2022/2/14 + */ +public class ManageDsListenerRegisterListener implements AncestorListener { + + private ChangeListener changeListener; + + public ManageDsListenerRegisterListener(ChangeListener changeListener) { + this.changeListener = changeListener; + } + + @Override + public void ancestorAdded(AncestorEvent event) { + DesignTableDataManager.addDsChangeListener(changeListener); + // 添加后 fire一下 更新数据 + changeListener.stateChanged(null); + } + + @Override + public void ancestorRemoved(AncestorEvent event) { + DesignTableDataManager.removeDsChangeLister(changeListener); + } + + @Override + public void ancestorMoved(AncestorEvent event) { + // do nothing + } +} diff --git a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java index 9c23dcc51a..85b4e4e78f 100644 --- a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java +++ b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java @@ -22,6 +22,7 @@ import com.fr.design.login.DesignerLoginType; import com.fr.design.login.config.DesignerLoginConfigManager; import com.fr.design.mainframe.vcs.VcsConfigManager; import com.fr.design.notification.SnapChatConfig; +import com.fr.design.os.impl.SupportOSImpl; import com.fr.design.port.DesignerPortContext; import com.fr.design.style.color.ColorSelectConfigManager; import com.fr.design.update.push.DesignerPushUpdateConfigManager; @@ -202,6 +203,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { private boolean showTemplateMissingPlugin = true; + private boolean useOptimizedUPM4Adapter; + /** * DesignerEnvManager. */ @@ -639,6 +642,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.showTemplateMissingPlugin = showTemplateMissingPlugin; } + public boolean isUseOptimizedUPM4Adapter() { + return useOptimizedUPM4Adapter; + } + + public void setUseOptimizedUPM4Adapter(boolean useOptimizedUPM4Adapter) { + this.useOptimizedUPM4Adapter = useOptimizedUPM4Adapter; + } + /** * 知否自动备份 * @@ -867,6 +878,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { designerLoginConfigManager.setPluginRemindOnFirstLaunch(pluginRemindOnFirstLaunch); } + public boolean isUseOldVersionLogin() { + return designerLoginConfigManager.isUseOldVersionLogin(); + } + + public void setUseOldVersionLogin(boolean useOldVersionLogin) { + designerLoginConfigManager.setUseOldVersionLogin(useOldVersionLogin); + } + /** * 内置服务器是否使用时启动 * @@ -1821,6 +1840,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { } this.setEmbedServerLazyStartup(reader.getAttrAsBoolean("embedServerLazyStartup", false)); this.setShowTemplateMissingPlugin(reader.getAttrAsBoolean("showTemplateMissingPlugin", true)); + this.setUseOptimizedUPM4Adapter(reader.getAttrAsBoolean("useOptimizedUPM4Adapter", SupportOSImpl.MACOS_12_VERSION_ADAPTER.support())); } private void readReportPaneAttributions(XMLableReader reader) { @@ -2093,6 +2113,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { if (!this.isShowTemplateMissingPlugin()) { writer.attr("showTemplateMissingPlugin", this.isShowTemplateMissingPlugin()); } + writer.attr("useOptimizedUPM4Adapter", this.isUseOptimizedUPM4Adapter()); writer.end(); } diff --git a/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java b/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java index cd9c835f39..d575c68d01 100644 --- a/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java +++ b/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java @@ -427,7 +427,9 @@ public class EnvChangeEntrance { DesignerExiter.getInstance().execute(); } else { updateNotRememberPwdEnv(); - VersionCheckUtils.showVersionCheckDialog(envListPane.getSelectedName()); + if (DesignerContext.getDesignerFrame().isVisible()) { + VersionCheckUtils.showVersionCheckDialog(envListPane.getSelectedName()); + } } } diff --git a/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java b/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java index 5c12ff29c3..72001a5624 100644 --- a/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java @@ -185,12 +185,24 @@ public abstract class UpdateAction extends ShortCut implements Action { * @param resource 图标资源路径 */ public void setSmallIcon(String resource) { + setSmallIcon(resource, true); + } + + /** + * 使用传入资源url的方式设置Icon,会自动设置_normal.svg,然后通过needDisable参数判断是否需要自动设置_disable.svg + * 因为有些地方是不需要设置灰化图标的,所以不存在灰化图标资源,这边如果一并设置,就会报错文件找不到 + * @param resource + * @param needDisable + */ + public void setSmallIcon(String resource, boolean needDisable) { if (StringUtils.equals(resource, StringUtils.EMPTY)) { this.putValue(Action.SMALL_ICON, null); return; } this.putValue(Action.SMALL_ICON, IconUtils.readIcon(resource)); - this.putValue(UpdateAction.DISABLED_ICON, IconUtils.readSVGIcon(resource, IconUtils.ICON_TYPE_DISABLED)); + if (needDisable) { + this.putValue(UpdateAction.DISABLED_ICON, IconUtils.readSVGIcon(resource, IconUtils.ICON_TYPE_DISABLED)); + } } public void setSmallIcon(Icon[] smallIcon, boolean white) { diff --git a/designer-base/src/main/java/com/fr/design/actions/community/BugAction.java b/designer-base/src/main/java/com/fr/design/actions/community/BugAction.java index a162571002..5365e556b6 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/BugAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/BugAction.java @@ -17,7 +17,7 @@ public class BugAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.bugs", "http://bbs.fanruan.com/forum-156-1.html"); + return CloudCenter.getInstance().acquireUrlByKind("bbs.bugs", "https://service.fanruan.com/PF/FR/feedback?type=2"); } public static final MenuKeySet BUG = new MenuKeySet() { diff --git a/designer-base/src/main/java/com/fr/design/actions/community/NeedAction.java b/designer-base/src/main/java/com/fr/design/actions/community/NeedAction.java index c8b2ccdae1..62d4b9c95f 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/NeedAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/NeedAction.java @@ -18,7 +18,7 @@ public class NeedAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.needs", "http://bbs.fanruan.com/forum-56-1.html"); + return CloudCenter.getInstance().acquireUrlByKind("bbs.needs", "https://service.fanruan.com/PF/FR/feedback?type=1"); } public static final MenuKeySet NEED = new MenuKeySet() { diff --git a/designer-base/src/main/java/com/fr/design/actions/community/StudyPlanAction.java b/designer-base/src/main/java/com/fr/design/actions/community/StudyPlanAction.java new file mode 100644 index 0000000000..d0dcc4195d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/community/StudyPlanAction.java @@ -0,0 +1,17 @@ +package com.fr.design.actions.community; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.login.AbstractDesignerSSO; +import com.fr.general.CloudCenter; + +public class StudyPlanAction extends AbstractDesignerSSO { + public StudyPlanAction() { + this.setName(Toolkit.i18nText("Fine-Design_Study_Plan")); + this.setSmallIcon("/com/fr/design/images/bbs/studyPlan"); + } + + @Override + public String getJumpUrl() { + return CloudCenter.getInstance().acquireUrlByKind("bbs.studyPlan", "https://edu.fanruan.com/studypath/finereport"); + } +} 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 24e359d6f0..db94ace66f 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 @@ -15,9 +15,10 @@ 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.icombobox.UIDictionaryComboBox; +import com.fr.design.gui.ifilechooser.FileChooserArgs; +import com.fr.design.gui.ifilechooser.FileChooserFactory; import com.fr.design.gui.ifilechooser.FileChooserProvider; import com.fr.design.gui.ifilechooser.FileSelectionMode; -import com.fr.design.gui.ifilechooser.JavaFxNativeFileChooser; import com.fr.design.gui.ilable.ActionLabel; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.iprogressbar.UIProgressBarUI; @@ -28,7 +29,6 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.layout.VerticalFlowLayout; -import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.vcs.VcsConfigManager; import com.fr.design.mainframe.vcs.common.VcsHelper; import com.fr.design.os.impl.SupportOSImpl; @@ -50,8 +50,6 @@ import com.fr.transaction.Worker; import com.fr.workspace.WorkContext; import com.fr.workspace.server.vcs.VcsOperator; import com.fr.workspace.server.vcs.git.config.GcConfig; -import com.sun.javafx.tk.FileChooserType; -import javafx.stage.FileChooser; import javax.swing.BorderFactory; import javax.swing.BoxLayout; @@ -500,9 +498,8 @@ public class PreferencePane extends BasicPane { @Override public void actionPerformed(ActionEvent evt) { FileChooserProvider fileChooserProvider = - new JavaFxNativeFileChooser.Builder(). - fileSelectionMode(FileSelectionMode.DIR). - build(); + FileChooserFactory.createFileChooser(FileChooserArgs.newBuilder(). + setFileSelectionMode(FileSelectionMode.DIR).build()); int saveValue = fileChooserProvider.showDialog(chooseDirBtn); if (saveValue == JFileChooser.APPROVE_OPTION) { File selectedFile = fileChooserProvider.getSelectedFile(); @@ -715,7 +712,8 @@ public class PreferencePane extends BasicPane { this.portEditor.setValue(new Integer(designerEnvManager.getEmbedServerPort())); if (useOptimizedUPMCheckbox != null) { - useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM()); + useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM() + || DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter()); } useUniverseDBMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseUniverseDBM()); @@ -790,6 +788,7 @@ public class PreferencePane extends BasicPane { designerEnvManager.setJoinProductImprove(this.joinProductImproveCheckBox.isSelected()); designerEnvManager.setEmbedServerLazyStartup(this.embedServerLazyStartupCheckBox.isSelected()); designerEnvManager.setImageCompress(this.imageCompressPanelCheckBox.isSelected()); + designerEnvManager.setUseOptimizedUPM4Adapter(this.useOptimizedUPMCheckbox != null && this.useOptimizedUPMCheckbox.isSelected()); VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager(); vcsConfigManager.setSaveInterval(this.saveIntervalEditor.getValue()); vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected()); diff --git a/designer-base/src/main/java/com/fr/design/actions/help/AboutPane.java b/designer-base/src/main/java/com/fr/design/actions/help/AboutPane.java index 6158540888..52e63df2db 100644 --- a/designer-base/src/main/java/com/fr/design/actions/help/AboutPane.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/AboutPane.java @@ -14,6 +14,7 @@ import com.fr.general.CloudCenter; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; import com.fr.general.GeneralUtils; +import com.fr.i18n.UrlI18nManager; import com.fr.locale.InterProviderFactory; import com.fr.stable.ProductConstants; import com.fr.stable.StringUtils; @@ -82,7 +83,7 @@ public class AboutPane extends JPanel { addPhoneAndQQPane(contentPane); // 官网 - JPanel urlActionPane = getURLActionPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Official_Website"), CloudCenter.getInstance().acquireConf("website." + GeneralContext.getLocale(), ProductConstants.WEBSITE_URL)); + JPanel urlActionPane = getURLActionPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Official_Website"), UrlI18nManager.getInstance().getI18nUrl("website")); // 支持邮箱 String defaultEmail = CloudCenter.getInstance().acquireConf("support.email", ProductConstants.SUPPORT_EMAIL); @@ -126,8 +127,8 @@ public class AboutPane extends JPanel { if (GeneralContext.getLocale().equals(Locale.TAIWAN)) { return; } - boxCenterAlignmentPane = new BoxCenterAligmentPane("QQ: " + CloudCenter.getInstance().acquireUrlByKind("help.qq")); - contentPane.add(boxCenterAlignmentPane); + JPanel servicePlatformPane = getURLActionPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Service_Platform"), CloudCenter.getInstance().acquireUrlByKind("service.platform")); + contentPane.add(servicePlatformPane); } // 是否显示鸣谢面板 diff --git a/designer-base/src/main/java/com/fr/design/actions/help/SystemInfoPane.java b/designer-base/src/main/java/com/fr/design/actions/help/SystemInfoPane.java index 7fe26054f6..f50bb703ce 100644 --- a/designer-base/src/main/java/com/fr/design/actions/help/SystemInfoPane.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/SystemInfoPane.java @@ -41,19 +41,15 @@ public class SystemInfoPane extends JPanel { for (int i = 0; i < keys.length; i++) { Object[] tableRowData = new Object[2]; String keyValue = keys[i].toString(); - // james:屏蔽掉exe4j的内容 - if (keyValue.indexOf("exe4j") != -1) { - continue; + + if (needToShield(keyValue)) { + continue; } - // james:这个也是exe4j的东东 - if ("install4j.exeDir".equals(keyValue)) { - continue; + + if(keyValue.contains("FineReport")){ + keys[i] = keyValue.replaceAll("FineReport", ProductConstants.APP_NAME); } - - if(keyValue.indexOf("FineReport") != -1){ - keys[i] = keyValue.replaceAll("FineReport", ProductConstants.APP_NAME); - } - + tableRowData[0] = keys[i]; tableRowData[1] = properties.getProperty((String) keys[i]); tableModel.addRow(tableRowData); @@ -66,4 +62,14 @@ public class SystemInfoPane extends JPanel { add(new JScrollPane(table), BorderLayout.CENTER); } + + /** + * 是否属于需要屏蔽的内容(当前屏蔽掉exe4j与jxbrowser的内容) + * + * @param keyValue 对应的key值 + * @return 需要屏蔽则返回true + */ + private boolean needToShield(String keyValue) { + return keyValue.contains("exe4j") || keyValue.contains("jxbrowser") || "install4j.exeDir".equals(keyValue); + } } \ No newline at end of file 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 f1094d3315..4f06b1c56b 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 @@ -3,9 +3,9 @@ package com.fr.design.actions.help; import com.fr.design.i18n.Toolkit; import com.fr.design.login.AbstractDesignerSSO; import com.fr.design.menu.MenuKeySet; -import com.fr.general.CloudCenter; import com.fr.general.GeneralContext; import com.fr.general.http.HttpToolbox; +import com.fr.i18n.UrlI18nManager; import com.fr.stable.CommonUtils; import com.fr.stable.ProductConstants; import com.fr.stable.StringUtils; @@ -28,7 +28,7 @@ public class TutorialAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind(createDocKey(), "http://help.finereport.com"); + return UrlI18nManager.getInstance().getI18nUrl("help"); } public String getOffLineWarnMessage() { diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineCloudConstants.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineCloudConstants.java new file mode 100644 index 0000000000..714c1f481d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineCloudConstants.java @@ -0,0 +1,200 @@ +package com.fr.design.actions.help.alphafine; + +import com.fr.design.i18n.Toolkit; +import com.fr.general.CloudCenter; +import com.fr.json.JSONArray; + +import java.util.HashMap; +import java.util.Map; + +/** + * 云端变量统一管理 + * + * @author Link + * @version 11.0 + * Created by Link on 2022/9/28 + */ +public class AlphaFineCloudConstants { + + private static final String PLUGIN_SEARCH_API = "plugin.searchAPI"; + private static final String PLUGIN_ALL_SEARCH_API = "plugin.all.searchAPI"; + private static final String AF_PLUGIN_INFO = "af.pluginInfo"; + private static final String AF_REUSE_INFO = "af.reuseInfo"; + private static final String AF_DOC_VIEW = "af.doc_view"; + private static final String AF_DOC_SEARCH = "af.doc_search"; + private static final String AF_DOC_INFO = "af.doc_info"; + private static final String AF_PLUGIN_IMAGE = "af.plugin_image"; + private static final String AF_RECORD = "af.record"; + private static final String AF_CLOUD_SEARCH = "af.cloud_search"; + private static final String AF_SIMILAR_SEARCH = "af.similar_search"; + private static final String AF_ADVICE_SEARCH = "af.advice_search"; + private static final String AF_HOT_SEARCH = "af.hot_search"; + private static final String AF_GO_FORUM = "af.go_fourm"; + private static final String AF_GO_WEB = "af.go_web"; + private static final String AF_PREVIEW = "af.preview"; + private static final String AF_CID_NEW = "af.cid.new"; + private static final String AF_CID_USER_GROUP_INFO = "af.cid.user.group.info"; + private static final String AF_HELP_QUICK_START = "af.help.quick.start"; + private static final String AF_HELP_REPORT_LEARNING_PATH = "af.help.report.learning.path"; + private static final String AF_HELP_PARAM_LEARNING_PATH = "af.help.param.learning.path"; + private static final String AF_HELP_FILL_LEARNING_PATH = "af.help.fill.learning.path"; + private static final String AF_HELP_API_SUMMARY = "af.help.api.summary"; + private static final String AF_HELP_MONTHLY_DOCUMENT = "af.help.monthly.document"; + private static final String AF_RECOMMEND = "af.recommend"; + + private static final String LINK_NAME = "name"; + private static final String LINK_URL = "link"; + + /** + * 获取插件搜索api + */ + public static String getPluginSearchUrl() { + return CloudCenter.getInstance().acquireUrlByKind(PLUGIN_SEARCH_API); + }; + + /** + * 帆软市场里全部插件api + */ + public static String getSearchAllPluginUrl() { + return CloudCenter.getInstance().acquireUrlByKind(PLUGIN_ALL_SEARCH_API); + } + + /** + * 获取插件信息api + */ + public static String getPluginUrl() { + return CloudCenter.getInstance().acquireUrlByKind(AF_PLUGIN_INFO); + } + + /** + * 获取组件信息api + */ + public static String getReuseUrl() { + return CloudCenter.getInstance().acquireUrlByKind(AF_REUSE_INFO); + } + + /** + * 获取帮助文档url + */ + public static String getDocumentDocUrl() { + return CloudCenter.getInstance().acquireUrlByKind(AF_DOC_VIEW); + } + + /** + * 帮助文档搜索api + */ + public static String getDocumentSearchUrl() { + return CloudCenter.getInstance().acquireUrlByKind(AF_DOC_SEARCH); + } + + /** + * 帮助文档信息api + */ + public static String getDocumentInformationUrl() { + return CloudCenter.getInstance().acquireUrlByKind(AF_DOC_INFO); + } + + /** + * 插件图片api + */ + public static String getPluginImageUrl() { + return CloudCenter.getInstance().acquireUrlByKind(AF_PLUGIN_IMAGE); + } + + /** + * 获取云端接口,用于上传alphafine搜索记录 + */ + public static String getCloudServerUrl() { + return CloudCenter.getInstance().acquireUrlByKind(AF_RECORD); + } + + /** + * 获取搜索api,输入搜索词,返回fr的相关功能 + */ + public static String getSearchApi() { + return CloudCenter.getInstance().acquireUrlByKind(AF_CLOUD_SEARCH); + } + + /** + * 获取模糊搜索api前缀,输入搜索词,返回alphaFine相关内容,插件,文档,功能等 + */ + public static String getSimilarSearchUrlPrefix() { + return CloudCenter.getInstance().acquireUrlByKind(AF_SIMILAR_SEARCH); + } + + /** + * 补全建议搜索结果 api,与AF_SIMILAR_SEARCH接口类似,但是返回的信息更全 + */ + public static String getComplementAdviceSearchUrlPrefix() { + return CloudCenter.getInstance().acquireUrlByKind(AF_ADVICE_SEARCH); + } + + /** + * 获取热门问题 + */ + public static String getAlphaHotSearch() { + return CloudCenter.getInstance().acquireUrlByKind(AF_HOT_SEARCH); + } + + /** + * 跳转论坛url + */ + public static String getAlphaGoToForum() { + return CloudCenter.getInstance().acquireUrlByKind(AF_GO_FORUM); + } + + /** + * 推荐搜索api,输入搜索词,返回猜你想搜的内容(html格式) + */ + public static String getAlphaGoToWeb() { + return CloudCenter.getInstance().acquireUrlByKind(AF_GO_WEB); + } + + /** + * 帆软智能客服页面url + */ + public static String getAlphaPreview() { + return CloudCenter.getInstance().acquireUrlByKind(AF_PREVIEW); + } + + /** + * cid系统的产品动态api + */ + public static String getAlphaCid() { + return CloudCenter.getInstance().acquireUrlByKind(AF_CID_NEW); + } + + /** + * cid系统的 用户组信息api + */ + public static String getAlphaCidUserGroupInfo() { + return CloudCenter.getInstance().acquireUrlByKind(AF_CID_USER_GROUP_INFO); + } + + private static String getDefaultRecommend() { + String[][] links = new String[][]{ + {Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Quick_Start"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_QUICK_START)}, + {Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Report_Learning"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_REPORT_LEARNING_PATH)}, + {Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Parameter_Learning"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_PARAM_LEARNING_PATH)}, + {Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Fill_Learning"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_FILL_LEARNING_PATH)}, + {Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Api_Summary"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_API_SUMMARY)}, + {Toolkit.i18nText("Fine-Design_Report_AlphaFine_Doc_Monthly_Document"), CloudCenter.getInstance().acquireUrlByKind(AF_HELP_MONTHLY_DOCUMENT)} + }; + JSONArray jsonArray = new JSONArray(); + for (String[] link : links) { + Map map = new HashMap<>(); + map.put(LINK_NAME, link[0]); + map.put(LINK_URL, link[1]); + jsonArray.put(map); + } + + return jsonArray.toString(); + } + + /** + * 获取默认推荐帮助文档url + */ + public static String getAlphaHelpRecommend() { + return CloudCenter.getInstance().acquireUrlByKind(AF_RECOMMEND, getDefaultRecommend()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java index 0296327097..79e52f51d7 100644 --- a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigManager.java @@ -1,5 +1,7 @@ package com.fr.design.actions.help.alphafine; +import com.fr.base.FRContext; +import com.fr.design.DesignerEnvManager; import com.fr.general.ComparatorUtils; import com.fr.license.function.VT4FR; import com.fr.stable.OperatingSystem; @@ -10,10 +12,14 @@ import com.fr.stable.xml.XMLable; import com.fr.stable.xml.XMLableReader; import org.jetbrains.annotations.NotNull; -import javax.swing.*; +import javax.swing.KeyStroke; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; +import java.util.Stack; /** * AlphaFine配置类 @@ -23,6 +29,7 @@ import java.util.Map; */ public class AlphaFineConfigManager implements XMLable { + public static final String COMMA = ","; private static final long serialVersionUID = -8170289826729582122L; private static AlphaFineConfigManager alphaFineConfigManager = new AlphaFineConfigManager(); /** @@ -46,13 +53,17 @@ public class AlphaFineConfigManager implements XMLable { */ private boolean containRecommend = true; /** - * 设置 + * 功能 */ private boolean containAction = true; /** * 帮助文档 */ private boolean containDocument = true; + /** + * 我的模板 + * */ + private boolean containMyTemplate = true; /** * 模板 */ @@ -62,7 +73,7 @@ public class AlphaFineConfigManager implements XMLable { */ private boolean containFileContent; /** - * 应用中心 + * 插件中心 */ private boolean containPlugin = true; /** @@ -81,10 +92,37 @@ public class AlphaFineConfigManager implements XMLable { * 是否提醒 */ private boolean needRemind = true; - + /** + * 产品动态 + */ + private boolean productDynamics = true; + /** + * 模板商城是否展示 + */ + private boolean showTemplateShop = true; + /** + * tab页排序 + * 默认排序:动态,模板商城,帮助文档,插件中心,功能,我的模板 + */ + private String[] tabOrder; private Map actionSearchTextCache = new HashMap<>(8); - private String cacheBuildNO; + + private static final String CONTAIN_TEMPLATE_SHOP = "isContainTemplateShop"; + private static final String TAB_ORDER = "tabOrder"; + + /** + * key: 登录的bbs用户 + * value: alphaFine历史搜索记录 + */ + private Map> historySearchMap = new LinkedHashMap<>(); + + /** + * key: 登录的bbs用户 + * value: 已读的cid的集合 + */ + private Map> readSetMap = new LinkedHashMap<>(); + /** * 直接操作菜单次数 */ @@ -115,17 +153,24 @@ public class AlphaFineConfigManager implements XMLable { this.setContainPlugin(reader.getAttrAsBoolean("isContainDocument", true)); this.setContainDocument(reader.getAttrAsBoolean("isContainDocument", true)); this.setContainRecommend(reader.getAttrAsBoolean("isContainRecommend", true)); + this.setShowTemplateShop(reader.getAttrAsBoolean(CONTAIN_TEMPLATE_SHOP, true)); this.setContainAction(reader.getAttrAsBoolean("isContainAction", true)); this.setContainTemplate(reader.getAttrAsBoolean("isContainTemplate", true)); this.setContainFileContent(reader.getAttrAsBoolean("isContainFileContent", false)); this.setNeedSegmentationCheckbox(reader.getAttrAsBoolean("needSegmentationCheckbox", true)); this.setNeedIntelligentCustomerService(reader.getAttrAsBoolean("needIntelligentCustomerService", true)); + this.setProductDynamics(reader.getAttrAsBoolean("productDynamics", true)); this.setShortcuts(reader.getAttrAsString("shortcuts", getDefaultShortCuts())); this.setNeedRemind(reader.getAttrAsBoolean("isNeedRemind", true)); this.setOperateCount(reader.getAttrAsInt("operateCount", 0)); + this.setTabOrder(reader.getAttrAsString(TAB_ORDER, getDefaultTabOrder()).split(COMMA)); } else if (reader.isChildNode()) { if (ComparatorUtils.equals(reader.getTagName(), "ActionSearchTextCache")) { readActionSearchTextCacheXML(reader); + } else if ("SearchHistory".equals(reader.getTagName())) { + readHistorySearch(reader); + } else if ("ReadSet".equals(reader.getTagName())) { + readReadSet(reader); } } } @@ -152,6 +197,53 @@ public class AlphaFineConfigManager implements XMLable { }); } + private void readHistorySearch(XMLableReader reader) { + reader.readXMLObject(new XMLReadable() { + @Override + public void readXML(XMLableReader xmLableReader) { + if (ComparatorUtils.equals(reader.getTagName(), "history")) { + String tmpVal = reader.getElementValue(); + if (tmpVal != null) { + tmpVal = tmpVal.replace("[", StringUtils.EMPTY).replace("]", StringUtils.EMPTY); + Stack stack = new SizedStack<>(3); + String[] historyList = tmpVal.split(","); + for (String history : historyList) { + String value = history.trim(); + if (StringUtils.isNotEmpty(value)) { + stack.add(value); + } + } + historySearchMap.put(reader.getAttrAsString("user", StringUtils.EMPTY), stack); + } + } + } + }); + } + + + private void readReadSet(XMLableReader reader) { + reader.readXMLObject(new XMLReadable() { + @Override + public void readXML(XMLableReader xmLableReader) { + if (ComparatorUtils.equals(reader.getTagName(), "readId")) { + String tmpVal = reader.getElementValue(); + if (tmpVal != null) { + tmpVal = tmpVal.replace("[", StringUtils.EMPTY).replace("]", StringUtils.EMPTY); + String[] idArr = tmpVal.split(","); + Set setId = new HashSet<>(); + for (String id : idArr) { + String value = id.trim(); + if (StringUtils.isNotEmpty(value)) { + setId.add(Long.parseLong(value)); + } + } + readSetMap.put(reader.getAttrAsString("user", StringUtils.EMPTY), setId); + } + } + } + }); + } + @Override public void writeXML(XMLPrintWriter writer) { writer.startTAG("AlphaFineConfigManager"); @@ -167,8 +259,13 @@ public class AlphaFineConfigManager implements XMLable { .attr("isNeedRemind", this.isNeedRemind()) .attr("operateCount", this.getOperateCount()) .attr("needSegmentationCheckbox", this.isNeedSegmentationCheckbox()) - .attr("needIntelligentCustomerService", this.isNeedIntelligentCustomerService()); + .attr("needIntelligentCustomerService", this.isNeedIntelligentCustomerService()) + .attr("productDynamics", this.isProductDynamics()) + .attr(CONTAIN_TEMPLATE_SHOP, this.showTemplateShop) + .attr(TAB_ORDER, this.getTabOrderString()); writeActionSearchTextCacheXML(writer); + writeSearchHistory(writer); + writeReadSet(writer); writer.end(); } @@ -183,6 +280,22 @@ public class AlphaFineConfigManager implements XMLable { writer.end(); } + private void writeSearchHistory(XMLPrintWriter writer) { + writer.startTAG("SearchHistory"); + for (Map.Entry> entry : historySearchMap.entrySet()) { + writer.startTAG("history").attr("user", entry.getKey()).textNode(entry.getValue().toString()).end(); + } + writer.end(); + } + + private void writeReadSet(XMLPrintWriter writer) { + writer.startTAG("ReadSet"); + for (Map.Entry> entry : readSetMap.entrySet()) { + writer.startTAG("readId").attr("user", entry.getKey()).textNode(entry.getValue().toString()).end(); + } + writer.end(); + } + public boolean isSearchOnLine() { return searchOnLine; } @@ -212,6 +325,13 @@ public class AlphaFineConfigManager implements XMLable { return OperatingSystem.isMacOS() ? "meta + D" : "ctrl + D"; } + /** + * 返回默认排序 + */ + private String getDefaultTabOrder() { + return AlphaFineConstants.PRODUCT_NEWS + COMMA + AlphaFineConstants.TEMPLATE_SHOP + COMMA + AlphaFineConstants.HELP + COMMA + AlphaFineConstants.PLUGIN + COMMA + AlphaFineConstants.FUNCTION + COMMA + AlphaFineConstants.MY_TEMPLATES; + } + public boolean isContainAction() { return containAction; } @@ -228,6 +348,14 @@ public class AlphaFineConfigManager implements XMLable { this.containDocument = containDocument; } + public boolean isContainMyTemplate() { + return containMyTemplate; + } + + public void setContainMyTemplate(boolean containMyTemplate) { + this.containMyTemplate = containMyTemplate; + } + public boolean isContainTemplate() { return containTemplate; } @@ -335,4 +463,61 @@ public class AlphaFineConfigManager implements XMLable { public void setCacheBuildNO(@NotNull String cacheBuildNO) { this.cacheBuildNO = cacheBuildNO; } + + public Stack getHistorySearch() { + return historySearchMap.computeIfAbsent(DesignerEnvManager.getEnvManager().getDesignerLoginUsername(), k -> new SizedStack<>(3)); + } + + public Set getReadSet() { + return readSetMap.computeIfAbsent(DesignerEnvManager.getEnvManager().getDesignerLoginUsername(), k -> new HashSet<>()); + } + + public boolean isProductDynamics() { + return productDynamics && FRContext.isChineseEnv(); + } + + public void setProductDynamics(boolean productDynamics) { + this.productDynamics = productDynamics; + } + + public boolean hasTemplateShop() { + return showTemplateShop && FRContext.isChineseEnv(); + } + + public void setShowTemplateShop(boolean showTemplateShop) { + this.showTemplateShop = showTemplateShop; + } + + /** + * 是否展示alphafine窗口,设置-搜索范围 0勾选,则不显示 + */ + public boolean needShowAlphaFineDialog() { + return hasTemplateShop() || isContainDocument() || isContainPlugin() || + isContainAction() || isProductDynamics() || isContainMyTemplate(); + } + + /** + * 返回tab显示顺序 + */ + public String[] getTabOrder() { + if (tabOrder == null) { + tabOrder = getDefaultTabOrder().split(COMMA); + } + return tabOrder; + } + + public void setTabOrder(String[] tabOrder) { + this.tabOrder = tabOrder; + } + + /** + * getTabOrder的tostring + */ + public String getTabOrderString() { + StringBuilder sb = new StringBuilder(); + for (String s : getTabOrder()) { + sb.append(s + COMMA); + } + return sb.toString(); + } } diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java index 5bf0214e02..64ae6c8774 100644 --- a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConfigPane.java @@ -1,23 +1,41 @@ package com.fr.design.actions.help.alphafine; import com.fr.base.FRContext; +import com.fr.base.svg.IconUtils; import com.fr.design.DesignerEnvManager; +import com.fr.design.actions.help.alphafine.component.CustomSortPane; +import com.fr.design.constants.UIConstants; import com.fr.design.dialog.BasicPane; 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.imenu.UIPopupMenu; import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.utils.gui.GUICoreUtils; import com.fr.log.FineLoggerFactory; -import javax.swing.*; -import java.awt.*; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.KeyStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; /** * Created by XiaXiang on 2017/4/6. @@ -25,39 +43,32 @@ import java.awt.event.MouseEvent; public class AlphaFineConfigPane extends BasicPane { private static final String TYPE = "pressed"; private static final String DISPLAY_TYPE = "+"; - private static final String BACK_SLASH = "BACK_SLASH"; - private static final String DISPLAY_BACK_SLASH = "\\"; - private static final String SLASH = "SLASH"; - private static final String DISPLAY_SLASH = "/"; - private static final String CONTROL = "CONTROL"; - private static final String DISPLAY_CONTROL = "ctrl"; - private static final String OPEN_BRACKET = "OPEN_BRACKET"; - private static final String DISPLAY_OPEN_BRACKET = "{"; - private static final String CLOSE_BRACKET = "CLOSE_BRACKET"; - private static final String DISPLAY_CLOSE_BRACKET = "}"; - private static final String COMMA = "COMMA"; - private static final String DISPLAY_COMMA = ","; - private static final String PERIOD = "PERIOD"; - private static final String DISPLAY_PERIOD = "."; - private static final String SEMICOLON = "SEMICOLON"; - private static final String DISPLAY_SEMICOLON = ";"; - private static final String QUOTE = "QUOTE"; - private static final String DISPLAY_QUOTE = "'"; - private static final String EQUALS = "EQUALS"; - private static final String DISPLAY_EQUALS = "+"; - private static final String MINUS = "MINUS"; - private static final String DISPLAY_MINUS = "-"; - private static final String COMMAND = "META"; - private static final String SMALL_COMMAND = "meta"; - private static final String DISPLAY_COMMAND = "\u2318"; - - - private static final double COLUMN_GAP = 180; - private static final double ROW_GAP = 25; + private static final Color LABEL_TEXT = new Color(0x919193); + + private static final int SEARCH_CONFIG_PANE_HEIGHT = 70; + private static final int SEARCH_CONFIG_PANE_WIDTH = 87; + private static final double COLUMN_WIDTH = 150; + private static final double ROW_HEIGHT = 25; private KeyStroke shortCutKeyStore = null; - private UICheckBox enabledCheckbox, searchOnlineCheckbox, needSegmentationCheckbox, needIntelligentCustomerService, containRecommendCheckbox, containActionCheckbox, containDocumentCheckbox, containTemplateCheckbox, containPluginCheckbox, containFileContentCheckbox; + private UICheckBox enabledCheckbox, searchOnlineCheckbox, needSegmentationCheckbox; + private UICheckBox productDynamicsCheckbox, containTemplateShopCheckbox, containDocumentCheckbox, + containPluginCheckbox, containActionCheckbox, containMyTemplateCheckbox; + // 自定义排序按钮 + private ActionLabel customSortLabel; private UITextField shortcutsField; + + + // 当前tab排序。点击确定后会保存到配置文件中 + private String[] currentOrder; + + + // 搜索范围-我的模板,相关组件 + private JPanel containMyTemplatePane; + private JButton myTemplateSearchConfigButton; + private UIPopupMenu myTemplateSearchMenu; + private UICheckBox containTemplateNameSearchCheckbox, containFileContentSearchCheckbox; + public AlphaFineConfigPane() { this.initComponents(); } @@ -70,43 +81,154 @@ public class AlphaFineConfigPane extends BasicPane { createSearchConfigPane(contentPane); this.setLayout(FRGUIPaneFactory.createBorderLayout()); this.add(contentPane, BorderLayout.NORTH); - } - private Component[][] initSearchRangeComponents() { + private Component[][] initOnlineComponents() { Component[][] components = new Component[][]{ - new Component[]{containRecommendCheckbox, containActionCheckbox, containDocumentCheckbox}, - new Component[]{containTemplateCheckbox, containPluginCheckbox, containFileContentCheckbox}, - new Component[]{needIntelligentCustomerService, null, null} + new Component[]{searchOnlineCheckbox, needSegmentationCheckbox, null} }; return components; } - private Component[][] initOnlineComponents() { + /** + * 搜索范围面板 + */ + private void createSearchConfigPane(JPanel contentPane) { + double[] rowSize = {ROW_HEIGHT, ROW_HEIGHT, ROW_HEIGHT}; + double[] columnSize = {COLUMN_WIDTH, COLUMN_WIDTH, COLUMN_WIDTH}; + + JPanel searchConfigWrapperPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Search_Range")); + // 搜索选项 + productDynamicsCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_News")); + containActionCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Function")); + containPluginCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Plugin_Addon")); + containDocumentCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help")); + containMyTemplateCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_My_Templates")); + containFileContentSearchCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Templates_Content")); + containTemplateShopCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Shop")); + containMyTemplateCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_My_Templates")); + JPanel searchConfigPane = TableLayoutHelper.createTableLayoutPane(initSearchRangeComponents(), rowSize, columnSize); + + // 自定义排序 + JPanel customSortWrapperPane = new JPanel(); + customSortWrapperPane.setPreferredSize(new Dimension(SEARCH_CONFIG_PANE_HEIGHT, SEARCH_CONFIG_PANE_WIDTH)); + customSortWrapperPane.setAlignmentY(JPanel.TOP_ALIGNMENT); + customSortLabel = new ActionLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Config_Custom_Sort"), false); + customSortLabel.setForeground(UIConstants.NORMAL_BLUE); + customSortLabel.addActionListener((event)->{ + if (customSortLabel.isEnabled()) { + openCustomSortMenu(); + } + }); + customSortWrapperPane.add(customSortLabel); + if (!hasSelectedSearchRangeCheckBox()) { + customSortLabel.setEnabled(false); + } + + searchConfigWrapperPane.add(searchConfigPane); + searchConfigWrapperPane.add(customSortWrapperPane); + contentPane.add(searchConfigWrapperPane); + } + + /** + * 打开自定义排序面板 + * */ + private void openCustomSortMenu() { + CustomSortPane customSortPane = new CustomSortPane(getSelectedSearchRangeCheckBox(), this); + JPopupMenu popupMenu = new JPopupMenu(); + popupMenu.add(customSortPane); + GUICoreUtils.showPopupMenu(popupMenu, customSortLabel, 0, customSortLabel.getHeight()); + } + + + private Component[][] initSearchRangeComponents() { + // 我的模板checkbox设置,点击后 + initMyTemplateSearchPane(); + Component[][] components = new Component[][]{ - new Component[]{searchOnlineCheckbox, needSegmentationCheckbox, null} + new Component[]{productDynamicsCheckbox, containTemplateShopCheckbox, containDocumentCheckbox}, + new Component[]{containPluginCheckbox, containActionCheckbox, containMyTemplatePane}, }; + + // 添加选项点事件,无选中选项时自定排序按钮置灰 + UICheckBox[] checkBoxes = new UICheckBox[]{productDynamicsCheckbox, containTemplateShopCheckbox, containDocumentCheckbox, containPluginCheckbox, containActionCheckbox, containMyTemplateCheckbox}; + for (UICheckBox box : checkBoxes) { + box.addActionListener((e)->{ + customSortLabel.setEnabled(hasSelectedSearchRangeCheckBox()); + }); + } return components; } - private void createSearchConfigPane(JPanel contentPane) { - double[] rowSize = {ROW_GAP, ROW_GAP, ROW_GAP}; + /** + * 【搜索范围】中的复选框有无选中的 + * */ + private boolean hasSelectedSearchRangeCheckBox() { + return productDynamicsCheckbox.isSelected() || containTemplateShopCheckbox.isSelected() || containDocumentCheckbox.isSelected() + || containPluginCheckbox.isSelected() || containActionCheckbox.isSelected() || containMyTemplateCheckbox.isSelected(); + } + + /** + * 获取当前选中的搜索范围选项 + * */ + private List getSelectedSearchRangeCheckBox() { + List res = new ArrayList<>(); + UICheckBox[] checkBoxes = new UICheckBox[]{productDynamicsCheckbox, containTemplateShopCheckbox, containDocumentCheckbox, containPluginCheckbox, containActionCheckbox, containMyTemplateCheckbox}; + for (UICheckBox c : checkBoxes) { + if (c.isSelected()) { + res.add(c); + } + } + return res; + } - double[] columnSize = {COLUMN_GAP, COLUMN_GAP, COLUMN_GAP}; + /** + * 搜索范围-我的模板 + */ + private void initMyTemplateSearchPane() { + containMyTemplatePane = new JPanel(new FlowLayout(FlowLayout.LEFT, 4, 5)); + containMyTemplateCheckbox.setBorder(BorderFactory.createEmptyBorder()); + containMyTemplateCheckbox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (containMyTemplateCheckbox.isSelected()) { + myTemplateSearchConfigButton.setVisible(true); + } else { + myTemplateSearchConfigButton.setVisible(false); + } + } + }); + myTemplateSearchConfigButton = new JButton(); + myTemplateSearchConfigButton.setBorder(BorderFactory.createEmptyBorder()); + myTemplateSearchConfigButton.setMargin(new Insets(0, 0, 0, 0)); + myTemplateSearchConfigButton.setIcon(IconUtils.readIcon("/com/fr/design/mainframe/alphafine/images/config.svg")); + myTemplateSearchMenu = new UIPopupMenu(); + containTemplateNameSearchCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_AlphaFine_Config_Name_Search")); + containFileContentSearchCheckbox = new UICheckBox(Toolkit.i18nText("Fine-Design_AlphaFine_Config_Content_Search")); + containTemplateNameSearchCheckbox.setSelected(true); + containTemplateNameSearchCheckbox.setEnabled(false); + containTemplateNameSearchCheckbox.setBackground(null); + containFileContentSearchCheckbox.setBackground(null); + myTemplateSearchMenu.add(containTemplateNameSearchCheckbox); + myTemplateSearchMenu.add(containFileContentSearchCheckbox); + myTemplateSearchConfigButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + GUICoreUtils.showPopupMenu(myTemplateSearchMenu, containMyTemplatePane, containMyTemplateCheckbox.getWidth(), containMyTemplatePane.getY()); + } - JPanel northPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Search_Range")); - containRecommendCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Recommend")); - containActionCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Set")); - containPluginCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Plugin_Addon")); - containDocumentCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help")); - containTemplateCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Templates")); - containFileContentCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Templates_Content")); - needIntelligentCustomerService = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Intelligent_Customer_Service")); - JPanel searchConfigPane = TableLayoutHelper.createTableLayoutPane(initSearchRangeComponents(), rowSize, columnSize); - northPane.add(searchConfigPane); - contentPane.add(northPane); + @Override + public void mouseMoved(MouseEvent e) { + super.mouseMoved(e); + myTemplateSearchMenu.setVisible(false); + } + }); + containMyTemplatePane.add("containMyTemplateCheckbox", containMyTemplateCheckbox); + containMyTemplatePane.add("myTemplateSearchConfigButton", myTemplateSearchConfigButton); } + private void createShortcutsPane(JPanel contentPane) { JPanel northPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_Shortcut_Config")); shortcutsField = new UITextField(); @@ -117,7 +239,7 @@ public class AlphaFineConfigPane extends BasicPane { northPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Open") + ":")); northPane.add(shortcutsField); UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_AlphaFine_SetShortcuts")); - label.setForeground(Color.RED); + label.setForeground(LABEL_TEXT); northPane.add(label); contentPane.add(northPane); } @@ -139,7 +261,7 @@ public class AlphaFineConfigPane extends BasicPane { int keyCode = e.getKeyCode(); shortCutKeyStore = KeyStroke.getKeyStroke(keyCode, modifier); String str = shortCutKeyStore.toString(); - shortcutsField.setText(getDisplayShortCut(str)); + shortcutsField.setText(AlphaFineShortCutUtil.getDisplayShortCut(str)); shortcutsField.selectAll(); } }); @@ -153,24 +275,24 @@ public class AlphaFineConfigPane extends BasicPane { @Override public void actionPerformed(ActionEvent e) { if (!searchOnlineCheckbox.isSelected()) { - containRecommendCheckbox.setEnabled(false); + productDynamicsCheckbox.setEnabled(false); containPluginCheckbox.setEnabled(false); containDocumentCheckbox.setEnabled(false); - needIntelligentCustomerService.setEnabled(false); - containRecommendCheckbox.setSelected(false); + containTemplateShopCheckbox.setEnabled(false); + productDynamicsCheckbox.setSelected(false); containPluginCheckbox.setSelected(false); containDocumentCheckbox.setSelected(false); - needIntelligentCustomerService.setSelected(false); + containTemplateShopCheckbox.setSelected(false); } else { - containRecommendCheckbox.setEnabled(true); + productDynamicsCheckbox.setEnabled(true); containPluginCheckbox.setEnabled(true); containDocumentCheckbox.setEnabled(true); - needIntelligentCustomerService.setEnabled(true); + containTemplateShopCheckbox.setEnabled(true); } } }); - double[] rowSize = {ROW_GAP}; - double[] columnSize = {COLUMN_GAP, COLUMN_GAP, COLUMN_GAP}; + double[] rowSize = {ROW_HEIGHT}; + double[] columnSize = {COLUMN_WIDTH, COLUMN_WIDTH, COLUMN_WIDTH}; JPanel onlinePane = TableLayoutHelper.createTableLayoutPane(initOnlineComponents(), rowSize, columnSize); northPane.add(onlinePane); contentPane.add(northPane); @@ -198,8 +320,10 @@ public class AlphaFineConfigPane extends BasicPane { this.searchOnlineCheckbox.setSelected(enabled4Locale); this.containActionCheckbox.setSelected(alphaFineConfigManager.isContainAction()); - this.containTemplateCheckbox.setSelected(alphaFineConfigManager.isContainTemplate()); - this.containFileContentCheckbox.setSelected(alphaFineConfigManager.isContainFileContent()); + + this.containMyTemplateCheckbox.setSelected(alphaFineConfigManager.isContainMyTemplate()); + this.myTemplateSearchConfigButton.setVisible(alphaFineConfigManager.isContainMyTemplate()); + this.containFileContentSearchCheckbox.setSelected(alphaFineConfigManager.isContainFileContent()); this.containDocumentCheckbox.setSelected(alphaFineConfigManager.isContainDocument() && enabled4Locale); this.containDocumentCheckbox.setEnabled(enabled4Locale); @@ -207,17 +331,25 @@ public class AlphaFineConfigPane extends BasicPane { this.containPluginCheckbox.setSelected(alphaFineConfigManager.isContainPlugin() && enabled4Locale); this.containPluginCheckbox.setEnabled(enabled4Locale); - this.containRecommendCheckbox.setSelected(alphaFineConfigManager.isContainRecommend() && enabled4Locale); - this.containRecommendCheckbox.setEnabled(enabled4Locale); + this.productDynamicsCheckbox.setSelected(alphaFineConfigManager.isProductDynamics() && enabled4Locale); + this.productDynamicsCheckbox.setEnabled(enabled4Locale); - this.shortcutsField.setText(getDisplayShortCut(alphaFineConfigManager.getShortcuts())); + this.containTemplateShopCheckbox.setSelected(alphaFineConfigManager.hasTemplateShop() && enabled4Locale); + this.containTemplateShopCheckbox.setEnabled(enabled4Locale); - this.needSegmentationCheckbox.setSelected(alphaFineConfigManager.isNeedSegmentationCheckbox()); + this.shortcutsField.setText(AlphaFineShortCutUtil.getDisplayShortCut(alphaFineConfigManager.getShortcuts())); - this.needIntelligentCustomerService.setSelected(alphaFineConfigManager.isNeedIntelligentCustomerService() && enabled4Locale); - this.needIntelligentCustomerService.setEnabled(enabled4Locale); + this.needSegmentationCheckbox.setSelected(alphaFineConfigManager.isNeedSegmentationCheckbox()); shortCutKeyStore = convert2KeyStroke(alphaFineConfigManager.getShortcuts()); + + this.currentOrder = alphaFineConfigManager.getTabOrder().clone(); + + if (!hasSelectedSearchRangeCheckBox()) { + customSortLabel.setEnabled(false); + } else { + customSortLabel.setEnabled(true); + } } public void update() { @@ -226,14 +358,16 @@ public class AlphaFineConfigPane extends BasicPane { alphaFineConfigManager.setContainPlugin(this.containPluginCheckbox.isSelected()); alphaFineConfigManager.setContainAction(this.containActionCheckbox.isSelected()); alphaFineConfigManager.setContainDocument(this.containDocumentCheckbox.isSelected()); - alphaFineConfigManager.setContainRecommend(this.containRecommendCheckbox.isSelected()); + alphaFineConfigManager.setProductDynamics(this.productDynamicsCheckbox.isSelected()); + alphaFineConfigManager.setShowTemplateShop(this.containTemplateShopCheckbox.isSelected()); alphaFineConfigManager.setEnabled(this.enabledCheckbox.isSelected()); alphaFineConfigManager.setSearchOnLine(this.searchOnlineCheckbox.isSelected()); - alphaFineConfigManager.setContainTemplate(this.containTemplateCheckbox.isSelected()); - alphaFineConfigManager.setContainFileContent(this.containFileContentCheckbox.isSelected()); + alphaFineConfigManager.setContainMyTemplate(this.containMyTemplateCheckbox.isSelected()); + alphaFineConfigManager.setContainFileContent(this.containFileContentSearchCheckbox.isSelected()); alphaFineConfigManager.setNeedSegmentationCheckbox(this.needSegmentationCheckbox.isSelected()); - alphaFineConfigManager.setNeedIntelligentCustomerService(this.needIntelligentCustomerService.isSelected()); alphaFineConfigManager.setShortcuts(shortCutKeyStore != null ? shortCutKeyStore.toString().replace(TYPE, DISPLAY_TYPE) : this.shortcutsField.getText()); + alphaFineConfigManager.setTabOrder(currentOrder); + designerEnvManager.setAlphaFineConfigManager(alphaFineConfigManager); try { DesignerEnvManager.loadLogSetting(); @@ -245,13 +379,6 @@ public class AlphaFineConfigPane extends BasicPane { } - private String getDisplayShortCut(String shortCut) { - return shortCut.replace(TYPE, DISPLAY_TYPE).replace(BACK_SLASH, DISPLAY_BACK_SLASH).replace(SLASH, DISPLAY_SLASH) - .replace(CONTROL, DISPLAY_CONTROL).replace(OPEN_BRACKET, DISPLAY_OPEN_BRACKET).replace(CLOSE_BRACKET, DISPLAY_CLOSE_BRACKET) - .replace(COMMA, DISPLAY_COMMA).replace(PERIOD, DISPLAY_PERIOD).replace(SEMICOLON, DISPLAY_SEMICOLON).replace(QUOTE, DISPLAY_QUOTE) - .replace(EQUALS, DISPLAY_EQUALS).replace(MINUS, DISPLAY_MINUS).replace(COMMAND, DISPLAY_COMMAND).replace(SMALL_COMMAND, DISPLAY_COMMAND); - } - private KeyStroke convert2KeyStroke(String ks) { return KeyStroke.getKeyStroke(ks.replace(DISPLAY_TYPE, TYPE)); @@ -266,10 +393,18 @@ public class AlphaFineConfigPane extends BasicPane { } public UICheckBox getIsContainFileContentCheckbox() { - return containFileContentCheckbox; + return containFileContentSearchCheckbox; } public void setIsContainFileContentCheckbox(UICheckBox isContainFileContentCheckbox) { - this.containFileContentCheckbox = isContainFileContentCheckbox; + this.containFileContentSearchCheckbox = isContainFileContentCheckbox; + } + + public String[] getCurrentOrder() { + return currentOrder; + } + + public void setCurrentOrder(String[] currentOrder) { + this.currentOrder = currentOrder; } } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineConstants.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConstants.java similarity index 55% rename from designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineConstants.java rename to designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConstants.java index 3946c9cbc2..a6eb88ef8e 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/AlphaFineConstants.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineConstants.java @@ -1,13 +1,19 @@ -package com.fr.design.mainframe.alphafine; +package com.fr.design.actions.help.alphafine; import com.fr.base.extension.FileExtension; +import com.fr.base.svg.IconUtils; +import com.fr.design.i18n.Toolkit; import com.fr.design.utils.DesignUtils; -import com.fr.general.CloudCenter; +import com.fr.general.IOUtils; +import javax.swing.Icon; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; /** @@ -15,6 +21,19 @@ import java.util.ArrayList; */ public class AlphaFineConstants { + + public static final String FUNCTION = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Function"); + + public static final String MY_TEMPLATES = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_My_Templates"); + + public static final String PRODUCT_NEWS = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Product_News"); + + public static final String HELP = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Community_Help"); + + public static final String PLUGIN = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Plugin_Addon"); + + public static final String TEMPLATE_SHOP = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Template_Shop"); + public static final int SHOW_SIZE = 5; public static final int MAX_FILE_SIZE = 1000; @@ -33,7 +52,7 @@ public class AlphaFineConstants { public static final int CONTENT_HEIGHT = 405; - public static final int CELL_HEIGHT = 32; + public static final int CELL_HEIGHT = 29; public static final int CELL_TITLE_HEIGHT = 24; @@ -41,6 +60,15 @@ public class AlphaFineConstants { public static final int HOT_ITEMS = 6; + /** + * 限制搜索字符长度 + */ + public static final int LEN_LIMIT = 50; + + /** + * 帮助文档搜索间隔(ms) api限制了1s之内只能搜索一次 + */ + public static final long DOCUMENT_SEARCH_GAP = 1000; public static final Dimension FULL_SIZE = new Dimension(680, 460); @@ -54,10 +82,17 @@ public class AlphaFineConstants { public static final Dimension HOT_ISSUES_JAPNEL_SIZE = new Dimension(213, 182); + /** + * 展示面板的尺寸 + */ + public static final Dimension PREVIEW_SIZE = new Dimension(680, 305); + public static final Dimension CLOSE_BUTTON_SIZE = new Dimension(40, 40); public static final Color WHITE = new Color(0xf9f9f9); + public static final Color LABEL_SELECTED = new Color(0x419bf9); + public static final Color GRAY = new Color(0xd2d2d2); public static final Color LIGHT_GRAY = new Color(0xcccccc); @@ -88,60 +123,65 @@ public class AlphaFineConstants { public static final String ALPHA_HOT_IMAGE_NAME = "alphafine_hot"; - public static final String PLUGIN_SEARCH_URL = CloudCenter.getInstance().acquireUrlByKind("plugin.searchAPI"); - - public static final String PLUGIN_URL = CloudCenter.getInstance().acquireUrlByKind("af.pluginInfo"); - - public static final String REUSE_URL = CloudCenter.getInstance().acquireUrlByKind("af.reuseInfo"); + public static final String SPECIAL_CHARACTER_REGEX = "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】';:”“’。,、?]"; + public static final String BOTTOM_REGEX_FIRST = "
([\\s\\S]*?)class=\"jiaoyes\">YES
"; - public static final String DOCUMENT_DOC_URL = CloudCenter.getInstance().acquireUrlByKind("af.doc_view"); + public static final String BOTTOM_REGEX_SECOND = "
"; - public static final String DOCUMENT_SEARCH_URL = CloudCenter.getInstance().acquireUrlByKind("af.doc_search"); + public static final String LINK_REGEX = "javascript:;\"([\\s\\S]*?)','"; - public static final String DOCUMENT_INFORMATION_URL = CloudCenter.getInstance().acquireUrlByKind("af.doc_info"); + public static final String LINK_REGEX_ANOTHER = "javascript:([\\s\\S]*?)url=\""; - public static final String PLUGIN_IMAGE_URL = CloudCenter.getInstance().acquireUrlByKind("af.plugin_image"); + public static final String ALPHA_ROBOT_SEARCH_TOKEN = "K8dl0Np6l0gs"; - public static final String CLOUD_SERVER_URL = CloudCenter.getInstance().acquireUrlByKind("af.record"); + public static final String SEARCH_BY_ID = "?id="; - public static final String SEARCH_API = CloudCenter.getInstance().acquireUrlByKind("af.cloud_search"); + public static final String JAVASCRIPT_PREFIX = "javascript:SendJava"; - public static final String SPECIAL_CHARACTER_REGEX = "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】';:”“’。,、?]"; + public static final String CHINESE_CHARACTERS = "[\\u4e00-\\u9fa5]"; - public static final String BOTTOM_REGEX_FIRST = "
([\\s\\S]*?)class=\"jiaoyes\">YES
"; + public static final String FIRST_PAGE = "-1"; - public static final String BOTTOM_REGEX_SECOND = "
"; + public static final FileExtension[] FILE_EXTENSIONS = new FileExtension[]{FileExtension.CPT, FileExtension.FRM}; - public static final String LINK_REGEX = "javascript:;\"([\\s\\S]*?)','"; + public static final int RECOMMEND_MAX_ITEM_NUM = 3; - public static final String LINK_REGEX_ANOTHER = "javascript:([\\s\\S]*?)url=\""; + public static final String BACK_ICON_NAME = "back@1x.png"; - public static final String ALPHA_ROBOT_SEARCH_TOKEN = "K8dl0Np6l0gs"; + public static final Icon NO_RESULT_ICON = IOUtils.readIcon(AlphaFineConstants.IMAGE_URL + "noresult.png"); - public static final String SIMILAR_SEARCH_URL_PREFIX = CloudCenter.getInstance().acquireUrlByKind("af.similar_search"); + public static final Color SUSPENDED_COLOR = new Color(84, 165, 249); - public static final String COMPLEMENT_ADVICE_SEARCH_URL_PREFIX = CloudCenter.getInstance().acquireUrlByKind("af.advice_search"); + public static final Color FOREGROUND_COLOR = new Color(51, 51, 52); - public static final String ALPHA_HOT_SEARCH = CloudCenter.getInstance().acquireUrlByKind("af.hot_search"); + /** + * 后面数字代表透明度 80% + */ + public static final Color FOREGROUND_COLOR_8 = new Color(51, 51, 52, 204); - public static final String ALPHA_GO_TO_FORUM = CloudCenter.getInstance().acquireUrlByKind("af.go_fourm"); + public static final Color FOREGROUND_COLOR_6 = new Color(51, 51, 52, 153); - public static final String ALPHA_GO_TO_WEB = CloudCenter.getInstance().acquireUrlByKind("af.go_web"); + public static final Color FOREGROUND_COLOR_5 = new Color(51, 51, 52, 128); - public static final String ALPHA_PREVIEW = CloudCenter.getInstance().acquireUrlByKind("af.preview"); + public static final Color BACKGROUND_COLOR = new Color(245, 245, 247); - public static final String JAVASCRIPT_PREFIX = "javascript:SendJava"; + public static final Icon BULB_ICON = IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/bulb.svg"); - public static final String CHINESE_CHARACTERS = "[\\u4e00-\\u9fa5]"; + public static final Icon YELLOW_BULB_ICON = IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/yellow_bulb.svg"); - public static final String FIRST_PAGE = "-1"; + public static final Icon LIGHT_YELLOW_BULB_ICON = IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/light_yellow_bulb.svg"); - public static final FileExtension[] FILE_EXTENSIONS = new FileExtension[]{FileExtension.CPT, FileExtension.FRM}; + public static final String HOT_SEARCH = Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search"); - public static final int RECOMMEND_MAX_ITEM_NUM = 3; + public static final Set HOT_SEARCH_SET = new LinkedHashSet<>( + Arrays.asList( + Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search_TOP_ONE"), + Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search_TOP_TWO"), + Toolkit.i18nText("Fine-Design_Report_AlphaFine_Hot_Search_TOP_THREE") + ) + ); - public static final String BACK_ICON_NAME = "back@1x.png"; public static final ArrayList CONJUNCTION = new ArrayList() {{ add(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Conjunction_HE")); @@ -149,4 +189,11 @@ public class AlphaFineConstants { add(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_AlphaFine_Conjunction_DE")); }}; + public static final String LOADING = "loading"; + + public static final String NETWORK_ERROR = "network error"; + + public static final String TITLE = "AlphaFine"; + + public static final int DEFAULT_CLICK_COUNT = 1; } diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineShortCutUtil.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineShortCutUtil.java new file mode 100644 index 0000000000..e21fc84ee5 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/AlphaFineShortCutUtil.java @@ -0,0 +1,44 @@ +package com.fr.design.actions.help.alphafine; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/26 + */ +public class AlphaFineShortCutUtil { + + private static final String TYPE = "pressed"; + private static final String DISPLAY_TYPE = "+"; + private static final String BACK_SLASH = "BACK_SLASH"; + private static final String DISPLAY_BACK_SLASH = "\\"; + private static final String SLASH = "SLASH"; + private static final String DISPLAY_SLASH = "/"; + private static final String CONTROL = "CONTROL"; + private static final String DISPLAY_CONTROL = "ctrl"; + private static final String OPEN_BRACKET = "OPEN_BRACKET"; + private static final String DISPLAY_OPEN_BRACKET = "{"; + private static final String CLOSE_BRACKET = "CLOSE_BRACKET"; + private static final String DISPLAY_CLOSE_BRACKET = "}"; + private static final String COMMA = "COMMA"; + private static final String DISPLAY_COMMA = ","; + private static final String PERIOD = "PERIOD"; + private static final String DISPLAY_PERIOD = "."; + private static final String SEMICOLON = "SEMICOLON"; + private static final String DISPLAY_SEMICOLON = ";"; + private static final String QUOTE = "QUOTE"; + private static final String DISPLAY_QUOTE = "'"; + private static final String EQUALS = "EQUALS"; + private static final String DISPLAY_EQUALS = "+"; + private static final String MINUS = "MINUS"; + private static final String DISPLAY_MINUS = "-"; + private static final String COMMAND = "META"; + private static final String SMALL_COMMAND = "meta"; + private static final String DISPLAY_COMMAND = "\u2318"; + + public static String getDisplayShortCut(String shortCut) { + return shortCut.replace(TYPE, DISPLAY_TYPE).replace(BACK_SLASH, DISPLAY_BACK_SLASH).replace(SLASH, DISPLAY_SLASH) + .replace(CONTROL, DISPLAY_CONTROL).replace(OPEN_BRACKET, DISPLAY_OPEN_BRACKET).replace(CLOSE_BRACKET, DISPLAY_CLOSE_BRACKET) + .replace(COMMA, DISPLAY_COMMA).replace(PERIOD, DISPLAY_PERIOD).replace(SEMICOLON, DISPLAY_SEMICOLON).replace(QUOTE, DISPLAY_QUOTE) + .replace(EQUALS, DISPLAY_EQUALS).replace(MINUS, DISPLAY_MINUS).replace(COMMAND, DISPLAY_COMMAND).replace(SMALL_COMMAND, DISPLAY_COMMAND); + } +} diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/SizedStack.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/SizedStack.java new file mode 100644 index 0000000000..fbc6eca00c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/SizedStack.java @@ -0,0 +1,30 @@ +package com.fr.design.actions.help.alphafine; + +import java.util.Stack; + +/** + * @author hades + * @version 11.0 + * Created by hades on 2022/4/23 + */ +public class SizedStack extends Stack { + + private final int maxSize; + + public SizedStack(int size) { + super(); + this.maxSize = size; + } + + @Override + public T push(T object) { + while (this.size() >= maxSize) { + this.remove(0); + } + // 不重复 + if (this.contains(object)) { + return object; + } + return super.push(object); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/CustomSortPane.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/CustomSortPane.java new file mode 100644 index 0000000000..9e2af09379 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/CustomSortPane.java @@ -0,0 +1,229 @@ +package com.fr.design.actions.help.alphafine.component; + +import com.fr.base.svg.IconUtils; +import com.fr.design.actions.help.alphafine.AlphaFineConfigPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.plaf.PanelUI; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +/** + * alphafine设置 - 搜索范围 - 自定义排序 - 弹出面板 + * + * @author Link + * @version 11.0 + * Created by Link on 2022/9/18 + */ +public class CustomSortPane extends JPanel { + + + private static final int WIDTH = 147; + private static final int ITEM_HEIGHT = 23; + private static final int GAP = 1; + private static final Color BACKGROUND_COLOR = new Color(0xdadadd); + + private UIButton top; + private UIButton bottom; + private UIButton up; + private UIButton down; + private JPanel toolbarPane; + private MenuLabelPane sortItemPane; + private List sortItems; + private MenuLabel selectedLabel; + private AlphaFineConfigPane parentPane; + + public CustomSortPane(List items, AlphaFineConfigPane parentPane) { + this.sortItems = items; + this.parentPane = parentPane; + setLayout(new BorderLayout(GAP, GAP)); + int height = (sortItems.size() + 1) * (ITEM_HEIGHT + GAP) + GAP; + setPreferredSize(new Dimension(WIDTH, height)); + initComponent(); + add(toolbarPane, BorderLayout.NORTH); + add(sortItemPane, BorderLayout.CENTER); + revalidate(); + this.setVisible(true); + } + + @Override + public void setUI(PanelUI ui) { + super.setUI(ui); + setBackground(BACKGROUND_COLOR); + + } + + private void initComponent() { + createToolbarPane(); + createSortItemPane(); + } + + private void createToolbarPane() { + top = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/top.svg"), false); + bottom = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/bottom.svg"), false); + up = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/up.svg"), false); + down = new UIButton(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/down.svg"), false); + top.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/top_disable.svg")); + bottom.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/bottom_disable.svg")); + up.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/up_disable.svg")); + down.setDisabledIcon(IconUtils.readIcon("com/fr/design/mainframe/alphafine/images/down_disable.svg")); + top.addActionListener(e -> { + SwingUtilities.invokeLater(() -> { + sortItemPane.setComponentZOrder(selectedLabel, 0); + setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount()); + CustomSortPane.this.revalidate(); + CustomSortPane.this.repaint(); + refreshCurrentOrder(); + }); + + }); + bottom.addActionListener(e -> { + SwingUtilities.invokeLater(() -> { + sortItemPane.setComponentZOrder(selectedLabel, sortItemPane.getComponentCount() - 1); + setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount()); + CustomSortPane.this.revalidate(); + CustomSortPane.this.repaint(); + refreshCurrentOrder(); + }); + + }); + up.addActionListener(e -> { + SwingUtilities.invokeLater(() -> { + sortItemPane.setComponentZOrder(selectedLabel, sortItemPane.getComponentZOrder(selectedLabel) - 1); + setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount()); + CustomSortPane.this.revalidate(); + CustomSortPane.this.repaint(); + refreshCurrentOrder(); + }); + + }); + down.addActionListener(e -> { + SwingUtilities.invokeLater(() -> { + sortItemPane.setComponentZOrder(selectedLabel, sortItemPane.getComponentZOrder(selectedLabel) + 1); + setToolbarEnable(sortItemPane.getComponentZOrder(selectedLabel), sortItemPane.getComponentCount()); + CustomSortPane.this.revalidate(); + CustomSortPane.this.repaint(); + refreshCurrentOrder(); + }); + + }); + toolbarPane = new JPanel(new FlowLayout(FlowLayout.TRAILING, GAP, GAP)); + toolbarPane.setBorder(BorderFactory.createEmptyBorder()); + toolbarPane.add(top); + toolbarPane.add(bottom); + toolbarPane.add(up); + toolbarPane.add(down); + } + + private void createSortItemPane() { + String[] currentTabOrder = parentPane.getCurrentOrder(); + Map sortMap = new HashMap<>(); + for (int i = 0; i < currentTabOrder.length; i++) { + sortMap.put(currentTabOrder[i], i); + } + List sortLabels = new ArrayList<>(); + for (UICheckBox item : sortItems) { + MenuLabel label = new MenuLabel(item.getText(), (Function) o -> { + selectedLabel = o; + disableButton(); + return null; + }); + sortLabels.add(label); + } + sortLabels.sort(Comparator.comparingInt(tab -> sortMap.get(tab.getText()))); + sortItemPane = new MenuLabelPane(sortLabels); + } + + /** + * 如果选中第一个和最后一个,则置灰向上和向下的按钮 + */ + private void disableButton() { + int order = sortItemPane.getComponentZOrder(selectedLabel); + if (order == 0) { + setToolbarEnable(false, false, true, true); + } else if (order == sortItemPane.getComponentCount() - 1) { + setToolbarEnable(true, true, false, false); + } else { + setToolbarEnable(true, true, true, true); + } + } + + /** + * 设置 置顶,上移,下移,置底 按钮的状态 + * true:启用 + * false:关闭 + */ + private void setToolbarEnable(boolean top, boolean up, boolean down, boolean bottom) { + this.top.setEnabled(top); + this.up.setEnabled(up); + this.down.setEnabled(down); + this.bottom.setEnabled(bottom); + } + + /** + * 根据选项当前位置以及菜单大小设置 置顶,上移,下移,置底 按钮的状态 + */ + private void setToolbarEnable(int order, int maxOrder) { + this.top.setEnabled(true); + this.up.setEnabled(true); + this.down.setEnabled(true); + this.bottom.setEnabled(true); + // 选项处于顶端,则置灰上移和置顶按钮 + if (order == 0) { + this.top.setEnabled(false); + this.up.setEnabled(false); + } + // 选项处于底端,则置灰下移和置底按钮 + if (order == maxOrder - 1) { + this.down.setEnabled(false); + this.bottom.setEnabled(false); + } + } + + private void refreshCurrentOrder() { + String[] currentTabOrder = parentPane.getCurrentOrder(); + HashSet selectedTab = new HashSet<>(); + for (UICheckBox item : sortItems) { + selectedTab.add(item.getText()); + } + + // 未选中的tab,保持原排序不变 + Map exTab = new HashMap<>(); + for (int i = 0; i < currentTabOrder.length; i++) { + if (!selectedTab.contains(currentTabOrder[i])) { + exTab.put(currentTabOrder[i], i); + } + } + + // 计算当前排序 + String[] newOrder = new String[currentTabOrder.length]; + Component[] components = sortItemPane.getComponents(); + for (String s : exTab.keySet()) { + newOrder[exTab.get(s)] = s; + } + + int t = 0; + for (int i = 0; i < newOrder.length; i++) { + if (StringUtils.isEmpty(newOrder[i])) { + newOrder[i] = ((MenuLabel) components[t++]).getText(); + } + } + parentPane.setCurrentOrder(newOrder); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/MenuLabel.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/MenuLabel.java new file mode 100644 index 0000000000..5f3708ed97 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/MenuLabel.java @@ -0,0 +1,96 @@ +package com.fr.design.actions.help.alphafine.component; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.utils.DesignUtils; + +import javax.swing.BorderFactory; +import javax.swing.plaf.LabelUI; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.function.Function; + +/** + * 菜单选项label + * + * @author Link + * @version 11.0 + * Created by Link on 2022/9/18 + */ +public class MenuLabel extends UILabel { + + private static final Color BACKGROUND_COLOR = Color.white; + private static final Color SELECTED_COLOR = new Color(0x419BF9); + private static final Color HOVERED_COLOR = new Color(0xd9ebfe); + private static final int HEIGHT = 23; + private static final int WIDTH = 147; + + private MenuLabelPane parentMenu; + private final Function function; + private boolean selected; + + public MenuLabel(String text, Function function) { + super(text); + this.function = function; + setOpaque(true); + addMouseListener(createMouseListener()); + } + + public void setParentMenu(MenuLabelPane menu) { + this.parentMenu = menu; + } + + + @Override + public void setUI(LabelUI ui) { + super.setUI(ui); + this.setBackground(BACKGROUND_COLOR); + this.setBorder(BorderFactory.createEmptyBorder(2, 10, 1, 10)); + this.setPreferredSize(new Dimension(WIDTH, HEIGHT)); + this.setFont(DesignUtils.getDefaultGUIFont().applySize(12)); + } + + public boolean isSelected() { + return selected; + } + + public void setSelected(boolean selected) { + if (selected) { + parentMenu.setNoneSelected(); + setBackground(SELECTED_COLOR); + function.apply(this); + this.selected = true; + } else { + setBackground(BACKGROUND_COLOR); + this.selected = false; + } + } + + MouseListener createMouseListener() { + return new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + setSelected(true); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + if (!selected) { + setBackground(HOVERED_COLOR); + } + } + + @Override + public void mouseExited(MouseEvent e) { + super.mouseExited(e); + if (!selected) { + setBackground(BACKGROUND_COLOR); + } + } + }; + } +} diff --git a/designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/MenuLabelPane.java b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/MenuLabelPane.java new file mode 100644 index 0000000000..929f54837c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/help/alphafine/component/MenuLabelPane.java @@ -0,0 +1,34 @@ +package com.fr.design.actions.help.alphafine.component; + +import javax.swing.JPanel; +import java.awt.FlowLayout; +import java.util.List; + +/** + * 简单菜单面板 + * + * @author Link + * @version 11.0 + * Created by Link on 2022/9/18 + */ +public class MenuLabelPane extends JPanel { + + private static final int GAP = 1; + + private List labels; + + public MenuLabelPane(List labels) { + this.labels = labels; + setLayout(new FlowLayout(FlowLayout.CENTER, GAP, GAP)); + for (MenuLabel label : labels) { + label.setParentMenu(this); + add(label); + } + } + + public void setNoneSelected() { + for (MenuLabel label : labels) { + label.setSelected(false); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java b/designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java index 140a46579d..22fff0d178 100644 --- a/designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java +++ b/designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java @@ -27,11 +27,7 @@ public abstract class ClipboardFilter { } public static T cut(T selection) { - - ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign); - Set providers = manager.getArray(ClipboardHandlerProvider.XML_TAG); - providers.addAll(clipboardHandlerProviders); - for (ClipboardHandlerProvider provider : providers) { + for (ClipboardHandlerProvider provider : getClipboardHandlerProviders()) { if (provider.support(selection)) { selection = ((ClipboardHandlerProvider) provider).cut(selection); } @@ -40,10 +36,7 @@ public abstract class ClipboardFilter { } public static T copy(T selection) { - ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign); - Set providers = manager.getArray(ClipboardHandlerProvider.XML_TAG); - providers.addAll(clipboardHandlerProviders); - for (ClipboardHandlerProvider provider : providers) { + for (ClipboardHandlerProvider provider : getClipboardHandlerProviders()) { if (provider.support(selection)) { selection = ((ClipboardHandlerProvider) provider).copy(selection); } @@ -52,15 +45,27 @@ public abstract class ClipboardFilter { } public static T paste(T selection) { - ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign); - Set providers = manager.getArray(ClipboardHandlerProvider.XML_TAG); - providers.addAll(clipboardHandlerProviders); - - for (ClipboardHandlerProvider provider : providers) { + for (ClipboardHandlerProvider provider : getClipboardHandlerProviders()) { if (provider.support(selection)) { selection = ((ClipboardHandlerProvider) provider).paste(selection); } } return selection; } + + private static Set getClipboardHandlerProviders() { + Set providers = new HashSet<>(); + + for (ClipboardHandlerProvider clipboardHandlerProvider : clipboardHandlerProviders) { + providers.add(clipboardHandlerProvider); + } + + ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign); + Set pluginProviders = manager.getArray(ClipboardHandlerProvider.XML_TAG); + for (ClipboardHandlerProvider clipboardHandlerProvider : pluginProviders) { + providers.add(clipboardHandlerProvider); + } + + return providers; + } } diff --git a/designer-base/src/main/java/com/fr/design/beans/ErrorMsgTextFieldAdapter.java b/designer-base/src/main/java/com/fr/design/beans/ErrorMsgTextFieldAdapter.java new file mode 100644 index 0000000000..e2444a4eca --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/beans/ErrorMsgTextFieldAdapter.java @@ -0,0 +1,11 @@ +package com.fr.design.beans; + +import javax.swing.JComponent; + +public interface ErrorMsgTextFieldAdapter { + void setText(String str); + + String getText(); + + JComponent getErrorMsgTextField(); +} diff --git a/designer-base/src/main/java/com/fr/design/beans/UITextFieldAdapter.java b/designer-base/src/main/java/com/fr/design/beans/UITextFieldAdapter.java new file mode 100644 index 0000000000..48fa6944fc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/beans/UITextFieldAdapter.java @@ -0,0 +1,46 @@ +package com.fr.design.beans; + +import com.fr.design.gui.itextfield.UITextField; + +import javax.swing.JComponent; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +public class UITextFieldAdapter implements ErrorMsgTextFieldAdapter { + private final UITextField uiTextField = new UITextField(); + + public UITextFieldAdapter(){ + addDocumentListener(); + } + @Override + public void setText(String str) { + uiTextField.setText(str); + } + + @Override + public String getText() { + return uiTextField.getText(); + } + + public void addDocumentListener() { + uiTextField.getDocument().addDocumentListener(new DocumentListener() { + + public void changedUpdate(DocumentEvent e) { + uiTextField.setToolTipText(uiTextField.getText()); + } + + public void insertUpdate(DocumentEvent e) { + uiTextField.setToolTipText(uiTextField.getText()); + } + + public void removeUpdate(DocumentEvent e) { + uiTextField.setToolTipText(uiTextField.getText()); + } + }); + } + + @Override + public JComponent getErrorMsgTextField() { + return uiTextField; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/constants/TableDataConstants.java b/designer-base/src/main/java/com/fr/design/constants/TableDataConstants.java new file mode 100644 index 0000000000..7d8c66c093 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/constants/TableDataConstants.java @@ -0,0 +1,5 @@ +package com.fr.design.constants; + +public class TableDataConstants { + public static final String SEPARATOR = "_"; +} diff --git a/designer-base/src/main/java/com/fr/design/data/BasicTableDataUtils.java b/designer-base/src/main/java/com/fr/design/data/BasicTableDataUtils.java index 57c7e23a13..ae90c5bacc 100644 --- a/designer-base/src/main/java/com/fr/design/data/BasicTableDataUtils.java +++ b/designer-base/src/main/java/com/fr/design/data/BasicTableDataUtils.java @@ -1,6 +1,7 @@ package com.fr.design.data; import com.fr.data.TableDataSource; +import com.fr.design.constants.TableDataConstants; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.i18n.Toolkit; import com.fr.stable.StringUtils; @@ -11,8 +12,6 @@ import com.fr.stable.StringUtils; * Created by hades on 2020/4/27 */ public abstract class BasicTableDataUtils { - private static final String SEPARATOR = "-"; - private static final int LEN = 2; @@ -38,10 +37,10 @@ public abstract class BasicTableDataUtils { public static String getTableDataName(boolean isCover, TableDataSource tds, String tdName, String srcName, boolean isDsNameRepeaded) { if (isCover) { - return srcName + SEPARATOR + tdName; + return srcName + TableDataConstants.SEPARATOR + tdName; } if (tds.getTableData(tdName) != null || isDsNameRepeaded) {//如果有同名的就拼上来源名称 - tdName = srcName + SEPARATOR + tdName; + tdName = srcName + TableDataConstants.SEPARATOR + tdName; } int i = 0; while (tds.getTableData(tdName) != null) { 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 f1758f0689..8a57cca0bd 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 @@ -172,23 +172,38 @@ public abstract class DesignTableDataManager { globalDsListeners.add(l); } + private static String getCurrentChangeListenerKey() { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + String key = StringUtils.EMPTY; + if (template != null) { + key = template.getPath(); + } + return key; + } + /** * 添加模板数据集改变 监听事件. * * @param l ChangeListener监听器 */ public static void addDsChangeListener(ChangeListener l) { - JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - String key = StringUtils.EMPTY; - if (template != null) { - key = template.getPath(); - } + String key = getCurrentChangeListenerKey(); List dsListeners = dsListenersMap.get(key); if (dsListeners == null) { dsListeners = new ArrayList(); dsListenersMap.put(key, dsListeners); } - dsListeners.add(l); + if (!dsListeners.contains(l)) { + dsListeners.add(l); + } + } + + public static void removeDsChangeLister(ChangeListener l) { + String key = getCurrentChangeListenerKey(); + List dsListeners = dsListenersMap.get(key); + if (dsListeners != null) { + dsListeners.remove(l); + } } /** diff --git a/designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java b/designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java new file mode 100644 index 0000000000..57fba61780 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java @@ -0,0 +1,93 @@ +package com.fr.design.data; + +import org.jetbrains.annotations.NotNull; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2022/3/28 + */ +public final class MapCompareUtils { + + + /** + * 对比两个map 查找出相比orig,other中有哪些是新增的、删除的或者被修改的,并分别进行处理 + * + * 对比时默认用equals方法来判断是否为 EntryEventKind#UPDATED + * + * @param orig 原始map + * @param other 参考的新map + * @param eventHandler 有区别时的事件处理器 + * @param K + * @param V + */ + public static void contrastMapEntries(@NotNull Map orig, @NotNull Map other, @NotNull EventHandler eventHandler) { + + contrastMapEntries(orig, other, eventHandler, UpdateRule.DEFAULT); + } + + /** + * 对比两个map 查找出相比orig,other中有哪些是新增的、删除的或者被修改的,并分别进行处理 + * + * 对比时用自定义的规则来判断是否为 EntryEventKind#UPDATED + * + * @param orig 原始map + * @param other 参考的新map + * @param eventHandler 有区别时的事件处理器 + * @param updateRule 自定义的Update事件判定规则 + * @param + * @param + */ + public static void contrastMapEntries(@NotNull Map orig, @NotNull Map other, @NotNull EventHandler eventHandler, @NotNull UpdateRule updateRule) { + + Map copiedOrig = new LinkedHashMap<>(orig); + + other.forEach((k, v) -> { + V existedV = copiedOrig.remove(k); + if (existedV != null) { + if (updateRule.needUpdate(existedV, v)) { + eventHandler.on(EntryEventKind.UPDATED, k, v); + } + } else { + eventHandler.on(EntryEventKind.ADDED, k, v); + } + }); + + copiedOrig.forEach((k, v) -> eventHandler.on(EntryEventKind.REMOVED, k, v)); + } + + + /** + * 事件处理器,对应比较后的三种结果的事件处理 + * @param + * @param + */ + public interface EventHandler { + void on(EntryEventKind entryEventKind, K k, V v); + } + + /** + * 判定 数据被修改 的判定规则 + * @param + * @param + */ + public interface UpdateRule { + + EntryEventKind eventKind = EntryEventKind.UPDATED; + + UpdateRule DEFAULT = new UpdateRule() {}; + + default boolean needUpdate(V origin, V v) { + return !v.equals(origin); + } + } + + public enum EntryEventKind { + ADDED, + REMOVED, + UPDATED; + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java index f656105265..4c83667b41 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java @@ -1,17 +1,17 @@ package com.fr.design.data.datapane; import com.fr.base.TableData; -import com.fr.concurrent.NamedThreadFactory; +import com.fr.common.listener.ManageDsListenerRegisterListener; import com.fr.data.core.DataCoreUtils; import com.fr.data.core.db.DBUtils; import com.fr.data.core.db.TableProcedure; import com.fr.data.core.db.dialect.Dialect; import com.fr.data.core.db.dialect.DialectFactory; +import com.fr.data.impl.Connection; import com.fr.data.impl.DBTableData; import com.fr.data.operator.DataOperator; import com.fr.design.DesignerEnvManager; import com.fr.design.beans.BasicBeanPane; -import com.fr.design.data.DesignTableDataManager; import com.fr.design.data.datapane.RefreshLabel.Refreshable; import com.fr.design.data.datapane.preview.PreviewLabel; import com.fr.design.data.datapane.preview.PreviewLabel.Previewable; @@ -19,7 +19,7 @@ import com.fr.design.data.datapane.preview.PreviewTablePane; import com.fr.design.data.tabledata.Prepare4DataSourceChange; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.gui.icombobox.FilterableComboBoxModel; -import com.fr.design.gui.icombobox.SearchPreTaskTreeComboBox; +import com.fr.design.gui.icombobox.TableSearchTreeComboBox; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.icombobox.UIComboBoxEditor; import com.fr.design.gui.icombobox.UIComboBoxRenderer; @@ -40,11 +40,6 @@ import com.fr.stable.StringUtils; import com.fr.workspace.WorkContext; import com.fr.workspace.server.connection.DBConnectAuth; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.util.Collections; -import java.util.concurrent.CancellationException; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -58,21 +53,20 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeCellRenderer; -import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.ArrayList; import java.util.Collection; -import java.util.Enumeration; +import java.util.Collections; import java.util.List; import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; +import java.util.concurrent.CancellationException; /** * @author zhou @@ -97,41 +91,12 @@ public class ChoosePane extends BasicBeanPane implements Refresha /** * 表名 */ - protected SearchPreTaskTreeComboBox tableNameComboBox; - - private static final ExecutorService SERVICE = Executors.newSingleThreadExecutor(new NamedThreadFactory("ChoosePane")); + protected TableSearchTreeComboBox tableNameComboBox; private SwingWorker populateWorker; private SwingWorker, Void> initWorker; - private PopupMenuListener popupMenuListener = new PopupMenuListener() { - - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - FutureTask task = new FutureTask(new Callable() { - @Override - public Void call() throws Exception { - calculateTableDataNames(); - return null; - } - }); - tableNameComboBox.setPreSearchTask(task); - SERVICE.submit(task); - } - - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - // Do nothing - } - - @Override - public void popupMenuCanceled(PopupMenuEvent e) { - // Do nothing - } - }; - - private PopupMenuListener listener = new PopupMenuListener() { @Override public void popupMenuCanceled(PopupMenuEvent e) { @@ -181,7 +146,7 @@ public class ChoosePane extends BasicBeanPane implements Refresha schemaBox = new StringUIComboBox(); schemaBox.setEditor(new ComboBoxEditor()); - tableNameComboBox = new SearchPreTaskTreeComboBox(new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer, false); + tableNameComboBox = new TableSearchTreeComboBox(this, new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer); tableNameComboBox.setEditable(true); tableNameComboBox.setRenderer(listCellRenderer); registerDSChangeListener(); @@ -198,7 +163,6 @@ public class ChoosePane extends BasicBeanPane implements Refresha }); schemaBox.addPopupMenuListener(listener); addFocusListener(); - this.tableNameComboBox.addPopupMenuListener(popupMenuListener); } protected void addDSBoxListener() { @@ -355,7 +319,7 @@ public class ChoosePane extends BasicBeanPane implements Refresha GUICoreUtils.setSelectedItemQuietly(tableNameComboBox, -1); } - protected com.fr.data.impl.Connection getConnection() { + public Connection getConnection() { String selectedDSName = this.getDSName(); if (StringUtils.isEmpty(selectedDSName)) { return null; // peter:选中了当前的零长度的节点,直接返回. @@ -455,56 +419,6 @@ public class ChoosePane extends BasicBeanPane implements Refresha return "choosepane"; } - protected void calculateTableDataNames() { - JTree tree = tableNameComboBox.getTree(); - if (tree == null) { - return; - } - DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot(); - rootTreeNode.removeAllChildren(); - - String selectedDSName = this.getDSName(); - com.fr.data.impl.Connection selectedDatabase = this.getConnection(); - if (selectedDatabase == null) { - return; - } - try { - String schema = StringUtils.isEmpty(this.schemaBox.getSelectedItem()) ? null : this.schemaBox.getSelectedItem(); - TableProcedure[] sqlTableArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); - if (sqlTableArray.length > 0) { - ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table")); - rootTreeNode.add(tableTreeNode); - for (int i = 0; i < sqlTableArray.length; i++) { - ExpandMutableTreeNode tableChildTreeNode = new ExpandMutableTreeNode(sqlTableArray[i]); - tableTreeNode.add(tableChildTreeNode); - } - } - TableProcedure[] sqlViewArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); - if (sqlViewArray.length > 0) { - ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View")); - rootTreeNode.add(viewTreeNode); - for (int i = 0; i < sqlViewArray.length; i++) { - ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(sqlViewArray[i]); - viewTreeNode.add(viewChildTreeNode); - } - } - ((DefaultTreeModel) tree.getModel()).reload(); - // daniel 展开所有tree - TreeNode root = (TreeNode) tree.getModel().getRoot(); - TreePath parent = new TreePath(root); - TreeNode node = (TreeNode) parent.getLastPathComponent(); - for (Enumeration e = node.children(); e.hasMoreElements(); ) { - TreeNode n = (TreeNode) e.nextElement(); - TreePath path = parent.pathByAddingChild(n); - tree.expandPath(path); - } - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE); - } - } - /** * 创建选中的数据集数据 * @@ -558,22 +472,23 @@ public class ChoosePane extends BasicBeanPane implements Refresha return tableData; } - protected String getDSName() { + public String getDSName() { return this.dsNameComboBox.getSelectedItem(); } + public String getSchema() { + return this.schemaBox.getSelectedItem(); + } + protected void failedToFindTable() { // Do nothing } protected String getTableName() { String tableName = ""; - Object obj = this.tableNameComboBox.getSelectedItemObject(); + Object obj = this.tableNameComboBox.getSelectedItem(); if (obj == null) { - obj = this.tableNameComboBox.getSelectedItem(); - if (obj == null) { - obj = this.tableNameComboBox.getEditor().getItem(); - } + obj = this.tableNameComboBox.getEditor().getItem(); } if (obj instanceof TreePath) { Object tp = ((ExpandMutableTreeNode) ((TreePath) obj).getLastPathComponent()).getUserObject(); @@ -648,12 +563,49 @@ public class ChoosePane extends BasicBeanPane implements Refresha */ @Override public void registerDSChangeListener() { - DesignTableDataManager.addDsChangeListener(new ChangeListener() { + // 还是需要保留 恶心 + // 1. 切换工作目录需要依赖这个监听 切换工作目录没有一个数据连接的刷新触发 就很坑 + // 2. DesignerContext.getDesignerBean("databasename").refreshBeanElement()有坑 a.调用不全 b.某些场景下 因为注册覆盖 会失效 + // 监听内容变成刷新模式 不会覆盖 populate填充内容 + this.addAncestorListener(new ManageDsListenerRegisterListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - initDsNameComboBox(); + refreshDsNameComboBox(); } - }); + })); + } + + + @SuppressWarnings("unchecked") + private void refreshDsNameComboBox() { + if (initWorker != null && !initWorker.isDone()) { + initWorker.cancel(true); + } + dsNameComboBox.setRefreshingModel(true); + initWorker = new SwingWorker, Void>() { + + @Override + protected List doInBackground() throws Exception { + return getHasAuthConnections(); + } + + @Override + protected void done() { + try { + FilterableComboBoxModel dsNameComboBoxModel = new FilterableComboBoxModel(get()); + String selected = dsNameComboBox.getSelectedItem(); + dsNameComboBox.setModel(dsNameComboBoxModel); + dsNameComboBox.setRefreshingModel(true); + dsNameComboBox.setSelectedItem(selected); + dsNameComboBox.setRefreshingModel(false); + } catch (Exception e) { + if (!(e instanceof CancellationException)) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + }; + initWorker.execute(); } /** diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java index 14d0431e25..8fc62cd77a 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java @@ -83,7 +83,7 @@ public class ChoosePaneSupportFormula extends ChoosePane { * * @return */ - protected String getDSName() { + public String getDSName() { String selectedDSName = null; String item = Utils.objectToString(this.dsNameComboBox.getEditor().getItem()); // 没有选中的列表项 那么看看是不是手输值 diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataComboBox.java b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataComboBox.java index ebbdbf0f35..140b294bfa 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataComboBox.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataComboBox.java @@ -1,5 +1,6 @@ package com.fr.design.data.datapane; +import com.fr.common.listener.ManageDsListenerRegisterListener; import java.awt.Component; import java.awt.event.ItemEvent; import java.util.Iterator; @@ -148,7 +149,7 @@ public class TableDataComboBox extends UIComboBox implements Prepare4DataSourceC TableDataComboBox.this.refresh(DesignTableDataManager.getEditingTableDataSource()); } }; - DesignTableDataManager.addDsChangeListener(changeListener); + this.addAncestorListener(new ManageDsListenerRegisterListener(changeListener)); } public void registerGlobalDSChangeListener() { 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 31630b85c0..09c82ade6e 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,8 +11,10 @@ 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.datapane.auth.TableDataAuthHelper; import com.fr.design.data.tabledata.StoreProcedureWorkerListener; import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +import com.fr.design.data.tabledata.tabledatapane.loading.TableDataLoadingPane; import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicPane; @@ -31,6 +34,7 @@ import com.fr.design.menu.ToolBarDef; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; 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; @@ -42,6 +46,7 @@ import javax.swing.BorderFactory; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import javax.swing.ToolTipManager; import java.awt.BorderLayout; import java.awt.GridLayout; @@ -49,6 +54,7 @@ import java.awt.dnd.DnDConstants; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -239,7 +245,11 @@ public class TableDataTreePane extends BasicTableDataTreePane { doPropertyChange(dg, nPanel, oldName); } }); - dg.setVisible(true); + // 有些数据集(DBTableData)面板的初始化过程中是包含了SwingWorker处理(查询数据连接、查表等)的 + // 如果这里直接setVisible,可能阻塞SwingWorker的done方法,导致面板渲染出现问题 + SwingUtilities.invokeLater(() -> { + dg.setVisible(true); + }); } private class EditAction extends UpdateAction { @@ -249,13 +259,60 @@ public class TableDataTreePane extends BasicTableDataTreePane { this.setSmallIcon("/com/fr/design/images/control/edit"); } + @Override 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); + + String dsName = selectedNO.getName(); + DesignTableDataManager.removeSelectedColumnNames(dsName); + + AbstractTableDataWrapper wrapper = (AbstractTableDataWrapper) selectedNO.getObject(); + + AbstractTableDataPane tableDataPane = wrapper.creatTableDataPane(); + + if (TableDataAuthHelper.needCheckAuthWhenEdit(wrapper.getTableData())) { + // 先打开一个Loading面板 + TableDataLoadingPane loadingPane = new TableDataLoadingPane(); + BasicDialog loadingDialog = loadingPane.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), null); + // 查询权限 + new SwingWorker() { + @Override + protected Boolean doInBackground() throws Exception { + // 获取无权限连接名称集合 + Collection noAuthConnections = TableDataAuthHelper.getNoAuthConnections(); + // 获取当前数据集对应的数据连接名称 + String connectionName = TableDataAuthHelper.getConnectionNameByDBTableData((DBTableData) wrapper.getTableData()); + return !noAuthConnections.contains(connectionName); + } + + @Override + protected void done() { + try { + Boolean hasAuth = get(); + if (hasAuth) { + // 有权限时,关闭Loading面板,打开编辑面板 + loadingDialog.setVisible(false); + dgEdit(tableDataPane, dsName, false); + } else { + // 无权限时,给出无权限提示 + loadingPane.switchTo(TableDataLoadingPane.NO_AUTH_PANE_NAME); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error("loading connection error in remote design", e.getMessage()); + // 查询权限失败时,给出报错提示 + loadingPane.switchTo(TableDataLoadingPane.ERROR_NAME); + } + } + }.execute(); + loadingDialog.setVisible(true); + } else { + // 无需检查权限时,直接打开数据库查询编辑面板 + //下面创建creatTableDataPane后会直接populate,所以populate时不能用后设置的一些参数,比如name + dgEdit(tableDataPane, dsName, false); + } } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java b/designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java new file mode 100644 index 0000000000..382e04dd94 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java @@ -0,0 +1,57 @@ +package com.fr.design.data.datapane.auth; + +import com.fr.base.TableData; +import com.fr.data.impl.Connection; +import com.fr.data.impl.DBTableData; +import com.fr.data.impl.NameDatabaseConnection; +import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.connection.DBConnectAuth; + +import java.util.Collection; +import java.util.Collections; + +/** + * 数据连接权限相关的工具类 + * @author Yvan + */ +public class TableDataAuthHelper { + + /** + * 编辑数据集时是否需要检查权限 + * @param tableData + * @return + */ + public static boolean needCheckAuthWhenEdit(TableData tableData) { + // 远程设计下,编辑DBTableData时需要判断权限 + return !WorkContext.getCurrent().isLocal() && tableData instanceof DBTableData; + } + + /** + * 获取无权限数据连接集合 + * 远程下需要调用RPC,为耗时操作,谨慎使用 + * @return + */ + public static Collection getNoAuthConnections() { + // 获取无权限连接集合 + Collection noAuthConnections = WorkContext.getCurrent().get(DBConnectAuth.class).getNoAuthConnections(); + return noAuthConnections == null ? Collections.emptyList() : noAuthConnections; + } + + /** + * 通过数据集获取其数据连接的名称 + * + * 注意: + * 1. Connection接口本身是不提供名称的,只有我们内部为了使用方便,将其包装成了NameDataBaseConnection + * 如果不是NameDataBaseConnection类型,则无名称,因此这里只能用判断类型的方式获取名称 + * 2. 仅支持DBTableData获取连接名 + * @return + */ + public static String getConnectionNameByDBTableData(DBTableData tableData) { + Connection database = tableData.getDatabase(); + if (database instanceof NameDatabaseConnection) { + return ((NameDatabaseConnection) database).getName(); + } + return StringUtils.EMPTY; + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java index 5ed53cef40..9fa03aca11 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java @@ -8,21 +8,23 @@ import com.fr.design.DesignerEnvManager; import com.fr.design.actions.server.ConnectionListAction; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.dialog.FineJOptionPane; import com.fr.design.editlock.ConnectionLockChangeChecker; import com.fr.design.editlock.EditLockUtils; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UILockButton; +import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.file.ConnectionConfig; -import com.fr.general.ComparatorUtils; +import com.fr.report.LockItem; import com.fr.stable.StringUtils; import com.fr.transaction.CallBackAdaptor; import com.fr.transaction.Configurations; import com.fr.transaction.WorkerFacade; import com.fr.workspace.WorkContext; import com.fr.workspace.server.connection.DBConnectAuth; -import com.fr.report.LockItem; +import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import java.awt.Dimension; import java.awt.event.ActionEvent; @@ -33,6 +35,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; /** * 选择数据连接的下拉框 @@ -103,6 +106,7 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel { continue; } Connection connection = mgr.getConnection(conName); + // nameList依赖items方法初始化,父类ItemEditableComboBoxPanel里异步执行item方法 filterConnection(connection, conName, nameList); } @@ -145,10 +149,16 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel { connectionListDialog.setDoOKSucceed(false); return; } + AtomicBoolean saved = new AtomicBoolean(true); Configurations.modify(new WorkerFacade(ConnectionConfig.class) { @Override public void run() { - connectionListPane.update(connectionConfig); + try { + connectionListPane.update(connectionConfig); + } catch (Exception e) { + saved.set(false); + FineJOptionPane.showMessageDialog(connectionListPane, e.getMessage(), Toolkit.i18nText("Fine-Design_Basic_Error"), JOptionPane.ERROR_MESSAGE); + } } }.addCallBack(new CallBackAdaptor() { @Override @@ -159,9 +169,13 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel { @Override public void afterCommit() { - DesignerContext.getDesignerBean("databasename").refreshBeanElement(); - // 关闭定义数据连接页面,为其解锁 - EditLockUtils.unlock(LockItem.CONNECTION); + if (saved.get()) { + DesignerContext.getDesignerBean("databasename").refreshBeanElement(); + // 定义数据连接弹窗关闭后,解锁 + EditLockUtils.unlock(LockItem.CONNECTION); + } else { + connectionListDialog.setDoOKSucceed(false); + } } })); @@ -186,20 +200,34 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel { if (connection instanceof NameDatabaseConnection) { this.setSelectedItem(((NameDatabaseConnection) connection).getName()); } else { - String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection(); - if (StringUtils.isNotBlank(s)) { - for (int i = 0; i < this.getConnectionSize(); i++) { - String t = this.getConnection(i); - if (ComparatorUtils.equals(s, t)) { - this.setSelectedItem(s); - break; - } - } - } - // alex:如果这个ComboBox还是没有选中,那么选中第一个 - if (StringUtils.isBlank(this.getSelectedItem()) && this.getConnectionSize() > 0) { - this.setSelectedItem(this.getConnection(0)); + setRecentConnection(); + } + } + + /** + * 下拉框选项设置成最近选择的connection,如果最近选择不存在,则选择列表中的第一个 + */ + protected void setRecentConnection() { + String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection(); + if (StringUtils.isNotBlank(s)) { + // 之前的写法有多线程问题,nameList异步尚未初始化完成的时候,这里可能无法匹配设置数据连接名称,导致DBTableDataPane打开后连接面板空白 + // 这里的需求无非是设置上一次使用的数据连接,做个简单检查这个连接是否存在即可,存在就设置 + if (nameList.contains(s)) { + this.setSelectedItem(s); } } + // alex:如果这个ComboBox还是没有选中,那么选中第一个 + if (StringUtils.isBlank(this.getSelectedItem()) && this.getConnectionSize() > 0) { + this.setSelectedItem(this.getConnection(0)); + } + } + + /** + * 是否无选中状态(空白item也视为无选中) + * @return + */ + protected boolean isSelectedItemEmpty() { + String selectedItem = this.getSelectedItem(); + return selectedItem == null || StringUtils.equals(selectedItem, EMPTY.toString()); } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java index 1e3f96a986..1ba3de933b 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java @@ -1,30 +1,38 @@ package com.fr.design.data.datapane.connect; +import com.fr.data.driver.DriverClassNotFoundException; import com.fr.data.impl.Connection; import com.fr.data.impl.JDBCDatabaseConnection; import com.fr.data.impl.JNDIDatabaseConnection; +import com.fr.data.operator.DataOperator; import com.fr.design.ExtraDesignClassManager; +import com.fr.design.data.MapCompareUtils; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.fun.ConnectionProvider; 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.ilist.ListModelElement; import com.fr.design.i18n.Toolkit; import com.fr.file.ConnectionConfig; import com.fr.general.ComparatorUtils; import com.fr.general.NameObject; +import com.fr.log.FineLoggerFactory; import com.fr.stable.ArrayUtils; import com.fr.stable.Nameable; import com.fr.stable.StringUtils; import com.fr.stable.core.PropertyChangeAdapter; -import javax.swing.*; +import javax.swing.SwingUtilities; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; /** * Connection List Pane. @@ -32,7 +40,8 @@ import java.util.Set; public class ConnectionListPane extends JListControlPane implements ConnectionShowPane { public static final String TITLE_NAME = Toolkit.i18nText("Fine-Design_Basic_Server_Define_Data_Connection"); private boolean isNamePermitted = true; - private HashMap renameMap = new HashMap(); + private final HashMap renameMap = new HashMap<>(); + private final Map populatedConnectionsSnapshot = new LinkedHashMap<>(); public ConnectionListPane() { renameMap.clear(); @@ -136,27 +145,102 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh */ public void populate(ConnectionConfig connectionConfig) { List nameObjectList = new ArrayList(); + populatedConnectionsSnapshot.clear(); for (Map.Entry entry : connectionConfig.getConnections().entrySet()) { nameObjectList.add(new NameObject(entry.getKey(), entry.getValue())); + try { + populatedConnectionsSnapshot.put(entry.getKey(), (Connection) entry.getValue().clone()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } } this.populate(nameObjectList.toArray(new NameObject[nameObjectList.size()])); - } /** * Update. */ - public void update(ConnectionConfig connectionConfig) { + public void update(ConnectionConfig connectionConfig) throws Exception { // Nameable[]居然不能强转成NameObject[],一定要这么写... Nameable[] res = this.update(); - NameObject[] res_array = new NameObject[res.length]; - java.util.Arrays.asList(res).toArray(res_array); + Map updatedMap = new LinkedHashMap<>(); + Arrays.stream(res).map(n -> (NameObject) n).forEach(no -> updatedMap.put(no.getName(), (Connection) no.getObject())); + + List removedConnNames = new ArrayList<>(); + Map addedOrUpdatedConnections = new LinkedHashMap<>(); + MapCompareUtils.contrastMapEntries(populatedConnectionsSnapshot, updatedMap, (entryEventKind, s, connection) -> { + switch (entryEventKind) { + case REMOVED: + removedConnNames.add(s); + break; + case ADDED: + case UPDATED: + addedOrUpdatedConnections.put(s, connection); + default: + break; + } + }, new MapCompareUtils.UpdateRule() { + @Override + public boolean needUpdate(Connection origin, Connection connection) { + return needUpdate0(origin, connection); + } + + /** + * 是否需要更新处理 + * 1. Connection本身equals为false,代表字段修改 + * 2. 非内置的Connection,即插件提供的Connection + * todo 原本一个equals方法就可以搞定,但是插件里面没有实现equals,结果导致不能正确判断,只能主代码里做兼容,很恶心,先记个todo,以后看有没有办法改掉 + * @param origin + * @param connection + * @return + */ + private boolean needUpdate0(Connection origin, Connection connection) { + return !connection.equals(origin) || !isEmbedConnection(connection); + } - connectionConfig.removeAllConnection(); + /** + * 是否是主工程里内置的Connection + * @return + */ + private boolean isEmbedConnection(Connection connection) { + return connection instanceof JDBCDatabaseConnection || connection instanceof JNDIDatabaseConnection; + } + }); + + this.validateConnections(addedOrUpdatedConnections); + alterConnections(removedConnNames, addedOrUpdatedConnections); + } - for (int i = 0; i < res_array.length; i++) { - NameObject nameObject = res_array[i]; - connectionConfig.addConnection(nameObject.getName(), (Connection) nameObject.getObject()); + private void alterConnections(List removedConnNames, Map addedOrUpdatedConnections) { + removedConnNames.forEach(n -> ConnectionConfig.getInstance().removeConnection(n)); + addedOrUpdatedConnections.forEach((name, conn) -> ConnectionConfig.getInstance().addConnection(name, conn)); + } + + private void validateConnections(Map addedOrUpdatedConnections) throws Exception { + + for (Map.Entry entry : addedOrUpdatedConnections.entrySet()) { + Connection connection = entry.getValue(); + try { + DataOperator.getInstance().validateConnectionSettings(connection); + } catch (DriverClassNotFoundException e) { + FineLoggerFactory.getLogger().info(e.getMessage()); + } catch (SQLException e) { + throw new SQLException(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Invalid_Config", entry.getKey()) + ", " + e.getMessage(), e.getCause()); + } + } + } + + @Override + public void onCopyItem() { + super.onCopyItem(); + ListModelElement selectedValue = getSelectedValue(); + // identity 需要重置 + if (selectedValue != null && selectedValue.wrapper != null) { + Object temp = ((NameObject) selectedValue.wrapper).getObject(); + if (temp instanceof JDBCDatabaseConnection) { + JDBCDatabaseConnection object = (JDBCDatabaseConnection) temp; + object.setIdentity(UUID.randomUUID().toString()); + } } } } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java index 6c768145f3..eadf456e09 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionManagerPane.java @@ -4,9 +4,8 @@ import com.fr.design.gui.frpane.LoadingBasicPane; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.file.ConnectionConfig; - -import javax.swing.*; -import java.awt.*; +import javax.swing.JPanel; +import java.awt.BorderLayout; import java.util.HashMap; public class ConnectionManagerPane extends LoadingBasicPane implements ConnectionShowPane { @@ -39,7 +38,7 @@ public class ConnectionManagerPane extends LoadingBasicPane implements Connectio this.connectionListPane.populate(datasourceManager); } - public void update(ConnectionConfig datasourceManager) { + public void update(ConnectionConfig datasourceManager) throws Exception { this.connectionListPane.update(datasourceManager); } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionShowPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionShowPane.java index b5ae09be8e..2b74ddcf9e 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionShowPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionShowPane.java @@ -7,7 +7,7 @@ import com.fr.file.ConnectionConfig; * 数据链接显示面板 */ public interface ConnectionShowPane { - void update(ConnectionConfig connectionConfig); + void update(ConnectionConfig connectionConfig) throws Exception; void populate(ConnectionConfig connectionConfig); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java index a979a20cd6..613eed9a48 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java @@ -1,26 +1,32 @@ package com.fr.design.data.datapane.connect; import com.fr.base.BaseUtils; +import com.fr.base.svg.IconUtils; import com.fr.data.core.db.TableProcedure; import com.fr.data.impl.AbstractDatabaseConnection; import com.fr.data.impl.Connection; import com.fr.design.border.UIRoundedBorder; import com.fr.design.constants.UIConstants; +import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane; +import com.fr.design.data.tabledata.tabledatapane.loading.SwitchableTableDataPane; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ilist.TableViewList; import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.general.GeneralContext; import com.fr.stable.ArrayUtils; +import javax.swing.BorderFactory; import javax.swing.JPanel; import javax.swing.ToolTipManager; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -45,7 +51,39 @@ public class ConnectionTableProcedurePane extends BasicPane { private java.util.List listeners = new java.util.ArrayList(); public ConnectionTableProcedurePane() { + init(null); + } + + /** + * 传入父容器 + * @param parent + */ + public ConnectionTableProcedurePane(SwitchableTableDataPane parent) { + init(parent); + } + + private void init(SwitchableTableDataPane parent) { this.setLayout(new BorderLayout(4, 4)); + // 初始化数据连接下拉框 + initConnectionComboBox(parent); + // 初始化中间的面板 + JPanel centerPane = initCenterPane(); + this.add(connectionComboBox, BorderLayout.NORTH); + this.add(centerPane, BorderLayout.CENTER); + this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height)); + addKeyMonitor(); + } + + private JPanel initCenterPane() { + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + // 搜索面板 + centerPane.add(createSearchPane(), BorderLayout.NORTH); + // 数据库表视图面板 + centerPane.add(createTableViewBorderPane(), BorderLayout.CENTER); + return centerPane; + } + + private void initConnectionComboBox(SwitchableTableDataPane parent) { connectionComboBox = new ConnectionComboBoxPanel(com.fr.data.impl.Connection.class) { @Override @@ -60,10 +98,34 @@ public class ConnectionTableProcedurePane extends BasicPane { search(true); } } + + @Override + protected void afterRefreshItems() { + // 刷新完成后,如果未选中(在nameList初始化完成之前可能会出现),则尝试再次设置 + if (isSelectedItemEmpty()) { + setRecentConnection(); + } + // 获取数据连接之后,让父容器切换面板 + if (parent != null) { + parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME); + } + } + + @Override + protected void refreshItemsError() { + // 获取数据连接出现错误时,也让父容器从Loading面板切换至内容面板 + if (parent != null) { + parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME); + } + } }; + connectionComboBox.addComboBoxActionListener(filter); + } + + private JPanel createTableViewBorderPane() { tableViewList = new TableViewList(); ToolTipManager.sharedInstance().registerComponent(tableViewList); - connectionComboBox.addComboBoxActionListener(filter); + tableViewList.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { if (evt.getClickCount() >= 2) { @@ -80,23 +142,50 @@ public class ConnectionTableProcedurePane extends BasicPane { } } }); - JPanel filterPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + UIScrollPane tableViewListPane = new UIScrollPane(tableViewList); + tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + JPanel tableViewBorderPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + tableViewBorderPane.add(tableViewListPane, BorderLayout.CENTER); JPanel checkBoxgroupPane = createCheckBoxgroupPane(); if (checkBoxgroupPane != null) { - filterPane.add(createCheckBoxgroupPane(), BorderLayout.NORTH); + tableViewBorderPane.add(createCheckBoxgroupPane(), BorderLayout.SOUTH); } + return tableViewBorderPane; + } + + /** + * 创建搜索Panel,用于搜索表或视图 + * @return + */ + private JPanel createSearchPane() { + JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); JPanel searchPane = new JPanel(new BorderLayout(10, 0)); + searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR)); + searchPane.setBackground(Color.WHITE); searchField = new UITextField(); - searchPane.add(searchField, BorderLayout.CENTER); + searchField.setBorderPainted(false); + searchField.setPlaceholder(Toolkit.i18nText("Fine-Design_Basic_Table_Search")); searchField.getDocument().addDocumentListener(searchListener); - filterPane.add(searchPane, BorderLayout.CENTER); - UIScrollPane tableViewListPane = new UIScrollPane(tableViewList); - tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); - this.add(connectionComboBox, BorderLayout.NORTH); - this.add(tableViewListPane, BorderLayout.CENTER); - this.add(filterPane, BorderLayout.SOUTH); - this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height)); - addKeyMonitor(); + searchField.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.CHECKBOX_HOVER_SELECTED)); + } + + @Override + public void mouseExited(MouseEvent e) { + super.mouseExited(e); + searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR)); + } + }); + // 搜索图标 + UILabel searchLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/search")); + searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); + searchPane.add(searchField, BorderLayout.CENTER); + searchPane.add(searchLabel, BorderLayout.EAST); + panel.add(searchPane, BorderLayout.CENTER); + return panel; } protected void filter(Connection connection, String conName, List nameList) { @@ -224,4 +313,4 @@ public class ConnectionTableProcedurePane extends BasicPane { */ public void actionPerformed(TableProcedure target); } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java index d0738e57b8..a430a13bd1 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java @@ -127,10 +127,12 @@ public abstract class ItemEditableComboBoxPanel extends JPanel { itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() + 1); itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() - 1); } + afterRefreshItems(); } catch (Exception e) { if (!(e instanceof CancellationException)) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } + refreshItemsError(); } } @@ -160,6 +162,20 @@ public abstract class ItemEditableComboBoxPanel extends JPanel { */ protected abstract java.util.Iterator items(); + /** + * 刷新ComboBox.items之后 + */ + protected void afterRefreshItems() { + // 空实现,供子类重写 + } + + /** + * 刷新ComboBox.items时出现异常 + */ + protected void refreshItemsError() { + // 空实现,供子类重写 + } + /* * 弹出对话框编辑Items */ diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java index 0da46965b1..1f9b90dbbb 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java @@ -16,8 +16,8 @@ import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.DesignerContext; import com.fr.design.utils.BrowseUtils; import com.fr.file.filter.ChooseFileFilter; -import com.fr.general.CloudCenter; import com.fr.general.ComparatorUtils; +import com.fr.i18n.UrlI18nManager; import com.fr.stable.ArrayUtils; import com.fr.stable.EncodeConstants; import com.fr.stable.StringUtils; @@ -159,7 +159,7 @@ public class JDBCDefPane extends JPanel { odbcTipsLink.setPreferredSize(new Dimension(GraphHelper.getWidth(Toolkit.i18nText("Fine-Design_Basic_Odbc_Tips")), odbcTipsLink.getPreferredSize().height)); odbcTipsLink.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { - String url = CloudCenter.getInstance().acquireUrlByKind("odbc.help"); + String url = UrlI18nManager.getInstance().getI18nUrl("odbc.help"); BrowseUtils.browser(url); } }); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/CopyableJTable.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/CopyableJTable.java index eb8d188a1f..a452a4d371 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/CopyableJTable.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/CopyableJTable.java @@ -106,6 +106,7 @@ public class CopyableJTable extends SortableJTable { self.updateEndPoint(-1, column); self.refreshTable(); } + self.requestFocusInWindow(); } private int getColumn(MouseEvent e) { @@ -249,26 +250,9 @@ public class CopyableJTable extends SortableJTable { FineLoggerFactory.getLogger().info("copy cell value"); java.util.List> table = new ArrayList<>(); if ((startRow != endRow || startCol != endCol) && Math.min(startCol, endCol) > -1) { - for (int i = Math.min(startRow, endRow); i <= Math.max(startRow, endRow); i++) { - table.add(new ArrayList<>()); - for (int j = Math.min(startCol, endCol); j <= Math.max(startCol, endCol); j++) { - Object text = this.getTableValue(i, j); - table.get(table.size() - 1).add(text); - } - } + copyAreaData(table); } else if (pointList.size() > 0) { - Collections.sort(pointList, Comparator.comparing(Point::getX).thenComparing(Point::getY)); - int startRow = pointList.get(0).x; - int currentRow = startRow; - table.add(new ArrayList<>()); - for (Point point : pointList) { - while (currentRow < point.x) { - table.add(new ArrayList<>()); - currentRow++; - } - Object text = this.getTableValue(point.x, point.y); - table.get(table.size() - 1).add(text); - } + copyPointsData(table); } Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); @@ -276,6 +260,35 @@ public class CopyableJTable extends SortableJTable { clip.setContents(tText, null); } + private void copyAreaData(java.util.List> table) { + for (int i = Math.min(startRow, endRow); i <= Math.max(startRow, endRow); i++) { + table.add(new ArrayList<>()); + for (int j = Math.min(startCol, endCol); j <= Math.max(startCol, endCol); j++) { + Object text = this.getTableValue(i, j); + if (text != null) { + table.get(table.size() - 1).add(text); + } + } + } + } + + private void copyPointsData(java.util.List> table) { + Collections.sort(pointList, Comparator.comparing(Point::getX).thenComparing(Point::getY)); + int startRow = pointList.get(0).x; + int currentRow = startRow; + table.add(new ArrayList<>()); + for (Point point : pointList) { + while (currentRow < point.x) { + table.add(new ArrayList<>()); + currentRow++; + } + Object text = this.getTableValue(point.x, point.y); + if (text != null) { + table.get(table.size() - 1).add(text); + } + } + } + private Object getTableValue(int row, int col) { Object value = null; if (col > -1) { 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 fecf9c079e..f1b8043770 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 @@ -18,6 +18,8 @@ import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane.DoubleCl 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.tabledatapane.loading.SwitchableTableDataPane; +import com.fr.design.data.tabledata.tabledatapane.loading.TipsPane; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; @@ -30,6 +32,7 @@ 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.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.design.menu.SeparatorDef; import com.fr.design.menu.ToolBarDef; @@ -54,6 +57,7 @@ import javax.swing.JToolBar; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import java.awt.BorderLayout; +import java.awt.CardLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; @@ -64,7 +68,7 @@ import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.List; -public class DBTableDataPane extends AbstractTableDataPane { +public class DBTableDataPane extends AbstractTableDataPane implements SwitchableTableDataPane { 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"); @@ -78,8 +82,42 @@ public class DBTableDataPane extends AbstractTableDataPane { private String pageQuery = null; private DBTableData dbTableData; + private CardLayout card; + /** 数据库查询面板真正的内容面板 */ + private JPanel contentPane; + /** 加载中面板 */ + private JPanel loadingPane; + + public DBTableDataPane() { + initCards(); + initContentPane(); + } + + /** + * 初始化cardLayout以及LoadingPane等,并且布局切到LoadingPane + */ + protected void initCards() { + card = new CardLayout(); + setLayout(card); + + loadingPane = new TipsPane(true); + contentPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + + add(LOADING_PANE_NAME, loadingPane); + add(CONTENT_PANE_NAME, contentPane); + switchTo(LOADING_PANE_NAME); + } + + /** + * 初始化内容面板 + */ + protected void initContentPane() { + init(); + initMainSplitPane(); + } + private void init() { - this.setLayout(new BorderLayout(4, 4)); + contentPane.setLayout(new BorderLayout(4, 4)); sqlTextPane = new SQLEditPane(); sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); @@ -93,7 +131,7 @@ public class DBTableDataPane extends AbstractTableDataPane { editorPane = new UITableEditorPane(model); // 左边的Panel,上面是选择DatabaseConnection的ComboBox,下面DatabaseConnection对应的Table - connectionTableProcedurePane = new ConnectionTableProcedurePane() { + connectionTableProcedurePane = new ConnectionTableProcedurePane(this) { @Override protected void filter(Connection connection, String conName, List nameList) { @@ -194,15 +232,23 @@ public class DBTableDataPane extends AbstractTableDataPane { JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, connectionTableProcedurePane, sqlSplitPane); mainSplitPane.setBorder(BorderFactory.createLineBorder(GUICoreUtils.getTitleLineBorderColor())); mainSplitPane.setOneTouchExpandable(true); - this.add(mainSplitPane, BorderLayout.CENTER); + contentPane.add(mainSplitPane, BorderLayout.CENTER); } - public DBTableDataPane() { - init(); - initMainSplitPane(); + @Override + public void switchTo(String panelName) { + try { + if (panelName != null) { + card.show(this, panelName); + } + } catch (IllegalArgumentException ingore) { + // 有些直接继承此面板或者替换掉此面板的插件,在未适配此功能时会出现报错,因为不是CardLayout,无法切换,这里处理下 + FineLoggerFactory.getLogger().info("cannot switch pane by {}", this.getClass().getName()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } } - private boolean isPreviewOrRefreshButton(FocusEvent e) { if (e.getOppositeComponent() != null) { String name = e.getOppositeComponent().getName(); diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/SwitchableTableDataPane.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/SwitchableTableDataPane.java new file mode 100644 index 0000000000..221ee1cbba --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/SwitchableTableDataPane.java @@ -0,0 +1,23 @@ +package com.fr.design.data.tabledata.tabledatapane.loading; + + + +/** + * 可切换的DBTableData对应的数据集面板,需要使用CardLayout布局 + * 主要是给插件适配用的 + * @author Yvan + */ +public interface SwitchableTableDataPane { + + /** Loading面板 */ + String LOADING_PANE_NAME = "Loading"; + /** 内容面板 */ + String CONTENT_PANE_NAME = "Content"; + + /** + * 根据面板名称切换面板 + * @param paneName 面板名称 + */ + void switchTo(String paneName); + +} diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TableDataLoadingPane.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TableDataLoadingPane.java new file mode 100644 index 0000000000..c3f12c3e7f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TableDataLoadingPane.java @@ -0,0 +1,54 @@ +package com.fr.design.data.tabledata.tabledatapane.loading; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.i18n.Toolkit; + +import javax.swing.JPanel; +import java.awt.CardLayout; + +/** + * @author Yvan + */ +public class TableDataLoadingPane extends BasicPane { + + /** Loading面板 */ + public static final String LOADING_PANE_NAME = "Loading"; + /** 无权限提示面板 */ + public static final String NO_AUTH_PANE_NAME = "NoAuthority"; + /** 错误提示面板 */ + public static final String ERROR_NAME = "Error"; + + private CardLayout card; + + /** 加载中面板 */ + private JPanel loadingPane; + /** 错误提示面板 */ + private JPanel errorPane; + /** 数据连接无权限面板 */ + private JPanel noAuthorityPane; + + public TableDataLoadingPane() { + initPanes(); + } + + private void initPanes() { + card = new CardLayout(); + this.setLayout(card); + loadingPane = new TipsPane(true); + errorPane = new TipsPane(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Error")); + noAuthorityPane = new TipsPane(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_No_Auth")); + add(LOADING_PANE_NAME, loadingPane); + add(NO_AUTH_PANE_NAME, noAuthorityPane); + add(ERROR_NAME, errorPane); + switchTo(LOADING_PANE_NAME); + } + + public void switchTo(String panelName) { + card.show(this, panelName); + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query"); + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TipsPane.java b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TipsPane.java new file mode 100644 index 0000000000..40fcb6ef28 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TipsPane.java @@ -0,0 +1,45 @@ +package com.fr.design.data.tabledata.tabledatapane.loading; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; + +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; + +/** + * 提示面板,支持自定义提示,支持进度条配置可选 + * @author Yvan + */ +public class TipsPane extends JPanel { + + /** + * 默认提示 + */ + private static final String LOADING = Toolkit.i18nText("Fine-Design_Basic_Loading_And_Waiting"); + + public TipsPane () { + this(LOADING, false); + } + + public TipsPane (String tip) { + this(tip, false); + } + + public TipsPane (boolean needProgressBar) { + this(LOADING, needProgressBar); + } + + public TipsPane (String tips, boolean needProgressBar) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + UILabel tipsLabel = new UILabel(tips, SwingConstants.CENTER); + this.add(tipsLabel, BorderLayout.CENTER); + if (needProgressBar) { + JProgressBar progressBar = new JProgressBar(); + progressBar.setIndeterminate(true); + this.add(progressBar, BorderLayout.SOUTH); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java b/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java index 08274fd71d..515bd8dd08 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java @@ -63,26 +63,27 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { public StoreProcedureDataWrapper(Component component, StoreProcedure storeProcedure, String storeprocedureName, String dsName) { this(component, storeProcedure, storeprocedureName, dsName, true); } - + /** - * @param: component loadingBar的父弹框(如果不设置父弹框的话,可能出现loadingBar隐藏在一个弹框后的情况) - * @param: storeProcedure 存储过程 - * @param: storeprocedureName 存储过程的名字(某些情况下可以为空) - * @param: dsName 存储过程一个返回数据集的名字 - * @param: needLoad 是否要加载 + * @param component loadingBar的父弹框(如果不设置父弹框的话,可能出现loadingBar隐藏在一个弹框后的情况) + * @param storeProcedure 存储过程 + * @param storeprocedureName 存储过程的名字(某些情况下可以为空) + * @param dsName 存储过程一个返回数据集的名字 + * @param needLoad 是否要加载 **/ public StoreProcedureDataWrapper(Component component, StoreProcedure storeProcedure, String storeprocedureName, String dsName, boolean needLoad) { this.dsName = dsName; this.storeProcedure = storeProcedure; this.storeProcedure.setCalculating(false); this.storeprocedureName = storeprocedureName; - if (needLoad) { - setWorker(); - } if (component == null) { component = new JFrame(); } + if (needLoad) { + setWorker(component); + } loadingBar = new AutoProgressBar(component, Toolkit.i18nText("Fine-Design_Basic_Loading_Data"), "", 0, 100) { + @Override public void doMonitorCanceled() { getWorker().cancel(true); } @@ -93,16 +94,17 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { * 数据集执行结果返回的所有字段 * * @return 数据集执行结果返回的所有字段 - * - * - * @date 2014-12-3-下午7:43:17 - * - */ + * @date 2014-12-3-下午7:43:17 + */ + @Override public List calculateColumnNameList() { if (columnNameList != null) { return columnNameList; } - if (!createStore(false)) { + + try { + createStore(false); + } catch (Exception e) { FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Engine_No_TableData")); return new ArrayList(); } @@ -114,11 +116,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { * 生成子节点 * * @return 节点数组 - * - * - * @date 2014-12-3-下午7:06:47 - * - */ + * @date 2014-12-3-下午7:06:47 + */ + @Override public ExpandMutableTreeNode[] load() { List namelist; if (storeProcedure.isCalculating()) { @@ -134,23 +134,16 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { return res; } - private boolean createStore(boolean needLoadingBar) { - try { - dataModels = DesignTableDataManager.createLazyDataModel(storeProcedure, needLoadingBar); - if (dataModels == null || dataModels.length == 0) { - return false; - } - for (int i = 0; i < dataModels.length; i++) { - if (ComparatorUtils.equals(this.dsName, storeprocedureName + "_" + dataModels[i].getName())) { - procedureDataModel = dataModels[i]; + private void createStore(boolean needLoadingBar) throws Exception { + dataModels = DesignTableDataManager.createLazyDataModel(storeProcedure, needLoadingBar); + if (dataModels != null && dataModels.length != 0) { + for (ProcedureDataModel dataModel : dataModels) { + if (ComparatorUtils.equals(this.dsName, storeprocedureName + "_" + dataModel.getName())) { + procedureDataModel = dataModel; break; } } - return true; - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); } - return false; } @Override @@ -159,17 +152,15 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { } /** - * 预览数据 - * - * @param previewModel 预览模式, 全部还是一个 - * - * - * @date 2014-12-3-下午7:05:50 - * - */ + * 预览数据 + * + * @param previewModel 预览模式, 全部还是一个 + * @date 2014-12-3-下午7:05:50 + */ public void previewData(final int previewModel) { this.previewModel = previewModel; connectionBar = new AutoProgressBar(new JFrame(), Toolkit.i18nText("Fine-Design_Basic_Utils_Now_Create_Connection"), "", 0, 100) { + @Override public void doMonitorCanceled() { connectionBar.close(); worker.cancel(true); @@ -178,8 +169,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { worker.execute(); } - private void setWorker() { + private void setWorker(final Component parent) { worker = new SwingWorker() { + @Override protected Void doInBackground() throws Exception { loadingBar.close(); PreviewTablePane.resetPreviewTable(); @@ -195,6 +187,7 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { return null; } + @Override public void done() { try { get(); @@ -206,13 +199,15 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { case StoreProcedureDataWrapper.PREVIEW_ONE: previewData(); break; + default: + break; } } catch (Exception e) { + loadingBar.close(); if (!(e instanceof CancellationException)) { FineLoggerFactory.getLogger().error(e.getMessage(), e); - FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage()); + FineJOptionPane.showMessageDialog(parent, e.getMessage()); } - loadingBar.close(); } } }; @@ -227,10 +222,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { /** * 预览返回的一个数据集 * - * - * @date 2014-12-3-下午7:42:53 - * - */ + * @date 2014-12-3-下午7:42:53 + */ + @Override public void previewData() { previewData(-1, -1); } @@ -240,13 +234,11 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { /** * 预览返回的一个数据集,带有显示值和实际值的标记结果 * - * @param keyIndex 实际值 - * @param valueIndex 显示值 - * - * - * @date 2014-12-3-下午7:42:27 - * - */ + * @param keyIndex 实际值 + * @param valueIndex 显示值 + * @date 2014-12-3-下午7:42:27 + */ + @Override public void previewData(final int keyIndex, final int valueIndex) { PreviewTablePane.previewStoreData(procedureDataModel, keyIndex, valueIndex); } @@ -257,7 +249,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { */ public void previewAllTable() { if (procedureDataModel == null) { - if (!createStore(true)) { + try { + createStore(true); + } catch (Exception e) { return; } } @@ -269,6 +263,7 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { return dsName; } + @Override public TableData getTableData() { return storeProcedure; } @@ -282,10 +277,12 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper { * * @return 是否异常 */ + @Override public boolean isUnusual() { return false; } + @Override public boolean equals(Object obj) { return obj instanceof StoreProcedureDataWrapper && ComparatorUtils.equals(this.dsName, ((StoreProcedureDataWrapper) obj).getTableDataName()) diff --git a/designer-base/src/main/java/com/fr/design/dialog/InformationWarnPane.java b/designer-base/src/main/java/com/fr/design/dialog/InformationWarnPane.java index aac7461c33..e64133eea4 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/InformationWarnPane.java +++ b/designer-base/src/main/java/com/fr/design/dialog/InformationWarnPane.java @@ -37,6 +37,17 @@ public class InformationWarnPane extends JPanel{ public void show() { showWindow(SwingUtilities.getWindowAncestor(this)).setVisible(true); } + + public void showOnFront() { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + AlertDialog dialog = showWindow(SwingUtilities.getWindowAncestor(InformationWarnPane.this)); + dialog.setVisible(true); + dialog.toFront(); + } + }); + } public InformationWarnPane(String infor, String moreInfo, String title) { this.title = title; diff --git a/designer-base/src/main/java/com/fr/design/dialog/UIDetailErrorLinkDialog.java b/designer-base/src/main/java/com/fr/design/dialog/UIDetailErrorLinkDialog.java index b9854c6bcd..24ff7e10c7 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/UIDetailErrorLinkDialog.java +++ b/designer-base/src/main/java/com/fr/design/dialog/UIDetailErrorLinkDialog.java @@ -92,7 +92,7 @@ public class UIDetailErrorLinkDialog extends UIDialog { contentPane.add(link, BorderLayout.SOUTH); // 确定 + 取消 - JPanel actionPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, GAP_10, GAP_10)); + JPanel actionPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, GAP_10, GAP_5)); actionPane.add(createButton(Toolkit.i18nText("Fine-Design_Report_OK"))); actionPane.add(createButton(Toolkit.i18nText("Fine-Design_Basic_Cancel"))); this.getContentPane().add(topPane, BorderLayout.NORTH); diff --git a/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java b/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java index dd3ddab3b9..fe6614c0a0 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java +++ b/designer-base/src/main/java/com/fr/design/dialog/UIDialog.java @@ -18,6 +18,7 @@ import java.awt.BorderLayout; import java.awt.Dialog; import java.awt.FlowLayout; import java.awt.Frame; +import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; @@ -43,6 +44,10 @@ public abstract class UIDialog extends JDialog { super(parent); } + public UIDialog(Window parent) { + super(parent); + } + public UIDialog(Frame parent, BasicPane pane) { this(parent, pane, true); diff --git a/designer-base/src/main/java/com/fr/design/dialog/link/MessageWithLink.java b/designer-base/src/main/java/com/fr/design/dialog/link/MessageWithLink.java index f73ec77df5..b4229a2fae 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/link/MessageWithLink.java +++ b/designer-base/src/main/java/com/fr/design/dialog/link/MessageWithLink.java @@ -1,16 +1,18 @@ package com.fr.design.dialog.link; -import com.fr.design.gui.ilable.UILabel; +import com.fr.design.utils.LinkStrUtils; import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; import javax.swing.JEditorPane; import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; import java.awt.Color; import java.awt.Desktop; import java.awt.Font; import java.net.URI; +import java.net.URL; + +import static com.fr.design.utils.LinkStrUtils.LABEL; /** * 用来构建JOptionPane带超链的消息提示 @@ -21,8 +23,32 @@ import java.net.URI; */ public class MessageWithLink extends JEditorPane { - private static final UILabel LABEL = new UILabel(); + private static final String HTML_BODY = " 的话,将会自动点击匹配 url + * + * @param htmlText html内容 + */ + public MessageWithLink(String htmlText) { + + super("text/html", htmlText); + initListener(); + setEditable(false); + setBorder(null); + } + + public MessageWithLink(String htmlText, Runnable action) { + + super("text/html", htmlText); + initListener(action); + setEditable(false); + setBorder(null); + } public MessageWithLink(String message, String linkName, String link) { this(message, linkName, link, LABEL.getBackground(), LABEL.getFont()); @@ -37,43 +63,85 @@ public class MessageWithLink extends JEditorPane { } public MessageWithLink(String frontMessage, String linkName, String link, String backMessage) { - this(frontMessage, linkName, link, backMessage, LABEL.getBackground(), LABEL.getFont()); + this(frontMessage, linkName, link, backMessage, LABEL.getBackground(), LABEL.getFont(), LABEL.getForeground()); } public MessageWithLink(String message, String linkName, String link, Color color, Font font) { - this(message, linkName, link, StringUtils.EMPTY, color, font); + this(message, linkName, link, StringUtils.EMPTY, color, font, LABEL.getForeground()); } public MessageWithLink(String frontMessage, String linkName, String link, String backMessage, Color color, Font font) { - super("text/html", "" + frontMessage + "" + linkName + "" + backMessage + ""); + this(frontMessage, linkName, link, backMessage, color, font, LABEL.getForeground()); + } + + public MessageWithLink(String htmlText, Font font) { + this(setHtmlFont(htmlText, font)); + } + + + + /** + * 将指定的字体赋给html文本 + * 任何失败,返回原html文本 + * */ + private static String setHtmlFont(String htmlText, Font font) { + + try { + int bodyIndex = htmlText.indexOf(HTML_BODY); + StringBuilder sb = new StringBuilder(); + String left = htmlText.substring(0, bodyIndex + HTML_BODY.length()); + String right = htmlText.substring(bodyIndex + HTML_BODY.length()); + sb.append(left); + sb.append(String.format(HTML_STYLE_FORMAT, LinkStrUtils.generateStyle(Color.WHITE, font, Color.BLACK))); + sb.append(right); + return sb.toString(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + } + + return htmlText; + } + + public MessageWithLink(String frontMessage, String linkName, String link, String backMessage, Color backgroundColor, Font font, Color fontColor) { + + super("text/html", "" + frontMessage + "" + linkName + "" + backMessage + ""); initListener(link); setEditable(false); setBorder(null); } - protected void initListener(String link) { - addHyperlinkListener(new HyperlinkListener() { - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { - try { - Desktop.getDesktop().browse(URI.create(link)); - } catch (Exception exception) { - FineLoggerFactory.getLogger().error(exception.getMessage(), exception); - } + protected void initListener() { + + addHyperlinkListener(hyperlinkEvent -> { + try { + if (hyperlinkEvent.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { + URL url = hyperlinkEvent.getURL(); + Desktop.getDesktop().browse(url.toURI()); } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); } }); } - private static StringBuilder generateStyle(Color color, Font font) { - // 构建相同风格样式 - StringBuilder style = new StringBuilder("font-family:" + font.getFamily() + ";"); - style.append("font-weight:").append(font.isBold() ? "bold" : "normal").append(";"); - style.append("font-size:").append(font.getSize()).append("pt;"); - style.append("background-color: rgb(").append(color.getRed()).append(",").append(color.getGreen()).append(",").append(color.getBlue()).append(");"); + protected void initListener(Runnable runnable) { - return style; + addHyperlinkListener(e -> { + if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { + runnable.run(); + } + }); + } + + protected void initListener(String link) { + + initListener(() -> { + try { + Desktop.getDesktop().browse(URI.create(link)); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + }); } } diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java index 92fdd4878a..ea591f3bf4 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java @@ -3,6 +3,7 @@ package com.fr.design.extra.exe.callback; import com.fr.design.bridge.exec.JSCallback; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.extra.PluginOperateUtils; +import com.fr.design.extra.exe.callback.handle.PluginCallBackHelper; import com.fr.design.i18n.Toolkit; import com.fr.log.FineLoggerFactory; @@ -73,7 +74,7 @@ public class InstallFromDiskCallback extends AbstractPluginTaskCallback { }else { jsCallback.execute("failed"); FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Plugin_Install_Failed")); - FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE); + PluginCallBackHelper.showErrorMessage(result, pluginInfo); } } } diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java index 0b1eb33fb9..09c360b4f1 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java @@ -4,6 +4,7 @@ import com.fr.design.bridge.exec.JSCallback; import com.fr.design.bridge.exec.JSExecutor; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.extra.PluginOperateUtils; +import com.fr.design.extra.exe.callback.handle.PluginCallBackHelper; import com.fr.design.i18n.Toolkit; import com.fr.log.FineLoggerFactory; @@ -63,7 +64,7 @@ public class InstallOnlineCallback extends AbstractDealPreTaskCallback { } else { jsCallback.execute("failed"); FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Plugin_Install_Failed")); - FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE); + PluginCallBackHelper.showErrorMessage(result, pluginInfo); } } diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java index 21c7871f52..31bf482ebe 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java @@ -3,6 +3,7 @@ package com.fr.design.extra.exe.callback; import com.fr.design.bridge.exec.JSCallback; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.extra.PluginOperateUtils; +import com.fr.design.extra.exe.callback.handle.PluginCallBackHelper; import com.fr.design.i18n.Toolkit; import com.fr.log.FineLoggerFactory; @@ -72,7 +73,7 @@ public class UpdateFromDiskCallback extends AbstractPluginTaskCallback { }else { jsCallback.execute("failed"); FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Plugin_Update_Failed")); - FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE); + PluginCallBackHelper.showErrorMessage(result, pluginInfo); } } } diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java index 8dbad6a541..3469ed1a59 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java @@ -3,6 +3,7 @@ package com.fr.design.extra.exe.callback; import com.fr.design.bridge.exec.JSCallback; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.extra.PluginOperateUtils; +import com.fr.design.extra.exe.callback.handle.PluginCallBackHelper; import com.fr.design.i18n.Toolkit; import com.fr.log.FineLoggerFactory; @@ -38,7 +39,7 @@ public class UpdateOnlineCallback extends AbstractDealPreTaskCallback { } else { jsCallback.execute("failed"); FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Plugin_Update_Failed")); - FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE); + PluginCallBackHelper.showErrorMessage(result, pluginInfo); } } } diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginCallBackHelper.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginCallBackHelper.java new file mode 100644 index 0000000000..fc5f957f63 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginCallBackHelper.java @@ -0,0 +1,70 @@ +package com.fr.design.extra.exe.callback.handle; + +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.dialog.link.MessageWithLink; +import com.fr.design.i18n.Toolkit; +import com.fr.plugin.error.PluginErrorCode; +import com.fr.plugin.manage.control.PluginTaskResult; + +/** + * 帮助处理插件操作(安装、更新等)的弹窗 + * @author Yvan + */ +public class PluginCallBackHelper { + + private static final String NEW_LINE_TAG = "
"; + private static final String REFERENCE = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_Reference"); + private static final String HELP_DOCUMENT_NAME = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_NAME"); + private static final String CONNECTOR = "-"; + private static final String HELP_DOCUMENT_LINK = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_LINK"); + + + /** + * 展示插件操作失败后的提示弹窗 + * @param result + * @param pluginInfo + */ + public static void showErrorMessage(PluginTaskResult result, String pluginInfo) { + // 单独处理下插件完整性校验失败的提示 + if (PluginCallBackHelper.needHandleInvalidatePackage(result)) { + MessageWithLink messageWithLink = PluginCallBackHelper.generate4InvalidatePackage(pluginInfo); + PluginTaskResultErrorDialog resultDialog = new PluginTaskResultErrorDialog(null, messageWithLink); + resultDialog.showResult(); + } else { + FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE); + } + } + + /** + * 判断是否需要处理 插件安装包校验失败 导致的安装失败任务 + * @param result + * @return + */ + private static boolean needHandleInvalidatePackage(PluginTaskResult result) { + return !result.isSuccess() && result.getCode() == PluginErrorCode.InstallPackageValidateFailed; + } + + /** + * 根据插件原始报错信息,构建MessageWithLink + * @param originInfo + * @return + */ + private static MessageWithLink generate4InvalidatePackage(String originInfo) { + + return new MessageWithLink(getSupplementaryMessage(originInfo), HELP_DOCUMENT_NAME, HELP_DOCUMENT_LINK); + } + + /** + * 根据插件原始报错信息,获取增加了补充说明后的信息 + * @param originInfo + * @return + */ + private static String getSupplementaryMessage(String originInfo) { + return new StringBuilder() + .append(originInfo) + .append(NEW_LINE_TAG) + .append(REFERENCE) + .append(CONNECTOR) + .toString(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginTaskResultErrorDialog.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginTaskResultErrorDialog.java new file mode 100644 index 0000000000..da4f432080 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginTaskResultErrorDialog.java @@ -0,0 +1,86 @@ +package com.fr.design.extra.exe.callback.handle; + +import com.fr.base.svg.IconUtils; +import com.fr.design.dialog.link.MessageWithLink; +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.VerticalFlowLayout; +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.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * 当前仅处理Error提示,之后有需要再扩展 + * @author Yvan + */ +public class PluginTaskResultErrorDialog extends JDialog { + + private static final Dimension LABEL = new Dimension(60, 90); + + private JPanel contentPane; + + private UILabel errorLabel; + + private UIButton confirmButton; + + private MessageWithLink messageWithLink; + + public PluginTaskResultErrorDialog(Frame parent, MessageWithLink messageWithLink) { + super(parent, true); + this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning")); + this.messageWithLink = messageWithLink; + + initContentPane(); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setResizable(false); + this.add(contentPane, BorderLayout.CENTER); + this.setSize(new Dimension( 380, 160)); + GUICoreUtils.centerWindow(this); + } + + /** + * 初始化内容面板 + */ + private void initContentPane() { + this.contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + // error图标 + errorLabel = new UILabel(IconUtils.readIcon("/com/fr/design/standard/system/error_tips.svg")); + errorLabel.setPreferredSize(LABEL); + errorLabel.setBorder(BorderFactory.createEmptyBorder(10, 20, 40, 20)); + // 提示内容 + JPanel messagePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + messagePane.add(errorLabel, BorderLayout.WEST); + messagePane.add(messageWithLink, BorderLayout.CENTER); + messagePane.setBorder(BorderFactory.createEmptyBorder(20, 10, 0, 10)); + this.contentPane.add(messagePane, BorderLayout.CENTER); + // 确定按钮 + confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Button_OK")); + confirmButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + hideResult(); + } + }); + JPanel confirmPane = new JPanel(new VerticalFlowLayout()); + confirmPane.add(confirmButton); + confirmPane.setBorder(BorderFactory.createEmptyBorder(0, 160, 10, 0)); + this.contentPane.add(confirmPane, BorderLayout.SOUTH); + } + + public void showResult() { + this.setVisible(true); + } + + public void hideResult() { + this.setVisible(false); + } +} diff --git a/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java b/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java index 52fb1bcfa2..3d23b31621 100644 --- a/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java +++ b/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java @@ -12,11 +12,9 @@ import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrameFileDealerPane; import com.fr.design.mainframe.JTemplate; import com.fr.design.mainframe.JVirtualTemplate; -import com.fr.design.module.DesignModuleFactory; import com.fr.design.ui.util.UIUtil; import com.fr.file.FILE; import com.fr.file.FileNodeFILE; -import com.fr.file.StashedFILE; import com.fr.general.ComparatorUtils; import com.fr.invoke.ClassHelper; import com.fr.log.FineLoggerFactory; @@ -26,7 +24,7 @@ import com.fr.stable.CoreConstants; import com.fr.stable.StringUtils; import com.fr.third.org.apache.commons.io.FilenameUtils; -import java.io.ByteArrayOutputStream; +import javax.swing.SwingWorker; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -34,7 +32,6 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Set; -import javax.swing.SwingWorker; /** * 历史模板缓存 @@ -361,22 +358,15 @@ public class HistoryTemplateListCache implements CallbackEvent { int size = historyList.size(); for (int i = 0; i < size; i++) { JTemplate template = historyList.get(i); - FILE file = template.getEditingFILE(); - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - BaseBook target = template.getTarget(); - if (target != null) { - target.export(outputStream); - stashFILEMap.put(i, new StashedFILE(file, outputStream.toByteArray())); - } - // 如果 target == null 那么这个模板是被模板内存优化功能处理过的,不用处理 - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); + FILE file = template.templateToStashFile(); + if (file != null) { + stashFILEMap.put(i, file); } } FineLoggerFactory.getLogger().info("Env Change Template Stashed."); } + private boolean checkStash() { try { return stashWorker.get(); @@ -455,22 +445,13 @@ public class HistoryTemplateListCache implements CallbackEvent { int size = historyList.size(); for (int i = 0; i < size; i++) { JTemplate template = historyList.get(i); + // 判断刷新逻辑比较耗时,且可能出现插件安装后误判导致不刷新 + // 插件安装/启用场景比较少,因此插件安装/启用后每次均进行刷新 FILE file = template.getEditingFILE(); - boolean needReload = context == null || needReloadTemplate(context, template); - if (needReload) { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - BaseBook target = template.getTarget(); - if (target != null) { - FineLoggerFactory.getLogger().info("{} is being reloaded", file.getName()); - target.export(outputStream); - FILE stashedFile = new StashedFILE(file, outputStream.toByteArray()); - template.refreshResource(stashedFile); - } - // 如果 target == null 那么这个模板是被模板内存优化功能处理过的,不用处理 - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } + FILE stashFile = template.templateToStashFile(); + if (stashFile != null) { + FineLoggerFactory.getLogger().info("{} is being reloaded", file.getName()); + template.refreshResource(stashFile); } } FineLoggerFactory.getLogger().info("Plugin env change reload all template ended"); @@ -492,28 +473,6 @@ public class HistoryTemplateListCache implements CallbackEvent { _reloadAllEditingTemplate(null); } - private boolean needReloadTemplate(PluginContext context, JTemplate template) { - BaseBook baseBook = template.getTarget(); - if (baseBook != null) { - String name = template.getEditingFILE().getName(); - String pluginId = context.getID(); - long start = System.currentTimeMillis(); - Set set = ClassHelper.getClassLoadersByFilter(baseBook, ClassFilter.getInstance()); - FineLoggerFactory.getLogger().info("{} find plugin classloader spend: {} ms", name, (System.currentTimeMillis() - start)); - if (set != null) { - for (ClassLoader classLoader : set) { - if (ComparatorUtils.equals(pluginId, PluginManager.detectLeakingPlugin(classLoader))) { - return true; - } - } - } else { - // set为null说明 检测classloader 这里返回true直接刷新 兜底行为 - return true; - } - } - return false; - } - public void replaceCurrentEditingTemplate(JTemplate jt) { int index = contains(this.editingTemplate); this.editingTemplate = jt; 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 87b7f2f25c..08fb3a8689 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 @@ -4,6 +4,7 @@ package com.fr.design.file; import com.fr.base.BaseUtils; import com.fr.base.GraphHelper; import com.fr.base.vcs.DesignerMode; +import com.fr.design.base.mode.DesignModeContext; import com.fr.design.constants.UIConstants; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.gui.imenu.UIMenuItem; @@ -753,7 +754,7 @@ public class MutilTempalteTabPane extends JComponent { /** * 关闭掉一个模板之后激活新的待显示模板 */ - private void activePrevTemplateAfterClose() { + public void activePrevTemplateAfterClose() { if (openedTemplate.isEmpty()) { //新建并激活模板 DesignerContext.getDesignerFrame().addAndActivateJTemplate(); @@ -765,8 +766,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--; } @@ -952,6 +953,10 @@ public class MutilTempalteTabPane extends JComponent { return; } } + //参考CloseCurrentTemplateAction,在closeFormat与closeSpecifiedTemplate之前要先设定isCloseCurrent,这样关闭之后才会自动切换tab + if (checkCurrentClose(template)) { + setIsCloseCurrent(true); + } closeFormat(template); closeSpecifiedTemplate(template); DesignerContext.getDesignerFrame().getContentFrame().repaint(); @@ -984,6 +989,12 @@ public class MutilTempalteTabPane extends JComponent { } + private boolean checkCurrentClose(JTemplate template) { + JTemplate currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + //10.0无JTemplate.isValid + return currentTemplate != null && ComparatorUtils.equals(template.getPath(), currentTemplate.getPath()); + } + private class MultiTemplateTabMouseMotionListener implements MouseMotionListener { /** diff --git a/designer-base/src/main/java/com/fr/design/fun/RegPaneProvider.java b/designer-base/src/main/java/com/fr/design/fun/RegPaneProvider.java new file mode 100644 index 0000000000..26fe62b5e6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/RegPaneProvider.java @@ -0,0 +1,11 @@ +package com.fr.design.fun; + +import com.fr.design.gui.frpane.RegFieldPane; +import com.fr.stable.fun.mark.Immutable; + +public interface RegPaneProvider extends Immutable { + int CURRENT_LEVEL = 1; + String XML_TAG = "RegPaneProvider"; + + RegFieldPane createRegPane(); +} diff --git a/designer-base/src/main/java/com/fr/design/fun/TextFieldAdapterProvider.java b/designer-base/src/main/java/com/fr/design/fun/TextFieldAdapterProvider.java new file mode 100644 index 0000000000..7ab8c782b4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/TextFieldAdapterProvider.java @@ -0,0 +1,11 @@ +package com.fr.design.fun; + +import com.fr.design.beans.ErrorMsgTextFieldAdapter; +import com.fr.stable.fun.mark.Immutable; + +public interface TextFieldAdapterProvider extends Immutable { + String XML_TAG = "TextFieldAdapterProvider"; + int CURRENT_LEVEL = 1; + + ErrorMsgTextFieldAdapter createTextFieldAdapter(); +} diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractRegPaneProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractRegPaneProvider.java new file mode 100644 index 0000000000..98185f2a5a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractRegPaneProvider.java @@ -0,0 +1,22 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.RegPaneProvider; +import com.fr.stable.fun.mark.API; + +/** + * @author Joe + * 2021/10/8 15:19 + */ +@API(level = RegPaneProvider.CURRENT_LEVEL) +public abstract class AbstractRegPaneProvider implements RegPaneProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public int layerIndex() { + return DEFAULT_LAYER_INDEX; + } +} diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractTextFieldAdapterProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractTextFieldAdapterProvider.java new file mode 100644 index 0000000000..bc0836eb40 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractTextFieldAdapterProvider.java @@ -0,0 +1,22 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.TextFieldAdapterProvider; +import com.fr.stable.fun.mark.API; + +/** + * @author Joe + * 2021/10/8 15:17 + */ +@API(level = TextFieldAdapterProvider.CURRENT_LEVEL) +public abstract class AbstractTextFieldAdapterProvider implements TextFieldAdapterProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public int layerIndex() { + return DEFAULT_LAYER_INDEX; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/chart/ChartEditPaneProvider.java b/designer-base/src/main/java/com/fr/design/gui/chart/ChartEditPaneProvider.java index 3003800364..0a3684ba30 100644 --- a/designer-base/src/main/java/com/fr/design/gui/chart/ChartEditPaneProvider.java +++ b/designer-base/src/main/java/com/fr/design/gui/chart/ChartEditPaneProvider.java @@ -16,4 +16,7 @@ public interface ChartEditPaneProvider { default void removeChartEditPaneActionListener(ChartEditPaneActionListener l) { } + default void resetLastChartCollection() { + } + } diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/JControlPane.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/JControlPane.java index 0d01ddbdaa..37fef509db 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/JControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/JControlPane.java @@ -9,10 +9,16 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.menu.ToolBarDef; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.stable.ArrayUtils; +import com.fr.stable.Filter; import com.fr.stable.Nameable; -import javax.swing.*; -import java.awt.*; +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.util.Arrays; +import java.util.stream.Stream; /** * Coder: zack @@ -27,6 +33,8 @@ abstract class JControlPane extends BasicPane implements UnrepeatedNameHelper, S ShortCut4JControlPane[] shorts; NameableCreator[] creators; + + protected Filter creatorsFilter; private ToolBarDef toolbarDef; UIToolbar toolBar; @@ -38,6 +46,7 @@ abstract class JControlPane extends BasicPane implements UnrepeatedNameHelper, S JControlPane() { this.initShortCutFactory(); + this.initCreatorsFilter(); this.initComponentPane(); } @@ -106,6 +115,10 @@ abstract class JControlPane extends BasicPane implements UnrepeatedNameHelper, S this.checkButtonEnabled(); } + protected void initCreatorsFilter() { + this.creatorsFilter = nameableCreator -> true; + } + protected void initCardPane() { this.controlUpdatePane = createControlUpdatePane(); @@ -183,7 +196,12 @@ abstract class JControlPane extends BasicPane implements UnrepeatedNameHelper, S } public NameableCreator[] creators() { - return creators == null ? new NameableCreator[0] : creators; + if (creators == null) { + return new NameableCreator[0]; + } else { + Stream nameableCreatorStream = Arrays.stream(creators).filter(creator -> creatorsFilter.accept(creator)); + return nameableCreatorStream.toArray(NameableCreator[]::new); + } } /** diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java index 6ec5f496a6..063491f884 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java @@ -125,7 +125,9 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li for (int i = 0, size = widget.getListenerSize(); i < size; i++) { Listener listener = widget.getListener(i); if (!listener.isDefault()) { - nameObjectList.add(i, new NameObject(switchLang(listener.getEventName()) + (i + 1), listener)); + String eventName = switchLang(listener.getEventName()) + (nameObjectList.size() + 1); + NameObject nameObject = new NameObject(eventName, listener); + nameObjectList.add(nameObject); } } populate(getHelper().processCatalog(nameObjectList)); diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/shortcutfactory/ShortCutFactory.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/shortcutfactory/ShortCutFactory.java index 7d16995435..da0b552682 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/shortcutfactory/ShortCutFactory.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/shortcutfactory/ShortCutFactory.java @@ -142,10 +142,6 @@ public class ShortCutFactory extends AbstractShortCutFactory { private void wrapActionListener(NameableCreator[] creators) { for (final NameableCreator creator : creators) { - Filter> filter = DesignModuleFactory.getHyperlinkGroupType().getFilter(); - if (!filter.accept(creator.getHyperlink())) { - continue; - } boolean isTrue = ComparatorUtils.equals(creator.menuName(), com.fr.design.i18n.Toolkit.i18nText("Datasource-Stored_Procedure")) || ComparatorUtils.equals(creator.menuName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS_Relation_TableData")) || ComparatorUtils.equals(creator.menuName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_DS_Multi_Dimensional_Database")); if (isTrue) { diff --git a/designer-base/src/main/java/com/fr/design/gui/frpane/RegFieldPane.java b/designer-base/src/main/java/com/fr/design/gui/frpane/RegFieldPane.java index 5d37fb4a96..38e33514bc 100644 --- a/designer-base/src/main/java/com/fr/design/gui/frpane/RegFieldPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/frpane/RegFieldPane.java @@ -1,21 +1,25 @@ package com.fr.design.gui.frpane; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.beans.ErrorMsgTextFieldAdapter; +import com.fr.design.beans.UITextFieldAdapter; import com.fr.design.constants.LayoutConstants; import com.fr.design.designer.IntervalConstants; import com.fr.design.dialog.BasicPane; +import com.fr.design.fun.TextFieldAdapterProvider; import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.itextfield.UITextField; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayoutHelper; import com.fr.form.ui.TextEditor; import com.fr.form.ui.reg.NoneReg; import com.fr.form.ui.reg.RegExp; +import com.fr.log.FineLoggerFactory; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.awt.*; +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; /** * Created by kerry on 2017/9/4. @@ -23,7 +27,7 @@ import java.awt.*; public class RegFieldPane extends RegPane { protected RegErrorMsgPane regErrorMsgPane; - public RegFieldPane(){ + public RegFieldPane() { this(ALL_REG_TYPE); } @@ -39,8 +43,8 @@ public class RegFieldPane extends RegPane { @Override public void regChangeAction() { - RegExp regExp = (RegExp)getRegComboBox().getSelectedItem(); - if(regExp instanceof NoneReg){ + RegExp regExp = (RegExp) getRegComboBox().getSelectedItem(); + if (regExp instanceof NoneReg) { regErrorMsgPane.setVisible(false); return; } @@ -67,33 +71,35 @@ public class RegFieldPane extends RegPane { } private static class RegErrorMsgPane extends BasicPane { - private UITextField regErrorMsgField; + private ErrorMsgTextFieldAdapter errorMsgTextFieldAdapter; public RegErrorMsgPane() { + initRegErrorMsgField(); + setStyle(); + } + + private void setStyle() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); this.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L6, IntervalConstants.INTERVAL_L5, 0, 0)); - initRegErrorMsgField(); UILabel tipLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Widget_Error_Tip")); tipLabel.setPreferredSize(new Dimension(60, 20)); - JPanel panel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{tipLabel, regErrorMsgField}}, TableLayoutHelper.FILL_LASTCOLUMN, 10, LayoutConstants.VGAP_MEDIUM); + JPanel panel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{tipLabel, errorMsgTextFieldAdapter.getErrorMsgTextField()}}, TableLayoutHelper.FILL_LASTCOLUMN, 10, LayoutConstants.VGAP_MEDIUM); this.add(panel); } private void initRegErrorMsgField() { - regErrorMsgField = new UITextField(); - regErrorMsgField.getDocument().addDocumentListener(new DocumentListener() { - public void changedUpdate(DocumentEvent e) { - regErrorMsgField.setToolTipText(regErrorMsgField.getText()); - } - - public void insertUpdate(DocumentEvent e) { - regErrorMsgField.setToolTipText(regErrorMsgField.getText()); - } + TextFieldAdapterProvider provider = ExtraDesignClassManager.getInstance().getSingle(TextFieldAdapterProvider.XML_TAG); + if (provider == null) { + errorMsgTextFieldAdapter = new UITextFieldAdapter(); + return; + } + try { + errorMsgTextFieldAdapter = provider.createTextFieldAdapter(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + errorMsgTextFieldAdapter = new UITextFieldAdapter(); - public void removeUpdate(DocumentEvent e) { - regErrorMsgField.setToolTipText(regErrorMsgField.getText()); - } - }); + } } @Override @@ -102,11 +108,11 @@ public class RegFieldPane extends RegPane { } public void populate(TextEditor textEditor) { - regErrorMsgField.setText(textEditor.getRegErrorMessage()); + errorMsgTextFieldAdapter.setText(textEditor.getRegErrorMessage()); } public void update(TextEditor textEditor) { - textEditor.setRegErrorMessage(regErrorMsgField.getText()); + textEditor.setRegErrorMessage(errorMsgTextFieldAdapter.getText()); } } diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButton.java index 335397d908..fd3fac7bca 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButton.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButton.java @@ -61,6 +61,14 @@ public class UIButton extends JButton implements UIObserver, UITextComponent { init(); } + public UIButton(Icon icon, boolean decorate) { + this(icon); + if (!decorate) { + setContentAreaFilled(false); + setFocusPainted(false); + setBorderPainted(false); + } + } public UIButton(Icon icon) { super(icon); diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java index 624e2e8ee8..5ca303fd57 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java @@ -379,7 +379,10 @@ public class UIButtonGroup extends JPanel implements GlobalNameObserver { * @param l */ public void removeChangeListener(ChangeListener l) { - this.listenerList.remove(ChangeListener.class, l); + for (int i = 0; i < labelButtonList.size(); i++) { + labelButtonList.get(i).removeChangeListener(l); + listenerList.remove(ChangeListener.class, l); + } } diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java index 8fe79d41ed..c122394476 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java @@ -248,7 +248,7 @@ public class FRTreeComboBox extends UIComboBox { private static TreePopup treePopup; - private static class FRTreeComboBoxUI extends BasicComboBoxUI implements MouseListener{ + protected static class FRTreeComboBoxUI extends BasicComboBoxUI implements MouseListener{ private boolean isRollover = false; public FRTreeComboBoxUI() { @@ -535,7 +535,7 @@ public class FRTreeComboBox extends UIComboBox { public class FrTreeSearchComboBoxEditor extends UIComboBoxEditor implements DocumentListener { private volatile boolean setting = false; private FRTreeComboBox comboBox; - private Object item; + protected Object item; public FrTreeSearchComboBoxEditor(FRTreeComboBox comboBox) { super(); diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/SearchPreTaskTreeComboBox.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/SearchPreTaskTreeComboBox.java deleted file mode 100644 index 2d936d8964..0000000000 --- a/designer-base/src/main/java/com/fr/design/gui/icombobox/SearchPreTaskTreeComboBox.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.fr.design.gui.icombobox; - -import com.fr.log.FineLoggerFactory; - -import javax.swing.JTree; -import javax.swing.SwingWorker; -import javax.swing.tree.TreeCellRenderer; -import java.util.concurrent.FutureTask; - -/** - * 模糊搜索前需执行完前置任务的TreeComboBox - * @author Lucian.Chen - * @version 10.0 - * Created by Lucian.Chen on 2021/4/14 - */ -public class SearchPreTaskTreeComboBox extends FRTreeComboBox { - - /** - * 模糊搜索前任务 - */ - private FutureTask preSearchTask; - - public SearchPreTaskTreeComboBox(JTree tree, TreeCellRenderer renderer, boolean editable) { - super(tree, renderer, editable); - } - - public FutureTask getPreSearchTask() { - return preSearchTask; - } - - public void setPreSearchTask(FutureTask preSearchTask) { - this.preSearchTask = preSearchTask; - } - - protected UIComboBoxEditor createEditor() { - return new SearchPreTaskComboBoxEditor(this); - } - - private class SearchPreTaskComboBoxEditor extends FrTreeSearchComboBoxEditor { - - public SearchPreTaskComboBoxEditor(FRTreeComboBox comboBox) { - super(comboBox); - } - - protected void changeHandler() { - if (isSetting()) { - return; - } - setPopupVisible(true); - new SwingWorker() { - @Override - protected Void doInBackground() { - FutureTask task = getPreSearchTask(); - try { - // 确保模糊搜索前任务执行完成后,再进行模糊搜索 - if (task != null) { - task.get(); - } - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - if (task != null) { - // 任务执行后置空,否则会被别的操作重复触发 - setPreSearchTask(null); - } - return null; - } - - @Override - protected void done() { - // 模糊搜索 - search(); - } - }.execute(); - } - } -} diff --git a/designer-base/src/main/java/com/fr/design/gui/icombobox/TableSearchTreeComboBox.java b/designer-base/src/main/java/com/fr/design/gui/icombobox/TableSearchTreeComboBox.java new file mode 100644 index 0000000000..916cd3cf6f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/icombobox/TableSearchTreeComboBox.java @@ -0,0 +1,236 @@ +package com.fr.design.gui.icombobox; + +import com.fr.concurrent.NamedThreadFactory; +import com.fr.data.core.DataCoreUtils; +import com.fr.data.core.db.TableProcedure; +import com.fr.data.impl.Connection; +import com.fr.design.DesignerEnvManager; +import com.fr.design.data.datapane.ChoosePane; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.mainframe.DesignerContext; +import com.fr.log.FineLoggerFactory; +import com.fr.module.ModuleContext; +import com.fr.stable.ArrayUtils; +import com.fr.stable.Filter; +import com.fr.stable.StringUtils; + +import javax.swing.JOptionPane; +import javax.swing.JTree; +import javax.swing.SwingWorker; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.util.Enumeration; +import java.util.concurrent.ExecutorService; + +/** + * 实现模糊搜索表名的FRTreeComboBox + * FRTreeComboBox:搜索后滚动到首个匹配节点 + * SearchFRTreeComboBox:显示所有匹配的节点 + * + * @author Lucian.Chen + * @version 10.0 + * Created by Lucian.Chen on 2021/4/14 + */ +public class TableSearchTreeComboBox extends FRTreeComboBox { + // 持有父容器,需要实时获取其他组件值 + private final ChoosePane parent; + /** + * 保证模糊搜索的原子性操作 + */ + private final ExecutorService singleExecutor = ModuleContext.getExecutor().newSingleThreadScheduledExecutor(new NamedThreadFactory("TableSearchTreeComboBox")); + + public TableSearchTreeComboBox(ChoosePane parent, JTree tree, TreeCellRenderer renderer) { + super(tree, renderer); + this.parent = parent; + initPopupListener(); + } + + protected UIComboBoxEditor createEditor() { + return new TableSearchComboBoxEditor(this); + } + + @Override + protected String pathToString(TreePath path) { + Object obj = ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject(); + if (obj instanceof TableProcedure) { + return ((TableProcedure) obj).getName(); + } + return super.pathToString(path); + } + + @Override + public void setSelectedItemString(String _name) { + super.setSelectedItemString(_name); + // 会因为连续两次选中的值一致,导致未触发编辑框联动 + this.getEditor().setItem(_name); + } + + /** + * 执行模糊搜索 + */ + private void searchExecute() { + UIComboBoxEditor searchEditor = (UIComboBoxEditor) this.getEditor(); + String searchText = (String) searchEditor.getItem(); + singleExecutor.execute(new SwingWorker() { + @Override + protected Void doInBackground() { + processTableDataNames( + parent.getDSName(), + parent.getConnection(), + parent.getSchema(), + createFilter(searchText)); + return null; + } + + @Override + protected void done() { + expandTree(); + // 输入框获取焦点 + searchEditor.getEditorComponent().requestFocus(); + } + }); + } + + private TableNameFilter createFilter(String text) { + return StringUtils.isEmpty(text) ? EMPTY_FILTER : new TableNameFilter(text); + } + + /** + * 查询数据库表,并构建节点目录 + * + * @param databaseName 数据库名 + * @param connection 数据连接 + * @param schema 模式 + * @param filter 模糊搜索过滤器 + */ + private void processTableDataNames(String databaseName, Connection connection, String schema, TableNameFilter filter) { + if (tree == null) { + return; + } + DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot(); + rootTreeNode.removeAllChildren(); + + if (connection == null) { + return; + } + try { + schema = StringUtils.isEmpty(schema) ? null : schema; + TableProcedure[] sqlTableArray = DataCoreUtils.getTables(connection, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); + if (ArrayUtils.isNotEmpty(sqlTableArray)) { + ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table")); + rootTreeNode.add(tableTreeNode); + addArrayNode(tableTreeNode, sqlTableArray, filter); + } + TableProcedure[] sqlViewArray = DataCoreUtils.getTables(connection, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); + if (ArrayUtils.isNotEmpty(sqlViewArray)) { + ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View")); + rootTreeNode.add(viewTreeNode); + addArrayNode(viewTreeNode, sqlViewArray, filter); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE); + } + } + + private void addArrayNode(ExpandMutableTreeNode rootNode, TableProcedure[] sqlArray, TableNameFilter filter) { + if (sqlArray != null) { + for (TableProcedure procedure : sqlArray) { + if (filter.accept(procedure)) { + ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(procedure); + rootNode.add(viewChildTreeNode); + } + } + } + } + + /** + * 展开节点 + */ + private void expandTree() { + ((DefaultTreeModel) tree.getModel()).reload(); + // daniel 展开所有tree + TreeNode root = (TreeNode) tree.getModel().getRoot(); + TreePath parent = new TreePath(root); + TreeNode node = (TreeNode) parent.getLastPathComponent(); + for (Enumeration e = node.children(); e.hasMoreElements(); ) { + TreeNode n = (TreeNode) e.nextElement(); + TreePath path = parent.pathByAddingChild(n); + tree.expandPath(path); + } + } + + /** + * 表名模糊搜索实现 + */ + private static class TableNameFilter implements Filter { + private String searchFilter; + + public TableNameFilter() { + } + + public TableNameFilter(String searchFilter) { + this.searchFilter = searchFilter.toLowerCase().trim(); + } + + // 表名匹配 + @Override + public boolean accept(TableProcedure procedure) { + return procedure.getName().toLowerCase().contains(searchFilter); + } + } + + private static final TableNameFilter EMPTY_FILTER = new TableNameFilter() { + public boolean accept(TableProcedure procedure) { + return true; + } + }; + + private void initPopupListener() { + // 点击下拉时触发模糊搜索 + this.addPopupMenuListener(new PopupMenuListener() { + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + searchExecute(); + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + + } + }); + } + + /** + * 重写输入框编辑器,实现输入框模糊搜索逻辑 + */ + private class TableSearchComboBoxEditor extends FrTreeSearchComboBoxEditor { + + public TableSearchComboBoxEditor(FRTreeComboBox comboBox) { + super(comboBox); + } + + @Override + protected void changeHandler() { + if (isSetting()) { + return; + } + setPopupVisible(true); + this.item = textField.getText(); + searchExecute(); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/icontainer/UIEastResizableContainer.java b/designer-base/src/main/java/com/fr/design/gui/icontainer/UIEastResizableContainer.java index 125cd3aa16..dcd33498a4 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icontainer/UIEastResizableContainer.java +++ b/designer-base/src/main/java/com/fr/design/gui/icontainer/UIEastResizableContainer.java @@ -296,10 +296,9 @@ public class UIEastResizableContainer extends JPanel { model = UIConstants.MODEL_NORMAL; refreshContainer(); } - @Override - public void mouseClicked(MouseEvent e) { - if (e.getX() <= ARROW_RANGE) { + public void mouseReleased(MouseEvent e) { + if (isInPane(e)) { if (containerWidth == leftPaneWidth) { showContainer(); } else { @@ -309,7 +308,9 @@ public class UIEastResizableContainer extends JPanel { } }); } - + public boolean isInPane(MouseEvent e){ + return e.getX() <= ARROW_RANGE && e.getX() >= 0 && e.getY() <= topToolPaneHeight && e.getY() >= 0; + } @Override public void paint(Graphics g) { Image button; diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/ExtensionFilter.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/ExtensionFilter.java new file mode 100644 index 0000000000..9ec582f693 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/ExtensionFilter.java @@ -0,0 +1,25 @@ +package com.fr.design.gui.ifilechooser; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2021/12/29 + */ +public class ExtensionFilter { + + private final String des; + private final String[] extensions; + + public ExtensionFilter(String des, String... extensions) { + this.des = des; + this.extensions = extensions; + } + + public String getDes() { + return des; + } + + public String[] getExtensions() { + return extensions; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserArgs.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserArgs.java new file mode 100644 index 0000000000..b011e5b350 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserArgs.java @@ -0,0 +1,109 @@ +package com.fr.design.gui.ifilechooser; + +/** + * 文件选择器可设置的参数集合 + * + * @author hades + * @version 10.0 + * Created by hades on 2021/12/21 + */ +public class FileChooserArgs { + + private final FileSelectionMode fileSelectionMode; + private final String filterDes; + private final String[] extensions; + private final String selectedPath; + private final ExtensionFilter[] filters; + private final String tipText; + private final boolean multiSelectionEnabled; + + public static Builder newBuilder() { + return new Builder(); + } + + private FileChooserArgs(Builder builder) { + this.fileSelectionMode = builder.fileSelectionMode; + this.filterDes = builder.filterDes; + this.extensions = builder.extensions; + this.selectedPath = builder.selectedPath; + this.filters = builder.filters; + this.tipText = builder.tipText; + this.multiSelectionEnabled = builder.multiSelectionEnabled; + } + + public FileSelectionMode getFileSelectionMode() { + return fileSelectionMode; + } + + public String getFilterDes() { + return filterDes; + } + + public String[] getExtensions() { + return extensions; + } + + public String getSelectedPath() { + return selectedPath; + } + + public ExtensionFilter[] getFilters() { + return filters; + } + + public String getTipText() { + return tipText; + } + + public boolean isMultiSelectionEnabled() { + return multiSelectionEnabled; + } + + public static class Builder { + + private FileSelectionMode fileSelectionMode; + private String filterDes; + private String[] extensions; + private String selectedPath; + private ExtensionFilter[] filters = new ExtensionFilter[0]; + private String tipText; + private boolean multiSelectionEnabled; + + public Builder setFileSelectionMode(FileSelectionMode fileSelectionMode) { + this.fileSelectionMode = fileSelectionMode; + return this; + } + + public Builder setFilter(String filterDes, String... extensions) { + this.filterDes = filterDes; + this.extensions = extensions; + return this; + } + + public Builder setSelectedPath(String selectedPath) { + this.selectedPath = selectedPath; + return this; + } + + public Builder setFilters(ExtensionFilter[] filters) { + this.filters = filters; + return this; + } + + public Builder setTipText(String tipText) { + this.tipText = tipText; + return this; + } + + public Builder setMultiSelectionEnabled(boolean multiSelectionEnabled) { + this.multiSelectionEnabled = multiSelectionEnabled; + return this; + } + + public FileChooserArgs build() { + return new FileChooserArgs(this); + } + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserFactory.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserFactory.java new file mode 100644 index 0000000000..36a53c8dc9 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserFactory.java @@ -0,0 +1,44 @@ +package com.fr.design.gui.ifilechooser; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.os.impl.SupportOSImpl; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2021/12/21 + */ +public class FileChooserFactory { + + public static FileChooserProvider createFileChooser(FileChooserArgs fileChooserArgs) { + if (SupportOSImpl.OLD_STYLE_CHOOSER.support()) { + return new SwingFileChooser.Builder(). + setFileSelectionMode(fileChooserArgs.getFileSelectionMode()). + setFileFilter(fileChooserArgs.getFilterDes(), fileChooserArgs.getExtensions()). + setSelectedFile(fileChooserArgs.getSelectedPath()). + setMultiSelectionEnabled(fileChooserArgs.isMultiSelectionEnabled()). + setTipText(fileChooserArgs.getTipText()). + setFileFilter(fileChooserArgs.getFilters()).build(); + } else { + return new JavaFxNativeFileChooser.Builder(). + fileSelectionMode(fileChooserArgs.getFileSelectionMode()). + filter(fileChooserArgs.getFilterDes(), fileChooserArgs.getExtensions()). + currentDirectory(fileChooserArgs.getSelectedPath()). + title(fileChooserArgs.getTipText()). + filters(fileChooserArgs.getFilters()).build(); + } + } + + public static FileChooserProvider createImageFileChooser() { + if (SupportOSImpl.OLD_STYLE_CHOOSER.support()) { + return new SwingImageFileChooser(); + } else { + return new JavaFxNativeFileChooser.Builder(). + fileSelectionMode(FileSelectionMode.FILE). + title(Toolkit.i18nText("Fine-Design_Basic_Open")). + filter(Toolkit.i18nText("Fine-Design_Basic_Image_Image_Files"), "*.jpg", "*.gif", "*.png", "*.bmp"). + build(); + } + } + +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserProvider.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserProvider.java index aa95fe27bd..a5d7e97303 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserProvider.java +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserProvider.java @@ -9,4 +9,17 @@ public interface FileChooserProvider { File getSelectedFile(); int showDialog(Component parent); + + + default int showOpenDialog(Component parent, String approveButtonText) { + return -1; + } + + default void setMultiSelectionEnabled(boolean multiple) { + + } + + default void setCurrentDirectory(File file) { + + } } diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/JavaFxNativeFileChooser.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/JavaFxNativeFileChooser.java index 452deb5c8d..5403ae1591 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/JavaFxNativeFileChooser.java +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/JavaFxNativeFileChooser.java @@ -4,6 +4,8 @@ package com.fr.design.gui.ifilechooser; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.log.FineLoggerFactory; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; import com.sun.javafx.application.PlatformImpl; import javafx.application.Platform; import javafx.scene.Scene; @@ -163,6 +165,8 @@ public class JavaFxNativeFileChooser implements FileChooserProvider { try { latch.await(); } catch (InterruptedException ignore) { + } finally { + setShowDialogState(false); } return selectedFiles.length > 0 ? JFileChooser.APPROVE_OPTION : JFileChooser.CANCEL_OPTION; } @@ -171,10 +175,20 @@ public class JavaFxNativeFileChooser implements FileChooserProvider { this.fileSelectionMode = fileSelectionMode; } + @Override public void setCurrentDirectory(File currentDirectory) { this.currentDirectory = currentDirectory; } + @Override + public void setMultiSelectionEnabled(boolean multiple) { + this.setSelectionMode(multiple ? FileSelectionMode.MULTIPLE_FILE : FileSelectionMode.FILE); + } + + @Override + public int showOpenDialog(Component parent, String approveButtonText) { + return this.showDialog(parent); + } public static class Builder { private FileSelectionMode fileSelectionMode = FileSelectionMode.FILE; @@ -183,17 +197,32 @@ public class JavaFxNativeFileChooser implements FileChooserProvider { private File currentDirectory; public Builder fileSelectionMode(FileSelectionMode fileSelectionMode) { - this.fileSelectionMode = fileSelectionMode; + if (fileSelectionMode != null) { + this.fileSelectionMode = fileSelectionMode; + } return this; } public Builder title(String title) { - this.title = title; + if (StringUtils.isNotEmpty(title)) { + this.title = title; + } return this; } public Builder filters(FileChooser.ExtensionFilter[] filters) { - this.filters = filters; + if (filters != null) { + this.filters = filters; + } + return this; + } + + public Builder filters(ExtensionFilter[] filters) { + if (filters != null) { + for (ExtensionFilter filter : filters) { + this.filters = ArrayUtils.add(this.filters, new FileChooser.ExtensionFilter(filter.getDes(), filter.getExtensions())); + } + } return this; } @@ -204,7 +233,6 @@ public class JavaFxNativeFileChooser implements FileChooserProvider { return this; } - public Builder currentDirectory(File currentDirectory) { if (currentDirectory != null) { if (!currentDirectory.isDirectory()) { diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingFileChooser.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingFileChooser.java new file mode 100644 index 0000000000..47abaa8b67 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingFileChooser.java @@ -0,0 +1,134 @@ +package com.fr.design.gui.ifilechooser; + +import com.fr.common.annotations.Negative; +import com.fr.design.upm.UpmUtils; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; +import java.awt.Component; +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileNameExtensionFilter; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2021/12/21 + */ +@Negative(until = "2022-6-1") +class SwingFileChooser implements FileChooserProvider { + + private final JFileChooser fileChooser; + private final Builder builder; + + private SwingFileChooser(Builder builder) { + fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(builder.fileSelectionMode); + fileChooser.setFileFilter(builder.fileFilter); + fileChooser.setSelectedFile(builder.selectedFile); + fileChooser.setMultiSelectionEnabled(builder.multiSelectionEnabled); + this.builder = builder; + } + + @Override + public File[] getSelectedFiles() { + if (ArrayUtils.isNotEmpty(fileChooser.getSelectedFiles())) { + return fileChooser.getSelectedFiles(); + } else { + return new File[]{fileChooser.getSelectedFile()}; + } + } + + @Override + public File getSelectedFile() { + return fileChooser.getSelectedFile(); + } + + @Override + public int showDialog(Component parent) { + if (StringUtils.isEmpty(builder.tipText)) { + return fileChooser.showOpenDialog(parent); + } else { + return fileChooser.showDialog(parent, builder.tipText); + } + } + + @Override + public int showOpenDialog(Component parent, String approveButtonText) { + return fileChooser.showDialog(parent, approveButtonText); + } + + @Override + public void setCurrentDirectory(File file) { + fileChooser.setCurrentDirectory(file); + } + + @Override + public void setMultiSelectionEnabled(boolean multiple) { + fileChooser.setMultiSelectionEnabled(multiple); + } + + /** + * 和一般builder不同的是 setXXX还做参数转换逻辑 + */ + public static class Builder { + + private int fileSelectionMode = JFileChooser.FILES_ONLY; + private FileFilter fileFilter; + private File selectedFile; + private boolean multiSelectionEnabled; + private String tipText; + + public Builder setFileSelectionMode(FileSelectionMode fileSelectionMode) { + if (FileSelectionMode.DIR.equals(fileSelectionMode)) { + this.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY; + } else if (FileSelectionMode.FILE.equals(fileSelectionMode)) { + this.fileSelectionMode = JFileChooser.FILES_ONLY; + } else if (FileSelectionMode.MULTIPLE_FILE.equals(fileSelectionMode)) { + this.fileSelectionMode = JFileChooser.FILES_AND_DIRECTORIES; + } + return this; + } + + public Builder setFileFilter(String des, String... extension) { + if (StringUtils.isNotEmpty(des) && ArrayUtils.isNotEmpty(extension)) { + this.fileFilter = new FileNameExtensionFilter(des, UpmUtils.findMatchedExtension(extension)); + } + return this; + } + + public Builder setFileFilter(ExtensionFilter[] extensionFilters) { + StringBuilder desBuilder = new StringBuilder(); + String[] extensions = new String[0]; + for (ExtensionFilter extensionFilter : extensionFilters) { + desBuilder.append(extensionFilter.getDes()).append(" "); + extensions = ArrayUtils.addAll(extensions, UpmUtils.findMatchedExtension(extensionFilter.getExtensions())); + } + if (ArrayUtils.isNotEmpty(extensionFilters)) { + this.fileFilter = new FileNameExtensionFilter(desBuilder.toString().trim(), extensions); + } + return this; + } + + public Builder setSelectedFile(String selectedPath) { + if (StringUtils.isNotEmpty(selectedPath)) { + this.selectedFile = new File(selectedPath); + } + return this; + } + + public Builder setMultiSelectionEnabled(boolean multiSelectionEnabled) { + this.multiSelectionEnabled = multiSelectionEnabled; + return this; + } + + public Builder setTipText(String tipText) { + this.tipText = tipText; + return this; + } + + public SwingFileChooser build() { + return new SwingFileChooser(this); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingImageFileChooser.java b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingImageFileChooser.java new file mode 100644 index 0000000000..3c0c6c1afc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingImageFileChooser.java @@ -0,0 +1,276 @@ +package com.fr.design.gui.ifilechooser; + +import com.fr.base.BaseUtils; +import com.fr.common.annotations.Negative; +import com.fr.design.DesignerEnvManager; +import com.fr.design.style.ChooseFileView; +import com.fr.design.style.background.image.ExpandFileChooser; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.Enumeration; +import java.util.Hashtable; +import javax.swing.filechooser.FileFilter; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2021/12/30 + */ +@Negative(until = "2022-6-1") +class SwingImageFileChooser extends ExpandFileChooser implements FileChooserProvider { + + public SwingImageFileChooser() { + super(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Image_Compress"),com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Open")); + ExampleFileFilter bothFilter = new ExampleFileFilter( + new String[]{"jpg", "gif", "png", "bmp"}, + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Image_Image_Files")); + bothFilter.setExtensionListInDescription(true); + this.addChoosableFileFilter(bothFilter); + this.setAcceptAllFileFilterUsed(false); + + // Create Custom FileView + ChooseFileView fileView = new ChooseFileView(); + fileView.putIcon("jpg", BaseUtils.readIcon("/com/fr/base/images/dialog/file/jpgFile.gif")); + fileView.putIcon("gif", BaseUtils.readIcon("/com/fr/base/images/dialog/file/gifFile.gif")); + fileView.putIcon("png", BaseUtils.readIcon("/com/fr/base/images/dialog/file/pngFile.png")); + fileView.putIcon("bmp", BaseUtils.readIcon("/com/fr/base/images/dialog/file/bmpFile.gif")); + + this.setFileView(fileView); + } + + @Override + public int showDialog(Component parent, String approveButtonText) { + return super.showDialog(parent, approveButtonText); + } + + @Override + public ActionListener checkAction() { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + DesignerEnvManager.getEnvManager().setImageCompress(isCheckSelected()); + DesignerEnvManager.getEnvManager().saveXMLFile(); + } + }; + + } + + @Override + public int showDialog(Component parent) { + return showOpenDialog(parent); + } + + /** + * A convenience implementation of FileFilter that filters out + * all files except for those type extensions that it knows about. + *

D:\finereport\develop\code\test\TestCase\WEB-INF\reportlets\TestCase\01903.cpt + *

+ * Extensions are of the type ".foo", which is typically found on + * Windows and Unix boxes, but not on Macinthosh. Case is ignored. + *

+ * Example - create a new filter that filerts out all files + * but gif and jpg image files: + *

+ * JFileChooser chooser = new JFileChooser(); + * ExampleFileFilter filter = new ExampleFileFilter( + * new String{"gif", "jpg"}, "JPEG & GIF Images") + * chooser.addChoosableFileFilter(filter); + * chooser.showOpenDialog(this); + * + * @author Jeff Dinkins + * @version 1.12 12/03/01 + */ + class ExampleFileFilter extends FileFilter { + private Hashtable filters = null; + private String description = null; + private String fullDescription = null; + private boolean useExtensionsInDescription = true; + + /** + * Creates a file filter. If no filters are added, then all + * files are accepted. + * + * @see #addExtension + */ + public ExampleFileFilter() { + this.filters = new Hashtable(); + } + + /** + * Creates a file filter that accepts files with the given extension. + * Example: new ExampleFileFilter("jpg"); + * + * @see #addExtension + */ + public ExampleFileFilter(String extension) { + this(extension, null); + } + + /** + * Creates a file filter that accepts the given file type. + * Example: new ExampleFileFilter("jpg", "JPEG Image Images"); + *

+ * Note that the "." before the extension is not needed. If + * provided, it will be ignored. + * + * @see #addExtension + */ + public ExampleFileFilter(String extension, String description) { + this(); + if (extension != null) addExtension(extension); + if (description != null) setDescription(description); + } + + /** + * Creates a file filter from the given string array. + * Example: new ExampleFileFilter(String {"gif", "jpg"}); + *

+ * Note that the "." before the extension is not needed adn + * will be ignored. + * + * @see #addExtension + */ + public ExampleFileFilter(String[] filters) { + this(filters, null); + } + + /** + * Creates a file filter from the given string array and description. + * Example: new ExampleFileFilter(String {"gif", "jpg"}, "Gif and JPG Images"); + *

+ * Note that the "." before the extension is not needed and will be ignored. + * + * @see #addExtension + */ + public ExampleFileFilter(String[] filters, String description) { + this(); + for (int i = 0; i < filters.length; i++) { + // add filters one by one + addExtension(filters[i]); + } + if (description != null) setDescription(description); + } + + /** + * Return true if this file should be shown in the directory pane, + * false if it shouldn't. + *

+ * Files that begin with "." are ignored. + * + * @see #getExtension + */ + @Override + public boolean accept(File f) { + if (f != null) { + if (f.isDirectory()) { + return true; + } + String extension = getExtension(f); + if (extension != null && filters.get(getExtension(f)) != null) { + return true; + } + } + return false; + } + + /** + * Return the extension portion of the file's name . + * + * @see #getExtension + * @see FileFilter#accept + */ + public String getExtension(File f) { + if (f != null) { + String filename = f.getName(); + int i = filename.lastIndexOf('.'); + if (i > 0 && i < filename.length() - 1) { + return filename.substring(i + 1).toLowerCase(); + } + } + return null; + } + + /** + * Adds a filetype "dot" extension to filter against. + *

+ * For example: the following code will create a filter that filters + * out all files except those that end in ".jpg" and ".tif": + *

+ * ExampleFileFilter filter = new ExampleFileFilter(); + * filter.addExtension("jpg"); + * filter.addExtension("tif"); + *

+ * Note that the "." before the extension is not needed and will be ignored. + */ + public void addExtension(String extension) { + if (filters == null) { + filters = new Hashtable(5); + } + filters.put(extension.toLowerCase(), this); + fullDescription = null; + } + + + /** + * Returns the human readable description of this filter. For + * example: "JPEG and GIF Image Files (*.jpg, *.gif)" + * + * @see FileFilter#getDescription + */ + @Override + public String getDescription() { + if (fullDescription == null) { + if (description == null || isExtensionListInDescription()) { + fullDescription = description == null ? "(" : description + " ("; + // build the description from the extension list + Enumeration extensions = filters.keys(); + if (extensions != null) { + fullDescription += "." + extensions.nextElement(); + while (extensions.hasMoreElements()) { + fullDescription += ", ." + extensions.nextElement(); + } + } + fullDescription += ")"; + } else { + fullDescription = description; + } + } + return fullDescription; + } + + /** + * Sets the human readable description of this filter. For + * example: filter.setDescription("Gif and JPG Images"); + */ + public void setDescription(String description) { + this.description = description; + fullDescription = null; + } + + /** + * Determines whether the extension list (.jpg, .gif, etc) should + * show up in the human readable description. + *

+ * Only relevent if a description was provided in the constructor + * or using setDescription(); + */ + public void setExtensionListInDescription(boolean b) { + useExtensionsInDescription = b; + fullDescription = null; + } + + /** + * Returns whether the extension list (.jpg, .gif, etc) should + * show up in the human readable description. + *

+ * Only relevent if a description was provided in the constructor + * or using setDescription(); + */ + public boolean isExtensionListInDescription() { + return useExtensionsInDescription; + } + } + +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ilable/ActionLabel.java b/designer-base/src/main/java/com/fr/design/gui/ilable/ActionLabel.java index ebccd24f45..38b559c88d 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ilable/ActionLabel.java +++ b/designer-base/src/main/java/com/fr/design/gui/ilable/ActionLabel.java @@ -13,11 +13,23 @@ import java.awt.event.MouseEvent; */ public class ActionLabel extends UILabel { private ActionListener actionListener; + private Color color; + // 文字是否有下划线 + private boolean drawUnderLine = true; public ActionLabel(String text) { - super(text); + this(text, Color.blue); + } - this.setForeground(Color.blue); + public ActionLabel(String text, boolean drawUnderLine) { + this(text, Color.blue); + this.drawUnderLine = drawUnderLine; + } + + public ActionLabel(String text, Color color) { + super(text); + this.color = color; + this.setForeground(color); this.addMouseListener(mouseInputAdapter); this.addMouseMotionListener(mouseInputAdapter); } @@ -33,8 +45,10 @@ public class ActionLabel extends UILabel { public void paintComponent(Graphics _gfx) { super.paintComponent(_gfx); - _gfx.setColor(Color.blue); - _gfx.drawLine(0, this.getHeight() - 1, this.getWidth(), this.getHeight() - 1); + _gfx.setColor(this.color); + if (drawUnderLine) { + _gfx.drawLine(0, this.getHeight() - 1, this.getWidth(), this.getHeight() - 1); + } } private MouseInputAdapter mouseInputAdapter = new MouseInputAdapter() { @@ -90,4 +104,12 @@ public class ActionLabel extends UILabel { } } }; -} \ No newline at end of file + + public boolean isDrawUnderLine() { + return drawUnderLine; + } + + public void setDrawUnderLine(boolean drawUnderLine) { + this.drawUnderLine = drawUnderLine; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/itextfield/UINumberField.java b/designer-base/src/main/java/com/fr/design/gui/itextfield/UINumberField.java index 0d1287d8c0..f40237659c 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itextfield/UINumberField.java +++ b/designer-base/src/main/java/com/fr/design/gui/itextfield/UINumberField.java @@ -4,6 +4,7 @@ import com.fr.base.Utils; import com.fr.general.ComparatorUtils; import com.fr.stable.CoreConstants; import com.fr.stable.StringUtils; + import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.PlainDocument; @@ -164,10 +165,16 @@ public class UINumberField extends UITextField { || ComparatorUtils.equals(s, "D") || ComparatorUtils.equals(s, "d") || (ComparatorUtils.equals(str.trim(), "0") && !ComparatorUtils.equals(s.substring(0, 1), ".") && offset != 0)// 第一位是0时,第二位只能为小数点 - || (ComparatorUtils.equals(s, ".") && maxDecimalLength == 0)); + || (ComparatorUtils.equals(s, ".") && maxDecimalLength == 0)) + || s.contains(" ")//不允许空格 + || (ComparatorUtils.equals(s.substring(0, 1),"-") && offset != 0)//负号只允许出现在第一位 + || (ComparatorUtils.equals(s.substring(0, 1),".") && offset == 0)//小数点不能在第一位 + || s.contains("-.") + || s.contains(".-")//不能包含-.或.-非法格式 + || (str.startsWith("-") && ComparatorUtils.equals(s.substring(0, 1), ".") && offset == 1 )//负号不能接小数点 + || (s.contains("-") && !ComparatorUtils.equals(s.substring(0,1), "-"));//输入的字符串如果包含负号,负号必须在第一位 } - public void insertString(int offset, String s, AttributeSet a) throws BadLocationException { String str = getText(0, getLength()); 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 9f948e7a18..a3151b2e71 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 @@ -17,14 +17,19 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.style.color.NewColorSelectBox; - +import com.fr.design.utils.gui.AdjustWorkBookDefaultStyleUtils; import com.fr.stable.Constants; import com.fr.stable.CoreConstants; -import javax.swing.*; +import javax.swing.Icon; +import javax.swing.JPanel; +import javax.swing.SwingConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.GridLayout; import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -198,7 +203,7 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse public Style update(Style style) { if (style == null) { - style = Style.DEFAULT_STYLE; + style = AdjustWorkBookDefaultStyleUtils.adjustCellElement(Style.DEFAULT_STYLE); } if (backgroundPane.currentPane.isBackgroundChange()) { diff --git a/designer-base/src/main/java/com/fr/design/javascript/ExportJavaScriptPane.java b/designer-base/src/main/java/com/fr/design/javascript/ExportJavaScriptPane.java index 460e838c51..b58dd6f655 100644 --- a/designer-base/src/main/java/com/fr/design/javascript/ExportJavaScriptPane.java +++ b/designer-base/src/main/java/com/fr/design/javascript/ExportJavaScriptPane.java @@ -279,8 +279,8 @@ public class ExportJavaScriptPane extends AbstractHyperLinkPane { + private Map map = new HashMap<>(); + + public ShowOnlineWidgetMark() { + map.put(Locale.CHINA, true); + map.put(Locale.TAIWAN, true); + map.put(Locale.US, false); + map.put(Locale.KOREA, false); + map.put(Locale.JAPAN, false); + } + + @Override + public Boolean getValue() { + Boolean result = map.get(GeneralContext.getLocale()); + return result == null ? false : result; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/SupportLocaleImpl.java b/designer-base/src/main/java/com/fr/design/locale/impl/SupportLocaleImpl.java index 0373dad033..e50d2b603c 100644 --- a/designer-base/src/main/java/com/fr/design/locale/impl/SupportLocaleImpl.java +++ b/designer-base/src/main/java/com/fr/design/locale/impl/SupportLocaleImpl.java @@ -171,5 +171,17 @@ public enum SupportLocaleImpl implements SupportLocale { set.add(Locale.TAIWAN); return set; } + }, + + /** + * 帮助-服务平台(只针对中国大陆) + */ + SERVICE_PLATFORM { + @Override + public Set support() { + Set set = new HashSet<>(); + set.add(Locale.CHINA); + return set; + } } } diff --git a/designer-base/src/main/java/com/fr/design/login/DesignerLoginHelper.java b/designer-base/src/main/java/com/fr/design/login/DesignerLoginHelper.java index 2d2dd935d1..8976a07345 100644 --- a/designer-base/src/main/java/com/fr/design/login/DesignerLoginHelper.java +++ b/designer-base/src/main/java/com/fr/design/login/DesignerLoginHelper.java @@ -47,7 +47,7 @@ public class DesignerLoginHelper { } public static void showLoginDialog(DesignerLoginSource source, Map params, Window window) { - if (!SupportOSImpl.DESIGNER_LOGIN.support()) { + if (!SupportOSImpl.DESIGNER_LOGIN.support() || DesignerEnvManager.getEnvManager().isUseOldVersionLogin()) { WebViewDlgHelper.createLoginDialog(window); return; } diff --git a/designer-base/src/main/java/com/fr/design/login/config/DefaultLoginKeys.java b/designer-base/src/main/java/com/fr/design/login/config/DefaultLoginKeys.java new file mode 100644 index 0000000000..36988aa5ca --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/login/config/DefaultLoginKeys.java @@ -0,0 +1,48 @@ +package com.fr.design.login.config; + +import com.fr.log.FineLoggerFactory; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +/** + * @author Lanlan + * @version 10.0 + * Created by Lanlan on 2022/6/20 + */ +public class DefaultLoginKeys { + + private static final String FILENAME = "com/fr/design/config/default"; + + private static final DefaultLoginKeys INSTANCE = new DefaultLoginKeys(); + + public static DefaultLoginKeys getInstance() { + return INSTANCE; + } + + private final Map keys = new HashMap<>(); + + private DefaultLoginKeys() { + Properties properties = load(); + for (Map.Entry entry : properties.entrySet()) { + String name = entry.getKey().toString(); + keys.put(name, entry.getValue().toString()); + } + } + + public String getKey(String name) { + return keys.get(name); + } + + private Properties load() { + Properties properties = new Properties(); + try (InputStream inputStream = DefaultLoginKeys.class.getClassLoader().getResourceAsStream(FILENAME)) { + properties.load(inputStream); + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return properties; + } +} diff --git a/designer-base/src/main/java/com/fr/design/login/config/DesignerLoginConfigManager.java b/designer-base/src/main/java/com/fr/design/login/config/DesignerLoginConfigManager.java index a0ab68109d..b0fb0e292a 100644 --- a/designer-base/src/main/java/com/fr/design/login/config/DesignerLoginConfigManager.java +++ b/designer-base/src/main/java/com/fr/design/login/config/DesignerLoginConfigManager.java @@ -70,6 +70,10 @@ public class DesignerLoginConfigManager implements XMLReadable, XMLWriter { * 插件管理第一次启动时的提醒 */ private boolean pluginRemindOnFirstLaunch = true; + /** + * 使用旧版登录 + */ + private boolean useOldVersionLogin = false; private DesignerLoginConfigManager() { @@ -98,6 +102,7 @@ public class DesignerLoginConfigManager implements XMLReadable, XMLWriter { this.setLastLoginAccount(reader.getAttrAsString("lastLoginAccount", StringUtils.EMPTY)); this.setLoginRemindBeforeJumpBBS(reader.getAttrAsBoolean("loginRemindBeforeJumpBBS", true)); this.setPluginRemindOnFirstLaunch(reader.getAttrAsBoolean("pluginRemindOnFirstLaunch", true)); + this.setUseOldVersionLogin(reader.getAttrAsBoolean("useOldVersionLogin", false)); } } @@ -117,6 +122,7 @@ public class DesignerLoginConfigManager implements XMLReadable, XMLWriter { writer.attr("lastLoginAccount", lastLoginAccount); writer.attr("loginRemindBeforeJumpBBS", loginRemindBeforeJumpBBS); writer.attr("pluginRemindOnFirstLaunch", pluginRemindOnFirstLaunch); + writer.attr("useOldVersionLogin", useOldVersionLogin); writer.end(); } @@ -223,4 +229,12 @@ public class DesignerLoginConfigManager implements XMLReadable, XMLWriter { public void setPluginRemindOnFirstLaunch(boolean pluginRemindOnFirstLaunch) { this.pluginRemindOnFirstLaunch = pluginRemindOnFirstLaunch; } + + public boolean isUseOldVersionLogin() { + return useOldVersionLogin; + } + + public void setUseOldVersionLogin(boolean useOldVersionLogin) { + this.useOldVersionLogin = useOldVersionLogin; + } } diff --git a/designer-base/src/main/java/com/fr/design/login/guide/DesignerGuideHelper.java b/designer-base/src/main/java/com/fr/design/login/guide/DesignerGuideHelper.java index b3513bb6da..3e4c0dae51 100644 --- a/designer-base/src/main/java/com/fr/design/login/guide/DesignerGuideHelper.java +++ b/designer-base/src/main/java/com/fr/design/login/guide/DesignerGuideHelper.java @@ -8,9 +8,7 @@ import com.fr.design.login.utils.DesignerLoginUtils; import com.fr.design.mainframe.DesignerContext; import com.fr.design.os.impl.SupportOSImpl; import com.fr.design.update.push.DesignerPushUpdateManager; -import com.fr.general.CloudCenter; -import com.fr.general.CloudCenterConfig; -import com.fr.general.http.HttpToolbox; +import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; import javax.swing.WindowConstants; @@ -39,7 +37,11 @@ public class DesignerGuideHelper { public static void prepareShowGuideDialog() { // 如果存在更新升级的弹窗,则不显示引导页面 - if (!DesignerLoginUtils.isOnline() || !SupportOSImpl.DESIGNER_LOGIN.support() || !FRContext.isChineseEnv() || DesignerPushUpdateManager.getInstance().isShouldPopUp()) { + if (!DesignerLoginUtils.isOnline() + || !SupportOSImpl.DESIGNER_LOGIN.support() + || !FRContext.isChineseEnv() + || DesignerPushUpdateManager.getInstance().isShouldPopUp() + || DesignerEnvManager.getEnvManager().isUseOldVersionLogin()) { return; } if (isActivatedForOneWeek()) { @@ -52,7 +54,11 @@ public class DesignerGuideHelper { DesignerContext.getDesignerFrame().addDesignerOpenedListener(new DesignerOpenedListener() { @Override public void designerOpened() { - showGuideDialog(); + try { + showGuideDialog(); + } catch (Throwable t) { + FineLoggerFactory.getLogger().warn(t.getMessage(), t); + } } }); } diff --git a/designer-base/src/main/java/com/fr/design/login/service/DesignerPassportManager.java b/designer-base/src/main/java/com/fr/design/login/service/DesignerPassportManager.java index 446a30f8b1..19eefa85d1 100644 --- a/designer-base/src/main/java/com/fr/design/login/service/DesignerPassportManager.java +++ b/designer-base/src/main/java/com/fr/design/login/service/DesignerPassportManager.java @@ -5,6 +5,7 @@ import com.fr.design.login.DesignerLoginType; import com.fr.design.upm.event.CertificateEvent; import com.fr.event.EventDispatcher; import com.fr.json.JSONObject; +import com.fr.stable.StringUtils; /** * @author Lanlan @@ -96,6 +97,14 @@ public class DesignerPassportManager { return uid; } + /** + * 登出帆软通行证 + */ + public void logout() { + saveUserInfo(-1, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, DesignerLoginType.UNKNOWN, StringUtils.EMPTY); + EventDispatcher.fire(CertificateEvent.LOGOUT, StringUtils.EMPTY); + } + /** * 保存登录信息 */ diff --git a/designer-base/src/main/java/com/fr/design/login/utils/DesignerLoginUtils.java b/designer-base/src/main/java/com/fr/design/login/utils/DesignerLoginUtils.java index a39a0be4bf..8845f00e1f 100644 --- a/designer-base/src/main/java/com/fr/design/login/utils/DesignerLoginUtils.java +++ b/designer-base/src/main/java/com/fr/design/login/utils/DesignerLoginUtils.java @@ -1,6 +1,7 @@ package com.fr.design.login.utils; import com.fr.design.DesignerEnvManager; +import com.fr.design.login.config.DefaultLoginKeys; import com.fr.design.mainframe.toast.DesignerToastMsgUtil; import com.fr.general.CloudCenter; import com.fr.general.CloudCenterConfig; @@ -28,8 +29,6 @@ public class DesignerLoginUtils { private static final String PRODUCT_FINEREPORT = "product-finereport"; - private static final String KEY = "i7hP48WAcuTrmxfN"; - public static Map renderMap() { Map map4Tpl = new HashMap<>(); map4Tpl.put("language", GeneralContext.getLocale().toString()); @@ -86,7 +85,11 @@ public class DesignerLoginUtils { jo.put("username", manager.getDesignerLoginUsername()); jo.put("source", PRODUCT_FINEREPORT); byte[] iv = randomIv(); - return new String(Hex.encode(iv)) + encrypt(jo.toString(), KEY.getBytes(), iv); + return new String(Hex.encode(iv)) + encrypt( + jo.toString(), + DefaultLoginKeys.getInstance().getKey("Fine-Designer_Login").getBytes(), + iv + ); } private static byte[] randomIv() { 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 798441c536..86e64d2edf 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 @@ -356,7 +356,12 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta public void fireDesignerOpened() { for (DesignerOpenedListener listener : designerOpenedListenerList) { - listener.designerOpened(); + // 捕获下异常 避免造成启动过程监听触发异常导致设计器闪退 + try { + listener.designerOpened(); + } catch (Throwable e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } } designerOpened = true; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java index 2925e03a84..a33aa91d5d 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java @@ -34,6 +34,7 @@ import com.fr.design.menu.KeySetUtils; import com.fr.design.menu.ShortCut; import com.fr.design.menu.ToolBarDef; import com.fr.design.roleAuthority.RolesAlreadyEditedPane; +import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.DesignUtils; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.event.Event; @@ -101,6 +102,23 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt return context.contain(PluginModule.ExtraDesign, ShortCut.TEMPLATE_TREE); } }); + GeneralContext.listenPluginRunningChanged(new PluginEventListener() { + @Override + public void on(PluginEvent event) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + DesignerFrameFileDealerPane.getInstance().refresh(); + DesignerFrameFileDealerPane.getInstance().stateChange(); + } + }); + } + }, new PluginFilter() { + @Override + public boolean accept(PluginContext context) { + return context.contain(PluginModule.ExtraDesign, App.MARK_STRING); + } + }); } private List otherToolbarStateChangeListeners = new ArrayList<>(); 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 0e26ff3ded..74dc180755 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,9 +10,11 @@ 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.utils.LoadingUtils; import javax.swing.JComponent; import javax.swing.JLayeredPane; +import javax.swing.JPanel; import java.awt.BorderLayout; import java.awt.Component; @@ -31,7 +33,7 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener private static final long serialVersionUID = 1L; private JTemplate component; private TransparentPane transparentPane = new TransparentPane(); - private OpenLoadingPane loadingPane = new OpenLoadingPane(); + private JPanel loadingPane = LoadingUtils.createLoadingPane(); private OpenFailedPane failedPane = new OpenFailedPane(); private JLayeredPane layeredPane = new JLayeredPane() { @Override @@ -86,7 +88,7 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener } else if (jt.isOpening()) { showOpenStatus(); } else if (jt.isOpenFailed()) { - showOpenFailedCover(); + showOpenFailedCover(jt.getTemplateOpenFailedTip()); } else { hideCover(); } @@ -115,7 +117,8 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener layeredPane.moveToFront(loadingPane); } - public void showOpenFailedCover() { + public void showOpenFailedCover(String text) { + failedPane.setFailedTip(text); layeredPane.moveToFront(failedPane); } 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 d4931763c8..52dd81b334 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 @@ -50,12 +50,14 @@ import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.DesignUtils; import com.fr.design.worker.save.CallbackSaveWorker; import com.fr.design.worker.save.EmptyCallBackSaveWorker; +import com.fr.design.worker.save.SaveFailureHandler; import com.fr.design.write.submit.DBManipulationInWidgetEventPane; import com.fr.design.write.submit.DBManipulationPane; import com.fr.event.EventDispatcher; import com.fr.file.FILE; import com.fr.file.FILEChooserPane; import com.fr.file.MemFILE; +import com.fr.file.StashedFILE; import com.fr.form.ui.NoneWidget; import com.fr.form.ui.Widget; import com.fr.general.ComparatorUtils; @@ -84,6 +86,7 @@ import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.undo.UndoManager; import java.awt.BorderLayout; +import java.io.ByteArrayOutputStream; import java.util.Set; import java.util.concurrent.Callable; @@ -114,6 +117,8 @@ public abstract class JTemplate> private JComponent centerPane; private DesignModelAdapter designModel; private PreviewProvider previewType; + private String templateOpenFailedTip; + /** * 统计模板制作耗时 * @@ -369,6 +374,22 @@ public abstract class JTemplate> PluginListenerRegistration.getInstance().stopListen(this.pluginListener); } + public FILE templateToStashFile() { + FILE file = this.getEditingFILE(); + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BaseBook target = this.getTarget(); + if (target != null) { + target.export(outputStream); + return new StashedFILE(file, outputStream.toByteArray(), template.suffix()); + } + // 如果 target == null 那么这个模板是被模板内存优化功能处理过的,不用处理 + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } + /** * 刷新内部资源 @@ -379,7 +400,9 @@ public abstract class JTemplate> */ @Deprecated public void refreshResource() { - refreshResource(this.editingFILE); + if (JTemplateFactory.isAvailable()) { + refreshResource(this.editingFILE); + } } public void refreshResource(FILE file) { @@ -402,8 +425,11 @@ public abstract class JTemplate> } private void setTargetByFile(FILE file) { - this.template = JTemplateFactory.asIOFile(file, this.suffix()); - setTarget(this.template); + T newTemplate = JTemplateFactory.asIOFile(file, this.suffix()); + if (newTemplate != null) { + this.template = newTemplate; + setTarget(this.template); + } } private void addCenterPane() { @@ -574,6 +600,16 @@ public abstract class JTemplate> fireSuperTargetModified(); } + public void undoToCurrent() { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + BaseUndoState current = JTemplate.this.getUndoState(); + current.applyState(); + } + }); + } + /** * 模板更新 */ @@ -865,7 +901,7 @@ public abstract class JTemplate> export(); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); - JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage(), "Save Error", JOptionPane.ERROR_MESSAGE); + SaveFailureHandler.getInstance().process(e); return false; } this.editingFILE = editingFILE; @@ -877,7 +913,7 @@ public abstract class JTemplate> } protected boolean export() throws Exception { - return this.getTarget().export(TemplateResourceManager.getResource().saveTemplate(editingFILE)); + return this.getTarget().export(TemplateResourceManager.getResource().saveTemplate(getEditingFILE())); } @@ -1051,35 +1087,49 @@ public abstract class JTemplate> /** * 判断是否是新版设计器 * + * @param showTipPane 是否需要展示弹窗 * @return 是返回true */ - public boolean isNewDesigner() { + public boolean isNewDesigner(boolean showTipPane) { String xmlDesignerVersion = getTarget().getXMLDesignerVersion(); if (isLowerThanHBB(xmlDesignerVersion)) { String info = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Open-New_Form_Tip"); String moreInfo = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Server_Version_Tip_More_Info"); - new InformationWarnPane(info, moreInfo, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")).show(); + if (showTipPane) { + new InformationWarnPane(info, moreInfo, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")).showOnFront(); + } return true; } return false; } + public boolean isNewDesigner() { + return isNewDesigner(true); + } + /** * 是否是就版本设计器 * + * @param showTipPane 是否需要展示弹窗 * @return 是就返回true */ - public boolean isOldDesigner() { + public boolean isOldDesigner(boolean showTipPane) { String xmlDesignerVersion = getTarget().getXMLDesignerVersion(); if (isHigherThanCurrent(xmlDesignerVersion)) { String infor = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Template_Version_Not_Match", DesignUtils.parseVersion(xmlDesignerVersion)); String moreInfo = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Server_Version_Tip_More_Info"); - new InformationWarnPane(infor, moreInfo, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")).show(); + if (showTipPane) { + new InformationWarnPane(infor, moreInfo, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")).showOnFront(); + } return true; } return false; } + public boolean isOldDesigner() { + return isOldDesigner(true); + } + /** * */ @@ -1460,7 +1510,7 @@ public abstract class JTemplate> if (editingFILE == null || editingFILE instanceof MemFILE) { return false; } - this.getTarget().export(TemplateResourceManager.getResource().saveTemplate(editingFILE)); + export(); this.editingFILE = editingFILE; return true; } @@ -1505,6 +1555,7 @@ public abstract class JTemplate> refreshToolArea(); } DesignerFrameFileDealerPane.getInstance().refresh(); + DesignerFrameFileDealerPane.getInstance().stateChange(); } }); @@ -1628,4 +1679,12 @@ public abstract class JTemplate> public String getRuntimeId() { return runtimeId; } + + public String getTemplateOpenFailedTip() { + return templateOpenFailedTip; + } + + public void setTemplateOpenFailedTip(String templateOpenFailedTip) { + this.templateOpenFailedTip = templateOpenFailedTip; + } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplateFactory.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplateFactory.java index 5e75cc64be..9aa8204d60 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplateFactory.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplateFactory.java @@ -93,4 +93,7 @@ public final class JTemplateFactory { ALL_APP.remove(app); } } -} \ No newline at end of file + + public static boolean isAvailable() { + return !ALL_APP.isEmpty(); + }} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplateNameHelper.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplateNameHelper.java index 22d5985ba9..ee5273d8db 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplateNameHelper.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplateNameHelper.java @@ -3,8 +3,10 @@ package com.fr.design.mainframe; import com.fr.design.file.TemplateTreePane; import com.fr.design.gui.itree.filetree.TemplateFileTree; import com.fr.stable.StringUtils; +import org.jetbrains.annotations.Nullable; import javax.swing.tree.DefaultMutableTreeNode; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -27,19 +29,18 @@ public class JTemplateNameHelper { DefaultMutableTreeNode gen = (DefaultMutableTreeNode) tt.getModel().getRoot(); String[] str = new String[gen.getChildCount()]; - List reportNum = new ArrayList<>(); + List reportNum = new ArrayList<>(); for (int j = 0; j < gen.getChildCount(); j++) { str[j] = gen.getChildAt(j).toString(); //返回文件名中的index(算法中没有再匹配文件后缀了,因为DefaultMutableTreeNode中已经匹配过了) - Integer index = getFileNameIndex(prefix, str[j]); + BigInteger index = getFileNameIndex(prefix, str[j]); if (index != null) { reportNum.add(index); } } Collections.sort(reportNum); - int idx = reportNum.size() > 0 ? reportNum.get(reportNum.size() - 1) + 1 : 1; - - idx = idx + currentIndex; + BigInteger idx = reportNum.size() > 0 ? reportNum.get(reportNum.size() - 1).add(BigInteger.valueOf(1)) : BigInteger.valueOf(1); + idx = idx.add(BigInteger.valueOf(currentIndex)); currentIndex++; return prefix + idx; } @@ -52,35 +53,58 @@ public class JTemplateNameHelper { * @Author Henry.Wang * @Date 2021/4/9 11:13 **/ - private static Integer getFileNameIndex(String prefix, String fileName) { - if (fileName.length() <= prefix.length()) { + @Nullable + private static BigInteger getFileNameIndex(String prefix, String fileName) { + //如果文件名长度小于等于前缀长度或者匹配前缀失败,直接返回就可以了 + if ((prefix.length() >= fileName.length()) || (!StringUtils.equals(prefix, fileName.substring(0, prefix.length())))) { return null; } - char[] chars = new char[fileName.length()]; - int i = 0; - for (; i < fileName.length(); i++) { + BigInteger integer = null; + integer = matchFileNameIndex(prefix, fileName); + return integer; + } + + /** + * 匹配文件名称的数字后缀Index + * @param prefix 前缀 + * @param fileName 文件名称全名 + * @return 返回对应的数字后缀Index + */ + @Nullable + private static BigInteger matchFileNameIndex(String prefix, String fileName) { + StringBuilder result = new StringBuilder(); + for (int i = prefix.length(); i < fileName.length(); i++) { char c = fileName.charAt(i); - //匹配前缀 - if (i < prefix.length()) { - if (c != prefix.charAt(i)) { - return null; - } + if (isDot(c)) { + break; } else { - if (c == '.') { - break; - } else { - //匹配0~9 - if (c < 48 || c > 57) { - return null; - } - chars[i - prefix.length()] = c; + if (isNotNumber(c)) { + return null; } + result.append(c); } } - String s = new String(chars).substring(0, i - prefix.length()); - if (StringUtils.isBlank(s)) { + if (StringUtils.isBlank(result.toString())) { return null; } - return Integer.valueOf(s); + return new BigInteger(result.toString(), 10); + } + + /** + * 是否不属于数字0-9 + * @param c 用于判断的char + * @return 返回对应判断结果 + */ + private static boolean isNotNumber(char c) { + return c < 48 || c > 57; + } + + /** + * 是否属于'.' + * @param c 用于判断的char + * @return 返回对应判断结果 + */ + private static boolean isDot(char c) { + return c == '.'; } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java index b070710579..67784159c0 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java @@ -17,6 +17,7 @@ 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.plugin.observer.PluginEventType; import com.fr.stable.os.support.OSBasedAction; import com.fr.stable.os.support.OSSupportCenter; @@ -38,6 +39,17 @@ public class NorthRegionContainerPane extends JPanel { private JMenuBar menuBar; + private PluginFilter pluginFilter = new PluginFilter() { + + @Override + public boolean accept(PluginContext context) { + + return context.contain(PluginModule.ExtraDesign); + } + }; + + private volatile boolean existDesignExtraPlugin; + public static NorthRegionContainerPane getInstance() { if (THIS == null) { synchronized (NorthRegionContainerPane.class) { @@ -66,34 +78,63 @@ public class NorthRegionContainerPane extends JPanel { //hugh: private修改为protected方便oem的时候修改右上的组件构成 //顶部日志+登陆按钮 final JPanel northEastPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + initPluginListener(northEastPane, ad); + refreshNorthEastPane(northEastPane, ad); + return northEastPane; + } + + private void initPluginListener(JPanel northEastPane, ToolBarMenuDock ad) { //优先级为-1,保证最后全面刷新一次 - GeneralContext.listenPluginRunningChanged(new PluginEventListener(-1) { + PluginEventListener pluginOnRunOrStopListener = new PluginEventListener(-1) { @Override public void on(PluginEvent event) { - - refreshNorthEastPane(northEastPane, ad); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (DesignerContext.getDesignerFrame() == null) { - return; - } - DesignerContext.getDesignerFrame().refresh(); - DesignerContext.getDesignerFrame().repaint(); - } - }); + refreshAll(northEastPane, ad); } - }, new PluginFilter() { + }; + // 在设计器启动时仅在最后一个插件启用时候进行刷新一次 如果插件启用过程中存在实现了设计器接口的插件 + PluginEventListener afterAllPluginsActiveListener = new PluginEventListener() { + @Override + public void on(PluginEvent event) { + //优先级为-1,保证最后全面刷新一次 + GeneralContext.listenPluginRunningChanged(pluginOnRunOrStopListener, pluginFilter); + // 在设计器启动时仅在最后一个插件启用时候进行刷新一次 如果插件启用过程中存在实现了设计器接口的插件 + if (existDesignExtraPlugin) { + refreshAll(northEastPane, ad); + } + } + }; + PluginEventListener beforeAllPluginStopListener = new PluginEventListener() { + @Override + public void on(PluginEvent event) { + GeneralContext.stopListenPlugin(pluginOnRunOrStopListener); + } + }; + PluginEventListener pluginEventListener = new PluginEventListener() { @Override - public boolean accept(PluginContext context) { + public void on(PluginEvent event) { + existDesignExtraPlugin = true; + } + }; + GeneralContext.listenPluginRunningChanged(pluginEventListener, pluginFilter); + GeneralContext.listenPlugin(PluginEventType.AfterAllActive, afterAllPluginsActiveListener); + GeneralContext.listenPlugin(PluginEventType.BeforeAllStop, beforeAllPluginStopListener); - return context.contain(PluginModule.ExtraDesign); + } + + private void refreshAll(JPanel northEastPane, ToolBarMenuDock ad) { + refreshNorthEastPane(northEastPane, ad); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (DesignerContext.getDesignerFrame() == null) { + return; + } + DesignerContext.getDesignerFrame().refresh(); + DesignerContext.getDesignerFrame().repaint(); } }); - refreshNorthEastPane(northEastPane, ad); - return northEastPane; } private void refreshNorthEastPane(final JPanel northEastPane, final ToolBarMenuDock ad) { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/OpenFailedPane.java b/designer-base/src/main/java/com/fr/design/mainframe/OpenFailedPane.java index 132569c236..63ab984da6 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/OpenFailedPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/OpenFailedPane.java @@ -24,6 +24,7 @@ public class OpenFailedPane extends JPanel { private UILabel label; private MessageWithLink link; + private String defaultFailedText; public OpenFailedPane() { this.setLayout(new LayoutManager() { @@ -83,11 +84,18 @@ public class OpenFailedPane extends JPanel { }); } }; + this.defaultFailedText = link.getText(); link.setBackground(Color.WHITE); this.add(label); this.add(link); } - + public void setFailedTip(String text) { + if (StringUtils.isEmpty(text)) { + this.link.setText(defaultFailedText); + } else { + this.link.setText(text); + } + } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/check/CheckFontInfoDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/check/CheckFontInfoDialog.java index 0671ed1b63..a8c19c6976 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/check/CheckFontInfoDialog.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/check/CheckFontInfoDialog.java @@ -7,8 +7,8 @@ import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.general.CloudCenter; import com.fr.general.IOUtils; +import com.fr.i18n.UrlI18nManager; import javax.swing.BorderFactory; import javax.swing.JDialog; @@ -49,7 +49,8 @@ public class CheckFontInfoDialog extends JDialog implements ActionListener { JPanel messagePanel = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true); MessageWithLink linkMessage = new MessageWithLink(Toolkit.i18nText("Fine_Designer_Check_Font_Message"), Toolkit.i18nText("Fine_Designer_Check_Font_Install_Font"), - CloudCenter.getInstance().acquireUrlByKind("help.install.font", "https://help.fanruan.com/finereport/doc-view-3999.html")); + UrlI18nManager.getInstance().getI18nUrl("help.install.font") + ); linkMessage.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink")); messagePanel.add(linkMessage); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/platform/ServicePlatformAction.java b/designer-base/src/main/java/com/fr/design/mainframe/platform/ServicePlatformAction.java new file mode 100644 index 0000000000..c6dc9a9b66 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/platform/ServicePlatformAction.java @@ -0,0 +1,30 @@ +package com.fr.design.mainframe.platform; + +import com.fr.design.actions.UpdateAction; +import com.fr.design.i18n.Toolkit; +import com.fr.design.utils.BrowseUtils; +import com.fr.general.CloudCenter; +import com.fr.log.FineLoggerFactory; + +import java.awt.Desktop; +import java.awt.event.ActionEvent; +import java.net.URI; + +/** + * 帮助-服务平台 + * + * @author Destiny.Lin + * @version 11.0 + * created by Destiny.Lin on 2022-12-14 + */ +public class ServicePlatformAction extends UpdateAction { + public ServicePlatformAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Service_Platform_Title")); + this.setSmallIcon("/com/fr/design/images/platform/platform", false); + } + + @Override + public void actionPerformed(ActionEvent e) { + BrowseUtils.browser(CloudCenter.getInstance().acquireUrlByKind("service.platform")); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java b/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java index 3ea805deb0..47b7dc7ef0 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java @@ -288,12 +288,17 @@ public class ComponentCollector implements XMLable { private JSONArray getGroupingDetail() { JSONArray ja = JSONFactory.createJSON(JSON.ARRAY); - Group[] groups = DefaultShareGroupManager.getInstance().getAllGroup(); - for(Group group : groups) { - JSONObject jo = JSONFactory.createJSON(JSON.OBJECT); - jo.put(GROUP_NAME, group.getGroupName()); - jo.put(CONTAIN_AMOUNT, group.getAllBindInfoList().length); - ja.add(jo); + try { + DefaultShareGroupManager.getInstance().refresh(); + Group[] groups = DefaultShareGroupManager.getInstance().getAllGroup(); + for(Group group : groups) { + JSONObject jo = JSONFactory.createJSON(JSON.OBJECT); + jo.put(GROUP_NAME, group.getGroupName()); + jo.put(CONTAIN_AMOUNT, group.getAllBindInfoList().length); + ja.add(jo); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage()); } return ja; } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentSender.java b/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentSender.java index 5043e5fb7d..8941cfba80 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentSender.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentSender.java @@ -17,13 +17,7 @@ public class ComponentSender { private static final String CLOUD_REUSE_URL = "https://cloud.fanruan.com/api/monitor/record_of_reusePlugin/single"; public static boolean send() { - - long start = System.currentTimeMillis(); - String content = ComponentCollector.getInstance().generateTotalInfo(); - - long end = System.currentTimeMillis(); - FineLoggerFactory.getLogger().error("cal time cost {} ms", end - start); return sendInfo(CLOUD_REUSE_URL, content); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toast/DesignerToastMsgUtil.java b/designer-base/src/main/java/com/fr/design/mainframe/toast/DesignerToastMsgUtil.java index 4e69c34c56..fc326c60e6 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/toast/DesignerToastMsgUtil.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/toast/DesignerToastMsgUtil.java @@ -6,17 +6,17 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.stable.Constants; -import java.awt.Dialog; -import java.awt.Frame; -import java.awt.Window; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JEditorPane; import javax.swing.JPanel; import javax.swing.SwingConstants; import java.awt.BorderLayout; +import java.awt.Dialog; import java.awt.Dimension; import java.awt.Font; +import java.awt.Frame; +import java.awt.Window; /** * Created by kerry on 5/6/21 @@ -31,6 +31,13 @@ public class DesignerToastMsgUtil { } + public static ToastMsgDialog createPromptDialog(String text) { + return createDialog(PROMPT_ICON, toastPane(text), DesignerContext.getDesignerFrame()); + } + + public static ToastMsgDialog createPromptDialog(JPanel contentPane) { + return createDialog(PROMPT_ICON, contentPane, DesignerContext.getDesignerFrame()); + } public static void toastPrompt(JPanel contendPane) { toastPane(PROMPT_ICON, contendPane, DesignerContext.getDesignerFrame()); @@ -69,6 +76,11 @@ public class DesignerToastMsgUtil { } private static void toastPane(Icon icon, JPanel contendPane, Window parent) { + ToastMsgDialog dialog = createDialog(icon, contendPane, parent); + dialog.setVisible(true); + } + + private static ToastMsgDialog createDialog(Icon icon, JPanel contendPane, Window parent) { JPanel pane = FRGUIPaneFactory.createBorderLayout_S_Pane(); UILabel uiLabel = new UILabel(icon); uiLabel.setVerticalAlignment(SwingConstants.TOP); @@ -83,7 +95,7 @@ public class DesignerToastMsgUtil { } else { dialog = new ToastMsgDialog((Frame) parent, pane); } - dialog.setVisible(true); + return dialog; } @@ -118,4 +130,4 @@ public class DesignerToastMsgUtil { .toString(); } -} +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toast/SimpleToast.java b/designer-base/src/main/java/com/fr/design/mainframe/toast/SimpleToast.java new file mode 100644 index 0000000000..c0ea5be20f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/toast/SimpleToast.java @@ -0,0 +1,202 @@ +package com.fr.design.mainframe.toast; + +import com.fr.concurrent.NamedThreadFactory; +import com.fr.design.dialog.UIDialog; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.module.ModuleContext; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Window; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * + * alphafine - 下载模板时的toast弹窗 + * + * @author Link + * @version 10.0 + * Created by Link on 2022/9/22 + * */ +public class SimpleToast extends UIDialog { + private static final int MIN_HEIGHT = 36; + private static final String TOAST_MSG_TIMER = "TOAST_MSG_TIMER"; + private static final long DEFAULT_DISAPPEAR_DELAY = 5000; + private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS; + + + private ScheduledExecutorService timer; + private int hideHeight = 0; + private JPanel contentPane; + private boolean show = false; + private Window parent; + private boolean autoDisappear; + + public SimpleToast(Window parent, Icon icon, String text, boolean autoDisappear) { + super(parent); + this.parent = parent; + this.autoDisappear = autoDisappear; + JPanel panel = createContentPane(icon, text); + init(panel); + } + + private JPanel createContentPane(Icon icon, String text) { + JPanel pane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + UILabel iconLabel = new UILabel(icon); + iconLabel.setVerticalAlignment(SwingConstants.TOP); + iconLabel.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0)); + + + UILabel textLabel = new UILabel(text); + pane.add(iconLabel, BorderLayout.WEST); + pane.add(textLabel, BorderLayout.CENTER); + pane.setBorder(BorderFactory.createEmptyBorder(8, 15, 8, 15)); + + return pane; + } + + + private void init(JPanel panel) { + setFocusable(false); + setAutoRequestFocus(false); + setUndecorated(true); + contentPane = panel; + initComponent(); + } + + private void initComponent() { + this.getContentPane().setLayout(null); + this.getContentPane().add(contentPane); + Dimension dimension = calculatePreferSize(); + hideHeight = dimension.height; + setSize(new Dimension(dimension.width, 0)); + contentPane.setSize(dimension); + setRelativeLocation(dimension); + if (autoDisappear) { + disappear(contentPane); + } + } + + private void setRelativeLocation(Dimension dimension) { + int positionX = parent.getLocationOnScreen().x + (parent.getWidth() - dimension.width) / 2; + int positionY = parent.getLocationOnScreen().y + 10; + this.setLocation(positionX, positionY); + } + + private Dimension calculatePreferSize() { + Dimension contentDimension = contentPane.getPreferredSize(); + int height = Math.max(MIN_HEIGHT, contentDimension.height); + return new Dimension(contentDimension.width, height); + } + + + /** + * 显示toast + * */ + public void display(JPanel outerPanel) { + show = true; + outerPanel.setLocation(0, -hideHeight); + ScheduledExecutorService tipToolTimer = createToastScheduleExecutorService(); + tipToolTimer.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + SwingUtilities.invokeLater(()->{ + displayStep(outerPanel, tipToolTimer); + }); + } + }, 0, 50, TimeUnit.MILLISECONDS); + + } + + void displayStep(JPanel outerPanel, ScheduledExecutorService timer) { + Point point = outerPanel.getLocation(); + if (point.y >= 0 && !timer.isShutdown()) { + timer.shutdown(); + } + int showDistance = 5 + point.y < 0 ? 5 : -point.y; + outerPanel.setLocation(point.x, point.y + showDistance); + Dimension dimension = SimpleToast.this.getSize(); + SimpleToast.this.setSize(new Dimension(dimension.width, dimension.height + showDistance)); + } + + + + + + + private void disappear(JPanel outerPanel, long delay, TimeUnit timeUnit) { + timer = createToastScheduleExecutorService(); + timer.schedule(new DisappearMotion(outerPanel), delay, timeUnit); + } + + /** + * toast消失的动画效果 + * */ + class DisappearMotion implements Runnable { + JPanel panel; + + DisappearMotion(JPanel panel) { + this.panel = panel; + } + + @Override + public void run() { + ScheduledExecutorService tipToolTimer = createToastScheduleExecutorService(); + tipToolTimer.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + SwingUtilities.invokeLater(()->{ + disappearStep(tipToolTimer); + }); + } + }, 0, 50, TimeUnit.MILLISECONDS); + } + + void disappearStep(ScheduledExecutorService timer) { + Point point = panel.getLocation(); + if (point.y <= -hideHeight && !timer.isShutdown()) { + timer.shutdown(); + SimpleToast.this.setVisible(false); + SimpleToast.this.dispose(); + SimpleToast.this.show = false; + } + panel.setLocation(point.x, point.y - 5); + Dimension dimension = SimpleToast.this.getSize(); + SimpleToast.this.setSize(new Dimension(dimension.width, dimension.height - 5)); + } + } + + private void disappear(JPanel outerPanel) { + disappear(outerPanel, DEFAULT_DISAPPEAR_DELAY, DEFAULT_TIME_UNIT); + } + + private ScheduledExecutorService createToastScheduleExecutorService() { + return ModuleContext.getExecutor().newSingleThreadScheduledExecutor(new NamedThreadFactory(TOAST_MSG_TIMER)); + } + + @Override + public void checkValid() throws Exception { + } + + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible) { + display(contentPane); + } + } + + @Override + public void dispose() { + super.dispose(); + } + +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toast/ToastMsgDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/toast/ToastMsgDialog.java index 00f4f95ead..83cd84e9cc 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/toast/ToastMsgDialog.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/toast/ToastMsgDialog.java @@ -3,10 +3,11 @@ package com.fr.design.mainframe.toast; import com.fr.concurrent.NamedThreadFactory; import com.fr.design.dialog.UIDialog; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; import com.fr.module.ModuleContext; -import java.awt.Dialog; import javax.swing.JPanel; +import java.awt.Dialog; import java.awt.Dimension; import java.awt.Frame; import java.awt.Point; @@ -24,6 +25,7 @@ public class ToastMsgDialog extends UIDialog { private ScheduledExecutorService TIMER; private int hide_height = 0; private JPanel contentPane; + private boolean show = false; public ToastMsgDialog(Frame parent, JPanel panel) { super(parent); @@ -50,12 +52,16 @@ public class ToastMsgDialog extends UIDialog { hide_height = dimension.height; setSize(new Dimension(dimension.width, 0)); contentPane.setSize(dimension); - setLocationRelativeTo(DesignerContext.getDesignerFrame().getContentFrame()); - int positionY = DesignerContext.getDesignerFrame().getContentFrame().getLocationOnScreen().y + 10; - setLocation((DesignerContext.getDesignerFrame().getWidth() - dimension.width) / 2, positionY); + setRelativeLocation(dimension); addMouseEvent(contentPane); } + private void setRelativeLocation(Dimension dimension) { + DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + int positionX = designerFrame.getLocationOnScreen().x + (designerFrame.getWidth() - dimension.width) / 2; + int positionY = designerFrame.getContentFrame().getLocationOnScreen().y + 10; + this.setLocation(positionX, positionY); + } private Dimension calculatePreferSize() { Dimension contentDimension = contentPane.getPreferredSize(); @@ -65,6 +71,7 @@ public class ToastMsgDialog extends UIDialog { public void display(JPanel outerJPanel) { + show = true; outerJPanel.setLocation(0, -hide_height); ScheduledExecutorService TIP_TOOL_TIMER = createToastScheduleExecutorService(); TIP_TOOL_TIMER.scheduleAtFixedRate(new Runnable() { @@ -98,12 +105,13 @@ public class ToastMsgDialog extends UIDialog { TIP_TOOL_TIMER.shutdown(); ToastMsgDialog.this.setVisible(false); ToastMsgDialog.this.dispose(); + ToastMsgDialog.this.show = false; } outerJPanel.setLocation(point.x, point.y - 5); Dimension dimension = ToastMsgDialog.this.getSize(); ToastMsgDialog.this.setSize(new Dimension(dimension.width, dimension.height - 5)); } - }, 0,50, TimeUnit.MILLISECONDS); + }, 0, 50, TimeUnit.MILLISECONDS); } }, 5000, TimeUnit.MILLISECONDS); @@ -159,5 +167,7 @@ public class ToastMsgDialog extends UIDialog { super.dispose(); } - -} + public boolean isShow() { + return show; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java b/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java index 866c2fabea..629d3b5b0f 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java @@ -17,6 +17,7 @@ import com.fr.design.actions.community.FacebookFansAction; import com.fr.design.actions.community.NeedAction; import com.fr.design.actions.community.QuestionAction; import com.fr.design.actions.community.SignAction; +import com.fr.design.actions.community.StudyPlanAction; import com.fr.design.actions.community.TechSolutionAction; import com.fr.design.actions.community.TechSupportAction; import com.fr.design.actions.community.TemplateStoreAction; @@ -55,6 +56,7 @@ import com.fr.design.gui.itoolbar.UIToolbar; import com.fr.design.locale.impl.SupportLocaleImpl; import com.fr.design.mainframe.JTemplate; import com.fr.design.mainframe.ToolBarNewTemplatePane; +import com.fr.design.mainframe.platform.ServicePlatformAction; import com.fr.design.menu.MenuDef; import com.fr.design.menu.SeparatorDef; import com.fr.design.menu.ShortCut; @@ -408,7 +410,9 @@ public abstract class ToolBarMenuDock { menuDef.addShortCut(new OpenRecentReportMenuDef()); - addCloseCurrentTemplateAction(menuDef); + if (!DesignModeContext.isDuchampMode()) { + addCloseCurrentTemplateAction(menuDef); + } scs = plus.shortcut4FileMenu(); if (!ArrayUtils.isEmpty(scs)) { @@ -558,14 +562,16 @@ public abstract class ToolBarMenuDock { //远程不使用更新升级,产品演示 if (WorkContext.getCurrent().isLocal()) { shortCuts.add(new WebDemoAction()); - if (!Locale.getDefault().equals(Locale.JAPAN) && !Locale.getDefault().equals(Locale.JAPANESE)) { - LocaleCenter.buildAction(() -> shortCuts.add(new SoftwareUpdateAction()), SupportLocaleImpl.UPDATE_HELP); - } + LocaleCenter.buildAction(() -> shortCuts.add(new SoftwareUpdateAction()), SupportLocaleImpl.UPDATE_HELP); } if (AlphaFineConfigManager.isALPHALicAvailable()) { shortCuts.add(new AlphaFineAction()); } + //服务平台(仅针对中国大陆) + LocaleCenter.buildAction(() -> shortCuts.add(new ServicePlatformAction()), SupportLocaleImpl.SERVICE_PLATFORM); + + shortCuts.add(SeparatorDef.DEFAULT); if (DesignerEnvManager.getEnvManager().isOpenDebug()) { OSSupportCenter.buildAction(objects -> shortCuts.add(new FineUIAction()), SupportOSImpl.FINEUI); @@ -595,6 +601,7 @@ public abstract class ToolBarMenuDock { shortCuts.add(new TutorialAction()); } }, SupportLocaleImpl.TUTORIAL_COMMUNITY); + shortCuts.add(new StudyPlanAction()); shortCuts.add(new QuestionAction()); shortCuts.add(new TechSolutionAction()); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AbstractTemplateStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AbstractTemplateStylePane.java index 482b2cebcd..399047a853 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AbstractTemplateStylePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AbstractTemplateStylePane.java @@ -7,4 +7,8 @@ public abstract class AbstractTemplateStylePane extends BasicPane { public abstract void populate(T ob); public abstract T update(); + + public AbstractTemplateStylePane generateCleanPane() { + return this; + } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleTemplateStyleEditor.java b/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleTemplateStyleEditor.java index 195a92e8a9..4f863e28b8 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleTemplateStyleEditor.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/AccessibleTemplateStyleEditor.java @@ -32,6 +32,11 @@ public class AccessibleTemplateStyleEditor extends UneditableAccessibleEditor { setValue(stylePane.update()); fireStateChanged(); } + + @Override + public void doCancel() { + stylePane = stylePane.generateCleanPane(); + } }); stylePane.populate(getValue()); dlg.setVisible(true); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/MobileTemplateStylePane.java b/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/MobileTemplateStylePane.java index 38f70de814..55c543b8f8 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/MobileTemplateStylePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/widget/accessibles/MobileTemplateStylePane.java @@ -44,12 +44,14 @@ public class MobileTemplateStylePane extends AbstractTemplateStylePane> extraStyle = new HashSet<>(); + private WCardTagLayout tagLayout; public MobileTemplateStylePane(WCardTagLayout tagLayout){ init(tagLayout); } public void init(WCardTagLayout tagLayout){ this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.tagLayout = tagLayout; listModel = new DefaultListModel(); card = new CardLayout(); right = FRGUIPaneFactory.createCardLayout_S_Pane(); @@ -147,4 +149,9 @@ public class MobileTemplateStylePane extends AbstractTemplateStylePane generateCleanPane() { + return new MobileTemplateStylePane(this.tagLayout); + } } diff --git a/designer-base/src/main/java/com/fr/design/notification/ui/NotificationCenterDialog.java b/designer-base/src/main/java/com/fr/design/notification/ui/NotificationCenterDialog.java index 10e10ecdbb..2541d04b43 100644 --- a/designer-base/src/main/java/com/fr/design/notification/ui/NotificationCenterDialog.java +++ b/designer-base/src/main/java/com/fr/design/notification/ui/NotificationCenterDialog.java @@ -2,6 +2,7 @@ package com.fr.design.notification.ui; import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; import com.fr.design.notification.Notification; import com.fr.design.notification.NotificationCenter; import java.awt.BorderLayout; @@ -119,7 +120,7 @@ public class NotificationCenterDialog extends JDialog { if (winSize.width > screenSize.width) { winSize.width = screenSize.width; } - //这里设置位置:水平居中,竖直偏上 - win.setLocation(screenSize.width - winSize.width - 90, 50); + win.setLocation((DesignerContext.getDesignerFrame().getWidth() - winSize.width - 100 + DesignerContext.getDesignerFrame().getX()), + DesignerContext.getDesignerFrame().getY() + winSize.height); } } diff --git a/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java b/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java index 057b561fa0..669ef6ef4a 100644 --- a/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java +++ b/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java @@ -3,19 +3,26 @@ package com.fr.design.os.impl; import com.fr.design.data.datapane.connect.ConnectionManagerPane; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.dialog.FineJOptionPane; import com.fr.design.editlock.EditLockUtils; +import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrame; import com.fr.file.ConnectionConfig; +import com.fr.report.LockItem; import com.fr.stable.os.support.OSBasedAction; import com.fr.transaction.CallBackAdaptor; import com.fr.transaction.Configurations; import com.fr.transaction.WorkerFacade; -import com.fr.report.LockItem; + +import javax.swing.JOptionPane; +import java.util.concurrent.atomic.AtomicBoolean; + import static com.fr.design.actions.server.ConnectionListAction.doWithDatasourceManager; /** * 数据连接窗口 + * * @author pengda * @date 2019/10/9 */ @@ -52,10 +59,17 @@ public class DatabaseDialogAction implements OSBasedAction { databaseListDialog.setDoOKSucceed(false); return; } + + AtomicBoolean saved = new AtomicBoolean(true); Configurations.modify(new WorkerFacade(ConnectionConfig.class) { @Override public void run() { - databaseManagerPane.update(datasourceManager); + try { + databaseManagerPane.update(datasourceManager); + } catch (Exception e) { + saved.set(false); + FineJOptionPane.showMessageDialog(databaseManagerPane, e.getMessage(), Toolkit.i18nText("Fine-Design_Basic_Error"), JOptionPane.ERROR_MESSAGE); + } } }.addCallBack(new CallBackAdaptor() { @Override @@ -66,9 +80,13 @@ public class DatabaseDialogAction implements OSBasedAction { @Override public void afterCommit() { - DesignerContext.getDesignerBean("databasename").refreshBeanElement(); - // 定义数据连接弹窗关闭后,解锁 - EditLockUtils.unlock(LockItem.CONNECTION); + if (saved.get()) { + DesignerContext.getDesignerBean("databasename").refreshBeanElement(); + // 定义数据连接弹窗关闭后,解锁 + EditLockUtils.unlock(LockItem.CONNECTION); + } else { + databaseListDialog.setDoOKSucceed(false); + } } })); } diff --git a/designer-base/src/main/java/com/fr/design/os/impl/PMDialogAction.java b/designer-base/src/main/java/com/fr/design/os/impl/PMDialogAction.java index 990e73ee9c..16944da068 100644 --- a/designer-base/src/main/java/com/fr/design/os/impl/PMDialogAction.java +++ b/designer-base/src/main/java/com/fr/design/os/impl/PMDialogAction.java @@ -1,6 +1,7 @@ package com.fr.design.os.impl; import com.fr.config.ServerPreferenceConfig; +import com.fr.design.DesignerEnvManager; import com.fr.design.extra.WebViewDlgHelper; import com.fr.design.jdk.JdkVersion; import com.fr.design.upm.UpmFinder; @@ -23,7 +24,9 @@ public class PMDialogAction implements OSBasedAction { DesignUtils.visitEnvServerByParameters( PLUGIN_MANAGER_ROUTE,null,null); return; } - if (ServerPreferenceConfig.getInstance().isUseOptimizedUPM() || SupportOSImpl.MACOS_NEW_PLUGIN_MANAGEMENT.support()) { + if (ServerPreferenceConfig.getInstance().isUseOptimizedUPM() + || SupportOSImpl.MACOS_NEW_PLUGIN_MANAGEMENT.support() + || DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter()) { UpmFinder.showUPMDialog(); } else { WebViewDlgHelper.createPluginDialog(); diff --git a/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java b/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java index 949d770456..801822e488 100644 --- a/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java +++ b/designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java @@ -7,13 +7,18 @@ import com.fr.general.GeneralContext; import com.fr.json.JSON; import com.fr.json.JSONFactory; import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; import com.fr.stable.os.Arch; import com.fr.stable.os.OperatingSystem; import com.fr.stable.os.support.SupportOS; import com.fr.workspace.WorkContext; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; +import java.util.Scanner; /** * @author pengda @@ -142,6 +147,50 @@ public enum SupportOSImpl implements SupportOS { } }, + OLD_STYLE_CHOOSER { + @Override + public boolean support() { + boolean javafxExist = true; + try { + Class.forName("javafx.stage.FileChooser"); + } catch (ClassNotFoundException e) { + javafxExist = false; + } + return !javafxExist || (OperatingSystem.isLinux() && Arch.getArch() == Arch.ARM) || MACOS_12_VERSION_ADAPTER.support(); + } + }, + + MACOS_12_VERSION_ADAPTER { + @Override + public boolean support() { + return (OperatingSystem.isMacos() && getMacOsVersionNumber() >= macosMontereyVersionNum); + } + + private final int macosMontereyVersionNum = 12; + + /** + * System.getProperty("os.version") 在最新macos版本存在bug + * https://bugs.openjdk.java.net/browse/JDK-8253702 + * + * @return + */ + private int getMacOsVersionNumber() { + String result; + List command = new ArrayList<>(); + command.add("/usr/bin/sw_vers"); + command.add("-productVersion"); + try (InputStream inputStream = new ProcessBuilder(command).start().getInputStream(); + Scanner s = new Scanner(inputStream).useDelimiter("\\A")) { + result = s.hasNext() ? s.next() : StringUtils.EMPTY; + String[] versionSlice = result.split("\\."); + return Integer.parseInt(versionSlice[0]); + } catch (Exception e) { + FineLoggerFactory.getLogger().warn(e.getMessage(), e); + return 0; + } + } + }, + DESIGNER_LOGIN { @Override public boolean support() { diff --git a/designer-base/src/main/java/com/fr/design/remote/button/IconButton.java b/designer-base/src/main/java/com/fr/design/remote/button/IconButton.java index 598ec7f057..d2d04b8d4c 100644 --- a/designer-base/src/main/java/com/fr/design/remote/button/IconButton.java +++ b/designer-base/src/main/java/com/fr/design/remote/button/IconButton.java @@ -4,6 +4,7 @@ import com.fr.base.BaseUtils; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.stable.StringUtils; +import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; @@ -15,14 +16,19 @@ import java.awt.Graphics2D; import java.awt.Point; public final class IconButton extends JButton { - public IconButton() { + + public IconButton(Icon icon) { super(StringUtils.EMPTY); setContentAreaFilled(false); setFocusPainted(false); - setIcon(BaseUtils.readIcon("com/fr/design/remote/images/icon_tab_close_normal.png")); + setIcon(icon); setBorder(null); } + public IconButton() { + this(BaseUtils.readIcon("com/fr/design/remote/images/icon_tab_close_normal.png")); + } + @Override protected void paintBorder(Graphics g) { } diff --git a/designer-base/src/main/java/com/fr/design/report/WatermarkSettingPane.java b/designer-base/src/main/java/com/fr/design/report/WatermarkSettingPane.java index 0cc211c5f1..f3de6eef96 100644 --- a/designer-base/src/main/java/com/fr/design/report/WatermarkSettingPane.java +++ b/designer-base/src/main/java/com/fr/design/report/WatermarkSettingPane.java @@ -1,5 +1,6 @@ package com.fr.design.report; +import com.fr.base.iofile.attr.WaterMarkProvideConstant; import com.fr.base.iofile.attr.WatermarkAttr; import com.fr.design.dialog.AbstractTemplateServerSettingPane; import com.fr.report.core.ReportUtils; @@ -33,6 +34,7 @@ public class WatermarkSettingPane extends AbstractTemplateServerSettingPane { @Override protected void populateServerSettings() { WatermarkAttr watermarkAttr = ReportUtils.getWatermarkAttrFromServerConfig(); + watermarkAttr.setValid(true); watermarkPane.populate(watermarkAttr); } @@ -42,20 +44,21 @@ public class WatermarkSettingPane extends AbstractTemplateServerSettingPane { } public void populate(WatermarkAttr watermark) { - if (!watermark.isValid()) { + if (watermark.getWaterMarkProvider().equals(WaterMarkProvideConstant.TEMPLATE)) { + chooseComboBox.setSelectedIndex(SINGLE_SET); + watermarkPane.populate(watermark); + } else { chooseComboBox.setSelectedIndex(SERVER_SET); populateServerSettings(); - return; } - chooseComboBox.setSelectedIndex(SINGLE_SET); - watermarkPane.populate(watermark); } public WatermarkAttr update() { WatermarkAttr watermark = watermarkPane.update(); - if (isUsingServerSettings()) { - watermark.setValid(false); + if (!isUsingServerSettings()) { + watermark.setValid(true); + watermark.setWaterMarkProvider(WaterMarkProvideConstant.TEMPLATE); } return watermark; } diff --git a/designer-base/src/main/java/com/fr/design/report/fit/BaseFitAttrPane.java b/designer-base/src/main/java/com/fr/design/report/fit/BaseFitAttrPane.java new file mode 100644 index 0000000000..7a2e0e4729 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/BaseFitAttrPane.java @@ -0,0 +1,239 @@ +package com.fr.design.report.fit; + +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.DesignSizeI18nManager; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.report.fit.menupane.FitPreviewPane; +import com.fr.design.report.fit.menupane.FitRadioGroup; +import com.fr.design.report.fit.menupane.FontRadioGroup; +import com.fr.design.report.fit.provider.FitAttrModelProvider; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.ComparatorUtils; +import com.fr.report.fit.ReportFitAttr; + + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemListener; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.fr.design.i18n.Toolkit.i18nText; + +public abstract class BaseFitAttrPane extends BasicBeanPane { + + protected JPanel contentJPanel; + protected UILabel belowSetLabel; + protected UIComboBox itemChoose; + protected java.util.List fitAttrModelList = new ArrayList<>(); + + public FontRadioGroup fontRadioGroup; + public FitRadioGroup adaptRadioGroup; + public JPanel attrJPanel; + public FitPreviewPane previewJPanel; + public FitAttrModel fitAttrModel; + private static final int BELOW_SET_COMPONENT_HSPACE = 8; + + + protected BaseFitAttrPane() { + initFitAttrModel(); + } + + private void initFitAttrModel() { + fitAttrModelList.add(new FrmFitAttrModel()); + fitAttrModelList.add(new CptFitAttrModel()); + + Set fitAttrModelProviders = ExtraDesignClassManager.getInstance().getArray(FitAttrModelProvider.XML_TAG); + + for (FitAttrModelProvider fitAttrModelProvider : fitAttrModelProviders) { + fitAttrModelList.add(fitAttrModelProvider); + } + + fitAttrModelList = fitAttrModelList.stream().sorted(Comparator.comparing(FitAttrModel::getPriority).reversed()).collect(Collectors.toList()); + } + + protected void populateModel(FitAttrModel fitAttrModel) { + this.fitAttrModel = fitAttrModel; + if (attrJPanel != null) { + contentJPanel.remove(attrJPanel); + } + if (previewJPanel != null) { + contentJPanel.remove(previewJPanel); + } + + fontRadioGroup = new FontRadioGroup(); + adaptRadioGroup = new FitRadioGroup(); + initAttrJPanel(); + initPreviewJPanel(); + } + + + protected void initAttrJPanel() { + int colCount = fitAttrModel.getFitTypes().length + 1; + Component[][] components = new Component[2][colCount]; + initFitRadioGroup(fontRadioGroup, i18nText("Fine-Designer_Fit-Font"), new String[]{i18nText("Fine-Designer_Fit"), i18nText("Fine-Designer_Fit-No")}, components[0]); + initFitRadioGroup(adaptRadioGroup, fitAttrModel.getFitName(), Arrays.stream(fitAttrModel.getFitTypes()).map(FitType::description).toArray(String[]::new), components[1]); + + double[] rowSize = new double[2]; + double[] columnSize = new double[colCount]; + for (int i = 0; i < rowSize.length; i++) { + rowSize[i] = 20; + } + for (int i = 0; i < columnSize.length; i++) { + if (i == 0) { + columnSize[i] = DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.firstColumn").getWidth(); + } else { + columnSize[i] = DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.column").getWidth(); + } + } + + attrJPanel = TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); + attrJPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0)); + contentJPanel.add(attrJPanel); + } + + private void initFitRadioGroup(FitRadioGroup fitRadioGroup, String name, String[] options, Component[] components) { + components[0] = new UILabel(name); + for (int i = 0; i < options.length; i++) { + + if (options[i] != null) { + UIRadioButton fontFitRadio = new UIRadioButton(options[i]); + fitRadioGroup.add(fontFitRadio); + components[i + 1] = fontFitRadio; + } else { + components[i + 1] = null; + } + } + fitRadioGroup.addActionListener(getPreviewActionListener()); + } + + protected ActionListener getPreviewActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + refreshPreviewJPanel(); + } + }; + } + + protected void refreshPreviewJPanel() { + String previewIndex = getPreviewIndex(); + previewJPanel.refreshPreview(previewIndex, fontRadioGroup.isEnabled()); + } + + protected String getPreviewIndex() { + return getStateInPC(adaptRadioGroup.getSelectRadioIndex()) + "" + fontRadioGroup.getSelectRadioIndex(); + } + + protected void initPreviewJPanel() { + previewJPanel = new FitPreviewPane(); + previewJPanel.setBorder(BorderFactory.createEmptyBorder(0, getPreviewJPanelLeft(), 0, 0)); + contentJPanel.add(previewJPanel); + } + + private int getPreviewJPanelLeft() { + int left = 0; + if (belowSetLabel.getPreferredSize() != null) { + left = belowSetLabel.getPreferredSize().width + BELOW_SET_COMPONENT_HSPACE; + } + return left; + } + + protected int getStateInPC(int index) { + FitType[] fitTypes = fitAttrModel.getFitTypes(); + return fitTypes[index].getState(); + } + + protected int getOptionIndex(int state) { + FitType[] fitTypes = fitAttrModel.getFitTypes(); + for (int i = 0; i < fitTypes.length; i++) { + if (ComparatorUtils.equals(state, fitTypes[i].getState())) { + return i; + } + } + return 0; + } + + + @Override + public void populateBean(ReportFitAttr ob) { + fontRadioGroup.selectIndexButton(ob.isFitFont() ? 0 : 1); + adaptRadioGroup.selectIndexButton(getOptionIndex(ob.fitStateInPC())); + refreshPreviewJPanel(); + } + + @Override + public ReportFitAttr updateBean() { + ReportFitAttr reportFitAttr = new ReportFitAttr(); + reportFitAttr.setFitFont(fontRadioGroup.isFontFit()); + reportFitAttr.setFitStateInPC(getStateInPC(adaptRadioGroup.getSelectRadioIndex())); + return reportFitAttr; + } + + + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + fontRadioGroup.setEnabled(enabled); + adaptRadioGroup.setEnabled(enabled); + refreshPreviewJPanel(); + } + + @Override + protected String title4PopupWindow() { + return i18nText("Fine-Designer_PC_Fit_Attr"); + } + + protected abstract String[] getItemNames(); + + protected void initComponents() { + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + contentJPanel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(false, FlowLayout.LEFT, 0, 0); + this.add(contentJPanel); + initItemChoose(); + initPrompt(); + } + + + private void initItemChoose() { + JPanel chooseJPanel = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + ItemListener itemListener = getItemListener(); + itemChoose = new UIComboBox(getItemNames()); + itemChoose.addItemListener(itemListener); + belowSetLabel = new UILabel(i18nText("Fine-Design_Report_Blow_Set")); + JPanel hSpaceLabel = new JPanel(); + hSpaceLabel.setSize(BELOW_SET_COMPONENT_HSPACE, 0); + JPanel buttonPane = GUICoreUtils.createFlowPane(new Component[]{ + belowSetLabel, hSpaceLabel, itemChoose}, FlowLayout.LEFT); + chooseJPanel.add(buttonPane); + chooseJPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0)); + contentJPanel.add(chooseJPanel); + } + + + protected abstract ItemListener getItemListener(); + + + public void populate(ReportFitAttr reportFitAttr) { + + } + + protected void initPrompt() { + } + + protected void refresh() { + validate(); + repaint(); + revalidate(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/report/fit/CptFitAttrModel.java b/designer-base/src/main/java/com/fr/design/report/fit/CptFitAttrModel.java new file mode 100644 index 0000000000..176f2cee1a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/CptFitAttrModel.java @@ -0,0 +1,51 @@ +package com.fr.design.report.fit; + + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.report.fit.ReportFitAttr; +import com.fr.report.fit.ReportFitConfig; + + +public class CptFitAttrModel implements FitAttrModel { + + @Override + public FitType[] getFitTypes() { + return new FitType[]{ + FitType.HORIZONTAL_FIT, + FitType.DOUBLE_FIT, + FitType.NOT_FIT + }; + } + + @Override + public String getFitName() { + return Toolkit.i18nText("Fine-Designer_Fit-Element"); + } + + + @Override + public String getModelName() { + return Toolkit.i18nText("Fine-Design_Basic_Plain_Report"); + } + + @Override + public ReportFitAttr getGlobalReportFitAttr() { + return ReportFitConfig.getInstance().getCptFitAttr(); + } + + @Override + public void setGlobalReportFitAttr(ReportFitAttr reportFitAttr) { + ReportFitConfig.getInstance().setCptFitAttr(reportFitAttr); + } + + @Override + public int getPriority() { + return 0; + } + + @Override + public boolean isAvailable(JTemplate jTemplate) { + return jTemplate.isJWorkBook(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/report/fit/FitAttrModel.java b/designer-base/src/main/java/com/fr/design/report/fit/FitAttrModel.java new file mode 100644 index 0000000000..1d1ac02f0d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/FitAttrModel.java @@ -0,0 +1,44 @@ +package com.fr.design.report.fit; + +import com.fr.design.mainframe.JTemplate; +import com.fr.report.fit.ReportFitAttr; + +public interface FitAttrModel { + /** + * @Description 名称,比如:普通报表、决策报表等 + **/ + String getModelName(); + + /** + * @Description 自适应选项的名称,比如返回:表格 + **/ + String getFitName(); + + /** + * @Description 自适应选项 + **/ + FitType[] getFitTypes(); + + + /** + * @Description 获取全局的自适应属性 + **/ + ReportFitAttr getGlobalReportFitAttr(); + + /** + * @Description 设置全局的自适应属性 + * @param: reportFitAttr + **/ + void setGlobalReportFitAttr(ReportFitAttr reportFitAttr); + + /** + * @Description 优先级 + **/ + int getPriority(); + + /** + * @Description 是否可用 + * @param: jTemplate + **/ + boolean isAvailable(JTemplate jTemplate); +} diff --git a/designer-base/src/main/java/com/fr/design/report/fit/FrmFitAttrModel.java b/designer-base/src/main/java/com/fr/design/report/fit/FrmFitAttrModel.java new file mode 100644 index 0000000000..258dfbf49c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/FrmFitAttrModel.java @@ -0,0 +1,53 @@ +package com.fr.design.report.fit; + + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.report.fit.ReportFitAttr; +import com.fr.report.fit.ReportFitConfig; + + +public class FrmFitAttrModel implements FitAttrModel { + + + @Override + public String getModelName() { + return Toolkit.i18nText("Fine-Design_Basic_Decision_Report"); + } + + @Override + public String getFitName() { + return Toolkit.i18nText("Fine-Designer_Fit-Element"); + } + + public FitType[] getFitTypes() { + return new FitType[]{ + FitType.DEFAULT, + FitType.HORIZONTAL_FIT, + FitType.DOUBLE_FIT, + FitType.NOT_FIT + }; + } + + @Override + public ReportFitAttr getGlobalReportFitAttr() { + return ReportFitConfig.getInstance().getFrmFitAttr(); + } + + @Override + public void setGlobalReportFitAttr(ReportFitAttr reportFitAttr) { + ReportFitConfig.getInstance().setFrmFitAttr(reportFitAttr); + } + + @Override + public int getPriority() { + return 1; + } + + @Override + public boolean isAvailable(JTemplate jTemplate) { + return !jTemplate.isJWorkBook(); + } + + +} diff --git a/designer-base/src/main/java/com/fr/design/report/fit/menupane/ReportFitAttrAction.java b/designer-base/src/main/java/com/fr/design/report/fit/menupane/ReportFitAttrAction.java index ae0cfd2b65..c1dd3afd6e 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/menupane/ReportFitAttrAction.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/menupane/ReportFitAttrAction.java @@ -1,10 +1,10 @@ package com.fr.design.report.fit.menupane; -import com.fr.base.svg.IconUtils; import com.fr.design.actions.JTemplateAction; import com.fr.design.beans.BasicBeanPane; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.dialog.UIDialog; +import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; @@ -35,22 +35,6 @@ public class ReportFitAttrAction extends JTemplateAction { return null; } }; - private static final MenuKeySet REPORT_FIT_ATTR_ELEMENTCASE = new MenuKeySet() { - @Override - public char getMnemonic() { - return 'T'; - } - - @Override - public String getMenuName() { - return Toolkit.i18nText("Fine-Designer_PC_Element_Case_Fit_Attr"); - } - - @Override - public KeyStroke getKeyStroke() { - return null; - } - }; public ReportFitAttrAction(JTemplate jTemplate) { super(jTemplate); @@ -58,12 +42,7 @@ public class ReportFitAttrAction extends JTemplateAction { } private void initMenuStyle() { - JTemplate jTemplate = getEditingComponent(); - if (jTemplate.isJWorkBook()) { - this.setMenuKeySet(REPORT_FIT_ATTR); - } else { - this.setMenuKeySet(REPORT_FIT_ATTR_ELEMENTCASE); - } + this.setMenuKeySet(REPORT_FIT_ATTR); this.setName(getMenuKeySet().getMenuKeySetName() + "..."); this.setMnemonic(getMenuKeySet().getMnemonic()); this.setSmallIcon("/com/fr/design/images/reportfit/fit"); @@ -82,24 +61,19 @@ public class ReportFitAttrAction extends JTemplateAction { } final FitProvider wbTpl = (FitProvider) jwb.getTarget(); ReportFitAttr fitAttr = wbTpl.getReportFitAttr(); - if (jwb.isJWorkBook()) { - final TemplateFitAttrPane attrPane = new TemplateFitAttrPane(); - showReportFitDialog(fitAttr, jwb, wbTpl, attrPane); - } else { - final ReportFitAttrPane attrPane = new ReportFitAttrPane(); - showReportFitDialog(fitAttr, jwb, wbTpl, attrPane); - } + TemplateFitAttrPane templateFitAttrPane = new TemplateFitAttrPane(jwb); + showReportFitDialog(fitAttr, jwb, wbTpl, templateFitAttrPane); } private void showReportFitDialog(ReportFitAttr fitAttr, final JTemplate jwb, final FitProvider wbTpl, final BasicBeanPane attrPane) { attrPane.populateBean(fitAttr); - UIDialog dialog = attrPane.showMediumWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + UIDialog dialog = attrPane.showWindowWithCustomSize(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { @Override public void doOk() { wbTpl.setReportFitAttr(attrPane.updateBean()); jwb.fireTargetModified(); } - }); + }, DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.templatePane.dialog")); dialog.setVisible(true); } diff --git a/designer-base/src/main/java/com/fr/design/report/fit/menupane/TemplateFitAttrPane.java b/designer-base/src/main/java/com/fr/design/report/fit/menupane/TemplateFitAttrPane.java index 66673fc5f5..8854b0ee92 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/menupane/TemplateFitAttrPane.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/menupane/TemplateFitAttrPane.java @@ -1,55 +1,92 @@ package com.fr.design.report.fit.menupane; -import com.fr.design.beans.BasicBeanPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.report.fit.BaseFitAttrPane; +import com.fr.design.report.fit.FitAttrModel; +import com.fr.general.ComparatorUtils; +import com.fr.report.fit.FitProvider; import com.fr.report.fit.ReportFitAttr; -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; -/** - * Created by 夏翔 on 2016/6/24. - */ -public class TemplateFitAttrPane extends BasicBeanPane { - private TemplateBrowserFitAttrPane attrPane; +public class TemplateFitAttrPane extends BaseFitAttrPane { - public TemplateFitAttrPane() { + private JTemplate jwb; + + public TemplateFitAttrPane(JTemplate jwb) { + this.jwb = jwb; initComponents(); } - private void initComponents() { - this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - attrPane = new TemplateBrowserFitAttrPane(); - this.add(attrPane); + @Override + protected void initComponents() { + super.initComponents(); + for (FitAttrModel fitAttrModel : fitAttrModelList) { + if (fitAttrModel.isAvailable(jwb)) { + populateModel(fitAttrModel); + break; + } + } + } + @Override + public void populateBean(ReportFitAttr reportFitAttr) { + if (reportFitAttr == null) { + itemChoose.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_Using_Server_Report_View_Settings")); + } else { + itemChoose.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single")); + } + populate(reportFitAttr); } - /** - * 展示界面 - * - * @param fitAttr 自适应属性 - */ - public void populateBean(ReportFitAttr fitAttr) { - attrPane.populateBean(fitAttr); + public void populate(ReportFitAttr reportFitAttr) { + if (reportFitAttr == null) { + reportFitAttr = fitAttrModel.getGlobalReportFitAttr(); + } + + super.setEnabled(isTemplateSingleSet()); + super.populateBean(reportFitAttr); } - /** - * 提交数据 - * - * @return 界面上的更新数据 - */ public ReportFitAttr updateBean() { - return attrPane.updateBean(); + if (!isTemplateSingleSet()) { + return null; + } else { + return super.updateBean(); + } + } + + @Override + protected String[] getItemNames() { + return new String[]{Toolkit.i18nText("Fine-Design_Report_Using_Server_Report_View_Settings"), + Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single")}; + } + + @Override + protected ItemListener getItemListener() { + return new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + if(isTemplateSingleSet()){ + if (jwb != null) { + FitProvider wbTpl = (FitProvider) jwb.getTarget(); + ReportFitAttr fitAttr = wbTpl.getReportFitAttr(); + populate(fitAttr); + } + }else { + populate(fitAttrModel.getGlobalReportFitAttr()); + } + } + } + }; } - /** - * 标题 - * - * @return 标题 - */ - protected String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_PC_Fit_Attr"); + private boolean isTemplateSingleSet() { + return ComparatorUtils.equals(Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single"), itemChoose.getSelectedItem()); } -} +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/report/fit/provider/AbstractFitAttrModelProvider.java b/designer-base/src/main/java/com/fr/design/report/fit/provider/AbstractFitAttrModelProvider.java new file mode 100644 index 0000000000..44d048b7de --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/provider/AbstractFitAttrModelProvider.java @@ -0,0 +1,18 @@ +package com.fr.design.report.fit.provider; + +import com.fr.stable.fun.mark.API; + + +@API(level = FitAttrModelProvider.CURRENT_LEVEL) +public abstract class AbstractFitAttrModelProvider implements FitAttrModelProvider { + + @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/report/fit/provider/FitAttrModelProvider.java b/designer-base/src/main/java/com/fr/design/report/fit/provider/FitAttrModelProvider.java new file mode 100644 index 0000000000..88f7335d42 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/report/fit/provider/FitAttrModelProvider.java @@ -0,0 +1,11 @@ +package com.fr.design.report.fit.provider; + + +import com.fr.design.report.fit.FitAttrModel; +import com.fr.stable.fun.mark.Mutable; + + +public interface FitAttrModelProvider extends Mutable, FitAttrModel { + String XML_TAG = "FitAttrModelProvider"; + int CURRENT_LEVEL = 1; +} 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 1d66094f15..4e82d38051 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 @@ -1,30 +1,33 @@ package com.fr.design.style; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ibutton.UIButtonUI; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.style.background.BackgroundJComponent; +import com.fr.design.utils.gui.GUIPaintUtils; +import com.fr.stable.Constants; + +import javax.swing.AbstractButton; +import javax.swing.JPanel; +import javax.swing.JWindow; +import javax.swing.border.AbstractBorder; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import javax.swing.plaf.ButtonUI; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; import java.awt.RenderingHints; +import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; -import javax.swing.AbstractButton; -import javax.swing.JPanel; -import javax.swing.border.AbstractBorder; -import javax.swing.event.AncestorEvent; -import javax.swing.event.AncestorListener; -import javax.swing.plaf.ButtonUI; - -import com.fr.design.constants.UIConstants; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.gui.ibutton.UIButtonUI; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.utils.gui.GUIPaintUtils; -import com.fr.design.style.background.BackgroundJComponent; -import com.fr.stable.Constants; - /** * @author kunsnat E-mail:kunsnat@gmail.com * @version 创建时间:2011-10-31 下午03:28:31 类说明: 抽象出来的弹出box. 可以弹出颜色选择, 图案选择, 纹理选择. @@ -94,6 +97,34 @@ public abstract class AbstractSelectBox extends AbstractPopBox implements Mou hidePopupMenu(); } }); + + displayComponent.addMouseListener(new MouseAdapter() { + @Override + public void mouseExited(MouseEvent e) { + if (!isPopupVisible()) { + //如果弹出框==null 或者 弹出框不可见 直接return + return; + } + Point popMenuP = getControlWindow().getLocation(); + Point displayComponentP = displayComponent.getLocationOnScreen(); + if (popMenuP.getX() < displayComponentP.getX() - 1) { + //如果 弹出框横向超出屏幕 往左调整了 和displayComponent横向错开 就不处理了 + return; + } + + Rectangle rectangle = displayComponent.getBounds(); + boolean bottomPopAndExitTop = displayComponentP.getY() < popMenuP.getY() && e.getY() <= rectangle.y; + boolean topPopAndExitBottom = displayComponentP.getY() > popMenuP.getY() && e.getY() >= rectangle.y + rectangle.getHeight(); + boolean exitLeftOrRight = rectangle.x > e.getX() || rectangle.x + rectangle.getWidth() < e.getX(); + if (bottomPopAndExitTop || topPopAndExitBottom || exitLeftOrRight) { + //弹出框在displayComponent下面 且 鼠标是从displayComponent上面离开的,隐藏弹出界面。 + //弹出框在displayComponent上面 且 鼠标是从displayComponent下面离开的,隐藏弹出界面。 + //鼠标从displayComponent左边 或者 右边 离开,隐藏弹出界面。 + hidePopupMenu(); + } + + } + }); } public void setEnabled(boolean enabled) { diff --git a/designer-base/src/main/java/com/fr/design/style/background/image/ImageFileChooser.java b/designer-base/src/main/java/com/fr/design/style/background/image/ImageFileChooser.java index 9c5b1af4d1..739dc81d55 100644 --- a/designer-base/src/main/java/com/fr/design/style/background/image/ImageFileChooser.java +++ b/designer-base/src/main/java/com/fr/design/style/background/image/ImageFileChooser.java @@ -4,62 +4,47 @@ package com.fr.design.style.background.image; import com.fr.design.DesignerEnvManager; -import com.fr.design.gui.ifilechooser.FileSelectionMode; -import com.fr.design.gui.ifilechooser.JavaFxNativeFileChooser; -import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ifilechooser.FileChooserFactory; +import com.fr.design.gui.ifilechooser.FileChooserProvider; import com.fr.design.i18n.Toolkit; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.share.collect.ComponentCollector; import com.fr.design.mainframe.toast.DesignerToastMsgUtil; -import javafx.stage.FileChooser; -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; + +import java.awt.Component; import java.io.File; +import javax.swing.SwingUtilities; /** * This class used to choose image files. */ public class ImageFileChooser { - - JavaFxNativeFileChooser javaFxNativeFileChooser; + private final FileChooserProvider fileChooserProvider; public ImageFileChooser() { - javaFxNativeFileChooser = - new JavaFxNativeFileChooser.Builder(). - fileSelectionMode(FileSelectionMode.FILE). - title(Toolkit.i18nText("Fine-Design_Basic_Open")). - filter(Toolkit.i18nText("Fine-Design_Basic_Image_Image_Files"), "*.jpg", "*.gif", "*.png", "*.bmp"). - build(); + fileChooserProvider = FileChooserFactory.createImageFileChooser(); } public int showOpenDialog(Component parent, String approveButtonText) { - return showOpenDialog(parent); + return fileChooserProvider.showOpenDialog(parent, approveButtonText); } public int showOpenDialog(Component parent) { showImageCompressMoveTip(); - return javaFxNativeFileChooser.showDialog(parent); + return fileChooserProvider.showDialog(parent); } public void setCurrentDirectory(File file) { - javaFxNativeFileChooser.setCurrentDirectory(file); + fileChooserProvider.setCurrentDirectory(file); } public void setMultiSelectionEnabled(boolean multiple) { - if (multiple) { - javaFxNativeFileChooser.setSelectionMode(FileSelectionMode.MULTIPLE_FILE); - } else { - javaFxNativeFileChooser.setSelectionMode(FileSelectionMode.FILE); - } + fileChooserProvider.setMultiSelectionEnabled(multiple); } public File getSelectedFile() { - return javaFxNativeFileChooser.getSelectedFile(); + return fileChooserProvider.getSelectedFile(); } public boolean isCheckSelected() { diff --git a/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java b/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java index 90d6accf6b..09fa2bbc08 100644 --- a/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java +++ b/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java @@ -26,6 +26,7 @@ import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.io.File; import java.util.Map; /** @@ -170,6 +171,10 @@ public class ModernUIPane extends BasicPane { public void clearCache() { if (browser != null) { browser.getCacheStorage().clearCache(); + File file = new File(browser.getContext().getCacheDir()); + if (file.exists()) { + file.delete(); + } } } diff --git a/designer-base/src/main/java/com/fr/design/upm/UpmBridge.java b/designer-base/src/main/java/com/fr/design/upm/UpmBridge.java index fee07ac467..01369116d7 100644 --- a/designer-base/src/main/java/com/fr/design/upm/UpmBridge.java +++ b/designer-base/src/main/java/com/fr/design/upm/UpmBridge.java @@ -14,9 +14,10 @@ import com.fr.design.extra.exe.GetPluginPrefixExecutor; import com.fr.design.extra.exe.PluginLoginExecutor; import com.fr.design.extra.exe.ReadUpdateOnlineExecutor; import com.fr.design.extra.exe.SearchOnlineExecutor; +import com.fr.design.gui.ifilechooser.FileChooserArgs; +import com.fr.design.gui.ifilechooser.FileChooserFactory; import com.fr.design.gui.ifilechooser.FileChooserProvider; import com.fr.design.gui.ifilechooser.FileSelectionMode; -import com.fr.design.gui.ifilechooser.JavaFxNativeFileChooser; import com.fr.design.i18n.Toolkit; import com.fr.design.locale.impl.BbsRegisterMark; import com.fr.design.locale.impl.BbsResetMark; @@ -39,11 +40,12 @@ import com.teamdev.jxbrowser.chromium.Browser; import com.teamdev.jxbrowser.chromium.JSArray; import com.teamdev.jxbrowser.chromium.JSFunction; import com.teamdev.jxbrowser.chromium.JSObject; -import javafx.stage.FileChooser; -import javax.swing.*; +import java.awt.Desktop; +import javax.swing.JFileChooser; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import javax.swing.filechooser.FileNameExtensionFilter; -import java.awt.*; import java.io.File; import java.net.URI; import java.util.ArrayList; @@ -312,10 +314,10 @@ public class UpmBridge { RunnableFuture future = new FutureTask<>(new Callable() { @Override public String call() { - FileChooserProvider fileChooserProvider = new JavaFxNativeFileChooser.Builder(). - fileSelectionMode(FileSelectionMode.FILE). - filter(des, filter). - build(); + FileChooserProvider fileChooserProvider = FileChooserFactory.createFileChooser( + FileChooserArgs.newBuilder(). + setFileSelectionMode(FileSelectionMode.FILE). + setFilter(des, filter).build()); int result = fileChooserProvider.showDialog(UpmFinder.getDialog()); if (result == JFileChooser.APPROVE_OPTION) { return fileChooserProvider.getSelectedFile().getAbsolutePath(); diff --git a/designer-base/src/main/java/com/fr/design/utils/LinkStrUtils.java b/designer-base/src/main/java/com/fr/design/utils/LinkStrUtils.java new file mode 100644 index 0000000000..e394bbbacc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/utils/LinkStrUtils.java @@ -0,0 +1,108 @@ +package com.fr.design.utils; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.stable.StringUtils; + +import javax.swing.JComponent; +import java.awt.Color; +import java.awt.Font; + +/** + * + * 链接字符串工具类 + * + * @author Harrison + * @version 10.0 + * created by Harrison on 2022/05/24 + **/ +public class LinkStrUtils { + + public static final UILabel LABEL = new UILabel(); + + /** + * 创建链接label + * */ + public static UILabel generateLabel(String html, JComponent templateLabel) { + + String style = generateStyle(templateLabel.getBackground(), templateLabel.getFont(), templateLabel.getForeground()); + String fullHtml = generateHtmlTag(style, html); + return new UILabel(fullHtml); + } + + /** + * 创建链接字符串,html格式 + * */ + public static String generateHtmlTag(String html) { + + String defaultStyle = generateDefaultStyle(); + return generateHtmlTag(defaultStyle, html); + } + + /** + * 创建链接字符串,html格式 + * */ + public static String generateHtmlTag(String style, String html) { + + if (StringUtils.isEmpty(style)) { + throw new NullPointerException("style"); + } + if (StringUtils.isEmpty(html)) { + throw new NullPointerException("html"); + } + return "" + html + ""; + } + + /** + * 创建链接字符串,html格式 + * */ + public static String generateLinkTag(String link, String text) { + + return "" + text + ""; + } + + /** + * 创建链接字符串,无下划线,html格式 + * */ + public static String generateLinkTagWithoutUnderLine(String link, String text) { + return "" + text + ""; + } + + /** + * 创建链接字符串的html style + * */ + public static String generateStyle(Color backgroundColor, Font font, Color fontColor) { + + // 构建相同风格样式 + StringBuilder style = new StringBuilder("font-family:" + font.getFamily() + ";"); + + style.append("font-weight:").append(font.isBold() ? "bold" : "normal").append(";"); + style.append("font-size:").append(font.getSize()).append("pt;"); + style.append("color:rgb(").append(fontColor.getRed()).append(",").append(fontColor.getGreen()).append(",").append(fontColor.getBlue()).append(");"); + style.append("background-color: rgb(").append(backgroundColor.getRed()).append(",").append(backgroundColor.getGreen()).append(",").append(backgroundColor.getBlue()).append(");"); + + return style.toString(); + } + + /** + * 创建链接字符串的html style + * */ + public static String generateStyle(Font font, Color fontColor) { + + // 构建相同风格样式 + StringBuilder style = new StringBuilder("font-family:" + font.getFamily() + ";"); + + style.append("font-weight:").append(font.isBold() ? "bold" : "normal").append(";"); + style.append("font-size:").append(font.getSize()).append("pt;"); + style.append("color:rgb(").append(fontColor.getRed()).append(",").append(fontColor.getGreen()).append(",").append(fontColor.getBlue()).append(");"); + return style.toString(); + } + + + /** + * 创建默认style + * */ + public static String generateDefaultStyle() { + + return generateStyle(LABEL.getBackground(), LABEL.getFont(), LABEL.getForeground()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/OpenLoadingPane.java b/designer-base/src/main/java/com/fr/design/utils/LoadingUtils.java similarity index 78% rename from designer-base/src/main/java/com/fr/design/mainframe/OpenLoadingPane.java rename to designer-base/src/main/java/com/fr/design/utils/LoadingUtils.java index adc30b2bff..e14f3f1018 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/OpenLoadingPane.java +++ b/designer-base/src/main/java/com/fr/design/utils/LoadingUtils.java @@ -1,35 +1,29 @@ -package com.fr.design.mainframe; +package com.fr.design.utils; import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.general.IOUtils; + +import javax.swing.ImageIcon; +import javax.swing.JPanel; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.LayoutManager; -import javax.swing.ImageIcon; -import javax.swing.JPanel; - -/** - * @author hades - * @version 10.0 - * Created by hades on 2021/4/9 - */ -public class OpenLoadingPane extends JPanel { - private static final ImageIcon LOADING_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/mainframe/openloading.png")); +public class LoadingUtils { + private static final ImageIcon LOADING_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/mainframe/loading.png")); private static final Color TIP_COLOR = new Color(108, 174, 235); private static final int Y_GAP = 50; private static final int X_GAP = 10; - private UILabel loadingLabel; - private UILabel tipLabel; - - public OpenLoadingPane() { - - setLayout(new LayoutManager() { - + public static JPanel createLoadingPane() { + JPanel jPanel = new JPanel(); + UILabel loadingLabel = new UILabel(LOADING_ICON); + UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Loading")); + tipLabel.setForeground(TIP_COLOR); + jPanel.setLayout(new LayoutManager() { @Override public void removeLayoutComponent(Component comp) { } @@ -64,12 +58,10 @@ public class OpenLoadingPane extends JPanel { public void addLayoutComponent(String name, Component comp) { } }); - setBackground(Color.WHITE); - loadingLabel = new UILabel(LOADING_ICON); - tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Open_Template_Loading")); - tipLabel.setForeground(TIP_COLOR); - add(loadingLabel); - add(tipLabel); + jPanel.setBackground(Color.WHITE); + jPanel.add(loadingLabel); + jPanel.add(tipLabel); + return jPanel; } -} +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/utils/SvgPaintUtils.java b/designer-base/src/main/java/com/fr/design/utils/SvgPaintUtils.java new file mode 100644 index 0000000000..9f3dd0c466 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/utils/SvgPaintUtils.java @@ -0,0 +1,28 @@ +package com.fr.design.utils; + +import com.fr.base.svg.SVGIcon; +import com.fr.base.svg.SystemScaleUtils; +import java.awt.Graphics2D; + +/** + * 用于绘制svg图片缩放(高分屏下) + * + * @author hades + * @version 11.0 + * Created by hades on 2022/5/6 + */ +public class SvgPaintUtils { + + public static void beforePaint(Graphics2D g2) { + if (SystemScaleUtils.isJreHiDPIEnabled()) { + g2.scale(1 / SVGIcon.SYSTEM_SCALE, 1 / SVGIcon.SYSTEM_SCALE); + } + } + + public static void afterPaint(Graphics2D g2) { + if (SystemScaleUtils.isJreHiDPIEnabled()) { + g2.scale(SVGIcon.SYSTEM_SCALE, SVGIcon.SYSTEM_SCALE); + } + } + +} diff --git a/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java b/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java index abae997e39..bfa742f9b1 100644 --- a/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/gui/AdjustWorkBookDefaultStyleUtils.java @@ -17,30 +17,52 @@ public class AdjustWorkBookDefaultStyleUtils { private static final Color TEMPLATE_BACKGROUND = new Color(16, 11, 43); private static final Color CELL_ELEMENT_BORDER = new Color(110, 110, 110); + private static final Color CELL_ELEMENT_FONT_FOREGROUND = Color.WHITE; + + private static Color currentStoryBack = null; + + public static void setCurrentStoryBack(Color color) { + currentStoryBack = color; + } + + private static Color getCurrentStoryBack() { + return currentStoryBack == null ? TEMPLATE_BACKGROUND : currentStoryBack; + } public static void adjustCellElement(CellElement cellElement) { if (DesignModeContext.isDuchampMode()) { Style style = cellElement.getStyle(); - style = style.deriveFRFont(style.getFRFont().applyForeground(Color.WHITE)); + style = adjustCellElement(style); + cellElement.setStyle(style); + } + } + + public static Style adjustCellElement(Style style) { + if (DesignModeContext.isDuchampMode()) { + style = style.deriveFRFont(style.getFRFont().applyForeground(CELL_ELEMENT_FONT_FOREGROUND)); style = style.deriveBorder(0, CELL_ELEMENT_BORDER, 0, CELL_ELEMENT_BORDER, 0, CELL_ELEMENT_BORDER, 0, CELL_ELEMENT_BORDER); - cellElement.setStyle(style); } + return style; + } + + public static Color adjustCellElementFontForeground(Color color) { + return DesignModeContext.isDuchampMode() ? CELL_ELEMENT_FONT_FOREGROUND : color; } public static void adjustFloatElement(FloatElement floatElement) { if (DesignModeContext.isDuchampMode()) { Style style = floatElement.getStyle(); - style = style.deriveBackground(ColorBackground.getInstance(TEMPLATE_BACKGROUND)); + style = style.deriveBackground(ColorBackground.getInstance(getCurrentStoryBack())); style = style.deriveFRFont(style.getFRFont().applyForeground(Color.WHITE)); floatElement.setStyle(style); } } public static Color adjustBack(Color color) { - return DesignModeContext.isDuchampMode() ? TEMPLATE_BACKGROUND : color; + return DesignModeContext.isDuchampMode() ? getCurrentStoryBack() : color; } } diff --git a/designer-base/src/main/java/com/fr/design/versioncheck/VersionCheckUtils.java b/designer-base/src/main/java/com/fr/design/versioncheck/VersionCheckUtils.java index e5624c4531..d7823aadf5 100644 --- a/designer-base/src/main/java/com/fr/design/versioncheck/VersionCheckUtils.java +++ b/designer-base/src/main/java/com/fr/design/versioncheck/VersionCheckUtils.java @@ -52,6 +52,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import javax.swing.SwingWorker; /** * @author pengda @@ -64,6 +65,11 @@ public class VersionCheckUtils { private static final String ID = "id"; private static final String VERSION = "version"; private static final String NAME = "name"; + private static final String RUNNING = "running"; + private static final String SYNC = "sync"; + private static final String GROUP = "group"; + private static final String BI = "bi"; + private static final String BIPREFIX = "com.finebi"; private static final Set pluginsNeedIgnore = new HashSet<>(); static { pluginsNeedIgnore.addAll(Arrays.asList( @@ -90,9 +96,23 @@ public class VersionCheckUtils { } public static void showVersionCheckDialog(String envName) { - if (!VersionCheckUtils.versionCheck(envName)) { - showNotificationDialog(envName); - } + new SwingWorker() { + @Override + protected Boolean doInBackground() { + return !VersionCheckUtils.versionCheck(envName); + } + + @Override + protected void done() { + try { + if (get()) { + showNotificationDialog(envName); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().warn(e.getMessage(), e); + } + } + }.execute(); } private static void showNotificationDialog(String envName) { @@ -263,13 +283,10 @@ public class VersionCheckUtils { Map pluginsNameMap = ReportHelper.getPluginNameMap(); for (int i = 0; i < remotePlugins.size(); i++) { remotePlugin = remotePlugins.getJSONObject(i); - if (ComparatorUtils.equals(remotePlugin.getString("running"), "false") || (remotePlugin.containsKey("sync") && !remotePlugin.getBoolean("sync"))) { + if (isPluginNeedIgnore(remotePlugin)) { continue; } String remotePluginID = remotePlugin.getString(ID); - if (pluginsNeedIgnore.contains(remotePluginID)) { - continue; - } if (localPluginsMap.containsKey(remotePluginID)) { if (ComparatorUtils.equals(localPluginsMap.get(remotePluginID).getVersion(), remotePlugin.getString(VERSION))) { continue; @@ -290,6 +307,12 @@ public class VersionCheckUtils { return differentPlugins; } + private static boolean isPluginNeedIgnore(JSONObject remotePlugin) { + return ComparatorUtils.equals(remotePlugin.getString(RUNNING), "false") || (remotePlugin.containsKey(SYNC) && !remotePlugin.getBoolean(SYNC)) + || (remotePlugin.containsKey(GROUP) && ComparatorUtils.equals(remotePlugin.getString(GROUP), BI) || remotePlugin.getString(ID).startsWith(BIPREFIX) + || pluginsNeedIgnore.contains(remotePlugin.getString(ID))); + } + public static JSONArray syncPlugins(JSONArray differentPlugins) { Set uninstallFailed = uninstallPlugins(differentPlugins); List plugins = getSyncPlugins(differentPlugins, uninstallFailed); diff --git a/designer-base/src/main/java/com/fr/design/web/CustomIconPane.java b/designer-base/src/main/java/com/fr/design/web/CustomIconPane.java index 9e03dcc9dc..564b09d467 100644 --- a/designer-base/src/main/java/com/fr/design/web/CustomIconPane.java +++ b/designer-base/src/main/java/com/fr/design/web/CustomIconPane.java @@ -4,14 +4,14 @@ import com.fr.base.BaseUtils; import com.fr.base.GraphHelper; import com.fr.base.Icon; import com.fr.base.IconManager; -import com.fr.design.designer.IntervalConstants; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ifilechooser.FileChooserArgs; +import com.fr.design.gui.ifilechooser.FileChooserFactory; import com.fr.design.gui.ifilechooser.FileChooserProvider; -import com.fr.design.gui.ifilechooser.JavaFxNativeFileChooser; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.iscrollbar.UIScrollBar; import com.fr.design.gui.itextarea.DescriptionTextArea; @@ -30,23 +30,35 @@ import com.fr.stable.ListMap; import com.fr.stable.StringUtils; import com.fr.transaction.Configurations; import com.fr.transaction.WorkerFacade; -import javafx.stage.FileChooser; -import javax.swing.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Window; +import javax.swing.ButtonGroup; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JToggleButton; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.plaf.basic.BasicButtonUI; -import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; /** * carl:自定义Icon编辑 @@ -414,7 +426,7 @@ public class CustomIconPane extends BasicPane { browseButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - onBrowseButtonClicked(); + onBrowseButtonClicked(SwingUtilities.getWindowAncestor(EditIconDialog.this)); } }); @@ -449,12 +461,11 @@ public class CustomIconPane extends BasicPane { this.add(centerPane, BorderLayout.CENTER); } - private void onBrowseButtonClicked() { + private void onBrowseButtonClicked(Window parent) { // carl:不知道是否只要png格式,反正导出时全部都转成png了 - FileChooserProvider fileChooserProvider = new JavaFxNativeFileChooser.Builder(). - filter("Icon Image File", "*.jpg", "*.jpeg", "*.png", "*.gif"). - build(); - if (JFileChooser.APPROVE_OPTION == fileChooserProvider.showDialog(DesignerContext.getDesignerFrame())) { + FileChooserProvider fileChooserProvider = FileChooserFactory.createFileChooser(FileChooserArgs.newBuilder(). + setFilter("Icon Image File", "*.jpg", "*.jpeg", "*.png", "*.gif").build()); + if (JFileChooser.APPROVE_OPTION == fileChooserProvider.showDialog(parent)) { String path = fileChooserProvider.getSelectedFile().getAbsolutePath(); // 图片存储有最大值48*48限制,没有超过最大值时,按原图大小存储,超过最大值后,压缩至最大值存储 Image image = BaseUtils.readImage(path); diff --git a/designer-base/src/main/java/com/fr/design/widget/WidgetBoundsPaneFactory.java b/designer-base/src/main/java/com/fr/design/widget/WidgetBoundsPaneFactory.java index ae3dfc2557..2b2dcc532c 100644 --- a/designer-base/src/main/java/com/fr/design/widget/WidgetBoundsPaneFactory.java +++ b/designer-base/src/main/java/com/fr/design/widget/WidgetBoundsPaneFactory.java @@ -46,12 +46,12 @@ public class WidgetBoundsPaneFactory { private static final int RIGHT_PANE_WIDTH = 145; - public static UIExpandablePane createBoundsPane(UISpinner width, UISpinner height, JComponent ratioLocked) { + public static UIExpandablePane createBoundsPane(UISpinner width, UISpinner height, JComponent ratioLocked, NameAttribute nameAttribute) { JPanel boundsPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); double f = TableLayout.FILL; double p = TableLayout.PREFERRED; Component[][] components = new Component[][]{ - new Component[]{FRWidgetFactory.createLineWrapLabel(Toolkit.i18nText("Fine-Design_Basic_Component_Size")), + new Component[]{FRWidgetFactory.createLineWrapLabel(nameAttribute.getSizeName()), ratioLocked != null ? createRightPane(width, ratioLocked, height) : createRightPane(width, height)}, new Component[]{null, createRightPane(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Tree_Width"), SwingConstants.CENTER), new UILabel(Toolkit.i18nText("Fine-Design_Basic_Tree_Height"), SwingConstants.CENTER))}, }; @@ -65,7 +65,7 @@ public class WidgetBoundsPaneFactory { } public static UIExpandablePane createBoundsPane(UISpinner width, UISpinner height) { - return createBoundsPane(width, height, null); + return createBoundsPane(width, height, null, NameAttribute.DEFAULT); } public static JPanel createRightPane(Component com1, Component com2) { diff --git a/designer-base/src/main/java/com/fr/design/widget/component/NumberEditorValidatePane.java b/designer-base/src/main/java/com/fr/design/widget/component/NumberEditorValidatePane.java index d77e1e9000..d10f58e185 100644 --- a/designer-base/src/main/java/com/fr/design/widget/component/NumberEditorValidatePane.java +++ b/designer-base/src/main/java/com/fr/design/widget/component/NumberEditorValidatePane.java @@ -1,6 +1,10 @@ package com.fr.design.widget.component; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.beans.ErrorMsgTextFieldAdapter; +import com.fr.design.beans.UITextFieldAdapter; import com.fr.design.designer.IntervalConstants; +import com.fr.design.fun.TextFieldAdapterProvider; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ispinner.UISpinner; @@ -9,6 +13,7 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.form.ui.NumberEditor; +import com.fr.log.FineLoggerFactory; import com.fr.stable.AssistUtils; import com.fr.stable.StringUtils; @@ -21,6 +26,9 @@ import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + /** * Created by kerry on 2017/9/10. @@ -35,7 +43,7 @@ public class NumberEditorValidatePane extends JPanel { private UISpinner minValueSpinner; private UISpinner decimalLength; private JPanel limitNumberPane; - private UITextField errorMsgTextField; + private ErrorMsgTextFieldAdapter errorMsgTextField; private JPanel errorMsgTextFieldPane; private ActionListener allowDecimalsListener; @@ -97,12 +105,35 @@ public class NumberEditorValidatePane extends JPanel { int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}; JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_L2, IntervalConstants.INTERVAL_L1); this.add(panel); + decimalLength.getTextField().addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + // Digit only + if (isDigit(e)) { + } else { + e.consume(); + } + } + }); + } + private boolean isDigit(KeyEvent e){ + return e.getKeyChar() >= KeyEvent.VK_0 && e.getKeyChar() <= KeyEvent.VK_9; } - private void initErrorMsgPane() { - errorMsgTextField = new UITextField(); + TextFieldAdapterProvider provider = ExtraDesignClassManager.getInstance().getSingle(TextFieldAdapterProvider.XML_TAG); + if (provider != null) { + try { + errorMsgTextField = provider.createTextFieldAdapter(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + errorMsgTextField = new UITextFieldAdapter(); + } + } else { + errorMsgTextField = new UITextFieldAdapter(); + } + errorMsgTextFieldPane = TableLayoutHelper.createGapTableLayoutPane( - new Component[][]{new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Widget_Error_Tip")), errorMsgTextField}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L2, IntervalConstants.INTERVAL_L1); + new Component[][]{new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Widget_Error_Tip")), errorMsgTextField.getErrorMsgTextField()}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L2, IntervalConstants.INTERVAL_L1); } diff --git a/designer-base/src/main/java/com/fr/design/worker/open/OpenWorker.java b/designer-base/src/main/java/com/fr/design/worker/open/OpenWorker.java index 819660a99d..40e6683eb5 100644 --- a/designer-base/src/main/java/com/fr/design/worker/open/OpenWorker.java +++ b/designer-base/src/main/java/com/fr/design/worker/open/OpenWorker.java @@ -7,12 +7,14 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrameFileDealerPane; import com.fr.design.mainframe.JTemplate; +import com.fr.design.utils.DesignUtils; import com.fr.design.worker.WorkerManager; import com.fr.exception.DecryptTemplateException; import com.fr.file.FILE; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; import javax.swing.JOptionPane; import javax.swing.SwingWorker; import javax.swing.UIManager; @@ -61,7 +63,7 @@ public class OpenWorker extends SwingWorker { } catch (CancellationException ignored) { return; } catch (Throwable t) { - processFailed(); + processFailed(StringUtils.EMPTY); Throwable cause = t.getCause(); if (cause instanceof DecryptTemplateException) { FineJOptionPane.showMessageDialog( @@ -91,6 +93,11 @@ public class OpenWorker extends SwingWorker { if (slowly && templateCallable != null) { try { JTemplate book = templateCallable.call(); + if (inValidDesigner(book)) { + String text = Toolkit.i18nText("Fine-Design_Report_Template_Version_Not_Match", DesignUtils.parseVersion(book.getTarget().getDesignerVersion())); + processFailed(text); + return; + } FILE tplFile = book.getEditingFILE(); JTemplate currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); // 当前tab页是正在打开的模板 @@ -117,11 +124,21 @@ public class OpenWorker extends SwingWorker { WorkerManager.getInstance().removeWorker(taskName); } - private void processFailed() { + private boolean inValidDesigner(JTemplate jt) { + return jt.isOldDesigner(false) || (!jt.isJWorkBook() && jt.isNewDesigner(false)); + } + + private void processFailed(String text) { this.template.setOpenFailed(true); this.template.setOpening(false); - DesignerContext.getDesignerFrame().getCenterTemplateCardPane().showOpenFailedCover(); - DesignerFrameFileDealerPane.getInstance().stateChange(); + JTemplate currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + // 需要判断当前打开的模板是不是异步执行后失败的模板 是的话立即展示失败后的提示内容 否则只设置下失败的提示内容 + if (ComparatorUtils.equals(currentTemplate.getEditingFILE().getName(), this.template.getEditingFILE().getName())) { + DesignerContext.getDesignerFrame().getCenterTemplateCardPane().showOpenFailedCover(text); + DesignerFrameFileDealerPane.getInstance().stateChange(); + } else { + this.template.setTemplateOpenFailedTip(text); + } WorkerManager.getInstance().removeWorker(taskName); } diff --git a/designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java b/designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java new file mode 100644 index 0000000000..31c622ab3a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java @@ -0,0 +1,70 @@ +package com.fr.design.worker.save; + +import com.fr.common.exception.ThrowableHandler; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.general.IOUtils; +import com.fr.workspace.exception.DiskSpaceFullException; +import java.awt.Frame; +import javax.swing.JOptionPane; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2021/12/7 + */ +public class SaveFailureHandler implements ThrowableHandler { + + private static final SaveFailureHandler INSTANCE = new SaveFailureHandler(); + + public static SaveFailureHandler getInstance() { + return INSTANCE; + } + + @Override + public boolean process(Throwable e) { + for (Handler handler : Handler.values()) { + if (handler.process(e)) { + break; + } + } + return true; + } + + public enum Handler implements ThrowableHandler { + + FullDisk { + @Override + public boolean process(Throwable e) { + if (e.getCause() instanceof DiskSpaceFullException + || e instanceof DiskSpaceFullException + || e.getCause().getCause() instanceof DiskSpaceFullException) { + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine_Design_Template_Save_Failed_By_Full_Disk"), + Toolkit.i18nText("Fine-Design_Basic_Alert"), + JOptionPane.WARNING_MESSAGE, + IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png")); + return true; + } + return false; + } + }, + + Other { + @Override + public boolean process(Throwable e) { + boolean minimized = (DesignerContext.getDesignerFrame().getExtendedState() & Frame.ICONIFIED ) != 0; + FineJOptionPane.showMessageDialog( + minimized ? null : DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine-Design-Basic_Save_Failure"), + Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), + JOptionPane.ERROR_MESSAGE); + return true; + } + }; + + + + } +} \ No newline at end of file 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 f47a4f88e7..c7a962c259 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 @@ -55,12 +55,7 @@ public class SaveWorker extends SwingWorker { } catch (Exception e) { processResult(); FineLoggerFactory.getLogger().error(e.getMessage(), e); - boolean minimized = (DesignerContext.getDesignerFrame().getExtendedState() & Frame.ICONIFIED ) != 0; - FineJOptionPane.showMessageDialog( - minimized ? null : DesignerContext.getDesignerFrame(), - Toolkit.i18nText("Fine-Design-Basic_Save_Failure"), - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), - JOptionPane.ERROR_MESSAGE); + SaveFailureHandler.getInstance().process(e); return; } processResult(); diff --git a/designer-base/src/main/java/com/fr/env/ErrorDialog.java b/designer-base/src/main/java/com/fr/env/ErrorDialog.java index be91955f2f..a26c673a45 100644 --- a/designer-base/src/main/java/com/fr/env/ErrorDialog.java +++ b/designer-base/src/main/java/com/fr/env/ErrorDialog.java @@ -39,7 +39,7 @@ public class ErrorDialog extends JDialog implements ActionListener { messagePanel.setBorder(BorderFactory.createEmptyBorder(5,0,0,0)); MessageWithLink messageWithLink = new MessageWithLink(message + ",", Toolkit.i18nText("Fine-Design_Basic_Sync_Help"), CloudCenter.getInstance().acquireUrlByKind("help.replacejars", "https://help.fanruan.com/finereport/doc-view-3268.html")); - messageWithLink.setPreferredSize(new Dimension(108, 20)); + messageWithLink.setPreferredSize(new Dimension(150, 20)); JPanel messageLinkPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); messageLinkPane.setBorder(BorderFactory.createEmptyBorder(5, 8, 5, 0)); messageLinkPane.add(messageWithLink); diff --git a/designer-base/src/main/java/com/fr/env/HelpLink.java b/designer-base/src/main/java/com/fr/env/HelpLink.java index c717ce6ea6..b5bd2210f0 100644 --- a/designer-base/src/main/java/com/fr/env/HelpLink.java +++ b/designer-base/src/main/java/com/fr/env/HelpLink.java @@ -1,7 +1,7 @@ package com.fr.env; -import com.fr.general.locale.LocaleCenter; -import com.fr.general.locale.LocaleMark; + +import com.fr.i18n.UrlI18nManager; import com.fr.locale.InterProviderFactory; import com.fr.stable.StringUtils; import java.util.HashMap; @@ -18,12 +18,13 @@ public class HelpLink { public static String getLink(String solution) { Map map = new HashMap<>(); - LocaleMark linkMark = LocaleCenter.getMark(RemoteDesignLocaleMark.class); - String link = linkMark.getValue(); + String link = UrlI18nManager.getInstance().getI18nUrl("help.remote.design"); map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_Change_PassWord"), StringUtils.EMPTY); map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_Cert_Error_Solution"), link); map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_Connection_Unknown_Error_Solution"), link); map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_NetWork_Connection_Error_Solution"), link); + map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_Redirect_Solution"), link); + map.put(InterProviderFactory.getProvider().getLocText("Fine-Core_Remote_Design_NetWork_Config_Solution"), link); return map.get(solution); } diff --git a/designer-base/src/main/java/com/fr/env/RemoteEnvPane.java b/designer-base/src/main/java/com/fr/env/RemoteEnvPane.java index 56f90e804e..31bdaa979b 100644 --- a/designer-base/src/main/java/com/fr/env/RemoteEnvPane.java +++ b/designer-base/src/main/java/com/fr/env/RemoteEnvPane.java @@ -9,9 +9,10 @@ import com.fr.design.fun.DesignerEnvProcessor; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ifilechooser.FileChooserArgs; +import com.fr.design.gui.ifilechooser.FileChooserFactory; import com.fr.design.gui.ifilechooser.FileChooserProvider; import com.fr.design.gui.ifilechooser.FileSelectionMode; -import com.fr.design.gui.ifilechooser.JavaFxNativeFileChooser; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ipasswordfield.UIPassWordField; import com.fr.design.gui.ipasswordfield.UIPasswordFieldWithFixedLength; @@ -564,7 +565,8 @@ public class RemoteEnvPane extends BasicBeanPane { fileChooserButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { - FileChooserProvider fileChooserProvider = new JavaFxNativeFileChooser.Builder().fileSelectionMode(FileSelectionMode.FILE).build(); + FileChooserProvider fileChooserProvider = FileChooserFactory.createFileChooser(FileChooserArgs.newBuilder(). + setFileSelectionMode(FileSelectionMode.FILE).build()); int saveValue = fileChooserProvider.showDialog(SwingUtilities.getWindowAncestor(RemoteEnvPane.this)); if (saveValue == JFileChooser.APPROVE_OPTION) { File selectedFile = fileChooserProvider.getSelectedFile(); diff --git a/designer-base/src/main/java/com/fr/env/SyncFailedPluginsDialog.java b/designer-base/src/main/java/com/fr/env/SyncFailedPluginsDialog.java index 8117f87395..fd4b98e33e 100644 --- a/designer-base/src/main/java/com/fr/env/SyncFailedPluginsDialog.java +++ b/designer-base/src/main/java/com/fr/env/SyncFailedPluginsDialog.java @@ -5,6 +5,7 @@ import com.fr.design.dialog.link.MessageWithLink; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.i18n.DesignSizeI18nManager; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; @@ -62,7 +63,7 @@ public class SyncFailedPluginsDialog extends JDialog { JPanel messagePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); MessageWithLink messageWithLink = new MessageWithLink(Toolkit.i18nText("Fine-Design_Basic_Sync_Plugin_Fail_Suggestion"),Toolkit.i18nText("Fine-Design_Basic_Sync_Deal_Immediately"), CloudCenter.getInstance().acquireUrlByKind("help.installplugins", "https://help.fanruan.com/finereport/doc-view-2198.html")); - messageWithLink.setPreferredSize(new Dimension(316, 20)); + messageWithLink.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.env.SyncFailedPluginsDialog.messageWithLink")); messagePane.add(messageWithLink); messagePane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 0)); diff --git a/designer-base/src/main/java/com/fr/file/StashedFILE.java b/designer-base/src/main/java/com/fr/file/StashedFILE.java index 454433874e..48f00f95b2 100644 --- a/designer-base/src/main/java/com/fr/file/StashedFILE.java +++ b/designer-base/src/main/java/com/fr/file/StashedFILE.java @@ -1,5 +1,9 @@ package com.fr.file; +import com.fr.base.io.XMLEncryptUtils; +import com.fr.io.EncryptUtils; +import com.fr.io.FineEncryptUtils; +import com.fr.stable.StringUtils; import javax.swing.Icon; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -11,10 +15,16 @@ public class StashedFILE extends AbstractFILE { private FILE file; private byte[] content; + private String suffix; public StashedFILE(FILE file, byte[] content) { + this(file, content, null); + } + + public StashedFILE(FILE file, byte[] content, String suffix) { this.file = file; this.content = content; + this.suffix = suffix; } @Override @@ -54,7 +64,12 @@ public class StashedFILE extends AbstractFILE { @Override public InputStream asInputStream() throws Exception { - return new ByteArrayInputStream(content); + ByteArrayInputStream in = new ByteArrayInputStream(content); + return needDecode() ? XMLEncryptUtils.decodeInputStream(EncryptUtils.decodeInputStream(FineEncryptUtils.decode(in))) : in; + } + + private boolean needDecode() { + return StringUtils.isNotEmpty(suffix) && (suffix.endsWith(".cpt") || suffix.endsWith(".frm")); } @Override 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 b3945d0d7f..d913f7a799 100644 --- a/designer-base/src/main/java/com/fr/start/BaseDesigner.java +++ b/designer-base/src/main/java/com/fr/start/BaseDesigner.java @@ -16,6 +16,7 @@ import com.fr.design.mainframe.DesignerFrame; import com.fr.design.mainframe.toolbar.ToolBarMenuDock; import com.fr.design.monitor.DesignerLifecycleMonitorContext; import com.fr.design.ui.util.UIUtil; +import com.fr.design.versioncheck.VersionCheckUtils; import com.fr.event.Event; import com.fr.event.EventDispatcher; import com.fr.event.Listener; @@ -84,10 +85,19 @@ public abstract class BaseDesigner extends ToolBarMenuDock { eventPipe.fire(new CarryMessageEvent(ReportState.STOP.getValue())); } collectUserInformation(); + checkVersion(); } }); } + private void checkVersion() { + try { + VersionCheckUtils.showVersionCheckDialog(DesignerEnvManager.getEnvManager().getCurEnvName()); + } catch (Exception e) { + FineLoggerFactory.getLogger().warn("Check Service Failed"); + } + } + public void show() { UIUtil.invokeLaterIfNeeded(this::refreshTemplateTree); } diff --git a/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java b/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java index 854d260bf5..5772d4e139 100644 --- a/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java +++ b/designer-base/src/main/java/com/fr/start/server/FineEmbedServerActivator.java @@ -13,7 +13,6 @@ import com.fr.third.springframework.web.context.support.AnnotationConfigWebAppli import com.fr.workspace.WorkContext; import org.apache.catalina.Context; import org.apache.catalina.LifecycleException; -import org.apache.catalina.Wrapper; import org.apache.catalina.loader.WebappLoader; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.webresources.StandardRoot; @@ -78,10 +77,6 @@ public class FineEmbedServerActivator extends Activator { String contextPath = "/" + ProductConstants.getAppFolderName(); final Context context = tomcat.addContext(contextPath, docBase); context.setResources(new StandardRoot(context)); - Wrapper servlet = Tomcat.addServlet(context, "DruidStatView", "com.fr.third.alibaba.druid.support.http.StatViewServlet"); - context.addServletMappingDecoded("/druid/*", "DruidStatView"); - servlet.setLoadOnStartup(1); - servlet.setOverridable(true); Tomcat.initWebappDefaults(context); //覆盖tomcat的WebAppClassLoader context.setLoader(new FRTomcatLoader()); diff --git a/designer-base/src/main/resources/com/fr/design/config/default b/designer-base/src/main/resources/com/fr/design/config/default new file mode 100644 index 0000000000..f808a82379 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/config/default @@ -0,0 +1 @@ +Fine-Designer_Login=i7hP48WAcuTrmxfN diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties index ef851ffe3f..786fe2ad0c 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties @@ -1,10 +1,15 @@ com.fr.design.mainframe.check.CheckButton=305*118 com.fr.design.mainframe.check.CheckFontInfoDialog.collapse=630*185 -com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink=630*31 +com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink=570*31 com.fr.design.mainframe.check.CheckFontInfoDialog.unfold=630*280 com.fr.design.report.ReportColumnsPane=800*600 com.fr.env.RemoteEnvPane.dialog=458*132 com.fr.design.version.check.dialog=490*95 com.fr.design.version.detail.label=750*30 com.fr.design.version.detail.dialog=900*500 -com.fr.design.web.pane.text.field=450*20 \ No newline at end of file +com.fr.env.SyncFailedPluginsDialog.messageWithLink=316*36 +com.fr.design.web.pane.text.field=450*20 +com.fr.design.actions.server.dialog=800*630 +com.fr.design.report.fit.templatePane.dialog=800*400 +com.fr.design.report.fit.firstColumn=120*20 +com.fr.design.report.fit.column=160*20 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties index 379c257449..0956fa79d7 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties @@ -1,9 +1,14 @@ com.fr.design.mainframe.check.CheckButton=280*118 com.fr.design.mainframe.check.CheckFontInfoDialog.collapse=610*185 -com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink=610*31 +com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink=550*31 com.fr.design.mainframe.check.CheckFontInfoDialog.unfold=610*280 com.fr.env.RemoteEnvPane.dialog=458*132 com.fr.design.version.check.dialog=430*95 com.fr.design.version.detail.label=650*30 com.fr.design.version.detail.dialog=800*500 -com.fr.design.web.pane.text.field=400*20 \ No newline at end of file +com.fr.env.SyncFailedPluginsDialog.messageWithLink=316*36 +com.fr.design.web.pane.text.field=400*20 +com.fr.design.actions.server.dialog=700*630 +com.fr.design.report.fit.templatePane.dialog=600*400 +com.fr.design.report.fit.firstColumn=170*20 +com.fr.design.report.fit.column=100*20 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties index 62ee87a7c4..17031793ff 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties @@ -1,9 +1,14 @@ com.fr.design.mainframe.check.CheckButton=230*118 -com.fr.design.mainframe.check.CheckFontInfoDialog.collapse=490*185 +com.fr.design.mainframe.check.CheckFontInfoDialog.collapse=550*185 com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink=490*35 -com.fr.design.mainframe.check.CheckFontInfoDialog.unfold=490*280 +com.fr.design.mainframe.check.CheckFontInfoDialog.unfold=550*280 com.fr.env.RemoteEnvPane.dialog=458*132 com.fr.design.version.check.dialog=450*95 com.fr.design.version.detail.label=700*30 com.fr.design.version.detail.dialog=850*500 -com.fr.design.web.pane.text.field=450*20 \ No newline at end of file +com.fr.env.SyncFailedPluginsDialog.messageWithLink=316*36 +com.fr.design.web.pane.text.field=450*20 +com.fr.design.actions.server.dialog=700*630 +com.fr.design.report.fit.templatePane.dialog=600*400 +com.fr.design.report.fit.firstColumn=130*20 +com.fr.design.report.fit.column=100*20 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties index fff64947d9..931b79b44f 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties @@ -1,10 +1,15 @@ # \u9ED8\u8BA4\u4E3A\u7C7B\u7684\u5168\u9650\u5B9A\u540D\uFF08\u53EF\u81EA\u5B9A\u4E49key\uFF09= width * height com.fr.design.mainframe.check.CheckButton=250*118 com.fr.design.mainframe.check.CheckFontInfoDialog.collapse=385*185 -com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink=385*31 +com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink=325*31 com.fr.design.mainframe.check.CheckFontInfoDialog.unfold=385*280 com.fr.env.RemoteEnvPane.dialog=308*132 com.fr.design.version.check.dialog=230*95 com.fr.design.version.detail.label=450*30 com.fr.design.version.detail.dialog=600*500 -com.fr.design.web.pane.text.field=450*20 \ No newline at end of file +com.fr.env.SyncFailedPluginsDialog.messageWithLink=316*20 +com.fr.design.web.pane.text.field=450*20 +com.fr.design.actions.server.dialog=700*630 +com.fr.design.report.fit.templatePane.dialog=600*400 +com.fr.design.report.fit.firstColumn=80*20 +com.fr.design.report.fit.column=100*20 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties index 4b2de3f02c..8ea7fd7c26 100644 --- a/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties +++ b/designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties @@ -1,9 +1,14 @@ com.fr.design.mainframe.check.CheckButton=250*118 com.fr.design.mainframe.check.CheckFontInfoDialog.collapse=385*185 -com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink=385*31 +com.fr.design.mainframe.check.CheckFontInfoDialog.messageWithLink=325*31 com.fr.design.mainframe.check.CheckFontInfoDialog.unfold=385*280 com.fr.env.RemoteEnvPane.dialog=308*132 com.fr.design.version.check.dialog=230*95 com.fr.design.version.detail.label=450*30 com.fr.design.version.detail.dialog=600*500 -com.fr.design.web.pane.text.field=450*20 \ No newline at end of file +com.fr.env.SyncFailedPluginsDialog.messageWithLink=316*20 +com.fr.design.web.pane.text.field=450*20 +com.fr.design.actions.server.dialog=700*630 +com.fr.design.report.fit.templatePane.dialog=600*400 +com.fr.design.report.fit.firstColumn=80*20 +com.fr.design.report.fit.column=100*20 \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/bbs/studyPlan.png b/designer-base/src/main/resources/com/fr/design/images/bbs/studyPlan.png new file mode 100644 index 0000000000..1a27244653 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/bbs/studyPlan.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/bbs/studyPlan_normal.svg b/designer-base/src/main/resources/com/fr/design/images/bbs/studyPlan_normal.svg new file mode 100644 index 0000000000..0237b2e459 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/bbs/studyPlan_normal.svg @@ -0,0 +1 @@ +l \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/mainframe/openloading.png b/designer-base/src/main/resources/com/fr/design/images/mainframe/loading.png similarity index 100% rename from designer-base/src/main/resources/com/fr/design/images/mainframe/openloading.png rename to designer-base/src/main/resources/com/fr/design/images/mainframe/loading.png diff --git a/designer-base/src/main/resources/com/fr/design/images/platform/platform_normal.svg b/designer-base/src/main/resources/com/fr/design/images/platform/platform_normal.svg new file mode 100644 index 0000000000..ab95e95f3c --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/platform/platform_normal.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-base/src/main/resources/com/fr/design/standard/system/error_tips.svg b/designer-base/src/main/resources/com/fr/design/standard/system/error_tips.svg new file mode 100644 index 0000000000..900205215b --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/standard/system/error_tips.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/designer-base/src/test/java/com/fr/design/data/MapCompareUtilsTest.java b/designer-base/src/test/java/com/fr/design/data/MapCompareUtilsTest.java new file mode 100644 index 0000000000..1f1e60e2be --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/data/MapCompareUtilsTest.java @@ -0,0 +1,57 @@ +package com.fr.design.data; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author rinoux + * @version 10.0 + * Created by rinoux on 2022/3/28 + */ +public class MapCompareUtilsTest { + + @Test + public void contrastMapEntries() { + + + Map orig = new LinkedHashMap<>(); + + orig.put("aaa", "aaa"); + orig.put("bbb", "bbb"); + orig.put("ccc", "ccc"); + orig.put("ddd", "ddd"); + + + Map other = new LinkedHashMap<>(); + + other.put("aaa", "111"); + other.put("bbb", "bbb"); + other.put("ccc", "ccc"); + other.put("eee", "eee"); + + + MapCompareUtils.contrastMapEntries(orig, other, new MapCompareUtils.EventHandler() { + @Override + public void on(MapCompareUtils.EntryEventKind entryEventKind, String s, String s2) { + switch (entryEventKind) { + case UPDATED: + Assert.assertEquals(s, "aaa"); + Assert.assertEquals(s2, "111"); + break; + case REMOVED: + Assert.assertEquals(s, "ddd"); + break; + case ADDED: + Assert.assertEquals(s, "eee"); + Assert.assertEquals(s2, "eee"); + break; + default: + Assert.fail(); + } + } + }); + } +} \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/gui/itextfield/UINumberFieldTest.java b/designer-base/src/test/java/com/fr/design/gui/itextfield/UINumberFieldTest.java new file mode 100644 index 0000000000..17b0f547cc --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/gui/itextfield/UINumberFieldTest.java @@ -0,0 +1,44 @@ +package com.fr.design.gui.itextfield; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Destiny.Lin + * @version 10.0 + * created by Destiny.Lin on 2022-07-11 + */ +public class UINumberFieldTest { + + @Test + public void testUINumberFieldTest(){ + UINumberField uiNumberField = new UINumberField(); + uiNumberField.setFieldDocument(); + //异常输入测试 + uiNumberField.setText("-.1"); + Assert.assertEquals("",uiNumberField.getText()); + uiNumberField.setText(".-1"); + Assert.assertEquals("",uiNumberField.getText()); + uiNumberField.setText("1-"); + Assert.assertEquals("",uiNumberField.getText()); + uiNumberField.setText("1-1"); + Assert.assertEquals("",uiNumberField.getText()); + uiNumberField.setText("1 "); + Assert.assertEquals("",uiNumberField.getText()); + uiNumberField.setText(".1"); + Assert.assertEquals("",uiNumberField.getText()); + uiNumberField.setText("1 -"); + Assert.assertEquals("",uiNumberField.getText()); + + //正常输入测试 + uiNumberField.setText("0.1"); + Assert.assertEquals("0.1",uiNumberField.getText()); + uiNumberField.setText("1"); + Assert.assertEquals("1",uiNumberField.getText()); + uiNumberField.setText("-1.5"); + Assert.assertEquals("-1.5",uiNumberField.getText()); + uiNumberField.setText("-123.123"); + Assert.assertEquals("-123.123",uiNumberField.getText()); + + } +} diff --git a/designer-base/src/test/java/com/fr/design/mainframe/JTemplateNameHelperTest.java b/designer-base/src/test/java/com/fr/design/mainframe/JTemplateNameHelperTest.java index 032e715f60..6781f3de97 100644 --- a/designer-base/src/test/java/com/fr/design/mainframe/JTemplateNameHelperTest.java +++ b/designer-base/src/test/java/com/fr/design/mainframe/JTemplateNameHelperTest.java @@ -1,5 +1,6 @@ package com.fr.design.mainframe; +import com.fr.invoke.Reflect; import junit.framework.TestCase; /** @@ -20,4 +21,26 @@ public class JTemplateNameHelperTest extends TestCase { assertEquals("TEST2", name1); } + + public void testGetFileNameIndex() { + //正常情况 + assertEquals("1", Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "WorkBook", "WorkBook1").toString()); + + //正常情况 + assertEquals("8888888888", Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "WorkBook", "WorkBook8888888888").toString()); + + //正常情况 + assertEquals("88812214128888881231238123123", Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "WorkBook", "WorkBook88812214128888881231238123123").toString()); + + //前缀不匹配 + assertNull(Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "Work123", "WorkBook8888888888").get()); + + //前缀为空 + assertNull(Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "", "WorkBook8888888888").get()); + + //文件长度小于前缀 + assertNull(Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "WorkBook", "").get()); + + + } } diff --git a/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java b/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java index 8600a8c149..2d54fc8189 100644 --- a/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java +++ b/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java @@ -149,7 +149,7 @@ public class ChartTypeInterfaceManager implements ExtraChartDesignClassManagerPr public static WidgetOption[] initWidgetOption() { - String[] chartIDs = ChartTypeManager.getInstance().getAllChartIDs(); + String[] chartIDs = ChartTypeManager.getInstance().getChartIDs4Create(); ChartWidgetOption[] child = new ChartWidgetOption[chartIDs.length]; int index = 0; diff --git a/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java b/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java index a5937c1d9d..d31cd32088 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java @@ -31,7 +31,7 @@ import java.awt.Component; public class ChartTypePane extends ChartCommonWizardPane implements CallbackEvent { private static final long serialVersionUID = -1175602484968520546L; - private String[] chartIDs = ChartTypeManager.getInstanceWithCheck().getAllChartIDs(); + private String[] chartIDs = ChartTypeManager.getInstanceWithCheck().getChartIDs4Create(); private JList mainTypeList = null; private JList iconViewList = null; diff --git a/designer-chart/src/main/java/com/fr/design/chart/series/PlotSeries/MapCustomPane.java b/designer-chart/src/main/java/com/fr/design/chart/series/PlotSeries/MapCustomPane.java index 133e2fef74..a5351c74bf 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/series/PlotSeries/MapCustomPane.java +++ b/designer-chart/src/main/java/com/fr/design/chart/series/PlotSeries/MapCustomPane.java @@ -9,8 +9,9 @@ import com.fr.design.data.DesignTableDataManager; import com.fr.design.data.tabledata.wrapper.TableDataWrapper; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icombobox.FilterComboBox; +import com.fr.design.gui.ifilechooser.FileChooserArgs; +import com.fr.design.gui.ifilechooser.FileChooserFactory; import com.fr.design.gui.ifilechooser.FileChooserProvider; -import com.fr.design.gui.ifilechooser.JavaFxNativeFileChooser; import com.fr.design.gui.ilable.BoldFontTextLabel; import com.fr.design.gui.ilable.UILabel; import com.fr.design.mainframe.DesignerContext; @@ -19,8 +20,6 @@ import com.fr.general.ComparatorUtils; import com.fr.general.GeneralUtils; import com.fr.general.data.DataModel; import com.fr.log.FineLoggerFactory; -import com.fr.stable.StringUtils; -import org.apache.batik.swing.svg.SVGFileFilter; import javax.swing.JFileChooser; import javax.swing.JPanel; @@ -110,10 +109,12 @@ public class MapCustomPane extends BasicBeanPane implements AbstrctMapAt private ActionListener selectPictureActionListener = new ActionListener() { + @Override public void actionPerformed(ActionEvent evt) { - FileChooserProvider fileChooserProvider = new JavaFxNativeFileChooser.Builder(). - filter(".svg, .svgz", "*.svg", "*.svgz"). - currentDirectory(lastSelectPath).build(); + FileChooserProvider fileChooserProvider = FileChooserFactory.createFileChooser( + FileChooserArgs.newBuilder(). + setFilter(".svg, .svgz", "*.svg", "*.svgz"). + setSelectedPath(lastSelectPath).build()); int returnVal = fileChooserProvider.showDialog(DesignerContext.getDesignerFrame()); if (returnVal != JFileChooser.CANCEL_OPTION) { File selectedFile = fileChooserProvider.getSelectedFile(); diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/ChartPropertyPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/ChartPropertyPane.java index 90b0e88054..4efe977ff3 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/ChartPropertyPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/ChartPropertyPane.java @@ -16,7 +16,6 @@ import com.fr.design.gui.chart.ChartEditPaneProvider; import com.fr.design.gui.frpane.UITitlePanel; import com.fr.design.mainframe.chart.ChartEditPane; import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.stable.AssistUtils; import javax.swing.BorderFactory; import javax.swing.Icon; @@ -36,9 +35,6 @@ public class ChartPropertyPane extends BaseChartPropertyPane { protected ChartEditPane chartEditPane; - //ID一样的话 不用新建chartEditPane - private String currentID; - private ChartPropertyPane() { initComponent(); } @@ -50,12 +46,9 @@ public class ChartPropertyPane extends BaseChartPropertyPane { @Override public void updateChartEditPane(String plotID) { - if (!AssistUtils.equals(currentID, plotID)) { - chartEditPane = ChartTypeInterfaceManager.getInstance().getChartEditPane(plotID); - chartEditPane.setContainer(container); - currentID = plotID; - resetChartEditPane(); - } + chartEditPane = ChartTypeInterfaceManager.getInstance().getChartEditPane(plotID); + chartEditPane.setContainer(container); + resetChartEditPane(); } @Override diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java index d6acb929a7..4c1c1b008a 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/ChartEditPane.java @@ -4,9 +4,9 @@ package com.fr.design.mainframe.chart; import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.ChartCollection; import com.fr.chartx.attr.ChartProvider; +import com.fr.common.listener.ManageDsListenerRegisterListener; import com.fr.design.ChartTypeInterfaceManager; import com.fr.design.beans.FurtherBasicBeanPane; -import com.fr.design.data.DesignTableDataManager; import com.fr.design.data.tabledata.Prepare4DataSourceChange; import com.fr.design.dialog.BasicPane; import com.fr.design.gui.chart.ChartEditPaneActionListener; @@ -22,9 +22,11 @@ import com.fr.design.mainframe.chart.gui.ChartStylePane; import com.fr.design.mainframe.chart.gui.ChartTypePane; import com.fr.design.mainframe.chart.gui.type.AbstractChartTypePane; import com.fr.design.mainframe.chart.info.ChartInfoCollector; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.form.main.Form; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; +import com.fr.plugin.chart.custom.VanChartCustomPlot; import com.fr.plugin.chart.vanchart.VanChart; import javax.swing.JPanel; @@ -118,6 +120,10 @@ public class ChartEditPane extends BasicPane implements AttributeChange, Prepare this.listenerList.remove(ChartEditPaneActionListener.class, l); } + public void resetLastChartCollection() { + this.lastCollection = null; + } + private void fireAttributeChange(ChartCollection chartCollection) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); @@ -330,7 +336,10 @@ public class ChartEditPane extends BasicPane implements AttributeChange, Prepare String chartID = chart.getID(); boolean currentPane = ChartTypeInterfaceManager.getInstance().isUseDefaultPane(chartID); - return (currentPane != isDefaultPane) || (!currentPane && lastIndex != currentIndex); + boolean duchampCustomChart = ChartEditContext.duchampMode() + && VanChartCustomPlot.VAN_CHART_CUSTOM_PLOT_ID.equals(chartID); + + return (currentPane != isDefaultPane) || (!currentPane && lastIndex != currentIndex) || duchampCustomChart; } return false; } @@ -398,14 +407,14 @@ public class ChartEditPane extends BasicPane implements AttributeChange, Prepare * 数据集改变的事件监听 */ public void registerDSChangeListener() { - DesignTableDataManager.addDsChangeListener(new ChangeListener() { + this.addAncestorListener(new ManageDsListenerRegisterListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { AbstractChartAttrPane attrPane = paneList.get(tabsHeaderIconPane.getSelectedIndex()); - if (attrPane.isShowing()) { + if (attrPane.isShowing() && collection != null) { attrPane.refreshChartDataPane(collection); } } - }); + })); } public boolean isInForm() { diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypePane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypePane.java index 985ee28afa..2eea49f16d 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChartTypePane.java @@ -4,6 +4,7 @@ import com.fr.chart.chartattr.ChartCollection; import com.fr.chart.charttypes.ChartTypeManager; import com.fr.chartx.attr.ChartProvider; import com.fr.design.ChartTypeInterfaceManager; +import com.fr.design.base.mode.DesignModeContext; import com.fr.design.beans.FurtherBasicBeanPane; import com.fr.design.dialog.BasicScrollPane; import com.fr.design.dialog.DialogActionAdapter; @@ -18,6 +19,7 @@ import com.fr.design.mainframe.chart.gui.item.FlexibleComboBox; import com.fr.design.mainframe.chart.gui.item.ItemEventType; import com.fr.design.mainframe.chart.gui.type.AbstractChartTypePane; import com.fr.design.mainframe.chart.mode.ChartEditContext; +import com.fr.design.mainframe.chart.mode.ChartEditMode; import com.fr.design.module.DesignModuleFactory; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; @@ -173,7 +175,7 @@ public class ChartTypePane extends AbstractChartAttrPane { Map>> allChartTypePane, ActionListener autoButtonListener) { - String[] chartIDs = ChartTypeManager.getInstance().getAllChartIDsIncludeDisabled(); + String[] chartIDs = ChartTypeManager.getInstance().getAllChartIDs(); for (String id : chartIDs) { @@ -288,7 +290,9 @@ public class ChartTypePane extends AbstractChartAttrPane { Map.Entry> entry = iterator.next(); String plotID = entry.getKey(); if (ignore || ChartTypeManager.enabledChart(plotID)) { - cards.add(entry.getValue()); + if (ChartTypeManager.getInstance().isShowInDesigner(plotID)) { + cards.add(entry.getValue()); + } } } @@ -310,7 +314,9 @@ public class ChartTypePane extends AbstractChartAttrPane { //第一步就是重构cards cards.clear(); - if (enabledChart) { + if (ChartEditContext.duchampMode()) { + addOnePlotIDCards(priority, chartID); + } else if (enabledChart) { if (collection.getChartCount() == 1) { addAllCards(); } else { diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPane.java index 9a906cc7c0..d07ec476e9 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPane.java @@ -13,6 +13,7 @@ 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.mainframe.chart.mode.ChartEditContext; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.FRFont; import com.fr.general.GeneralUtils; @@ -29,16 +30,21 @@ public class ChartTextAttrPane extends BasicPane { private static final long serialVersionUID = 6731679928019436869L; public static final int FONT_START = 6; public static final int FONT_END = 72; + public static final int FONT_END_4_DUCHAMP = 200; private UIComboBox fontNameComboBox; private UIComboBox fontSizeComboBox; private UIToggleButton bold; private UIToggleButton italic; private UIColorButton fontColor; public static Integer[] FONT_SIZES = new Integer[FONT_END - FONT_START + 1]; + private static Integer[] FONT_SIZES_4_DUCHAMP = new Integer[FONT_END_4_DUCHAMP - FONT_START + 1]; static { for (int i = FONT_START; i <= FONT_END; i++) { FONT_SIZES[i - FONT_START] = i; } + for (int i = FONT_START; i <= FONT_END_4_DUCHAMP; i++) { + FONT_SIZES_4_DUCHAMP[i - FONT_START] = i; + } } public ChartTextAttrPane() { @@ -176,7 +182,7 @@ public class ChartTextAttrPane extends BasicPane { } protected Object[] getFontSizeComboBoxModel() { - return FONT_SIZES; + return ChartEditContext.duchampMode() ? FONT_SIZES_4_DUCHAMP : FONT_SIZES; } protected void initState() { diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPaneWithAuto.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPaneWithAuto.java index 292d83c9e7..af157afca2 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPaneWithAuto.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/style/ChartTextAttrPaneWithAuto.java @@ -4,23 +4,30 @@ import com.fr.chart.base.ChartConstants; import com.fr.design.gui.ibutton.UIColorButton; import com.fr.design.gui.ibutton.UIColorButtonWithAuto; import com.fr.design.i18n.Toolkit; -import com.fr.plugin.chart.type.FontAutoType; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.general.ComparatorUtils; import com.fr.general.FRFont; import com.fr.general.GeneralUtils; +import com.fr.plugin.chart.type.FontAutoType; public class ChartTextAttrPaneWithAuto extends ChartTextAttrPane { private static final String AUTO = Toolkit.i18nText("Fine-Design_Basic_ChartF_Auto"); private FontAutoType type; public static String[] FONT_SIZES_WITH_AUTO = new String[FONT_END - FONT_START + 2]; + private static String[] FONT_SIZES_WITH_AUTO_4_DUCHAMP = new String[FONT_END_4_DUCHAMP - FONT_START + 2]; static { FONT_SIZES_WITH_AUTO[0] = AUTO; + FONT_SIZES_WITH_AUTO_4_DUCHAMP[0] = AUTO; for (int i = 1; i < FONT_SIZES_WITH_AUTO.length; i++) { FONT_SIZES_WITH_AUTO[i] = FONT_START + i - 1 + ""; } + + for (int i = 1; i < FONT_SIZES_WITH_AUTO_4_DUCHAMP.length; i++) { + FONT_SIZES_WITH_AUTO_4_DUCHAMP[i] = FONT_START + i - 1 + ""; + } } public ChartTextAttrPaneWithAuto(FontAutoType type) { @@ -42,7 +49,9 @@ public class ChartTextAttrPaneWithAuto extends ChartTextAttrPane { } protected Object[] getFontSizeComboBoxModel() { - return isFontSizeAuto() ? FONT_SIZES_WITH_AUTO : FONT_SIZES; + return isFontSizeAuto() + ? (ChartEditContext.duchampMode() ? FONT_SIZES_WITH_AUTO_4_DUCHAMP : FONT_SIZES_WITH_AUTO) + : super.getFontSizeComboBoxModel(); } protected float updateFontSize() { 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 6529efce05..8a0c2c5cb5 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 @@ -29,8 +29,6 @@ import javax.swing.JPanel; import javax.swing.SwingConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.util.ArrayList; -import java.util.List; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -42,6 +40,8 @@ import java.awt.LayoutManager; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; public class UIColorPickerPane extends BasicPane implements UIObserver { private static final int MARGIN_TOP = 7; @@ -691,14 +691,18 @@ public class UIColorPickerPane extends BasicPane implements UIObserver { fillStyleCombox.setSelectObject(mainColor); designTypeButtonGroup.setSelectedIndex(hotAreaColor.getUseType()); - double value = (double) hotAreaColor.getAreaNumber(); + int value = hotAreaColor.getAreaNumber(); UIColorPickerPane.this.add(textGroup); UIColorPickerPane.this.add(colorGroup); Color[] colors = hotAreaColor.initColor(); BaseFormula[] values = hotAreaColor.initValues(); + if (value != colors.length && hotAreaColor.getUseType() == MapHotAreaColor.CUSTOM) { + colors = getColorArray(mainColor, value); + values = getValueArray(value); + } refreshGroupPane(colors, values); this.initContainerLister(); - regionNumPane.populateBean(value); + regionNumPane.populateBean((double) value); refreshPane(); } diff --git a/designer-chart/src/main/java/com/fr/design/module/ChartEmptyDataStylePane.java b/designer-chart/src/main/java/com/fr/design/module/ChartEmptyDataStylePane.java index 31718fda82..4f11af9102 100644 --- a/designer-chart/src/main/java/com/fr/design/module/ChartEmptyDataStylePane.java +++ b/designer-chart/src/main/java/com/fr/design/module/ChartEmptyDataStylePane.java @@ -14,8 +14,8 @@ import com.fr.design.style.background.image.ImageFileChooser; import com.fr.design.style.background.image.ImagePreviewPane; import com.fr.design.utils.ImageUtils; import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.general.GeneralContext; -import com.fr.general.IOUtils; +import com.fr.general.locale.image.LocaleImageFactory; +import com.fr.general.locale.image.LocaleImageMark; import com.fr.stable.Constants; import com.fr.stable.CoreGraphHelper; import com.fr.stable.StringUtils; @@ -26,7 +26,6 @@ import javax.swing.JFileChooser; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingWorker; -import java.io.File; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; @@ -35,6 +34,8 @@ import java.awt.GridLayout; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.io.File; /** * Created by mengao on 2017/11/23. @@ -61,10 +62,11 @@ public class ChartEmptyDataStylePane extends AbstractAttrNoScrollPane { private Image emptyDataImage = DEFAULT_EMPTY_DATA_IMAGE; private SwingWorker imageWorker; + private static final String EMPTY_DATA_IMAGE_PATH = "/com/fr/design/images/emptydata.png"; static { - DEFAULT_EMPTY_DATA_IMAGE = GeneralContext.isChineseEnv() ? IOUtils.readImage("com/fr/design/images/zh_emptydata.png") - : IOUtils.readImage("com/fr/design/images/us_emptydata.png"); + LocaleImageMark localeImageMark = LocaleImageFactory.getOrCreateLocaleMark(EMPTY_DATA_IMAGE_PATH); + DEFAULT_EMPTY_DATA_IMAGE = localeImageMark.getValue(); } @Override diff --git a/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleConstants.java b/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleConstants.java new file mode 100644 index 0000000000..4cbba62906 --- /dev/null +++ b/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleConstants.java @@ -0,0 +1,85 @@ +package com.fr.van.chart.config; + +import com.fr.base.ChartPreStyleConfig; +import com.fr.chart.base.ChartBaseUtils; +import com.fr.chart.base.ChartConstants; +import com.fr.general.Background; +import com.fr.general.FRFont; +import com.fr.general.GeneralUtils; +import com.fr.stable.CodeUtils; +import com.fr.stable.Constants; + +import java.awt.Color; +import java.awt.Font; + +/** + * @author shine + * @version 10.0 + * Created by shine on 2021/6/25 + */ +public class DefaultStyleConstants { + static final FRFont TITLE = FRFont.getInstance(ChartBaseUtils.getLocalDefaultFont("Microsoft YaHei"), Font.BOLD, 19, new Color(241, 246, 255)); + static final FRFont LEGEND = FRFont.getInstance(ChartBaseUtils.getLocalDefaultFont("Microsoft YaHei"), Font.PLAIN, 12, new Color(159, 173, 191)); + + static final FRFont AXIS_LABEL = FRFont.getInstance(ChartBaseUtils.getLocalDefaultFont("Microsoft YaHei"), Font.PLAIN, 12, new Color(159, 173, 191)); + static final FRFont AXIS_TITLE = FRFont.getInstance(ChartBaseUtils.getLocalDefaultFont("Microsoft YaHei"), Font.PLAIN, 12, new Color(200, 211, 228)); + static final Color AXIS_LINE = new Color(46, 75, 102); + static final Color GRID_LINE = new Color(30, 55, 78); + + static final FRFont ALERT_FONT = FRFont.getInstance(ChartBaseUtils.getLocalDefaultFont("Microsoft YaHei"), Font.PLAIN, 12, new Color(255, 0, 0)); + + static final FRFont DATA_SHEET = FRFont.getInstance(ChartBaseUtils.getLocalDefaultFont("Microsoft YaHei"), Font.PLAIN, 12, new Color(159, 173, 191)); + static final Color DATA_SHEET_BORDER = new Color(46, 75, 102); + + static final Color BORDER = Color.BLACK; + static final int BORDER_WIDTH = Constants.LINE_NONE; + static final int SPECIAL_BORDER_WIDTH = Constants.LINE_THIN; + + static final FRFont PIE_CATEGORY_LABEL = FRFont.getInstance(ChartBaseUtils.getLocalDefaultFont("Microsoft YaHei"), Font.PLAIN, 13, new Color(232, 232, 232)); + + static final Color GAUGE_PANE_BACK_COLOR = null; + static final Color GAUGE_HINGE = null; + static final Color GAUGE_PANE_BACK_COLOR_4_RING = new Color(72, 73, 79); + static final Color GAUGE_SLOT_BACKGROUND_COLOR = new Color(72, 73, 79); + private static final String FONT_NAME = ChartBaseUtils.getLocalDefaultFont("verdana"); + static final FRFont THERMOMETER_LABEL_FONT = FRFont.getInstance(FONT_NAME, Font.BOLD, 12, new Color(232, 232, 232));//试管仪表盘标签的默认样式 + static final FRFont THERMOMETER_AXIS_LABEL = FRFont.getInstance(FONT_NAME, Font.PLAIN, 11, new Color(159, 173, 191)); + static final FRFont RING_VALUE_LABEL_FONT = FRFont.getInstance(FONT_NAME, Font.PLAIN, ChartConstants.AUTO_FONT_SIZE, new Color(232, 232, 232));//百分比圆环仪表盘值标签的默认样式 + static final FRFont POINTER_VALUE_LABEL_FONT = FRFont.getInstance(FONT_NAME, Font.PLAIN, ChartConstants.AUTO_FONT_SIZE, new Color(232, 232, 232));//多指针仪表盘值标签的默认样式 + static final FRFont POINTER_CATE_LABEL_FONT = FRFont.getInstance(FONT_NAME, Font.PLAIN, 13, new Color(232, 232, 232));//多指针仪表盘分类标签的默认样式 + + static final Color MAP_NULL_VALUE_COLOR = new Color(168, 168, 168); + static final Color MAP_BORDER = Color.BLACK; + static final Color MAP_LEGEND_BACK = Color.BLACK; + static final Color MAP_TITLE_BACK = Color.BLACK; + + static final Color DRILL_MAP_DRILL_TOOLS_BACK = Color.BLACK; + static final float DRILL_MAP_DRILL_TOOLS_BACK_OPACITY = 0.8f; + + static final Background BACK = null; + + static String COLORS = null; + + static { + ChartPreStyleConfig config = ChartPreStyleConfig.getInstance(); + try { + DefaultStyleConstants.COLORS = CodeUtils.cjkDecode("\u7ecf\u5178\u9ad8\u4eae"); + // 没有经典高亮, 用新特性 + if (config.getPreStyle(DefaultStyleConstants.COLORS) == null) { + DefaultStyleConstants.COLORS = CodeUtils.cjkDecode("\u65b0\u7279\u6027"); + } + // 没有新特性, 用第一个配色 + if (config.getPreStyle(DefaultStyleConstants.COLORS) == null) { + if (config.names().hasNext()) { + + String name = GeneralUtils.objectToString(config.names().next()); + if (config.getPreStyle(name) != null) { + DefaultStyleConstants.COLORS = name; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleHelper4Van.java b/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleHelper4Van.java new file mode 100644 index 0000000000..31694433ff --- /dev/null +++ b/designer-chart/src/main/java/com/fr/van/chart/config/DefaultStyleHelper4Van.java @@ -0,0 +1,207 @@ +package com.fr.van.chart.config; + +import com.fr.base.ChartColorMatching; +import com.fr.base.ChartPreStyleConfig; +import com.fr.chart.base.AttrBorder; +import com.fr.chart.base.AttrFillStyle; +import com.fr.chart.base.ChartConstants; +import com.fr.chart.chartattr.Plot; +import com.fr.chart.chartglyph.ConditionAttr; +import com.fr.chart.chartglyph.DataSheet; +import com.fr.config.predefined.ColorFillStyle; +import com.fr.design.mainframe.chart.mode.ChartEditContext; +import com.fr.plugin.chart.PiePlot4VanChart; +import com.fr.plugin.chart.attr.axis.VanChartAlertValue; +import com.fr.plugin.chart.attr.axis.VanChartAxis; +import com.fr.plugin.chart.attr.plot.VanChartPlot; +import com.fr.plugin.chart.attr.plot.VanChartRectanglePlot; +import com.fr.plugin.chart.base.AttrLabel; +import com.fr.plugin.chart.base.AttrLabelDetail; +import com.fr.plugin.chart.custom.type.CustomPlotType; +import com.fr.plugin.chart.gauge.VanChartGaugePlot; +import com.fr.plugin.chart.map.VanChartMapPlot; +import com.fr.plugin.chart.type.GaugeStyle; + +/** + * @author shine + * @version 10.0 + * Created by shine on 2021/10/22 + * vanchart的抽出来,因为主体代码 新增y轴 组合图新增图表都要用 + */ +public class DefaultStyleHelper4Van { + + private static boolean duchampMode() { + try { + return ChartEditContext.duchampMode(); + } catch (Throwable e) { + //tomcat预览 默认数据的图表 + return true; + } + } + + public static void dealVanPlot4Custom(VanChartPlot plot, CustomPlotType customPlotType) { + if (!duchampMode()) { + return; + } + dealVanPlotCommonAttr(plot); + switch (customPlotType) { + case PIE: + case DIFFERENT_PIE: + case SAME_PIE: + dealPie(plot); + break; + case SLOT: + case POINTER_360: + case POINTER_180: + case CUVETTE: + case RING: + dealGauge(plot); + break; + case COLUMN: + case LINE: + case AREA: + case BUBBLE: + case RADAR: + case STACK_RADAR: + case SCATTER: + default: + break; + } + + } + + public static VanChartAxis dealAxisDefault(VanChartAxis axis) { + if (!duchampMode()) { + return axis; + } + axis.getTitle().getTextAttr().setFRFont(DefaultStyleConstants.AXIS_TITLE); + axis.getTextAttr().setFRFont(DefaultStyleConstants.AXIS_LABEL); + axis.setAxisColor(DefaultStyleConstants.AXIS_LINE); + axis.setMainGridColor(DefaultStyleConstants.GRID_LINE); + return axis; + } + + public static void dealAxisAlert(VanChartAlertValue vanChartAlertValue) { + if (!duchampMode()) { + return; + } + vanChartAlertValue.setAlertFont(DefaultStyleConstants.ALERT_FONT); + } + + static void dealVanPlotCommonAttr(Plot plot) { + if (!duchampMode()) { + return; + } + if (plot instanceof VanChartPlot) { + VanChartPlot vanChartPlot = (VanChartPlot) plot; + + ChartPreStyleConfig manager = ChartPreStyleConfig.getInstance(); + Object preStyle = manager.getPreStyle(DefaultStyleConstants.COLORS); + if (preStyle instanceof ChartColorMatching) { + ColorFillStyle colorFillStyle = new ColorFillStyle(); + //default是默认的意思,为服务器默认配色方案 + //acc为多个颜色组合 + //gradient为渐变颜色 + colorFillStyle.setColorStyle(ChartConstants.COLOR_ACC); + colorFillStyle.setFillStyleName(DefaultStyleConstants.COLORS); + colorFillStyle.setColorList(((ChartColorMatching) preStyle).getColorList()); + + AttrFillStyle plotFillStyle = vanChartPlot.getPlotFillStyle(); + if (plotFillStyle == null) { + plotFillStyle = new AttrFillStyle(); + vanChartPlot.setPlotFillStyle(plotFillStyle); + } + plotFillStyle.setColorFillStyle(colorFillStyle); + } + + + if (vanChartPlot.getLegend() != null) { + vanChartPlot.getLegend().setFRFont(DefaultStyleConstants.LEGEND); + } + + if (vanChartPlot instanceof VanChartRectanglePlot) { + VanChartRectanglePlot vanChartRectanglePlot = (VanChartRectanglePlot) vanChartPlot; + + for (VanChartAxis axis : vanChartRectanglePlot.getXAxisList()) { + dealAxisDefault(axis); + } + for (VanChartAxis axis : vanChartRectanglePlot.getYAxisList()) { + dealAxisDefault(axis); + } + } + + dealBorder(vanChartPlot); + + DataSheet dataSheet = vanChartPlot.getDataSheet(); + dataSheet.getTextAttr().setFRFont(DefaultStyleConstants.DATA_SHEET); + dataSheet.setBorderColor(DefaultStyleConstants.DATA_SHEET_BORDER); + } + + } + + private static void dealBorder(VanChartPlot vanChartPlot) { + ConditionAttr defaultAttr = vanChartPlot.getConditionCollection().getDefaultAttr(); + AttrBorder attrBorder = defaultAttr.getExisted(AttrBorder.class); + if (attrBorder != null) { + attrBorder.setBorderColor(DefaultStyleConstants.BORDER); + attrBorder.setBorderStyle(defaultBorderWidth(vanChartPlot)); + } + } + + private static int defaultBorderWidth(VanChartPlot vanChartPlot) { + //pie multipie treemap map drillmap heatmap + if (vanChartPlot instanceof PiePlot4VanChart + || vanChartPlot instanceof VanChartMapPlot) { + return DefaultStyleConstants.SPECIAL_BORDER_WIDTH; + } + return DefaultStyleConstants.BORDER_WIDTH; + } + + static void dealPie(Plot plot) { + if (plot instanceof PiePlot4VanChart) { + ConditionAttr defaultAttr = plot.getConditionCollection().getDefaultAttr(); + AttrLabel attrLabel = defaultAttr.getExisted(AttrLabel.class); + if (attrLabel == null) { + attrLabel = ((PiePlot4VanChart) plot).getDefaultAttrLabel(); + defaultAttr.addDataSeriesCondition(attrLabel); + } + attrLabel.getSecondLabelDetail().getTextAttr().setFRFont(DefaultStyleConstants.PIE_CATEGORY_LABEL); + } + } + + static void dealGauge(Plot param) { + if (!(param instanceof VanChartGaugePlot)) { + return; + } + VanChartGaugePlot plot = (VanChartGaugePlot) param; + plot.getGaugeDetailStyle().setPaneBackgroundColor(plot.getGaugeStyle() == GaugeStyle.RING ? DefaultStyleConstants.GAUGE_PANE_BACK_COLOR_4_RING : DefaultStyleConstants.GAUGE_PANE_BACK_COLOR); + plot.getGaugeDetailStyle().setSlotBackgroundColor(DefaultStyleConstants.GAUGE_SLOT_BACKGROUND_COLOR); + plot.getGaugeDetailStyle().setHingeColor(DefaultStyleConstants.GAUGE_HINGE); + + ConditionAttr defaultAttr = plot.getConditionCollection().getDefaultAttr(); + AttrLabel attrLabel = defaultAttr.getExisted(AttrLabel.class); + if (attrLabel != null) { + AttrLabelDetail detail = attrLabel.getAttrLabelDetail(); + AttrLabelDetail valueDetail = attrLabel.getGaugeValueLabelDetail(); + + switch (plot.getGaugeStyle()) { + case POINTER: + case POINTER_SEMI: + detail.getContent().getCategoryFormat().setEnable(false); + detail.getTextAttr().setFRFont(DefaultStyleConstants.POINTER_CATE_LABEL_FONT); + valueDetail.getTextAttr().setFRFont(DefaultStyleConstants.POINTER_VALUE_LABEL_FONT); + break; + case RING: + case SLOT: + valueDetail.getTextAttr().setFRFont(DefaultStyleConstants.RING_VALUE_LABEL_FONT); + break; + case THERMOMETER: + detail.getTextAttr().setFRFont(DefaultStyleConstants.THERMOMETER_LABEL_FONT); + valueDetail.getTextAttr().setFRFont(DefaultStyleConstants.THERMOMETER_LABEL_FONT); + plot.getGaugeAxis().getTextAttr().setFRFont(DefaultStyleConstants.THERMOMETER_AXIS_LABEL); + break; + } + + } + } +} diff --git a/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartCustomPlotSelectPane.java b/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartCustomPlotSelectPane.java index 8f7b9557d0..99498c58a8 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartCustomPlotSelectPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartCustomPlotSelectPane.java @@ -6,13 +6,13 @@ import com.fr.design.dialog.FineJOptionPane; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; - import com.fr.plugin.chart.attr.plot.VanChartPlot; import com.fr.plugin.chart.attr.plot.VanChartRectanglePlot; import com.fr.plugin.chart.custom.CustomPlotFactory; import com.fr.plugin.chart.custom.VanChartCustomPlot; import com.fr.plugin.chart.custom.type.CustomPlotType; import com.fr.plugin.chart.custom.type.CustomStyle; +import com.fr.van.chart.config.DefaultStyleHelper4Van; import com.fr.van.chart.custom.CustomPlotDesignerPaneFactory; import javax.swing.JOptionPane; @@ -260,6 +260,7 @@ public class VanChartCustomPlotSelectPane extends BasicBeanPane { CustomPlotType customPlotType = selectedPlotTypeList.get(i); if (!CustomPlotFactory.customPlotContains(newCustomPlotList, customPlotType)){ VanChartPlot vanChartPlot = CustomPlotFactory.getCustomPlot(customPlotType); + DefaultStyleHelper4Van.dealVanPlot4Custom(vanChartPlot, customPlotType); vanChartPlot.setCustomType(CustomStyle.CUSTOM.toString()); //设置公共属性 setCommonAttr(vanChartPlot, customPlot); diff --git a/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartHyperLinkPane.java b/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartHyperLinkPane.java index b5efad3b66..eed8d69dd8 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartHyperLinkPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartHyperLinkPane.java @@ -13,6 +13,7 @@ import com.fr.design.chart.series.SeriesCondition.impl.ChartHyperRelateCellLinkP import com.fr.design.chart.series.SeriesCondition.impl.ChartHyperRelateFloatLinkPane; import com.fr.design.chart.series.SeriesCondition.impl.FormHyperlinkPane; import com.fr.design.designer.TargetComponent; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fun.HyperlinkProvider; import com.fr.design.gui.controlpane.NameObjectCreator; import com.fr.design.gui.controlpane.NameableCreator; @@ -21,7 +22,10 @@ import com.fr.design.hyperlink.ReportletHyperlinkPane; import com.fr.design.hyperlink.WebHyperlinkPane; import com.fr.design.javascript.JavaScriptImplPane; import com.fr.design.javascript.ParameterJavaScriptPane; +import com.fr.design.mainframe.BaseJForm; +import com.fr.design.mainframe.JTemplate; import com.fr.design.module.DesignModuleFactory; +import com.fr.general.ComparatorUtils; import com.fr.general.NameObject; import com.fr.js.EmailJavaScript; import com.fr.js.FormHyperlinkProvider; @@ -148,22 +152,23 @@ public class VanChartHyperLinkPane extends VanChartUIListControlPane { setPlot(plot); HashMap paneMap = getHyperlinkMap(plot); - //安装平台内打开插件时,添加相应按钮 - Set providers = ExtraDesignClassManager.getInstance().getArray(HyperlinkProvider.XML_TAG); - for (HyperlinkProvider provider : providers) { - NameableCreator nc = provider.createHyperlinkCreator(); - paneMap.put(nc.getHyperlink(), nc.getUpdatePane()); - } - java.util.List list = refreshList(paneMap); - NameObjectCreator[] creators = new NameObjectCreator[list.size()]; - for (int i = 0; list != null && i < list.size(); i++) { + Map creators = new ListMap<>(); + int size = list.size(); + for (int i = 0; i < size; i++) { UIMenuNameableCreator uiMenuNameableCreator = list.get(i); - creators[i] = new NameObjectCreator(uiMenuNameableCreator.getName(), uiMenuNameableCreator.getObj().getClass(), uiMenuNameableCreator.getPaneClazz()); - + NameObjectCreator creator = new NameObjectCreator(uiMenuNameableCreator.getName(), uiMenuNameableCreator.getObj().getClass(), uiMenuNameableCreator.getPaneClazz()); + creators.put(uiMenuNameableCreator.getName(), creator); } - - refreshNameableCreator(creators); + //安装平台内打开插件时, 添加/替换 相应按钮 + Set providers = ExtraDesignClassManager.getInstance().getArray(HyperlinkProvider.XML_TAG); + for (HyperlinkProvider provider : providers) { + NameableCreator creator = provider.createHyperlinkCreator(); + if (creator != null) { + creators.put(creator.menuName(), new NameObjectCreator(creator.menuName(), creator.getHyperlink(), creator.getUpdatePane())); + } + } + refreshNameableCreator(creators.values().toArray(new NameObjectCreator[0])); java.util.List nameObjects = new ArrayList(); @@ -279,4 +284,37 @@ public class VanChartHyperLinkPane extends VanChartUIListControlPane { } + @Override + protected void initCreatorsFilter() { + this.creatorsFilter = nameableCreator -> { + Class clazz = nameableCreator.getHyperlink(); + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template == null) { + return false; + } + + if (template.isJWorkBook()) { + // 如果是普通报表单元格,那么没有 FormHyperlink 选项 + FormHyperlinkProvider formHyperlink = StableFactory.getMarkedInstanceObjectFromClass(FormHyperlinkProvider.XML_TAG, FormHyperlinkProvider.class); + return !ComparatorUtils.equals(clazz, formHyperlink.getClass()); + } else { + // 如果是决策报表 + if (template.getEditingReportIndex() == BaseJForm.ELEMENTCASE_TAB) { + // 编辑的是决策报表中的报表块,那么没有 ChartHyperRelateFloatLink选项 + return !ComparatorUtils.equals(clazz, ChartHyperRelateFloatLink.class); + } + Class[] classes = new Class[]{ChartHyperRelateCellLink.class, ChartHyperRelateFloatLink.class}; + for (Class aClass : classes) { + if (template.getEditingReportIndex() == BaseJForm.FORM_TAB) { + // 编辑的是决策报表中的图表,那么没有 ChartHyperRelateFloatLink 和 ChartHyperRelateCellLink 选项 + if (ComparatorUtils.equals(aClass, clazz)) { + return false; + } + } + } + } + return true; + }; + } + } \ No newline at end of file diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartHtmlLabelPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartHtmlLabelPane.java index 0e9cc416f9..ebff936c1c 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartHtmlLabelPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartHtmlLabelPane.java @@ -5,6 +5,7 @@ import com.fr.design.constants.KeyWords; import com.fr.design.gui.autocomplete.AutoCompletion; import com.fr.design.gui.autocomplete.BasicCompletion; import com.fr.design.gui.autocomplete.DefaultCompletionProvider; +import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; import com.fr.design.gui.ibutton.UIToggleButton; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icontainer.UIScrollPane; @@ -45,7 +46,7 @@ public class VanChartHtmlLabelPane extends JPanel { private UICheckBox isCustomHeight; private UITextField customHeight; - private VanChartStylePane parent; + private AbstractAttrNoScrollPane parent; private JPanel widthAndHeightPane; @@ -53,7 +54,7 @@ public class VanChartHtmlLabelPane extends JPanel { contentTextArea.setText(text); } - public void setParent(VanChartStylePane parent) { + public void setParent(AbstractAttrNoScrollPane parent) { this.parent = parent; } @@ -126,7 +127,7 @@ public class VanChartHtmlLabelPane extends JPanel { }; } - private void fireJSChange() { + protected void fireJSChange() { if (parent != null) { parent.attributeChanged(); } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartUIListControlPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartUIListControlPane.java index 8a18814ebd..ce8253b981 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartUIListControlPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartUIListControlPane.java @@ -25,6 +25,7 @@ import java.awt.BorderLayout; import java.awt.Component; import java.awt.FlowLayout; import java.awt.Point; +import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -210,6 +211,16 @@ public abstract class VanChartUIListControlPane extends UIListControlPane implem public void doCancel() { setVisible(false); } + + @Override + public void setVisible(boolean b) { + super.setVisible(b); + + //把一些可能没隐藏的子弹框隐藏 比如 边框-颜色弹框 + for (Window window : getOwnedWindows()) { + window.setVisible(false); + } + } } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/marker/VanChartImageMarkerPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/marker/VanChartImageMarkerPane.java index d28354bdb7..3d6c85f4ec 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/component/marker/VanChartImageMarkerPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/marker/VanChartImageMarkerPane.java @@ -31,8 +31,8 @@ public class VanChartImageMarkerPane extends BasicBeanPane { public VanChartImageMarkerPane() { imageBackgroundPane = new ImageBackgroundQuickPane(false); imageBackgroundPane.setPreferredSize(getImageBackgroundPreferredSize(imageBackgroundPane.getPreferredSize())); - width = new UISpinnerWithPx(0, 100, 0.5, 30); - height = new UISpinnerWithPx(0, 100, 0.5, 30); + width = new UISpinnerWithPx(0, Integer.MAX_VALUE, 0.5, 30); + height = new UISpinnerWithPx(0, Integer.MAX_VALUE, 0.5, 30); double p = TableLayout.PREFERRED; double f = TableLayout.FILL; diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/data/VanChartMoreCateTableDataContentPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/data/VanChartMoreCateTableDataContentPane.java index dcf160aec1..4d9f0aa61f 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/data/VanChartMoreCateTableDataContentPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/data/VanChartMoreCateTableDataContentPane.java @@ -22,13 +22,14 @@ public class VanChartMoreCateTableDataContentPane extends CategoryPlotMoreCateTa @Override public void populateBean(ChartCollection collection) { super.populateBean(collection); - VanChartRectanglePlot plot = (VanChartRectanglePlot) collection.getSelectedChart().getPlot(); + VanChartRectanglePlot plot = collection.getSelectedChart().getPlot(); isSupportMultiCategory = plot.isSupportMultiCategory(); checkBoxList(isSupportMultiCategory); } protected void updateMoreCate(NormalTableDataDefinition normal, Plot plot) { super.updateMoreCate(normal, plot); + isSupportMultiCategory = ((VanChartRectanglePlot) plot).isSupportMultiCategory(); ((VanChartPlot) plot).setCategoryNum(getBoxList().size() + 1); if (!getBoxList().isEmpty()) { plot.getDataSheet().setVisible(false); diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/other/VanChartInteractivePane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/other/VanChartInteractivePane.java index 78be16ad55..dc72b90221 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/other/VanChartInteractivePane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/other/VanChartInteractivePane.java @@ -471,7 +471,11 @@ public class VanChartInteractivePane extends AbstractVanChartScrollPane { } protected Component[][] createToolBarComponents() { - return new Component[][]{ + return ChartEditContext.duchampMode() ? new Component[][]{ + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Content")), isSort}, + new Component[]{null, fullScreenDisplay}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Layout")), collapse}, + } : new Component[][]{ new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Content")), isSort}, new Component[]{null, exportImages}, new Component[]{null, fullScreenDisplay}, @@ -480,7 +484,10 @@ public class VanChartInteractivePane extends AbstractVanChartScrollPane { } protected Component[][] createToolBarComponentsWithOutSort() { - return new Component[][]{ + return ChartEditContext.duchampMode() ? new Component[][]{ + new Component[]{null, fullScreenDisplay}, + new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Layout")), collapse} + } : new Component[][]{ new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Content")), exportImages}, new Component[]{null, fullScreenDisplay}, new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Layout")), collapse} diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPane.java index 5c71317f20..e8379e78b4 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/axis/VanChartAxisPane.java @@ -14,16 +14,17 @@ import com.fr.plugin.chart.attr.plot.VanChartRectanglePlot; import com.fr.plugin.chart.base.AttrSeriesStackAndAxis; import com.fr.plugin.chart.base.VanChartConstants; import com.fr.plugin.chart.vanchart.VanChart; +import com.fr.van.chart.config.DefaultStyleHelper4Van; import com.fr.van.chart.designer.style.VanChartStylePane; import com.fr.van.chart.designer.style.axis.component.VanChartAxisButtonPane; import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.CardLayout; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.awt.BorderLayout; -import java.awt.CardLayout; /** * 样式-坐标轴界面 @@ -104,6 +105,7 @@ public class VanChartAxisPane extends BasicBeanPane { List xAxisList = editingPlot.getXAxisList(); VanChartAxis axis = editingPlot.createXAxis(name, VanChartConstants.AXIS_BOTTOM); xAxisList.add(axis); + DefaultStyleHelper4Van.dealAxisDefault(axis); VanChartXYAxisPaneInterface axisPane = initXAxisPane(axis); axisPane.populate(axis); @@ -119,6 +121,7 @@ public class VanChartAxisPane extends BasicBeanPane { List yAxisList = editingPlot.getYAxisList(); VanChartAxis axis = editingPlot.createYAxis(name, VanChartConstants.AXIS_LEFT); yAxisList.add(axis); + DefaultStyleHelper4Van.dealAxisDefault(axis); VanChartXYAxisPaneInterface axisPane = initYAxisPane(axis); axisPane.populate(axis); 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 ef042e0f2a..daa7ca3c95 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,15 +1,16 @@ package com.fr.van.chart.designer.style.axis; 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; import com.fr.plugin.chart.attr.axis.VanChartTimeAxis; import com.fr.plugin.chart.attr.axis.VanChartValueAxis; import com.fr.plugin.chart.type.AxisType; +import com.fr.van.chart.config.DefaultStyleHelper4Van; import com.fr.van.chart.designer.AbstractVanChartScrollPane; import com.fr.van.chart.designer.TableLayout4VanChartHelper; import com.fr.van.chart.designer.style.VanChartStylePane; @@ -83,9 +84,9 @@ public class VanChartAxisScrollPaneWithTypeSelect extends AbstractVanChartScroll public void populate(VanChartAxis axis){ AxisType axisType = axis.getAxisType(); - textAxisPane.populateBean(new VanChartAxis(axis.getAxisName(), axis.getPosition())); - timeAxisPane.populateBean(new VanChartTimeAxis(axis.getAxisName(), axis.getPosition())); - valueAxisPane.populateBean(new VanChartValueAxis(axis.getAxisName(), axis.getPosition())); + textAxisPane.populateBean(DefaultStyleHelper4Van.dealAxisDefault(new VanChartAxis(axis.getAxisName(), axis.getPosition()))); + timeAxisPane.populateBean(DefaultStyleHelper4Van.dealAxisDefault(new VanChartTimeAxis(axis.getAxisName(), axis.getPosition()))); + valueAxisPane.populateBean(DefaultStyleHelper4Van.dealAxisDefault(new VanChartValueAxis(axis.getAxisName(), axis.getPosition()))); if(ComparatorUtils.equals(axisType, AxisType.AXIS_CATEGORY)){ textAxisPane.populateBean(axis); } else if(ComparatorUtils.equals(axisType, AxisType.AXIS_TIME)){ diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/ChartNameObjectCreator.java b/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/ChartNameObjectCreator.java index 8a5a33ca85..4d8bbe990b 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/ChartNameObjectCreator.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/style/background/ChartNameObjectCreator.java @@ -3,10 +3,11 @@ package com.fr.van.chart.designer.style.background; import com.fr.design.beans.BasicBeanPane; import com.fr.design.gui.controlpane.NameObjectCreator; import com.fr.design.gui.controlpane.UnrepeatedNameHelper; -import com.fr.log.FineLoggerFactory; import com.fr.general.NameObject; +import com.fr.log.FineLoggerFactory; import com.fr.plugin.chart.attr.axis.VanChartAlertValue; import com.fr.stable.Nameable; +import com.fr.van.chart.config.DefaultStyleHelper4Van; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -37,6 +38,7 @@ public class ChartNameObjectCreator extends NameObjectCreator { VanChartAlertValue vanChartAlertValue = constructor.newInstance(); vanChartAlertValue.setAxisNamesArray((String[]) object); vanChartAlertValue.setAxisName(((String[]) object)[0]); + DefaultStyleHelper4Van.dealAxisAlert(vanChartAlertValue); return new NameObject(helper.createUnrepeatedName(this.menuName()), vanChartAlertValue); } catch (NoSuchMethodException e) { 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 c439c4d4d9..ce06ca4b6b 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 @@ -101,7 +101,12 @@ public class VanChartDrillMapInteractivePane extends VanChartInteractivePaneWith double f = TableLayout.FILL; double[] columnSize = {f}; double[] rowSize = {p, p, p, p, p, p}; - Component[][] components = new Component[][]{ + Component[][] components = ChartEditContext.duchampMode() ? new Component[][]{ + new Component[]{null}, + new Component[]{createTitlePane(Toolkit.i18nText("Fine-Design_Chart_Character"), textAttrPane)}, + new Component[]{backgroundPane}, + new Component[]{selectBackgroundPane} + } : new Component[][]{ new Component[]{null}, new Component[]{createTitlePane(Toolkit.i18nText("Fine-Design_Chart_Character"), textAttrPane)}, new Component[]{backgroundPane}, diff --git a/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/data/data/component/GanttTableDataContentPane.java b/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/data/data/component/GanttTableDataContentPane.java index b8a2001147..82bb26e438 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/data/data/component/GanttTableDataContentPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/gantt/designer/data/data/component/GanttTableDataContentPane.java @@ -93,13 +93,13 @@ public class GanttTableDataContentPane extends AbstractTableDataContentPane{ ganttDefinition.setEndTime(endTime == null ? StringUtils.EMPTY : String.valueOf(endTime)); Object markTime = markerTimeComboBox.getSelectedItem(); - ganttDefinition.setMarkTime(isNoneObject(markTime) ? StringUtils.EMPTY : String.valueOf(markTime)); + ganttDefinition.setMarkTime(isNoneObject(markTime) ? null : String.valueOf(markTime)); Object process = processComboBox.getSelectedItem(); - ganttDefinition.setProgress(isNoneObject(process) ? StringUtils.EMPTY : String.valueOf(process)); + ganttDefinition.setProgress(isNoneObject(process) ? null : String.valueOf(process)); Object taskID = taskIDComboBox.getSelectedItem(); - ganttDefinition.setLinkID(isNoneObject(taskID) ? StringUtils.EMPTY : String.valueOf(taskID)); + ganttDefinition.setLinkID(isNoneObject(taskID) ? null : String.valueOf(taskID)); } private boolean isNoneObject(Object markTime) { @@ -117,9 +117,9 @@ public class GanttTableDataContentPane extends AbstractTableDataContentPane{ seriesComboBox.setSelectedItem(ganttDefinition.getSeriesName()); startTimeComboBox.setSelectedItem(ganttDefinition.getStartTime()); endTimeComboBox.setSelectedItem(ganttDefinition.getEndTime()); - markerTimeComboBox.setSelectedItem(StringUtils.isEmpty(ganttDefinition.getMarkTime()) ? NONE : ganttDefinition.getMarkTime()); - processComboBox.setSelectedItem(StringUtils.isEmpty(ganttDefinition.getProgress()) ? NONE : ganttDefinition.getProgress()); - taskIDComboBox.setSelectedItem(StringUtils.isEmpty(ganttDefinition.getLinkID()) ? NONE : ganttDefinition.getLinkID()); + markerTimeComboBox.setSelectedItem(ganttDefinition.getMarkTime() == null ? NONE : ganttDefinition.getMarkTime()); + processComboBox.setSelectedItem(ganttDefinition.getProgress() == null ? NONE : ganttDefinition.getProgress()); + taskIDComboBox.setSelectedItem(ganttDefinition.getLinkID() == null ? NONE : ganttDefinition.getLinkID()); } } 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 d3f997295b..83c9c523d1 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 @@ -16,6 +16,7 @@ import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.chart.gui.ChartStylePane; import com.fr.design.mainframe.chart.gui.style.series.ColorPickerPaneWithMaxMin; import com.fr.design.mainframe.chart.gui.style.series.UIColorPickerPane; +import com.fr.design.mainframe.chart.mode.ChartEditContext; import com.fr.design.style.color.ColorSelectBox; import com.fr.general.ComparatorUtils; import com.fr.plugin.chart.attr.GaugeDetailStyle; @@ -199,7 +200,9 @@ public class VanChartGaugeSeriesPane extends VanChartMultiColorSeriesPane { if (attrLabelDetail == null || attrLabelDetail.getTextAttr() == null) { return; } - attrLabelDetail.getTextAttr().setFRFont(VanChartGaugePlot.THERMOMETER_LABEL_FONT); + if (!ChartEditContext.duchampMode()) { + attrLabelDetail.getTextAttr().setFRFont(VanChartGaugePlot.THERMOMETER_LABEL_FONT); + } if (gaugeLayout.getSelectedIndex() == 0) { attrLabel.getAttrLabelDetail().setPosition(Constants.LEFT); attrLabel.getGaugeValueLabelDetail().setPosition(Constants.LEFT); diff --git a/designer-chart/src/main/resources/com/fr/design/images/us_emptydata.png b/designer-chart/src/main/resources/com/fr/design/images/en_us_emptydata.png similarity index 100% rename from designer-chart/src/main/resources/com/fr/design/images/us_emptydata.png rename to designer-chart/src/main/resources/com/fr/design/images/en_us_emptydata.png diff --git a/designer-chart/src/main/resources/com/fr/design/images/zh_emptydata.png b/designer-chart/src/main/resources/com/fr/design/images/zh_cn_emptydata.png similarity index 100% rename from designer-chart/src/main/resources/com/fr/design/images/zh_emptydata.png rename to designer-chart/src/main/resources/com/fr/design/images/zh_cn_emptydata.png diff --git a/designer-chart/src/main/resources/com/fr/design/images/zh_tw_emptydata.png b/designer-chart/src/main/resources/com/fr/design/images/zh_tw_emptydata.png new file mode 100644 index 0000000000..738fa685ad Binary files /dev/null and b/designer-chart/src/main/resources/com/fr/design/images/zh_tw_emptydata.png differ diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRCardMainBorderLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRCardMainBorderLayoutAdapter.java index 9718d4a6fd..057baa9a31 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRCardMainBorderLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRCardMainBorderLayoutAdapter.java @@ -1,14 +1,17 @@ package com.fr.design.designer.beans.adapters.layout; +import com.fr.design.designer.beans.models.AddingModel; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.cardlayout.XWCardTagLayout; import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.form.layout.FRBorderLayout; +import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.WidgetPropertyPane; import com.fr.general.ComparatorUtils; - -import javax.swing.JOptionPane; import java.awt.BorderLayout; import java.awt.Rectangle; @@ -46,18 +49,37 @@ public class FRCardMainBorderLayoutAdapter extends FRBorderLayoutAdapter { Rectangle rectangle = creator.getBounds(); //不能超出控件边界 if (ComparatorUtils.equals(constraints, BorderLayout.NORTH) || ComparatorUtils.equals(constraints, BorderLayout.SOUTH)) { - int containerHeight = container.getHeight(); - if (rectangle.height > containerHeight) { - FineJOptionPane.showMessageDialog(null, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Beyond_Tablayout_Bounds")); - return true; - } + return isBeyondMinConstraint(rectangle.height, container.getHeight()); } else if (ComparatorUtils.equals(constraints, BorderLayout.EAST) || ComparatorUtils.equals(constraints, BorderLayout.WEST)) { - int containerWidth = container.getWidth(); - if (rectangle.width > containerWidth) { - FineJOptionPane.showMessageDialog(null, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Beyond_Tablayout_Bounds")); - return true; - } + return isBeyondMinConstraint(rectangle.width, container.getWidth()); } return false; } + + /** + * 是否超出最小限制 + * + * @param minConstraint 最小限制 + * @param value 数值 + * @return 是否超出最小限制 + */ + private boolean isBeyondMinConstraint(int minConstraint, int value) { + if (minConstraint > value) { + FineJOptionPane.showMessageDialog(null, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Beyond_Tablayout_Bounds")); + JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + if (jt != null) { + jt.undoToCurrent(); + } + + FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); + AddingModel model = formDesigner.getAddingModel(); + if (model != null) { + model.setAddedIllegal(true); + } + + return true; + } else { + return false; + } + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java index c893268ba1..8800bb6490 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java @@ -11,6 +11,7 @@ import com.fr.design.designer.beans.painters.FRFitLayoutPainter; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreatorUtils; 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.XWFitLayout; import com.fr.design.designer.creator.cardlayout.XWCardLayout; @@ -339,6 +340,10 @@ public class FRFitLayoutAdapter extends FRBodyLayoutAdapter { */ @Override public void fix(XCreator creator) { + //XWAbsoluteBodyLayout作为body不允许在Fit布局中调整尺寸 + if(creator.acceptType(XWAbsoluteBodyLayout.class)){ + return; + } //拖拽组件原大小、位置 Rectangle backupBound = creator.getBackupBound(); backupBound.x -= container.getX(); diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java index c0b6cd400a..edc5ca9982 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java @@ -24,6 +24,7 @@ public class AddingModel { private int currentX; private int currentY; private boolean added; + private boolean addedIllegal = false; // 有时候是添加完成了,但是添加会造成某些控件size不合法,例如tab public AddingModel(FormDesigner designer, XCreator xCreator) { this.creator = xCreator; @@ -142,4 +143,12 @@ public class AddingModel { y + designer.getVerticalScaleValue() - rect.y); return added; } + + public boolean isAddedIllegal() { + return addedIllegal; + } + + public void setAddedIllegal(boolean addedIllegal) { + this.addedIllegal = addedIllegal; + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/ModelUtil.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/ModelUtil.java index 0f75896e1b..8c4d9c494e 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/models/ModelUtil.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/ModelUtil.java @@ -18,16 +18,16 @@ import java.util.Set; /** * created by Harrison on 2020/06/05 **/ -abstract class ModelUtil { - +public abstract class ModelUtil { + public static void renameWidgetName(Form form, XCreator xCreator) { - + Set duplicated = new HashSet<>(); recursiveRenameWidgetName(form, xCreator, duplicated); } - + private static void recursiveRenameWidgetName(Form form, XCreator xCreator, Set duplicated) { - + Set nameRelatedCreators = new HashSet<>(); //直接遍历出来目标值,然后按需处理 xCreator.traversalNameRelatedXCreators(nameRelatedCreators); @@ -50,9 +50,9 @@ abstract class ModelUtil { duplicated.add(xCreator.toData().getWidgetName()); } } - + private static String uniqueName(Form form, XCreator xCreator, Set duplicated) { - + if (xCreator.acceptType(XWParameterLayout.class)) { return xCreator.createDefaultName(); } @@ -61,6 +61,15 @@ abstract class ModelUtil { if (StringUtils.isEmpty(widgetName)) { widgetName = xCreator.createDefaultName(); } + //先保存默认名字 + return uniqueName(form, widgetName, duplicated); + } + + public static String uniqueName(Form form, String widgetName) { + return uniqueName(form, widgetName, new HashSet<>()); + } + + private static String uniqueName(Form form, String widgetName, Set duplicated) { //先保存默认名字 String raw = widgetName; int i = 0; @@ -74,5 +83,4 @@ abstract class ModelUtil { duplicated.add(widgetName); return widgetName; } - } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java index df645e2dfe..0820757070 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java @@ -25,7 +25,6 @@ import com.fr.design.fun.FormWidgetOptionProvider; import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.FormSelection; import com.fr.design.mainframe.FormSelectionUtils; -import com.fr.design.mainframe.share.encrypt.clipboard.impl.EncryptSelectionClipboardHandler; import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.LayoutUtils; import com.fr.general.ComparatorUtils; @@ -140,11 +139,28 @@ public class SelectionModel { if (cutSelection != null) { cutSelection.cut2ClipBoard(clipboard); designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED); + setSelectedCreator(hasSelectedParaComponent() ? designer.getParaComponent() : designer.getRootComponent()); designer.repaint(); } } } + /** + * 判断是否选中参数面板中的组件 + * @return boolean + */ + private boolean hasSelectedParaComponent() { + XCreator[] roots = selection.getSelectedCreators(); + if (roots.length > 0) { + for (XCreator creator : roots) { + if ((creator.getParent() instanceof XWParameterLayout)) { + return true; + } + } + } + return false; + } + /** * 复制当前选中的组件到剪切板 */ 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 3d1550af67..b70754c11f 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 @@ -363,4 +363,9 @@ public class XChartEditor extends XBorderStyleWidgetCreator { return false; } + @Override + public boolean isComponent() { + return true; + } + } diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XCreator.java b/designer-form/src/main/java/com/fr/design/designer/creator/XCreator.java index 87a1926cbb..1b60d7bfff 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XCreator.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XCreator.java @@ -11,6 +11,7 @@ import com.fr.design.designer.beans.AdapterBus; import com.fr.design.designer.beans.ComponentAdapter; import com.fr.design.designer.beans.events.DesignerEditor; import com.fr.design.designer.beans.models.SelectionModel; +import com.fr.design.designer.ui.PopupDialogContext; import com.fr.design.designer.ui.SelectedPopupDialog; import com.fr.design.fun.ShareWidgetUIProcessor; import com.fr.design.fun.WidgetPropertyUIProvider; @@ -778,6 +779,7 @@ public abstract class XCreator extends JPanel implements XComponent, XCreatorToo if (popup == null) { popup = new SelectedPopupDialog(this, designer); } + PopupDialogContext.checkSelectedPop(this); JFrame frame = LogMessageBar.getInstance().getLogFrame(); if (frame!= null && frame.isActive()) { return; @@ -876,6 +878,7 @@ public abstract class XCreator extends JPanel implements XComponent, XCreatorToo if (popup != null) { popup.setVisible(false); } + PopupDialogContext.checkSelectedPop(this); } public void processPopup(boolean canVisible) { @@ -894,4 +897,12 @@ public abstract class XCreator extends JPanel implements XComponent, XCreatorToo } return ((XCreator) this.getParent()).getLevel() + 1; } + + /** + * 是否是组件(控件还是组件) + * @return 是否是组件 + */ + public boolean isComponent() { + return false; + } } 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 945d3bfdd3..338f406435 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 @@ -57,6 +57,7 @@ import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; import com.fr.form.ui.container.cardlayout.WCardTagLayout; import com.fr.form.ui.container.cardlayout.WCardTitleLayout; import com.fr.form.ui.container.cardlayout.WTabFitLayout; +import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; import com.fr.general.IOUtils; import com.fr.invoke.Reflect; @@ -68,6 +69,7 @@ import com.fr.plugin.observer.PluginEvent; import com.fr.plugin.observer.PluginEventListener; import com.fr.stable.StringUtils; import com.fr.third.javax.annotation.Nonnull; +import java.util.Set; import org.jetbrains.annotations.Nullable; import javax.swing.Icon; @@ -356,4 +358,65 @@ public class XCreatorUtils { } return null; } + + /** + * 把控件例如textEditor外层的容器剥掉 + * @param xCreator 控件 + * @return 内层控件 + */ + public static XCreator getXCreatorInnerWidget(XCreator xCreator) { + if (xCreator.acceptType(XWScaleLayout.class)) { + if (xCreator.getComponentCount() > 0 && ((XCreator) xCreator.getComponent(0)).shouldScaleCreator()) { + return (XCreator) xCreator.getComponent(0); + } + } + + if (xCreator.acceptType(XWTitleLayout.class)) { + return (XCreator) xCreator.getComponent(0); + } + + return xCreator; + } + + public static boolean isExtraContainer(XCreator creator) { + Set set = ExtraDesignClassManager.getInstance().getArray(FormWidgetOptionProvider.XML_TAG); + for (FormWidgetOptionProvider provider : set) { + if (provider.isContainer() + && ComparatorUtils.equals(provider.appearanceForWidget(), provider.appearanceForWidget()) + && ComparatorUtils.equals(provider.classForWidget(), creator.toData().getClass())) { + return true; + } + } + return false; + } + + public static XLayoutContainer getParent(XCreator source) { + if (source.acceptType(XWCardTagLayout.class) ) { + return (XLayoutContainer)source.getParent(); + } + XLayoutContainer container = XCreatorUtils.getParentXLayoutContainer(source); + boolean accept = (source.acceptType(XWFitLayout.class) || source.acceptType(XWParameterLayout.class)) && !isExtraContainer(source); + if (accept) { + container = null; + } + return container; + } + + /** + * 循环遍历组件,调整组件间隙 + * @param creator + */ + //循环遍历布局,按百分比调整子组件大小 + public static void traverAndAdjust(XCreator creator, double percent) { + for (int i = 0; i < creator.getComponentCount(); i++) { + Object object = creator.getComponent(i); + if (object instanceof XCreator) { + XCreator temp = (XCreator) object; + temp.adjustCompSize(percent); + traverAndAdjust(temp, percent); + } + } + + } + } \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XElementCase.java b/designer-form/src/main/java/com/fr/design/designer/creator/XElementCase.java index cf8b7a7661..f1a4f1716a 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XElementCase.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XElementCase.java @@ -365,4 +365,9 @@ public class XElementCase extends XBorderStyleWidgetCreator implements FormEleme public void releaseResources() { imageLable.setIcon(null); } + + @Override + public boolean isComponent() { + return true; + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java b/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java index f1d4c4f6d3..92c5dd6541 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java @@ -586,4 +586,9 @@ public abstract class XLayoutContainer extends XBorderStyleWidgetCreator impleme public void setDragInAble(boolean dragInAble) { this.dragInAble = dragInAble; } + + @Override + public boolean isComponent() { + return true; + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XCardSwitchButton.java b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XCardSwitchButton.java index 18bab55287..925ea036d2 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XCardSwitchButton.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XCardSwitchButton.java @@ -12,6 +12,7 @@ import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.creator.XButton; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWAbsoluteLayout; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.gui.ilable.UILabel; @@ -27,17 +28,28 @@ import com.fr.form.ui.container.WTabTextDirection; import com.fr.form.ui.container.cardlayout.WCardTagLayout; import com.fr.form.ui.container.cardlayout.WTabFitLayout; import com.fr.general.Background; -import com.fr.general.act.BorderPacker; import com.fr.general.ComparatorUtils; import com.fr.general.FRFont; +import com.fr.general.act.BorderPacker; import com.fr.general.act.TitlePacker; import com.fr.general.cardtag.TemplateStyle; import com.fr.stable.ProductConstants; import com.fr.stable.unit.PT; -import javax.swing.*; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; import javax.swing.plaf.basic.BasicLabelUI; -import java.awt.*; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.geom.Rectangle2D; import java.util.ArrayList; @@ -243,52 +255,43 @@ public class XCardSwitchButton extends XButton { //SwitchButton对应的XWCardLayout和XWCardTagLayout暂未存到xml中,重新打开时根据父子层关系获取 - private void initRelateLayout(){ - this.tagLayout = (XWCardTagLayout)this.getBackupParent(); + private void initRelateLayout() { + this.tagLayout = (XWCardTagLayout) this.getBackupParent(); XWCardTitleLayout titleLayout = (XWCardTitleLayout) this.tagLayout.getBackupParent(); - XWCardMainBorderLayout borderLayout = (XWCardMainBorderLayout)titleLayout.getBackupParent(); + XWCardMainBorderLayout borderLayout = (XWCardMainBorderLayout) titleLayout.getBackupParent(); this.cardLayout = borderLayout.getCardPart(); } - //是否进入点击关闭按钮区域 - private boolean isSelectedClose(MouseEvent e, FormDesigner designer){ + /** + *

是否进入点击关闭按钮区域 + *

计算逻辑: + *

先得到鼠标的绝对坐标 -> tab布局的绝对坐标 -> 得到鼠标相对tab的坐标(有参数面板时要减去参数面板的高度) + *

再计算删除区域位置的相对坐标,通过对比判定鼠标是否在点击关闭按钮区域内,即,鼠标的位置(ex,ey): + *

  • 当前点击tag删除区域的x坐标 < ex < 当前点击tag删除区域的x坐标 + 偏移量
  • + *
  • 当前点击tag删除区域的y坐标 < ey < 当前点击tag删除区域的y坐标 + 偏移量
  • + * + * @param e 鼠标事件 + * @param designer 表单编辑对象 + * @return true/false 在内/不在 + */ + private boolean isSelectedClose(MouseEvent e, FormDesigner designer) { int diff = designer.getHorizontalScaleValue(); // mouse position + // 这里是鼠标的绝对位置 int ex = e.getX() + diff; int ey = e.getY(); - - //获取tab布局的位置,鼠标相对于tab按钮的位置 - Container mainLayout = cardLayout.getBackupParent(); - Point point = mainLayout.getLocation(); - int y = 0; - int x = 0; - //遍历一下,不然是相对位置,嵌套后位置不对 - while (mainLayout.getParent() != null){ - if(mainLayout instanceof XWCardLayout){ - y += mainLayout.getY(); - } - - mainLayout = mainLayout.getParent(); - - if(mainLayout instanceof XWCardMainBorderLayout){ - x += mainLayout.getX(); - y += mainLayout.getY(); - } - } - double mainX = point.getX() + x; - double mainY = point.getY() + y; - + // 获取tab布局的位置,鼠标相对于tab按钮的位置 + double[] tabPositionInBody = getTabAbsolutePositionInBody(); // 参数界面对坐标的影响 JForm jform = (JForm) HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); - if(jform.getFormDesign().getParaComponent() != null){ + if (jform.getFormDesign().getParaComponent() != null) { ey -= jform.getFormDesign().getParaHeight(); } - //减掉tab布局的相对位置 - ex -= mainX; - ey -= mainY; + ex -= tabPositionInBody[0]; + ey -= tabPositionInBody[1]; XLayoutContainer titleLayout = tagLayout.getBackupParent(); Point titlePoint = titleLayout.getLocation(); @@ -298,10 +301,43 @@ public class XCardSwitchButton extends XButton { int width = button.getWidth(); // 鼠标进入按钮右侧删除图标区域 - double recX = position.getX() + titlePoint.getX() + (width - CLOSE_ICON_RIGHT_OFFSET); + double recX = position.getX() + titlePoint.getX() + (width - CLOSE_ICON_RIGHT_OFFSET); double recY = position.getY() + titlePoint.getY() + CLOSE_ICON_TOP_OFFSET; + // 比较的是相对位置的偏移量是否在一定距离内 + // 所以要得到鼠标相对于当前tab块的坐标 + return (recX < ex && ex < recX + CLOSE_ICON_RIGHT_OFFSET && ey < recY && ey > position.getY()); + } + + /** + * 获取tab布局在body内的绝对位置 + * + * @return + */ + private double[] getTabAbsolutePositionInBody() { + // 获取tab布局的位置,鼠标相对于tab按钮的位置 + Container mainLayout = cardLayout.getBackupParent(); + // 这个point是当前tab布局的相对坐标,是相对于父容器的坐标 + // 比如父级是一个absolute块,放在左上角,现在得到的point就是(0,0) + Point point = mainLayout.getLocation(); + int y = 0; + int x = 0; + // 遍历一下,不然是相对位置,嵌套后位置不对 + // 这里是要得到tab布局的绝对位置,所以要加上父组件的位置 + while (mainLayout.getParent() != null) { + if (mainLayout instanceof XWCardLayout) { + y += mainLayout.getY(); + } + + mainLayout = mainLayout.getParent(); - return (recX < ex && ex < recX + CLOSE_ICON_RIGHT_OFFSET && ey < recY && ey > position.getY()); + if ((mainLayout instanceof XWCardMainBorderLayout) || (mainLayout instanceof XWAbsoluteLayout)) { + x += mainLayout.getX(); + y += mainLayout.getY(); + } + } + double mainX = point.getX() + x; + double mainY = point.getY() + y; + return new double[]{mainX, mainY}; } //将当前switchButton改为选中状态 @@ -313,7 +349,7 @@ public class XCardSwitchButton extends XButton { } } - @Override + @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; 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 e1d4a416e7..1f9eb4572e 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 @@ -7,6 +7,7 @@ import com.fr.base.background.ColorBackground; import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.adapters.layout.FRCardLayoutAdapter; import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.beans.models.ModelUtil; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.creator.CRPropertyDescriptor; import com.fr.design.designer.creator.XCreator; @@ -21,6 +22,7 @@ import com.fr.design.mainframe.WidgetPropertyPane; import com.fr.design.mainframe.widget.editors.BooleanEditor; import com.fr.design.mainframe.widget.editors.CardTagWLayoutBorderStyleEditor; import com.fr.design.mainframe.widget.editors.DoubleEditor; +import com.fr.form.main.Form; import com.fr.form.ui.CardAddButton; import com.fr.form.ui.CardSwitchButton; import com.fr.form.ui.LayoutBorderStyle; @@ -39,6 +41,7 @@ import com.fr.general.cardtag.DefaultTemplateStyle; import com.fr.general.cardtag.TemplateStyle; import com.fr.stable.ArrayUtils; import com.fr.stable.Constants; +import com.fr.stable.StringUtils; import com.fr.stable.core.PropertyChangeAdapter; import javax.swing.border.Border; @@ -62,10 +65,6 @@ public class XWCardLayout extends XLayoutContainer { public static final String DEFAULT_NAME = "cardlayout"; - - //默认蓝色标题背景 - private static final Color TITLE_COLOR = new Color(51, 132, 240); - public XWCardLayout(WCardLayout widget, Dimension initSize) { super(widget, initSize); } @@ -250,7 +249,13 @@ public class XWCardLayout extends XLayoutContainer { */ @Override protected void setWrapperName(XLayoutContainer parentPanel, String widgetName) { - parentPanel.toData().setWidgetName("tablayout" + widgetName.replaceAll(createDefaultName(), "")); + FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); + Form form = formDesigner.getTarget(); + String name = "tablayout" + widgetName.replaceAll(createDefaultName(), StringUtils.EMPTY); + if (form.isNameExist(name)) { + name = ModelUtil.uniqueName(formDesigner.getTarget(), parentPanel.createDefaultName()); + } + parentPanel.toData().setWidgetName(name); } /** @@ -399,24 +404,10 @@ public class XWCardLayout extends XLayoutContainer { @Override public void refreshStylePreviewEffect() { BorderPacker style = toData().getBorderStyle(); - initBorderTitleStyle(style); refreshBorderAndBackgroundStylePreviewEffect(); clearOrShowTitleLayout(ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)); } - 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; - } - //隐藏或显示标题部分 protected void clearOrShowTitleLayout(boolean isTitleStyle) { XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout) this.getBackupParent(); diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java index 0db348a399..4e32eb1bdf 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java @@ -52,7 +52,7 @@ import java.util.List; * @date: 2014-12-9-下午9:59:31 */ public class XWCardMainBorderLayout extends XWBorderLayout { - + private static final String DEFAULT_NAME = "tablayout"; private static final int BORDER_WIDTH = 4; private static final Color OUTER_BORDER_COLOR = new Color(65, 155, 249, 30); @@ -85,6 +85,17 @@ public class XWCardMainBorderLayout extends XWBorderLayout { return (WCardMainBorderLayout) super.toData(); } + /** + * 获取默认名字 + * + * @return 默认名 + * @date 2014-11-25-下午6:22:40 + */ + @Override + public String createDefaultName() { + return DEFAULT_NAME; + } + /** * 添加标题区域 * @@ -472,4 +483,9 @@ public class XWCardMainBorderLayout extends XWBorderLayout { public void setShowOuterShadowBorder(boolean showOuterShadowBorder) { this.showOuterShadowBorder = showOuterShadowBorder; } + + @Override + public void recalculateChildrenSize() { + + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java index 010a382178..523b07a4b3 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java @@ -9,6 +9,7 @@ import com.fr.design.designer.beans.AdapterBus; import com.fr.design.designer.beans.ComponentAdapter; import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.adapters.layout.FRWCardTagLayoutAdapter; +import com.fr.design.designer.beans.models.ModelUtil; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreatorUtils; @@ -24,20 +25,24 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.mainframe.EditingMouseListener; import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.FormHierarchyTreePane; import com.fr.design.mainframe.WidgetPropertyPane; +import com.fr.design.utils.gui.LayoutUtils; import com.fr.form.ui.CardSwitchButton; import com.fr.form.ui.Widget; import com.fr.form.ui.container.WCardLayout; import com.fr.form.ui.container.WTabDisplayPosition; import com.fr.form.ui.container.cardlayout.WCardTagLayout; import com.fr.form.ui.container.cardlayout.WTabFitLayout; -import com.fr.general.act.BorderPacker; import com.fr.general.ComparatorUtils; import com.fr.general.FRFont; +import com.fr.general.act.BorderPacker; import com.fr.general.cardtag.DefaultTemplateStyle; import javax.swing.border.Border; -import java.awt.*; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Rectangle; import java.awt.event.ContainerEvent; import java.awt.event.MouseEvent; import java.util.HashMap; @@ -137,6 +142,8 @@ public class XWCardTagLayout extends XWHorizontalBoxLayout { WTabFitLayout fitLayout = new WTabFitLayout(widgetName, tabFitIndex, currentCard); fitLayout.setTabNameIndex(getTabNameIndex()); XWTabFitLayout tabFitLayout = new XWTabFitLayout(fitLayout, new Dimension()); + FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); + ModelUtil.renameWidgetName(formDesigner.getTarget(), tabFitLayout); WCardTagLayout layout = (WCardTagLayout) this.toData(); if(!ComparatorUtils.equals(layout.getTemplateStyle().getStyle(), DefaultTemplateStyle.DEFAULT_TEMPLATE_STYLE)){ @@ -438,7 +445,7 @@ public class XWCardTagLayout extends XWHorizontalBoxLayout { } - private void fixTitleLayout(XLayoutContainer parent){ + private void fixTitleLayout(XLayoutContainer parent) { FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); LayoutAdapter layoutAdapter = AdapterBus.searchLayoutAdapter(formDesigner, parent); if (layoutAdapter != null) { @@ -447,4 +454,31 @@ public class XWCardTagLayout extends XWHorizontalBoxLayout { } } + /** + *

    对于tab组件,WCardMainBorderLayout里面有两个子容器: + *

  • WCardTitleLayout,里面包含两个部分,一个是CardAddButton,另一个是WCardTagLayout - tabpane0
  • + *
  • WCardLayout,里面放的是WTabFitLayout - tab00、tab10
  • + *

    在右侧组件树选择删除WCardTagLayout时(tabpane0),按照现在的产品逻辑,应该删除整个tab组件 + * + * @param creator 组件 + * @param designer 表单设计器 + */ + @Override + public void deleteRelatedComponent(XCreator creator, FormDesigner designer) { + XWCardTagLayout tagLayout = (XWCardTagLayout) creator; + // 先删除所有tab按钮 + tagLayout.removeAll(); + //逐层回溯找出最外层的XWCardMainBorderLayout + XWCardTitleLayout cardTitleLayout = (XWCardTitleLayout) tagLayout.getBackupParent(); + XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout) cardTitleLayout.getBackupParent(); + // 删除tab布局 + SelectionModel selectionModel = designer.getSelectionModel(); + if (mainLayout != null) { + selectionModel.setSelectedCreator(mainLayout); + selectionModel.deleteSelection(); + } + LayoutUtils.layoutRootContainer(designer.getRootComponent()); + FormHierarchyTreePane.getInstance().refreshRoot(); + selectionModel.setSelectedCreator(designer.getRootComponent()); + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/ui/PopupDialogContext.java b/designer-form/src/main/java/com/fr/design/designer/ui/PopupDialogContext.java new file mode 100644 index 0000000000..06fb2cb765 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/designer/ui/PopupDialogContext.java @@ -0,0 +1,47 @@ +package com.fr.design.designer.ui; + +import com.fr.design.designer.creator.XCreator; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + + +/** + * 把弹窗统一管理起来 防止出现异常情况下游离的弹窗 + * + * @author hades + * @version 10.0 + * Created by hades on 2021/11/02 + */ +public class PopupDialogContext { + + private static List dialogs = new ArrayList<>(); + + public static void add(SelectedPopupDialog selectedPopupDialog) { + if (dialogs.contains(selectedPopupDialog)) { + return; + } + dialogs.add(selectedPopupDialog); + } + + public static void remove(SelectedPopupDialog selectedPopupDialog) { + dialogs.remove(selectedPopupDialog); + } + + public static void checkSelectedPop(XCreator creator) { + Iterator iterator = dialogs.iterator(); + List removedDialog = new ArrayList<>(); + while (iterator.hasNext()) { + SelectedPopupDialog dialog = iterator.next(); + if (dialog.isVisible() && creator != dialog.getCreator()) { + iterator.remove(); + removedDialog.add(dialog); + } + } + for (SelectedPopupDialog dialog : removedDialog) { + dialog.setVisible(false); + } + } + +} diff --git a/designer-form/src/main/java/com/fr/design/designer/ui/SelectedPopupDialog.java b/designer-form/src/main/java/com/fr/design/designer/ui/SelectedPopupDialog.java index 44978ad667..22f0d3760d 100644 --- a/designer-form/src/main/java/com/fr/design/designer/ui/SelectedPopupDialog.java +++ b/designer-form/src/main/java/com/fr/design/designer/ui/SelectedPopupDialog.java @@ -25,11 +25,14 @@ public class SelectedPopupDialog extends JDialog { private boolean canVisible = true; + private final XCreator creator; + public SelectedPopupDialog(XCreator creator, FormDesigner designer) { super(OperatingSystem.isMacos() ? new JFrame() : DesignerContext.getDesignerFrame()); this.setUndecorated(true); this.setModal(false); this.setFocusableWindowState(false); + this.creator = creator; controlPanel = new PopupControlPanel(creator, designer); this.getContentPane().add(controlPanel); this.setSize(controlPanel.getDefaultDimension()); @@ -44,6 +47,16 @@ public class SelectedPopupDialog extends JDialog { return controlPanel.hasVisibleButtons(); } + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible) { + PopupDialogContext.add(this); + } else { + PopupDialogContext.remove(this); + } + } + public void setRelativeBounds(Rectangle rectangle) { this.controlPanel.setRelativeBounds(rectangle); } @@ -55,4 +68,8 @@ public class SelectedPopupDialog extends JDialog { public void setCanVisible(boolean canVisible) { this.canVisible = canVisible; } + + public XCreator getCreator() { + return this.creator; + } } diff --git a/designer-form/src/main/java/com/fr/design/form/util/FontTransformUtil.java b/designer-form/src/main/java/com/fr/design/form/util/FontTransformUtil.java index 769707ebe5..eab2a64bb3 100644 --- a/designer-form/src/main/java/com/fr/design/form/util/FontTransformUtil.java +++ b/designer-form/src/main/java/com/fr/design/form/util/FontTransformUtil.java @@ -5,6 +5,7 @@ import com.fr.design.ExtraDesignClassManager; import com.fr.design.fun.FormAdaptiveConfigUIProcessor; import com.fr.stable.Constants; import com.fr.stable.unit.PT; +import java.math.BigDecimal; /** @@ -43,4 +44,11 @@ public class FontTransformUtil { return value * (double) Constants.DEFAULT_FONT_PAINT_RESOLUTION / (double) getDesignerFontResolution(); } + + public static int roundUp(double num) { + String numStr = Double.toString(num); + numStr = new BigDecimal(numStr).setScale(0, BigDecimal.ROUND_HALF_UP).toString(); + return Integer.valueOf(numStr); + } + } diff --git a/designer-form/src/main/java/com/fr/design/form/util/HtmlPaintUtils.java b/designer-form/src/main/java/com/fr/design/form/util/HtmlPaintUtils.java new file mode 100644 index 0000000000..f8620f52d2 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/form/util/HtmlPaintUtils.java @@ -0,0 +1,42 @@ +package com.fr.design.form.util; + +import com.fr.base.Style; +import com.fr.general.FRFont; +import com.fr.log.FineLoggerFactory; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 富文本导出工具栏 + * + * @author hades + * @version 11.0 + * Created by hades on 2022/5/19 + */ +public class HtmlPaintUtils { + + + private static final Pattern FONT_SIZE_PATTERN = Pattern.compile(Pattern.quote("font-size:") + "(.*?)" + Pattern.quote("px")); + + /** + * 设置单元格字体为富文本中的最大字体 + * + * @param style + */ + public static Style deriveMaxFontFromRichChar(Style style, String html) { + int maxSize = style.getFRFont().getSize(); + Matcher matcher = FONT_SIZE_PATTERN.matcher(html); + while (matcher.find()) { + String value = matcher.group(1); + try { + double pxSize = Double.parseDouble(value); + int ptSize = FontTransformUtil.roundUp(FontTransformUtil.px2pt(pxSize)); + maxSize = Math.max(maxSize, ptSize); + } catch (Throwable e) { + FineLoggerFactory.getLogger().debug(e.getMessage(), e); + } + } + FRFont cellFont = style.getFRFont(); + return style.deriveFRFont(cellFont.applySize(maxSize)); + } +} diff --git a/designer-form/src/main/java/com/fr/design/gui/xpane/BorderLineAndImagePane.java b/designer-form/src/main/java/com/fr/design/gui/xpane/BorderLineAndImagePane.java index 0f2b853d1b..47ea7fb0de 100644 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/BorderLineAndImagePane.java +++ b/designer-form/src/main/java/com/fr/design/gui/xpane/BorderLineAndImagePane.java @@ -31,6 +31,7 @@ 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.i18n.UrlI18nManager; import com.fr.stable.Constants; import com.fr.stable.GraphDrawHelper; import com.fr.stable.ProjectLibrary; @@ -121,7 +122,7 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { public void actionPerformed(ActionEvent e) { Desktop desktop = Desktop.getDesktop(); try { - desktop.browse(new URI(TWEAK_NINE_POINT_HELP_URL)); + desktop.browse(new URI(UrlI18nManager.getInstance().getI18nUrl("nine.point.help"))); } catch (IOException | URISyntaxException ioException) { ioException.printStackTrace(); } @@ -297,15 +298,16 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { Background borderImage = style.getBorderImage(); if (borderImage instanceof ImageBackground) { // 图片类型边框 - Image image = ((ImageBackground) borderImage).getImage(); - int[] ninePoint = ((ImageBackground) borderImage).getNinePoint(); + ImageBackground imageBackground = (ImageBackground) borderImage; + Image image = imageBackground.getImage(); if (image != null) { this.borderLineCombo.selectBorderImage(); this.imagePreviewPane.setImageWithSuffix(((ImageBackground) borderImage).getImageWithSuffix()); this.tweakNinePointButton.setEnabled(true); this.borderImageOpacityPane.populateBean(style.getBorderImageOpacity()); - if (ninePoint != null && ninePoint.length == 4 && ninePoint[0] > 0 && ninePoint[1] > 0 && ninePoint[2] > 0 && ninePoint[3] > 0) { + int[] ninePoint = ((ImageBackground) borderImage).getNinePoint(); + if (ninePoint != null && ninePoint.length == 4 && ninePoint[0] >= 0 && ninePoint[1] >= 0 && ninePoint[2] >= 0 && ninePoint[3] >= 0) { this.ninePoint = Arrays.copyOf(ninePoint, 4); } else { this.ninePoint = new int[4]; @@ -502,6 +504,7 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { private int ninePointBottom = -1; private static final int MIN_NINE_POINT = 0; + private static final int MIN_GAP_PARALLEL_LINES = 1; private int imgWidth; private int imgHeight; @@ -772,8 +775,8 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { private void onNinePointTopChanged(int value) { if (value < MIN_NINE_POINT) { value = MIN_NINE_POINT; - } else if (value >= imgHeight - ninePointBottom) { - value = imgHeight - ninePointBottom - MIN_NINE_POINT; + } else if (value >= imgHeight - ninePointBottom - MIN_GAP_PARALLEL_LINES) { + value = imgHeight - ninePointBottom - MIN_GAP_PARALLEL_LINES; } this.ninePointTop = value; repaint(); @@ -782,8 +785,8 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { private void onNinePointBottomChanged(int value) { if (value < MIN_NINE_POINT) { value = MIN_NINE_POINT; - } else if (value >= imgHeight - ninePointTop) { - value = imgHeight - ninePointTop - MIN_NINE_POINT; + } else if (value >= imgHeight - ninePointTop - MIN_GAP_PARALLEL_LINES) { + value = imgHeight - ninePointTop - MIN_GAP_PARALLEL_LINES; } this.ninePointBottom = value; repaint(); @@ -792,8 +795,8 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { private void onNinePointLeftChanged(int value) { if (value < MIN_NINE_POINT) { value = MIN_NINE_POINT; - } else if (value >= imgWidth - ninePointRight) { - value = imgWidth - ninePointRight - MIN_NINE_POINT; + } else if (value >= imgWidth - ninePointRight - MIN_GAP_PARALLEL_LINES) { + value = imgWidth - ninePointRight - MIN_GAP_PARALLEL_LINES; } this.ninePointLeft = value; repaint(); @@ -802,8 +805,8 @@ public class BorderLineAndImagePane extends JPanel implements UIObserver { private void onNinePointRightChanged(int value) { if (value < MIN_NINE_POINT) { value = MIN_NINE_POINT; - } else if (value >= imgWidth - ninePointLeft) { - value = imgWidth - ninePointLeft - MIN_NINE_POINT; + } else if (value >= imgWidth - ninePointLeft - MIN_GAP_PARALLEL_LINES) { + value = imgWidth - ninePointLeft - MIN_GAP_PARALLEL_LINES; } this.ninePointRight = value; repaint(); 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 37db551027..ab953166cf 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 @@ -3,6 +3,8 @@ */ package com.fr.design.gui.xpane; +import com.fr.form.ui.LayoutBorderStyle; + import javax.swing.JPanel; /** @@ -10,6 +12,8 @@ import javax.swing.JPanel; */ public class CardTagLayoutStylePane extends LayoutStylePane { + private LayoutBorderStyle backupStyleFromPopulating = new LayoutBorderStyle(); + @Override protected JPanel createTitleStylePane(){ JPanel panel = super.createTitleStylePane(); @@ -21,4 +25,18 @@ public class CardTagLayoutStylePane extends LayoutStylePane { protected JPanel createBackgroundStylePane(boolean supportCornerRadius) { return super.createBackgroundStylePane(false); } + + @Override + public void populateBean(LayoutBorderStyle style) { + this.backupStyleFromPopulating = style; + super.populateBean(style); + } + + @Override + public LayoutBorderStyle updateBean() { + LayoutBorderStyle style = super.updateBean(); + style.setTitle(backupStyleFromPopulating.getTitle()); + style.setType(backupStyleFromPopulating.getType()); + return style; + } } diff --git a/designer-form/src/main/java/com/fr/design/gui/xpane/FormHyperlinkGroupPane.java b/designer-form/src/main/java/com/fr/design/gui/xpane/FormHyperlinkGroupPane.java index 7afb15828e..4c3b769a38 100644 --- a/designer-form/src/main/java/com/fr/design/gui/xpane/FormHyperlinkGroupPane.java +++ b/designer-form/src/main/java/com/fr/design/gui/xpane/FormHyperlinkGroupPane.java @@ -1,13 +1,14 @@ package com.fr.design.gui.xpane; +import com.fr.chart.web.ChartHyperRelateFloatLink; import com.fr.design.form.javascript.FormEmailPane; import com.fr.design.gui.controlpane.NameObjectCreator; import com.fr.design.gui.controlpane.NameableCreator; import com.fr.design.gui.frpane.HyperlinkGroupPane; import com.fr.design.gui.frpane.HyperlinkGroupPaneActionProvider; import com.fr.general.ComparatorUtils; - import com.fr.js.EmailJavaScript; +import com.fr.js.JavaScript; public class FormHyperlinkGroupPane extends HyperlinkGroupPane { private static FormHyperlinkGroupPane singleton; @@ -23,6 +24,16 @@ public class FormHyperlinkGroupPane extends HyperlinkGroupPane { return singleton; } + @Override + protected void initCreatorsFilter() { + this.creatorsFilter = nameableCreator -> { + Class clazz = nameableCreator.getHyperlink(); + // 决策报表没有 ChartHyperRelateFloatLink + return !ComparatorUtils.equals(clazz, ChartHyperRelateFloatLink.class); + }; + } + + /** * 生成添加按钮的NameableCreator * 由于表单报表块的单元格超链和单元格条件属性超链中的emailPane都要用表单的emailPane,这里调整下 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 453bd5e0da..1d521cd6f0 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 @@ -22,6 +22,7 @@ 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.design.widget.FRWidgetFactory; import com.fr.form.ui.LayoutBorderStyle; import com.fr.form.ui.WidgetTitle; import com.fr.general.Background; @@ -30,11 +31,23 @@ 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.Icon; +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.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Stroke; /** * @author Starryi @@ -145,16 +158,16 @@ public class LayoutStylePane extends BasicBeanPane { 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")); + UILabel uiLabel = FRWidgetFactory.createLineWrapLabel(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}, + {FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Render_Style")), createBorderLayoutNorthPaneWithComponent(borderStyleCombo)}, {this.borderLineAndImagePane, null}, - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Radius")), cornerSpinner}, + {FRWidgetFactory.createLineWrapLabel(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)); @@ -180,7 +193,7 @@ public class LayoutStylePane extends BasicBeanPane { this.backgroundPane, this.backgroundOpacityPane); - UILabel uiLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Content")); + UILabel uiLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Body_Content")); Font font = uiLabel.getFont().deriveFont(Font.BOLD); uiLabel.setFont(font); uiLabel.setForeground(new Color(143, 143, 146)); @@ -297,11 +310,11 @@ public class LayoutStylePane extends BasicBeanPane { 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}, + {FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Content")), titleTextPane}, + {FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Format")), createBorderLayoutNorthPaneWithComponent(titleFontFamilyComboBox)}, {null, createTitleFontButtonPane()}, {titleInsetImagePane, null}, - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Text_Align")), titleAlignPane}, + {FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Style_Title_Text_Align")), titleAlignPane}, {this.createTitleBackgroundAndOpacityPane(), null}, }, rowSize, columnSize, IntervalConstants.INTERVAL_L1); @@ -312,9 +325,9 @@ public class LayoutStylePane extends BasicBeanPane { 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); + visibleComposedPane.add(FRWidgetFactory.createLineWrapLabel(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")); + UILabel uiLabel = FRWidgetFactory.createLineWrapLabel(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)); @@ -339,6 +352,12 @@ public class LayoutStylePane extends BasicBeanPane { return container; } + private JPanel createBorderLayoutNorthPaneWithComponent(JComponent content) { + JPanel jPanel = new JPanel(new BorderLayout()); + jPanel.add(content, BorderLayout.NORTH); + return jPanel; + } + protected JPanel createTitleFontButtonPane(){ double p = TableLayout.PREFERRED; double f = TableLayout.FILL; @@ -511,8 +530,8 @@ public class LayoutStylePane extends BasicBeanPane { // 确保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); + backgroundLabelPane.setBorder(BorderFactory.createEmptyBorder(7, 0, 0, 0)); + backgroundLabelPane.add(FRWidgetFactory.createLineWrapLabel(name), BorderLayout.NORTH); JPanel backgroundComposedPane = TableLayoutHelper.createGapTableLayoutPane( new JComponent[][]{ @@ -522,7 +541,7 @@ public class LayoutStylePane extends BasicBeanPane { JPanel opacityComposedPane = TableLayoutHelper.createGapTableLayoutPane( new JComponent[][]{ - {new UILabel(""), new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget-Style_Alpha"))}, + {new UILabel(""), FRWidgetFactory.createLineWrapLabel(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); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/ArrangementType.java b/designer-form/src/main/java/com/fr/design/mainframe/ArrangementType.java new file mode 100644 index 0000000000..58f4b34643 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/ArrangementType.java @@ -0,0 +1,33 @@ +package com.fr.design.mainframe; + +public enum ArrangementType { + LEFT_ALIGN(0), + RIGHT_ALIGN(1), + TOP_ALIGN(2), + BOTTOM_ALIGN(3), + HORIZONTAL_CENTER_ALIGN(4), + VERTICAL_CENTER_ALIGN(5), + HORIZONTAL_AUTO_DISTRIBUTION(6), + HORIZONTAL_MANUAL_DISTRIBUTION(7), + VERTICAL_AUTO_DISTRIBUTION(8), + VERTICAL_MANUAL_DISTRIBUTION(9); + + private int type; + + ArrangementType(int type) { + this.type = type; + } + + public int getType() { + return this.type; + } + + public static ArrangementType parse(int type) { + for (ArrangementType arrangementType : ArrangementType.values()) { + if (arrangementType.getType() == type) { + return arrangementType; + } + } + return LEFT_ALIGN; + } +} 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 23e08e5cfb..236843f0a8 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 @@ -5,6 +5,7 @@ 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.XCreatorUtils; import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.XWBorderLayout; import com.fr.design.designer.creator.XWFitLayout; @@ -428,7 +429,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent { if (root.acceptType(XWFitLayout.class)) { XWFitLayout layout = (XWFitLayout) root; layout.setContainerPercent(value / DEFAULT_SLIDER); - traverAndAdjust(layout, percent); + XCreatorUtils.traverAndAdjust(layout, percent); layout.adjustCreatorsWhileSlide(percent); // 拖动滑块,先将内部组件百分比大小计算,再计算容器大小 @@ -464,7 +465,7 @@ public class FormArea extends JComponent implements ScrollRulerComponent { if (root.acceptType(XWFitLayout.class)) { XWFitLayout layout = (XWFitLayout) root; layout.setContainerPercent(1.0); - traverAndAdjust(layout, 0.0); + XCreatorUtils.traverAndAdjust(layout, 0.0); layout.adjustCreatorsWhileSlide(0.0); // 拖动滑块,先将内部组件百分比大小计算,再计算容器大小 @@ -487,19 +488,6 @@ public class FormArea extends JComponent implements ScrollRulerComponent { } } - //循环遍历布局,按百分比调整子组件大小 - private void traverAndAdjust(XCreator creator, double percent) { - for (int i = 0; i < creator.getComponentCount(); i++) { - Object object = creator.getComponent(i); - if (object instanceof XCreator) { - XCreator temp = (XCreator) object; - temp.adjustCompSize(percent); - traverAndAdjust(temp, percent); - } - } - - } - /** * 增加刻度条 */ 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 7a6a73f4ba..c1a08dded4 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 @@ -18,6 +18,7 @@ import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.XWAbsoluteLayout; import com.fr.design.designer.creator.XWFitLayout; import com.fr.design.designer.creator.XWParameterLayout; +import com.fr.design.dialog.FineJOptionPane; import com.fr.design.form.util.XCreatorConstants; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.icon.IconPathConstants; @@ -27,19 +28,19 @@ 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.log.FineLoggerFactory; 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.JOptionPane; import javax.swing.JWindow; -import java.util.List; -import java.util.Map; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; import java.awt.Color; import java.awt.Component; import java.awt.Point; @@ -49,7 +50,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; /** * 添加模式下鼠标事件处理器。 @@ -141,7 +145,9 @@ public class FormCreatorDropTarget extends DropTarget { } designer.getSelectionModel().setSelectedCreators( FormSelectionUtils.rebuildSelection(xCreator, new Widget[]{widget})); - designer.getEditListenerTable().fireCreatorModified(addingModel.getXCreator(), DesignerEvent.CREATOR_ADDED); + if (!addingModel.isAddedIllegal()) { + designer.getEditListenerTable().fireCreatorModified(addingModel.getXCreator(), DesignerEvent.CREATOR_ADDED); + } tabDragInner.tryDragIn(); } else { Toolkit.getDefaultToolkit().beep(); @@ -316,6 +322,24 @@ public class FormCreatorDropTarget extends DropTarget { */ @Override public synchronized void drop(DropTargetDropEvent dtde) { + + try { + dropXCreator(dtde); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + if (addingModel.getXCreator().isShared()) { + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Drag_Component_Error_Info"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Error"), + JOptionPane.ERROR_MESSAGE, + UIManager.getIcon("OptionPane.errorIcon") + ); + } + dtde.rejectDrop(); + } + } + + private void dropXCreator(DropTargetDropEvent dtde) { Point loc = dtde.getLocation(); this.adding(designer.getRelativeX(loc.x), designer.getRelativeY(loc.y)); // 放到事件末尾执行 diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java b/designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java index 09e02ac670..9eb11607c6 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java @@ -7,6 +7,7 @@ import com.fr.design.constants.UIConstants; import com.fr.design.designer.beans.events.DesignerEditListener; import com.fr.design.designer.beans.events.DesignerEvent; import com.fr.design.designer.creator.XCreatorUtils; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fun.FormWidgetOptionProvider; import com.fr.design.gui.chart.ChartXMLTag; import com.fr.design.gui.core.FormWidgetOption; @@ -19,6 +20,7 @@ import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.share.collect.ComponentCollector; import com.fr.design.module.DesignModuleFactory; +import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.gui.LayoutUtils; import com.fr.form.ui.UserDefinedWidgetConfig; import com.fr.form.ui.Widget; @@ -39,10 +41,6 @@ import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JSeparator; import javax.swing.SwingConstants; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Cursor; @@ -53,6 +51,10 @@ import java.awt.event.ComponentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; /** * @author null @@ -99,6 +101,15 @@ public class FormParaWidgetPane extends JPanel { synchronized (FormParaWidgetPane.class) { THIS = null; } + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (template != null && !template.isJWorkBook()) { + DesignerContext.getDesignerFrame().resetToolkitByPlus(template); + } + } + }); } }, new PluginFilter() { @@ -185,7 +196,9 @@ public class FormParaWidgetPane extends JPanel { JPanel componentsPara = new JPanel(new FlowLayout(FlowLayout.LEFT)); WidgetOption[] chartOptions = loadChartOptions(); for (WidgetOption chartOption : chartOptions) { - componentsPara.add(new ToolBarButton(chartOption)); + ToolBarButton button = new ToolBarButton(chartOption); + button.setPreferredSize(new Dimension(widgetButtonWidth, widgetButtonHeight)); + componentsPara.add(button); } int x = COMMON_CHAR_NUM * (widgetButtonWidth + smallGAP); int y = (int) Math.ceil(chartOptions.length / ((double) COMMON_CHAR_NUM)) * (widgetButtonHeight + smallGAP); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormSelectionUtils.java b/designer-form/src/main/java/com/fr/design/mainframe/FormSelectionUtils.java index 7d3b17f5b7..257ec423aa 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormSelectionUtils.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormSelectionUtils.java @@ -16,6 +16,7 @@ import com.fr.design.designer.creator.XWTitleLayout; import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; import com.fr.design.fun.FormWidgetOptionProvider; import com.fr.design.utils.ComponentUtils; +import com.fr.design.utils.gui.LayoutUtils; import com.fr.form.main.Form; import com.fr.form.ui.Widget; import com.fr.form.ui.container.WTitleLayout; @@ -291,6 +292,9 @@ public class FormSelectionUtils { public static XCreator copyXcreator(Form form, XCreator xCreator) throws CloneNotSupportedException{ Widget copied = (Widget) xCreator.toData().clone(); XCreator copiedCreator = XCreatorUtils.createXCreator(copied, xCreator.getSize()); + //主要用来处理组件间隔和padding,保证界面上展示的组件尺寸是计算过padding和组件间隔的 + LayoutUtils.layoutContainer(copiedCreator); + XCreatorUtils.traverAndAdjust(copiedCreator, 0.0); ArrayList nameSpace = new ArrayList<>(); copyWidgetName(form, nameSpace, copiedCreator); return copiedCreator; diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormWidgetDetailPane.java b/designer-form/src/main/java/com/fr/design/mainframe/FormWidgetDetailPane.java index d792f0eca2..13857c5968 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormWidgetDetailPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormWidgetDetailPane.java @@ -6,10 +6,13 @@ import com.fr.design.gui.ibutton.UIHeadGroup; import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.locale.impl.ShowOnlineWidgetMark; import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo; import com.fr.design.mainframe.share.collect.ComponentCollector; import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane; +import com.fr.general.locale.LocaleCenter; +import com.fr.general.locale.LocaleMark; import javax.swing.BorderFactory; import javax.swing.Icon; @@ -31,6 +34,7 @@ import java.util.List; * Time: 下午8:18 */ public class FormWidgetDetailPane extends FormDockView{ + private static final int LOCAL_TAB = 0; private static final int ONLINE_TAB = 1; private JPanel centerPane; @@ -96,17 +100,22 @@ public class FormWidgetDetailPane extends FormDockView{ } headGroup = new UIHeadGroup(paneNames) { protected void tabChanged(int newSelectedIndex) { - if (newSelectedIndex == 1) { + //初始化还未展示的时候不需要收集其 marketClick + if (this.isShowing() && newSelectedIndex == 1) { ComponentCollector.getInstance().collectMarkerClick(); } cardLayout.show(centerPane, paneList.get(newSelectedIndex).getTitle()); } }; - headGroup.setSelectedIndex(ComponentReuseNotificationInfo.getInstance().isClickedWidgetLib() ? 0 : ONLINE_TAB); + headGroup.setSelectedIndex(isNeedSwitchToOnlineTab() ? ONLINE_TAB : LOCAL_TAB); this.add(headGroup, BorderLayout.NORTH); this.add(centerPane, BorderLayout.CENTER); } + private boolean isNeedSwitchToOnlineTab() { + return !ComponentReuseNotificationInfo.getInstance().isClickedWidgetLib() && isShowOnlineWidgetRepoPane(); + } + public void resetEmptyPane(){ this.isEmptyPane = false; } @@ -164,7 +173,13 @@ public class FormWidgetDetailPane extends FormDockView{ private void initPaneList() { paneList = new ArrayList<>(); paneList.add(LocalWidgetRepoPane.getInstance()); - paneList.add(OnlineWidgetRepoPane.getInstance()); + if (isShowOnlineWidgetRepoPane()) { + paneList.add(OnlineWidgetRepoPane.getInstance()); + } } + private boolean isShowOnlineWidgetRepoPane() { + LocaleMark localeMark = LocaleCenter.getMark(ShowOnlineWidgetMark.class); + return localeMark.getValue(); + } } 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 0bee88e903..66dc972c42 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 @@ -16,6 +16,7 @@ import com.fr.design.actions.core.WorkBookSupportable; import com.fr.design.actions.file.export.EmbeddedFormExportExportAction; import com.fr.design.base.mode.DesignModeContext; import com.fr.design.cell.FloatElementsProvider; +import com.fr.design.constants.TableDataConstants; import com.fr.design.data.datapane.TableDataTreePane; import com.fr.design.designer.TargetComponent; import com.fr.design.designer.beans.actions.CopyAction; @@ -576,7 +577,7 @@ public class JForm extends JTemplate implements BaseJForm implements BaseJForm selectedCreators; private Rectangle rec; public MultiSelectionArrangement(FormDesigner designer) { this.designer = designer; - update(); } - public void leftAlign() { + public void doArrangement(ArrangementType type) { + doArrangement(type, DEFAULT_GAP); + } + + public void doArrangement(ArrangementType type, int gap) { + updatePosition(); + switch (type) { + case RIGHT_ALIGN: + rightAlign(); + break; + case TOP_ALIGN: + topAlign(); + break; + case BOTTOM_ALIGN: + bottomAlign(); + break; + case HORIZONTAL_CENTER_ALIGN: + horizontalCenterAlign(); + break; + case VERTICAL_CENTER_ALIGN: + verticalCenterAlign(); + break; + case HORIZONTAL_AUTO_DISTRIBUTION: + horizontalAutoDistribution(); + break; + case HORIZONTAL_MANUAL_DISTRIBUTION: + horizontalManualDistribution(gap); + break; + case VERTICAL_AUTO_DISTRIBUTION: + verticalAutoDistribution(); + break; + case VERTICAL_MANUAL_DISTRIBUTION: + verticalManualDistribution(gap); + break; + case LEFT_ALIGN: + default: + leftAlign(); + break; + } + updateModel(); + } + + private void leftAlign() { for (XCreator creator : selectedCreators) { creator.setLocation(rec.x, creator.getY()); } - update(); } - public void rightAlign() { + private void rightAlign() { for (XCreator creator : selectedCreators) { creator.setLocation(rec.x + rec.width - creator.getWidth(), creator.getY()); } - update(); } - public void topAlign() { + private void topAlign() { for (XCreator creator : selectedCreators) { creator.setLocation(creator.getX(), rec.y); } - update(); } - public void bottomAlign() { + private void bottomAlign() { for (XCreator creator : selectedCreators) { creator.setLocation(creator.getX(), rec.y + rec.height - creator.getHeight()); } - update(); } - public void horizontalCenterAlign() { + private void horizontalCenterAlign() { for (XCreator creator : selectedCreators) { creator.setLocation(rec.x + rec.width / 2 - creator.getWidth() / 2, creator.getY()); } - update(); } - public void verticalCenterAlign() { + private void verticalCenterAlign() { for (XCreator creator : selectedCreators) { creator.setLocation(creator.getX(), rec.y + rec.height / 2 - creator.getHeight() / 2); } - update(); } // 水平分布,自动,间距由selectedCreators和border共同计算而来 - public void horizontalAutoDistribution() { + private void horizontalAutoDistribution() { sortHorizontal(); int[] gaps = calculateHorizontalGaps(); horizontalDistribution(gaps); } // 水平分布,手动,传入一个间距,排列selectedCreators - public void horizontalManualDistribution(int gap) { + private void horizontalManualDistribution(int gap) { sortHorizontal(); reSizeRecByHorizontal(gap); horizontalDistribution(fillGaps(gap, selectedCreators.size() - 1)); @@ -87,7 +123,6 @@ public class MultiSelectionArrangement { XCreator preCreator = selectedCreators.get(i - 1); creator.setLocation(preCreator.getX() + preCreator.getWidth() + gaps[i - 1], creator.getY()); } - update(); } private void reSizeRecByHorizontal(int gap) { @@ -145,13 +180,13 @@ public class MultiSelectionArrangement { return calculateIntegerGaps(distanceBetweenHeadAndTailCreators - sum, gapCount); } - public void verticalAutoDistribution() { + private void verticalAutoDistribution() { sortVertical(); int[] gaps = calculateVerticalGaps(); verticalDistribution(gaps); } - public void verticalManualDistribution(int gap) { + private void verticalManualDistribution(int gap) { sortVertical(); reSizeRecByVertical(gap); verticalDistribution(fillGaps(gap, selectedCreators.size() - 1)); @@ -163,7 +198,6 @@ public class MultiSelectionArrangement { XCreator preCreator = selectedCreators.get(i - 1); creator.setLocation(creator.getX(), preCreator.getY() + preCreator.getHeight() + gaps[i - 1]); } - update(); } private void reSizeRecByVertical(int gap) { @@ -252,12 +286,15 @@ public class MultiSelectionArrangement { return gaps; } - private void update() { + private void updatePosition() { FormSelection selection = designer.getSelectionModel().getSelection(); this.selectedCreators = Arrays.asList(selection.getSelectedCreators()); this.rec = selection.getSelctionBounds(); - this.parent = getParent(selection.getSelectedCreator()); + } + private void updateModel() { + FormSelection selection = designer.getSelectionModel().getSelection(); + XLayoutContainer parent = getParent(selection.getSelectedCreator()); if (parent != null) { // 这里要修改修改engine里面的对象才能成功保存,光修改设计器对象没用 WLayout wabs = parent.toData(); 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 1baac868ff..1b0f83c127 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 @@ -10,7 +10,9 @@ import com.fr.data.impl.NameTableData; import com.fr.data.impl.TableDataDictionary; import com.fr.design.actions.UpdateAction; import com.fr.design.data.DesignTableDataManager; +import com.fr.design.designer.creator.XChartEditor; import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XWTitleLayout; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.dialog.FineJOptionPane; @@ -33,6 +35,7 @@ import com.fr.form.ui.ChartEditor; import com.fr.form.ui.DataControl; import com.fr.form.ui.DictionaryContainer; import com.fr.form.ui.ElementCaseEditor; +import com.fr.form.ui.PaddingMargin; import com.fr.form.ui.Widget; import com.fr.general.IOUtils; import com.fr.log.FineLoggerFactory; @@ -56,6 +59,7 @@ import javax.swing.Action; import javax.swing.UIManager; import java.awt.Color; import java.awt.Component; +import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; @@ -81,6 +85,8 @@ import static javax.swing.JOptionPane.ERROR_MESSAGE; * 创建组件事件 */ public class CreateComponentAction extends UpdateAction { + private static final double MAX_WIDTH = 960.0; + private static final double MAX_HEIGHT = 540.0; ShareUIAspect aspect; /** * 等待时间 500 ms. @@ -119,6 +125,11 @@ public class CreateComponentAction extends UpdateAction { return; } + if (isBeyondMaxSize(sharedTriple.getRight())) { + showErrMsgDialog(Toolkit.i18nText("Fine-Design_Share_Widget_Size_Error_Tip")); + return; + } + Widget widget = sharedTriple.getLeft(); try { @@ -253,6 +264,17 @@ public class CreateComponentAction extends UpdateAction { BufferedImage im = new BufferedImage((int) rect.getWidth(), (int) rect.getHeight(), BufferedImage.TYPE_INT_ARGB); comp.paint(im.getGraphics()); + if (comp instanceof XWTitleLayout) { + XCreator body = ((XWTitleLayout) comp).getBodyCreator(); + if (body instanceof XChartEditor) { + XChartEditor chartEditor = (XChartEditor) body; + Dimension size = chartEditor.getSize(); + BufferedImage chartImage = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); + PaddingMargin margin = chartEditor.toData().getMargin(); + chartEditor.getDesignerEditor().paintEditor(chartImage.getGraphics(), size, margin); + im.getGraphics().drawImage(chartImage, 0, chartEditor.getY(), null); + } + } return im; } @@ -395,4 +417,20 @@ public class CreateComponentAction extends UpdateAction { } return paras; } + + private boolean isBeyondMaxSize(Rectangle rec) { + double width = rec.getWidth(); + double height = rec.getHeight(); + return width > 0 && height > 0 && (width > MAX_WIDTH || height > MAX_HEIGHT); + } + + private void showErrMsgDialog(String err) { + FineJOptionPane.showMessageDialog( + DesignerContext.getDesignerFrame(), + err, + Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), + ERROR_MESSAGE, + IOUtils.readIcon("/com/fr/base/images/share/Information_Icon_warning_normal_32x32.png") + ); + } } 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 a845759f73..e777e2b411 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 @@ -4,10 +4,11 @@ import com.fr.design.actions.UpdateAction; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.gui.ifilechooser.ExtensionFilter; +import com.fr.design.gui.ifilechooser.FileChooserArgs; +import com.fr.design.gui.ifilechooser.FileChooserFactory; import com.fr.design.gui.ifilechooser.FileChooserProvider; import com.fr.design.gui.ifilechooser.FileSelectionMode; -import com.fr.design.gui.ifilechooser.JavaFxNativeFileChooser; -import com.fr.design.gui.ilable.UILabel; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.share.ui.base.FailureMessagePane; @@ -15,17 +16,13 @@ import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; import com.fr.design.mainframe.share.util.InstallUtils; import com.fr.design.mainframe.share.util.ShareComponentUtils; import com.fr.design.mainframe.share.util.ShareUIUtils; -import com.fr.design.os.impl.SupportOSImpl; import com.fr.form.share.record.ShareWidgetInfoManager; import com.fr.form.share.utils.ReuxUtils; import com.fr.log.FineLoggerFactory; -import com.sun.javafx.tk.FileChooserType; -import javafx.stage.FileChooser; import javax.swing.Action; import javax.swing.JFileChooser; import javax.swing.SwingWorker; -import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.event.ActionEvent; import java.io.File; import java.util.ArrayList; @@ -46,15 +43,16 @@ public class InstallComponentAction extends UpdateAction { @Override public void actionPerformed(ActionEvent e) { - FileChooserProvider fileChooserProvider = - new JavaFxNativeFileChooser.Builder(). - fileSelectionMode(FileSelectionMode.MULTIPLE_FILE). - title(Toolkit.i18nText("Fine-Design_Basic_Select")). - filters(new FileChooser.ExtensionFilter[]{ - new FileChooser.ExtensionFilter("reu", "*.reu"), - new FileChooser.ExtensionFilter("reus", "*.reus"), - new FileChooser.ExtensionFilter("zip", "*.zip")}). - build(); + FileChooserProvider fileChooserProvider = FileChooserFactory.createFileChooser( + FileChooserArgs.newBuilder(). + setFileSelectionMode(FileSelectionMode.MULTIPLE_FILE). + setMultiSelectionEnabled(true). + setTipText(Toolkit.i18nText("Fine-Design_Basic_Select")). + setFilters(new ExtensionFilter[] { + new ExtensionFilter("reu", "*.reu"), + new ExtensionFilter("reus", "*.reus"), + new ExtensionFilter("zip", "*.zip"), + }).build()); int returnValue = fileChooserProvider.showDialog(null); installComponent(returnValue, fileChooserProvider.getSelectedFiles()); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/sort/OnlineWidgetSortType.java b/designer-form/src/main/java/com/fr/design/mainframe/share/sort/OnlineWidgetSortType.java index 437835662a..3a51357747 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/sort/OnlineWidgetSortType.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/sort/OnlineWidgetSortType.java @@ -27,7 +27,11 @@ public enum OnlineWidgetSortType implements SortType { public int compare(OnlineShareWidget o1, OnlineShareWidget o2) { double t1 = getSortValue(o1, parameterMap); double t2 = getSortValue(o2, parameterMap); - return ComparatorUtils.compareCommonType(t2, t1); + // Comparator中比较double/float相等时,不允许误差. 否则会违背 "若x = y , y = z, 则x = z"的约定。 + // 因为允许误差的情况下,x和y间的误差在允许范围内,被判定相等,y和间的误差在允许范围内,被判定相等, + // 但x和z间的误差可能超出允许范围,从而不相等,因此会违背上述约定。 + // 产生IllegalArgumentException: Comparison method violates its general contract! + return Double.compare(t2, t1); } }); } 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 911ff7b772..223e4a66d0 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 @@ -1,5 +1,6 @@ package com.fr.design.mainframe.share.ui.block; +import com.fr.base.FRContext; import com.fr.base.GraphHelper; import com.fr.base.iofile.attr.SharableAttrMark; import com.fr.design.actions.UpdateAction; @@ -37,17 +38,24 @@ import org.jetbrains.annotations.Nullable; import javax.swing.Action; import javax.swing.Icon; +import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.UIManager; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; +import java.awt.Font; import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; +import java.awt.RenderingHints; import java.awt.dnd.DnDConstants; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; +import java.awt.font.FontRenderContext; +import java.awt.font.LineMetrics; import java.util.UUID; /** @@ -67,6 +75,7 @@ public class LocalWidgetBlock extends PreviewWidgetBlock private boolean hover; private final Icon markedMode = IOUtils.readIcon("/com/fr/base/images/share/marked.png"); private final Icon unMarkedMode = IOUtils.readIcon("/com/fr/base/images/share/unmarked.png"); + private final Icon incompatibleMarker = IOUtils.readIcon("/com/fr/base/images/share/marker_incompatible.png"); public LocalWidgetBlock(DefaultSharableWidget provider, LocalWidgetSelectPane parentPane) { super(provider); @@ -198,11 +207,24 @@ public class LocalWidgetBlock extends PreviewWidgetBlock Widget creatorSource; String shareId; if (source instanceof LocalWidgetBlock) { - LocalWidgetBlock no = (LocalWidgetBlock) e.getSource(); - if (no == null) { + LocalWidgetBlock widgetBlock = (LocalWidgetBlock) e.getSource(); + if (widgetBlock == null) { return; } - shareId = no.getBindInfo().getId(); + SharableWidgetProvider widget = widgetBlock.getWidget(); + if (widget == null) { + return; + } + if (!widget.isCompatibleWithCurrentEnv()) { + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine-Design_Share_Drag_And_Make_Incompatible_Component_Tip"), + Toolkit.i18nText("Fine-Design_Basic_Error"), + JOptionPane.ERROR_MESSAGE, + UIManager.getIcon("OptionPane.errorIcon") + ); + return; + } + shareId = widgetBlock.getBindInfo().getId(); creatorSource = getGroup().getElCaseEditorById(shareId); if (creatorSource == null) { ShareUIUtils.showErrorMessageDialog(Toolkit.i18nText("Fine-Design_Share_Drag_Error_Info")); @@ -211,7 +233,7 @@ 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()); + XCreator xCreator = ShareComponentUtils.createXCreator(creatorSource, shareId, widgetBlock.getBindInfo()); WidgetToolBarPane.getTarget().startDraggingBean(xCreator); lastPressEvent = null; this.setBorder(null); @@ -221,6 +243,13 @@ public class LocalWidgetBlock extends PreviewWidgetBlock @Override public void paint(Graphics g) { super.paint(g); + Graphics2D g2d = (Graphics2D) g; + + boolean isUnusable = !getWidget().isCompatibleWithCurrentEnv(); + if (isUnusable) { + paintUnusableMask(g2d); + } + //绘制删除标志 if (isEdit) { Icon icon = isMarked ? markedMode : unMarkedMode; @@ -235,6 +264,42 @@ public class LocalWidgetBlock extends PreviewWidgetBlock } } + protected void paintUnusableMask(Graphics2D g2d) { + Color oldColor = g2d.getColor(); + Font oldFont = g2d.getFont(); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + Dimension coverDim = getCoverDimension(); + double canvasX = 0; + double canvasY = 0; + double canvasW = coverDim.getWidth(); + double canvasH = coverDim.getHeight(); + + g2d.setColor(new Color(0.0F, 0.0F, 0.0F, 0.4F)); + GraphHelper.fillRect(g2d, canvasX, canvasY, canvasW, canvasH); + + g2d.setColor(new Color(0.0F, 0.0F, 0.0F, 0.5F)); + GraphHelper.fillRect(g2d, canvasX, canvasH - 16, canvasW, 16); + + String tipText = Toolkit.i18nText("Fine-Design_Share_Incompatible_Version_Tip"); + Font tipFont = FRContext.getDefaultValues().getFRFont().deriveFont(8.0F); + FontRenderContext frc = g2d.getFontRenderContext(); + double tipTextWidth = GraphHelper.stringWidth(tipText, tipFont, frc); + LineMetrics metrics = tipFont.getLineMetrics(tipText, frc); + double tipTextHeight = metrics.getHeight(); + g2d.setColor(Color.WHITE); + g2d.setFont(tipFont); + GraphHelper.drawString(g2d, tipText, canvasX + (canvasW - tipTextWidth) / 2.0F, canvasY + canvasH - (16 - tipTextHeight) / 2.0F); + + int markerX = (int) (canvasX + (canvasW - incompatibleMarker.getIconWidth()) / 2); + int markerY = (int) (canvasY + (canvasH - incompatibleMarker.getIconHeight()) / 2); + incompatibleMarker.paintIcon(this, g2d, markerX, markerY); + + g2d.setColor(oldColor); + g2d.setFont(oldFont); + } + /** * 由鼠标释放时调用该方法来触发左键点击事件 */ 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 b8cb0e6788..74651ccae7 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 @@ -150,6 +150,14 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock { } } + private String createLocalReuFilename() { + String filename = widget.getFileLoca(); + if (StringUtils.isEmpty(filename) || !filename.endsWith(".reu")) { + filename = widget.getName() + "." + widget.getUuid() + ".reu"; + } + return filename; + } + private void downLoadWidget() { if (OnlineWidgetRepoPane.getInstance().isShowPackagePanel()) { ComponentCollector.getInstance().collectDownloadPktNum(); @@ -170,7 +178,8 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock { protected Boolean doInBackground() { String filePath; try { - filePath = DownloadUtils.download(widget.getId(), widget.getName() + "." + widget.getUuid(), process); + String filename = createLocalReuFilename(); + filePath = DownloadUtils.download(widget.getId(), filename, process); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); return false; @@ -179,7 +188,7 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock { //安装 File file = new File(filePath); try { - if (file.exists() && getDefaultGroup().installModule(file)) { + if (file.exists() && getDefaultGroup().installUniqueIdModule(file)) { ShareUtils.recordInstallTime(file.getName(), System.currentTimeMillis()); ComponentCollector.getInstance().collectCmpDownLoad(widget.getUuid()); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/LocalWidgetFilterCategory.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/LocalWidgetFilterCategory.java index 9e5d4f34ec..0e77c2d724 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/LocalWidgetFilterCategory.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/LocalWidgetFilterCategory.java @@ -1,5 +1,6 @@ package com.fr.design.mainframe.share.ui.widgetfilter; +import com.fr.design.i18n.Toolkit; import com.fr.form.share.bean.WidgetFilterInfo; import com.fr.form.share.bean.WidgetFilterTypeInfo; @@ -16,60 +17,60 @@ public class LocalWidgetFilterCategory { List category = new ArrayList<>(); WidgetFilterTypeInfo source = new WidgetFilterTypeInfo(); - source.setTitle("来源"); + source.setTitle(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Source")); source.setKey("2@source"); - source.addFilterItem(new WidgetFilterInfo("本地", "1", "source")); - source.addFilterItem(new WidgetFilterInfo("商城", "2", "source")); - source.addFilterItem(new WidgetFilterInfo("全部", "0", "source")); + source.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Local"), "1", "source")); + source.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Shop"), "2", "source")); + source.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "source")); WidgetFilterTypeInfo displayDevice = new WidgetFilterTypeInfo(); - displayDevice.setTitle("展示终端"); + displayDevice.setTitle(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Show_Device")); displayDevice.setKey("1@displayDevice"); - displayDevice.addFilterItem(new WidgetFilterInfo("PC端", "1", "displayDevice")); - displayDevice.addFilterItem(new WidgetFilterInfo("移动端", "2", "displayDevice")); - displayDevice.addFilterItem(new WidgetFilterInfo("全部", "0", "displayDevice")); + displayDevice.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_PC"), "1", "displayDevice")); + displayDevice.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Mobile"), "2", "displayDevice")); + displayDevice.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "displayDevice")); WidgetFilterTypeInfo fee = new WidgetFilterTypeInfo(); - fee.setTitle("价格"); + fee.setTitle(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Price")); fee.setKey("2@fee"); - fee.addFilterItem(new WidgetFilterInfo("付费", "2", "fee")); - fee.addFilterItem(new WidgetFilterInfo("免费", "1", "fee")); - fee.addFilterItem(new WidgetFilterInfo("全部", "0", "fee")); + fee.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Pay"), "2", "fee")); + fee.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Free"), "1", "fee")); + fee.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "fee")); WidgetFilterTypeInfo chart = new WidgetFilterTypeInfo(); - chart.setTitle("基础元素"); + chart.setTitle(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Basic_Element")); chart.setKey("3@chart"); - chart.addFilterItem(new WidgetFilterInfo("柱形图/条形图", "1", "chart")); - chart.addFilterItem(new WidgetFilterInfo("折线图", "3", "chart")); - chart.addFilterItem(new WidgetFilterInfo("组合图", "4", "chart")); - chart.addFilterItem(new WidgetFilterInfo("饼图", "2", "chart")); - chart.addFilterItem(new WidgetFilterInfo("仪表盘", "5", "chart")); - chart.addFilterItem(new WidgetFilterInfo("地图", "6", "chart")); - chart.addFilterItem(new WidgetFilterInfo("其他图表", "7", "chart")); - chart.addFilterItem(new WidgetFilterInfo("明细表", "8", "chart")); - chart.addFilterItem(new WidgetFilterInfo("基础控件", "9", "chart")); - chart.addFilterItem(new WidgetFilterInfo("全部", "0", "chart")); + chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Bar_Chart"), "1", "chart")); + chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Line_Chart"), "3", "chart")); + chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Combination_Chart"), "4", "chart")); + chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Pie_Chart"), "2", "chart")); + chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Dashboard_Chart"), "5", "chart")); + chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Map"), "6", "chart")); + chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Other_Chart"), "7", "chart")); + chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Detail_List"), "8", "chart")); + chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Basic_Widget"), "9", "chart")); + chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "chart")); WidgetFilterTypeInfo report = new WidgetFilterTypeInfo(); - report.setTitle("综合应用"); + report.setTitle(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Comprehensive_Application")); report.setKey("4@report"); - report.addFilterItem(new WidgetFilterInfo("指标卡", "1", "report")); - report.addFilterItem(new WidgetFilterInfo("标题头", "2", "report")); - report.addFilterItem(new WidgetFilterInfo("特殊功能卡", "4", "report")); - report.addFilterItem(new WidgetFilterInfo("多维度切换", "5", "report")); - report.addFilterItem(new WidgetFilterInfo("移动目录导航", "6", "report")); - report.addFilterItem(new WidgetFilterInfo("填报", "8", "report")); - report.addFilterItem(new WidgetFilterInfo("全部", "0", "report")); + report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Indicator_Card"), "1", "report")); + report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Title_Head"), "2", "report")); + report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Special_Function_Card"), "4", "report")); + report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Multi_Dimensional_Switch"), "5", "report")); + report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Move_Directory_Navigation"), "6", "report")); + report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Write_Report"), "8", "report")); + report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "report")); WidgetFilterTypeInfo style = new WidgetFilterTypeInfo(); - style.setTitle("风格"); + style.setTitle(Toolkit.i18nText("Fine-Design_Share_Filter_Style")); style.setKey("5@style"); - style.addFilterItem(new WidgetFilterInfo("简约清新", "1", "style")); - style.addFilterItem(new WidgetFilterInfo("商务稳重", "2", "style")); - style.addFilterItem(new WidgetFilterInfo("活泼绚丽", "3", "style")); - style.addFilterItem(new WidgetFilterInfo("酷炫科技", "4", "style")); - style.addFilterItem(new WidgetFilterInfo("其他风格", "5", "style")); - style.addFilterItem(new WidgetFilterInfo("全部", "0", "style")); + style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Simple_Fresh"), "1", "style")); + style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Business_Stable"), "2", "style")); + style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Lively_And_Bright"), "3", "style")); + style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Cool_Technology"), "4", "style")); + style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Other_Style"), "5", "style")); + style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "style")); category.add(displayDevice); category.add(source); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/util/DownloadUtils.java b/designer-form/src/main/java/com/fr/design/mainframe/share/util/DownloadUtils.java index 96c2cc28c6..6c6e156b07 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/util/DownloadUtils.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/util/DownloadUtils.java @@ -30,13 +30,16 @@ import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.interfaces.RSAPublicKey; import java.security.spec.X509EncodedKeySpec; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; /** * created by Harrison on 2020/05/27 **/ public class DownloadUtils { - private static final String REUSES_URL = CloudCenter.getInstance().acquireUrlByKind("af.reuseInfo") + "file/download"; - private static final String PACKAGE_REUSES_URL = CloudCenter.getInstance().acquireUrlByKind("af.reuseInfo") + "package/download/"; + private static final String REUSES_URL = ShareComponentConstants.REU_INFO_PATH + "file/download"; + private static final String PACKAGE_REUSES_URL = ShareComponentConstants.REU_INFO_PATH + "package/download/"; private static final String CERTIFICATE_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtsz62CPSWXZE/IYZRiAuTSZkw\n" + "1WOwer8+JFktK0uKLAUuQoBr+UjAMFtRA8W7JgKMDwZy/2liEAiXEOSPU/hrdV8D\n" + "tT541LnGi1X/hXiRwuttPWYN3L2GYm/d5blU+FBNwghBIrdAxXTzYBc6P4KL/oYX\n" + @@ -55,9 +58,9 @@ public class DownloadUtils { @NotNull public static String download(String id, String fileName, com.fr.design.extra.Process process) throws Exception { - CloseableHttpResponse fileRes = getHttpResponse(REUSES_URL, id); + CloseableHttpResponse fileRes = postDownloadHttpResponse(REUSES_URL, id); if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY) { - fileRes = getHttpResponse(fileRes.getHeaders("Location")[0].getValue()); + fileRes = getDownloadHttpResponse(fileRes.getHeaders("Location")[0].getValue()); } if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { String realPath = StableUtils.pathJoin(ProductConstants.getEnvHome(), ShareComponentConstants.PLUGIN_CACHE, ShareComponentConstants.DOWNLOAD_SHARE); @@ -67,7 +70,7 @@ public class DownloadUtils { long totalSize = entity.getContentLength(); InputStream content = entity.getContent(); - filePath = StableUtils.pathJoin(realPath, fileName + ".reu"); + filePath = StableUtils.pathJoin(realPath, fileName); StableUtils.makesureFileExist(new File(filePath)); FileOutputStream writer = new FileOutputStream(filePath); byte[] data = new byte[PluginConstants.BYTES_NUM]; @@ -93,9 +96,11 @@ public class DownloadUtils { public static String downloadPackage(String id, String fileName, CancelCheck cancelCheck) throws Exception { - CloseableHttpResponse fileRes = getHttpResponse(PACKAGE_REUSES_URL, id); + Map params = new HashMap<>(); + params.put("designerVersion", ProductConstants.RELEASE_VERSION); + CloseableHttpResponse fileRes = postDownloadHttpResponse(PACKAGE_REUSES_URL, id, params); if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY) { - fileRes = getHttpResponse(fileRes.getHeaders("Location")[0].getValue()); + fileRes = getDownloadHttpResponse(fileRes.getHeaders("Location")[0].getValue()); } String realPath = StableUtils.pathJoin(ProductConstants.getEnvHome(), ShareComponentConstants.PLUGIN_CACHE, ShareComponentConstants.DOWNLOAD_PACKAGE_SHARE); String filePath; @@ -130,21 +135,33 @@ public class DownloadUtils { } } - private static CloseableHttpResponse getHttpResponse(String url, String id) throws Exception { + private static CloseableHttpResponse postDownloadHttpResponse(String url, String id) throws Exception { + return postDownloadHttpResponse(url, id, new HashMap<>()); + } + + private static CloseableHttpResponse postDownloadHttpResponse(String url, String id, Map params) throws Exception { //先登录一下。不然可能失败 CloseableHttpClient client = createClient(); FineLoggerFactory.getLogger().info("login fr-market"); FineLoggerFactory.getLogger().info("start download widget {}", id); - HttpUriRequest file = RequestBuilder.post() + RequestBuilder builder = RequestBuilder.post() .setHeader("User-Agent", "Mozilla/5.0") - .setUri(url).addParameter("id", encrypt(id)).addParameter("userId", - String.valueOf(DesignerEnvManager.getEnvManager().getDesignerLoginUid())) - .build(); - return client.execute(file); + .setUri(url) + .addParameter("id", encrypt(id)) + .addParameter("userId", String.valueOf(DesignerEnvManager.getEnvManager().getDesignerLoginUid())); + + if (params != null) { + Set keys = params.keySet(); + for (String key: keys) { + builder.addParameter(key, params.get(key)); + } + } + + return client.execute(builder.build()); } - private static CloseableHttpResponse getHttpResponse(String url) throws Exception { + private static CloseableHttpResponse getDownloadHttpResponse(String url) throws Exception { //先登录一下。不然可能失败 CloseableHttpClient client = createClient(); HttpUriRequest file = RequestBuilder.get() 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 610f688a46..b3c711c01a 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 @@ -112,7 +112,7 @@ public class InstallUtils { private static boolean installReuFile(Group group, File chosenFile, long installTime) { try { - if (!group.installModule(chosenFile)) { + if (!group.installUniqueIdModule(chosenFile)) { return false; } ShareUtils.recordInstallTime(chosenFile.getName(), installTime); 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 80162a4065..56b9dd65ac 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 @@ -8,14 +8,11 @@ import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.XWTitleLayout; import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.i18n.Toolkit; -import com.fr.design.mainframe.FormSelection; -import com.fr.design.mainframe.JForm; import com.fr.design.mainframe.JTemplate; import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.bean.ShareLayoutWidget; import com.fr.form.share.constants.ComponentPath; import com.fr.form.ui.Widget; -import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; import com.fr.workspace.WorkContext; @@ -38,9 +35,7 @@ public class ShareComponentUtils { public static XCreator createXCreator(Widget creatorSource, String shareId, SharableWidgetProvider provider) { XCreator xCreator; - if (creatorSource instanceof WCardMainBorderLayout) { - xCreator = XCreatorUtils.createXCreator(creatorSource, new Dimension(500, 300)); - } else if (creatorSource instanceof ShareLayoutWidget) { + if (creatorSource instanceof ShareLayoutWidget) { xCreator = XCreatorUtils.createXCreator(((ShareLayoutWidget) creatorSource).getWidget(), new Dimension(provider.getWidth(), provider.getHeight())); } else { xCreator = XCreatorUtils.createXCreator(creatorSource, new Dimension(provider.getWidth(), provider.getHeight())); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/AbstractMultiSelectionArrangementButton.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/AbstractMultiSelectionArrangementButton.java index dc268f4c5b..9474295049 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/AbstractMultiSelectionArrangementButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/AbstractMultiSelectionArrangementButton.java @@ -5,6 +5,9 @@ import com.fr.design.event.UIObserverListener; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.mainframe.MultiSelectionArrangement; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public abstract class AbstractMultiSelectionArrangementButton extends UIButton implements MultiSelectionArrangementButton, UIObserver { private static final long serialVersionUID = -2114423583742242771L; protected MultiSelectionArrangement arrangement; @@ -29,4 +32,15 @@ public abstract class AbstractMultiSelectionArrangementButton extends UIButton i public boolean shouldResponseChangeListener() { return true; } + + @Override + public ActionListener getActionListener() { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + arrangement.doArrangement(getArrangementType()); + uiObserverListener.doChange(); + } + }; + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/BottomAlignButton.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/BottomAlignButton.java index 99bf3a6c3a..97974298a5 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/BottomAlignButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/BottomAlignButton.java @@ -1,14 +1,15 @@ package com.fr.design.mainframe.widget.arrangement.buttons; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.ArrangementType; import com.fr.design.mainframe.MultiSelectionArrangement; import com.fr.general.IOUtils; import javax.swing.Icon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; public class BottomAlignButton extends AbstractMultiSelectionArrangementButton { + private static final long serialVersionUID = 2397455240682353024L; + public BottomAlignButton(MultiSelectionArrangement arrangement) { super(arrangement); } @@ -24,13 +25,7 @@ public class BottomAlignButton extends AbstractMultiSelectionArrangementButton { } @Override - public ActionListener getActionListener() { - return new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - arrangement.bottomAlign(); - uiObserverListener.doChange(); - } - }; + public ArrangementType getArrangementType() { + return ArrangementType.BOTTOM_ALIGN; } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/HorizontalCenterButton.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/HorizontalCenterButton.java index 6dc9c09b4a..ec8f315df2 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/HorizontalCenterButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/HorizontalCenterButton.java @@ -1,14 +1,15 @@ package com.fr.design.mainframe.widget.arrangement.buttons; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.ArrangementType; import com.fr.design.mainframe.MultiSelectionArrangement; import com.fr.general.IOUtils; import javax.swing.Icon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; public class HorizontalCenterButton extends AbstractMultiSelectionArrangementButton { + private static final long serialVersionUID = 6290178236460051049L; + public HorizontalCenterButton(MultiSelectionArrangement arrangement) { super(arrangement); } @@ -24,13 +25,7 @@ public class HorizontalCenterButton extends AbstractMultiSelectionArrangementBut } @Override - public ActionListener getActionListener() { - return new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - arrangement.horizontalCenterAlign(); - uiObserverListener.doChange(); - } - }; + public ArrangementType getArrangementType() { + return ArrangementType.HORIZONTAL_CENTER_ALIGN; } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/HorizontalDistributionButton.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/HorizontalDistributionButton.java index 0a0e225fc6..0702248ed4 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/HorizontalDistributionButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/HorizontalDistributionButton.java @@ -1,14 +1,15 @@ package com.fr.design.mainframe.widget.arrangement.buttons; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.ArrangementType; import com.fr.design.mainframe.MultiSelectionArrangement; import com.fr.general.IOUtils; import javax.swing.Icon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; public class HorizontalDistributionButton extends AbstractMultiSelectionArrangementButton { + private static final long serialVersionUID = 5052092252720664954L; + public HorizontalDistributionButton(MultiSelectionArrangement arrangement) { super(arrangement); } @@ -24,13 +25,7 @@ public class HorizontalDistributionButton extends AbstractMultiSelectionArrangem } @Override - public ActionListener getActionListener() { - return new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - arrangement.horizontalAutoDistribution(); - uiObserverListener.doChange(); - } - }; + public ArrangementType getArrangementType() { + return ArrangementType.HORIZONTAL_AUTO_DISTRIBUTION; } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/LeftAlignButton.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/LeftAlignButton.java index 20a25a87cb..02a6a2c796 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/LeftAlignButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/LeftAlignButton.java @@ -1,14 +1,15 @@ package com.fr.design.mainframe.widget.arrangement.buttons; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.ArrangementType; import com.fr.design.mainframe.MultiSelectionArrangement; import com.fr.general.IOUtils; import javax.swing.Icon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; public class LeftAlignButton extends AbstractMultiSelectionArrangementButton { + private static final long serialVersionUID = -8177637788632733710L; + public LeftAlignButton(MultiSelectionArrangement arrangement) { super(arrangement); } @@ -24,13 +25,7 @@ public class LeftAlignButton extends AbstractMultiSelectionArrangementButton { } @Override - public ActionListener getActionListener() { - return new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - arrangement.leftAlign(); - uiObserverListener.doChange(); - } - }; + public ArrangementType getArrangementType() { + return ArrangementType.LEFT_ALIGN; } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/MultiSelectionArrangementButton.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/MultiSelectionArrangementButton.java index 99b7635708..96f5765988 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/MultiSelectionArrangementButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/MultiSelectionArrangementButton.java @@ -1,5 +1,7 @@ package com.fr.design.mainframe.widget.arrangement.buttons; +import com.fr.design.mainframe.ArrangementType; + import javax.swing.Icon; import java.awt.event.ActionListener; @@ -9,4 +11,6 @@ public interface MultiSelectionArrangementButton { String getTipText(); ActionListener getActionListener(); + + ArrangementType getArrangementType(); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/RightAlignButton.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/RightAlignButton.java index 5fac70bd7a..1b047b6ba8 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/RightAlignButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/RightAlignButton.java @@ -1,14 +1,15 @@ package com.fr.design.mainframe.widget.arrangement.buttons; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.ArrangementType; import com.fr.design.mainframe.MultiSelectionArrangement; import com.fr.general.IOUtils; import javax.swing.Icon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; public class RightAlignButton extends AbstractMultiSelectionArrangementButton { + private static final long serialVersionUID = -8698936349956288409L; + public RightAlignButton(MultiSelectionArrangement arrangement) { super(arrangement); } @@ -24,13 +25,7 @@ public class RightAlignButton extends AbstractMultiSelectionArrangementButton { } @Override - public ActionListener getActionListener() { - return new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - arrangement.rightAlign(); - uiObserverListener.doChange(); - } - }; + public ArrangementType getArrangementType() { + return ArrangementType.RIGHT_ALIGN; } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/TopAlignButton.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/TopAlignButton.java index ebb2c4d21a..0adfb9378e 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/TopAlignButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/TopAlignButton.java @@ -1,14 +1,15 @@ package com.fr.design.mainframe.widget.arrangement.buttons; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.ArrangementType; import com.fr.design.mainframe.MultiSelectionArrangement; import com.fr.general.IOUtils; import javax.swing.Icon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; public class TopAlignButton extends AbstractMultiSelectionArrangementButton { + private static final long serialVersionUID = 2896267783075870924L; + public TopAlignButton(MultiSelectionArrangement arrangement) { super(arrangement); } @@ -24,13 +25,7 @@ public class TopAlignButton extends AbstractMultiSelectionArrangementButton { } @Override - public ActionListener getActionListener() { - return new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - arrangement.topAlign(); - uiObserverListener.doChange(); - } - }; + public ArrangementType getArrangementType() { + return ArrangementType.TOP_ALIGN; } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/VerticalCenterButton.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/VerticalCenterButton.java index 9898f9002c..4fb8b62a28 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/VerticalCenterButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/VerticalCenterButton.java @@ -1,12 +1,11 @@ package com.fr.design.mainframe.widget.arrangement.buttons; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.ArrangementType; import com.fr.design.mainframe.MultiSelectionArrangement; import com.fr.general.IOUtils; import javax.swing.Icon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; public class VerticalCenterButton extends AbstractMultiSelectionArrangementButton { public VerticalCenterButton(MultiSelectionArrangement arrangement) { @@ -24,13 +23,7 @@ public class VerticalCenterButton extends AbstractMultiSelectionArrangementButto } @Override - public ActionListener getActionListener() { - return new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - arrangement.verticalCenterAlign(); - uiObserverListener.doChange(); - } - }; + public ArrangementType getArrangementType() { + return ArrangementType.VERTICAL_CENTER_ALIGN; } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/VerticalDistributionButton.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/VerticalDistributionButton.java index 50ec6ac894..76dcf9427a 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/VerticalDistributionButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/arrangement/buttons/VerticalDistributionButton.java @@ -1,12 +1,11 @@ package com.fr.design.mainframe.widget.arrangement.buttons; import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.ArrangementType; import com.fr.design.mainframe.MultiSelectionArrangement; import com.fr.general.IOUtils; import javax.swing.Icon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; public class VerticalDistributionButton extends AbstractMultiSelectionArrangementButton { public VerticalDistributionButton(MultiSelectionArrangement arrangement) { @@ -24,13 +23,7 @@ public class VerticalDistributionButton extends AbstractMultiSelectionArrangemen } @Override - public ActionListener getActionListener() { - return new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - arrangement.verticalAutoDistribution(); - uiObserverListener.doChange(); - } - }; + public ArrangementType getArrangementType() { + return ArrangementType.VERTICAL_AUTO_DISTRIBUTION; } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormMultiWidgetCardPane.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormMultiWidgetCardPane.java index ffd2a0f74e..cf59b595c5 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormMultiWidgetCardPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormMultiWidgetCardPane.java @@ -9,6 +9,7 @@ import com.fr.design.gui.itextfield.UITextField; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.ArrangementType; import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.MultiSelectionArrangement; import com.fr.design.mainframe.widget.arrangement.buttons.BottomAlignButton; @@ -186,9 +187,9 @@ public class FormMultiWidgetCardPane extends FormWidgetCardPane { int gap = (int) Math.floor(Float.parseFloat(text)); numberField.setValue(gap); if (isVertical) { - arrangement.verticalManualDistribution(gap); + arrangement.doArrangement(ArrangementType.VERTICAL_MANUAL_DISTRIBUTION, gap); } else { - arrangement.horizontalManualDistribution(gap); + arrangement.doArrangement(ArrangementType.HORIZONTAL_MANUAL_DISTRIBUTION, gap); } attributeChanged(); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormSingleWidgetCardPane.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormSingleWidgetCardPane.java index 9f0c44ded3..6869b8b30f 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormSingleWidgetCardPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormSingleWidgetCardPane.java @@ -30,6 +30,7 @@ import com.fr.design.widget.Operator; import com.fr.design.widget.ui.designer.component.WidgetAbsoluteBoundPane; import com.fr.design.widget.ui.designer.component.WidgetBoundPane; import com.fr.design.widget.ui.designer.component.WidgetCardTagBoundPane; +import com.fr.form.main.WidgetUtil; import com.fr.form.ui.ChartEditor; import com.fr.form.ui.Widget; import com.fr.form.ui.container.WScaleLayout; @@ -67,12 +68,9 @@ public class FormSingleWidgetCardPane extends FormWidgetCardPane { initDefinePane(); } + @Deprecated public XLayoutContainer getParent(XCreator source) { - XLayoutContainer container = XCreatorUtils.getParentXLayoutContainer(source); - if (source.acceptType(XWFitLayout.class) || source.acceptType(XWParameterLayout.class)) { - container = null; - } - return container; + return XCreatorUtils.getParent(source); } public WidgetBoundPane createWidgetBoundPane(XCreator xCreator) { @@ -113,7 +111,7 @@ public class FormSingleWidgetCardPane extends FormWidgetCardPane { } private void initComponents() { - XCreator innerCreator = getXCreatorDedicated(); + XCreator innerCreator = XCreatorUtils.getXCreatorInnerWidget(this.xCreator); attriCardPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); content.add(attriCardPane, BorderLayout.CENTER); @@ -166,7 +164,7 @@ public class FormSingleWidgetCardPane extends FormWidgetCardPane { private void initDefinePane() { currentEditorDefinePane = null; - XCreator creator = getXCreatorDedicated(); + XCreator creator = XCreatorUtils.getXCreatorInnerWidget(this.xCreator); FormWidgetDefinePaneFactoryBase.RN rn = FormWidgetDefinePaneFactoryBase.createWidgetDefinePane(creator, designer, creator.toData(), new Operator() { @Override public void did(DataCreatorUI ui, String cardName) { @@ -190,11 +188,6 @@ public class FormSingleWidgetCardPane extends FormWidgetCardPane { currentEditorDefinePane = definePane; } - private XCreator getXCreatorDedicated() { - boolean dedicateLayout = xCreator.acceptType(XWScaleLayout.class) && xCreator.getComponentCount() > 0 && ((XCreator) xCreator.getComponent(0)).shouldScaleCreator() || xCreator.acceptType(XWTitleLayout.class); - return dedicateLayout ? (XCreator) xCreator.getComponent(0) : xCreator; - } - @Override public String title4PopupWindow() { return "Widget"; @@ -251,7 +244,12 @@ public class FormSingleWidgetCardPane extends FormWidgetCardPane { showNameInvalidDialog(Toolkit.i18nText("Fine-Design_Form_Chart_Widget_Rename_Failure")); return; } + String oldName = widget.getWidgetName(); widgetPropertyPane.update(widget); + Widget innerWidget = WidgetUtil.getInnerWidget(widget); + if (!StringUtils.equals(oldName, innerWidget.getWidgetName())) { + innerWidget.setMobileOldWidgetName(oldName); + } // 上面一行更新了组件 这里必须重新调用getWidgetName xCreator.resetCreatorName(widget.getWidgetName()); xCreator.resetVisible(widget.isVisible()); @@ -283,7 +281,7 @@ public class FormSingleWidgetCardPane extends FormWidgetCardPane { } public void fireValueChanged() { - XCreator creator = getXCreatorDedicated(); + XCreator creator = XCreatorUtils.getXCreatorInnerWidget(this.xCreator); creator.firePropertyChange(); } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/FieldEditorDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/FieldEditorDefinePane.java index 45c2cd9686..4ee699e0fe 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/FieldEditorDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/FieldEditorDefinePane.java @@ -1,9 +1,17 @@ package com.fr.design.widget.ui.designer; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.beans.ErrorMsgTextFieldAdapter; +import com.fr.design.beans.UITextFieldAdapter; import com.fr.design.constants.LayoutConstants; import com.fr.design.designer.IntervalConstants; -import com.fr.design.designer.creator.*; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XCreatorUtils; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWFitLayout; +import com.fr.design.designer.creator.XWParameterLayout; import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.fun.TextFieldAdapterProvider; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.UITextField; @@ -11,19 +19,19 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.widget.ui.designer.component.FontSizeComboPane; import com.fr.form.ui.FieldEditor; +import com.fr.log.FineLoggerFactory; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.awt.*; +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; public abstract class FieldEditorDefinePane extends AbstractDataModify { protected UICheckBox allowBlankCheckBox; // richer:错误信息,是所有控件共有的属性,所以放到这里来 - protected UITextField errorMsgTextField; + protected ErrorMsgTextFieldAdapter errorMsgTextField; protected JPanel validatePane; protected FontSizeComboPane fontSizePane; protected UITextField labelNameTextField; @@ -40,7 +48,6 @@ public abstract class FieldEditorDefinePane extends Abstr allowBlankCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Allow_Null")); allowBlankCheckBox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); fontSizePane = new FontSizeComboPane(); - errorMsgTextField = new UITextField(); JPanel contentPane = this.setFirstContentPane(); JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); jPanel.add(contentPane, BorderLayout.CENTER); @@ -76,23 +83,17 @@ public abstract class FieldEditorDefinePane extends Abstr protected void initErrorMsgPane() { // 错误信息 - errorMsgTextField = new UITextField(); -// // richer:主要为了方便查看比较长的错误信息 - errorMsgTextField.getDocument().addDocumentListener(new DocumentListener() { - - public void changedUpdate(DocumentEvent e) { - errorMsgTextField.setToolTipText(errorMsgTextField.getText()); - } - - public void insertUpdate(DocumentEvent e) { - errorMsgTextField.setToolTipText(errorMsgTextField.getText()); - } - - public void removeUpdate(DocumentEvent e) { - errorMsgTextField.setToolTipText(errorMsgTextField.getText()); - } - }); - + TextFieldAdapterProvider provider = ExtraDesignClassManager.getInstance().getSingle(TextFieldAdapterProvider.XML_TAG); + if (provider == null) { + errorMsgTextField = new UITextFieldAdapter(); + return; + } + try { + errorMsgTextField = provider.createTextFieldAdapter(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + errorMsgTextField = new UITextFieldAdapter(); + } } @@ -111,7 +112,7 @@ public abstract class FieldEditorDefinePane extends Abstr validatePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); final UILabel uiLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Widget_Error_Tip")); JPanel borderPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - final JPanel errorTipPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{uiLabel, errorMsgTextField}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); + final JPanel errorTipPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{uiLabel, errorMsgTextField.getErrorMsgTextField()}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); errorTipPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L6, IntervalConstants.INTERVAL_L5, 0, 0)); borderPane.add(errorTipPane, BorderLayout.CENTER); allowBlankCheckBox.addItemListener(new ItemListener() { diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java index 1c30b1a557..992ea9cfb5 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/LabelDefinePane.java @@ -68,7 +68,7 @@ public class LabelDefinePane extends AbstractDataModify