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 17d7d5883..16c1a7e8a 100644 --- a/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java +++ b/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java @@ -134,7 +134,7 @@ public class EnvChangeEntrance { } //REPORT-13810如果只是添加了工作目录,没有切换,这里ToolArea也是要显示新建的工作目录 JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - if (template != null) { + if (JTemplate.isValid(template)) { template.refreshToolArea(); } PluginErrorDesignReminder.getInstance().remindStartFailedPlugins(); @@ -413,7 +413,7 @@ public class EnvChangeEntrance { @Override public void doOk() { SaveSomeTemplatePane saveSomeTemplatePane = new SaveSomeTemplatePane(true, SwingUtilities.getWindowAncestor(envListPane)); - if (!saveSomeTemplatePane.showSavePane()) { + if (!saveSomeTemplatePane.showSavePane(true)) { // 用户取消保存时,取消切换目录操作 return; } diff --git a/designer-base/src/main/java/com/fr/design/actions/community/BBSAction.java b/designer-base/src/main/java/com/fr/design/actions/community/BBSAction.java index 1acbbe417..ed487578c 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/BBSAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/BBSAction.java @@ -1,14 +1,22 @@ package com.fr.design.actions.community; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.login.AbstractDesignerSSO; import com.fr.design.menu.MenuKeySet; -import com.fr.general.CloudCenter; - -import javax.swing.*; +import javax.swing.KeyStroke; public class BBSAction extends AbstractDesignerSSO { + /** + * 云中心帆软社区页在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Bbs"; + + /** + * 云中心帆软社区页默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Bbs_Default"; public BBSAction() { this.setMenuKeySet(BBS); @@ -20,7 +28,7 @@ public class BBSAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs", "http://bbs.fanruan.com/"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); } public static final MenuKeySet BBS = new MenuKeySet() { 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 5365e556b..9da1539a5 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 @@ -1,13 +1,23 @@ package com.fr.design.actions.community; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.login.AbstractDesignerSSO; import com.fr.design.menu.MenuKeySet; -import com.fr.general.CloudCenter; -import javax.swing.*; +import javax.swing.KeyStroke; public class BugAction extends AbstractDesignerSSO { + /** + * 云中心产品反馈页在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Bugs"; + + /** + * 云中心产品反馈页默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Bugs_Default"; + public BugAction() { this.setMenuKeySet(BUG); this.setName(getMenuKeySet().getMenuName()); @@ -17,7 +27,7 @@ public class BugAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.bugs", "https://service.fanruan.com/PF/FR/feedback?type=2"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); } public static final MenuKeySet BUG = new MenuKeySet() { diff --git a/designer-base/src/main/java/com/fr/design/actions/community/CenterAction.java b/designer-base/src/main/java/com/fr/design/actions/community/CenterAction.java index 6ae03f1a8..093070b55 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/CenterAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/CenterAction.java @@ -1,7 +1,7 @@ package com.fr.design.actions.community; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.menu.MenuKeySet; -import com.fr.general.CloudCenter; import javax.swing.KeyStroke; @@ -9,6 +9,17 @@ import javax.swing.KeyStroke; * Created by XINZAI on 2018/8/23. */ public class CenterAction extends UpAction { + + /** + * 云中心活动中心页在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Act_Center"; + + /** + * 云中心活动中心页默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Act_Center_Default"; + public CenterAction() { this.setMenuKeySet(CENTER); this.setName(getMenuKeySet().getMenuName()); @@ -18,7 +29,7 @@ public class CenterAction extends UpAction { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.center", "http://bbs.fanruan.com/events/"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); } public static final MenuKeySet CENTER = new MenuKeySet() { diff --git a/designer-base/src/main/java/com/fr/design/actions/community/CusDemandAction.java b/designer-base/src/main/java/com/fr/design/actions/community/CusDemandAction.java index 007eeb9ab..ef4cea39d 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/CusDemandAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/CusDemandAction.java @@ -1,18 +1,28 @@ package com.fr.design.actions.community; import com.fr.base.BaseUtils; - +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.menu.MenuKeySet; import com.fr.design.utils.BrowseUtils; -import com.fr.general.CloudCenter; -import javax.swing.KeyStroke; +import javax.swing.KeyStroke; import java.awt.event.ActionEvent; /** * Created by XINZAI on 2018/8/23. */ public class CusDemandAction extends UpAction{ + + /** + * 云中心发布需求页在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Demand"; + + /** + * 云中心发布需求页默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Demand_Default"; + public CusDemandAction() { this.setMenuKeySet(DEMAND); @@ -25,7 +35,7 @@ public class CusDemandAction extends UpAction{ @Override public void actionPerformed(ActionEvent arg0) { - String url = CloudCenter.getInstance().acquireUrlByKind("bbs.demand", "https://market.fanruan.com/demand"); + String url = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); BrowseUtils.browser(url); } diff --git a/designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java b/designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java index e5ff4dd47..05ef85e44 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java @@ -1,14 +1,24 @@ package com.fr.design.actions.community; -import com.fr.base.svg.IconUtils; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.menu.MenuKeySet; import com.fr.design.utils.BrowseUtils; -import com.fr.general.CloudCenter; + import javax.swing.KeyStroke; import java.awt.event.ActionEvent; public class FacebookFansAction extends UpAction { + /** + * 云中心facebook页在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_FaceBook"; + + /** + * 云中心facebook页默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_FaceBook_Default"; + public FacebookFansAction() { this.setMenuKeySet(FACEBOOKFANS); this.setName(getMenuKeySet().getMenuName()); @@ -18,7 +28,7 @@ public class FacebookFansAction extends UpAction { @Override public void actionPerformed(ActionEvent arg0) { - BrowseUtils.browser(CloudCenter.getInstance().acquireUrlByKind("facebook.fans.tw", "https://www.facebook.com/twfinereport")); + BrowseUtils.browser(LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT)); } public static final MenuKeySet FACEBOOKFANS = 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 62d4b9c95..33279060b 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 @@ -1,13 +1,23 @@ package com.fr.design.actions.community; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.login.AbstractDesignerSSO; import com.fr.design.menu.MenuKeySet; -import com.fr.general.CloudCenter; -import javax.swing.*; +import javax.swing.KeyStroke; public class NeedAction extends AbstractDesignerSSO { + /** + * 云中心产品反馈页在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Need"; + + /** + * 云中心产品反馈页默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Need_Default"; + public NeedAction() { this.setMenuKeySet(NEED); this.setName(getMenuKeySet().getMenuName()); @@ -18,7 +28,7 @@ public class NeedAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.needs", "https://service.fanruan.com/PF/FR/feedback?type=1"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT); } public static final MenuKeySet NEED = new MenuKeySet() { diff --git a/designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java b/designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java index 5b4411225..e56359139 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java @@ -1,13 +1,23 @@ package com.fr.design.actions.community; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.login.AbstractDesignerSSO; import com.fr.design.menu.MenuKeySet; -import com.fr.general.CloudCenter; -import javax.swing.*; +import javax.swing.KeyStroke; public class QuestionAction extends AbstractDesignerSSO { + /** + * 云中心问答页在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Question"; + + /** + * 云中心问答页默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Question_Default"; + public QuestionAction() { this.setMenuKeySet(QUESTIONS); this.setName(getMenuKeySet().getMenuName()); @@ -18,7 +28,7 @@ public class QuestionAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.questions", "http://bbs.fanruan.com/wenda"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT); } public static final MenuKeySet QUESTIONS = new MenuKeySet() { diff --git a/designer-base/src/main/java/com/fr/design/actions/community/SignAction.java b/designer-base/src/main/java/com/fr/design/actions/community/SignAction.java index 8c29ee5e6..29817e36a 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/SignAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/SignAction.java @@ -1,14 +1,23 @@ package com.fr.design.actions.community; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.login.AbstractDesignerSSO; import com.fr.design.menu.MenuKeySet; -import com.fr.general.CloudCenter; - -import javax.swing.*; +import javax.swing.KeyStroke; public class SignAction extends AbstractDesignerSSO { + /** + * 云中心认证落地页在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Aut"; + + /** + * 云中心认证落地页默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Aut_Default"; + public SignAction() { this.setMenuKeySet(SIGN); this.setName(getMenuKeySet().getMenuName()); @@ -18,7 +27,7 @@ public class SignAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.aut", "https://bbs.fanruan.com/certification/"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT); } public static final MenuKeySet SIGN = 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 index d0dcc4195..0d2e79905 100644 --- 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 @@ -1,10 +1,21 @@ package com.fr.design.actions.community; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; import com.fr.design.login.AbstractDesignerSSO; -import com.fr.general.CloudCenter; public class StudyPlanAction extends AbstractDesignerSSO { + + /** + * 云中心帆软学院在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Study"; + + /** + * 云中心帆软学院默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Study_Default"; + public StudyPlanAction() { this.setName(Toolkit.i18nText("Fine-Design_Study_Plan")); this.setSmallIcon("/com/fr/design/images/bbs/studyPlan"); @@ -12,6 +23,6 @@ public class StudyPlanAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.studyPlan", "https://edu.fanruan.com/studypath/finereport"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT); } } diff --git a/designer-base/src/main/java/com/fr/design/actions/community/TechSolutionAction.java b/designer-base/src/main/java/com/fr/design/actions/community/TechSolutionAction.java index 897555578..f0e4f3ac3 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/TechSolutionAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/TechSolutionAction.java @@ -1,8 +1,8 @@ package com.fr.design.actions.community; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.login.AbstractDesignerSSO; import com.fr.design.menu.MenuKeySet; -import com.fr.general.CloudCenter; import javax.swing.KeyStroke; @@ -10,6 +10,17 @@ import javax.swing.KeyStroke; * Created by XINZAI on 2018/8/23. */ public class TechSolutionAction extends AbstractDesignerSSO { + + /** + * 云中心社区在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Community"; + + /** + * 云中心社区默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Community_Default"; + public TechSolutionAction() { this.setMenuKeySet(TSO); this.setName(getMenuKeySet().getMenuName()); @@ -20,7 +31,7 @@ public class TechSolutionAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.solution", "http://bbs.fanruan.com/forum-113-1.html"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT); } public static final MenuKeySet TSO = new MenuKeySet() { diff --git a/designer-base/src/main/java/com/fr/design/actions/community/TemplateStoreAction.java b/designer-base/src/main/java/com/fr/design/actions/community/TemplateStoreAction.java index eec904ebd..3c17df9b5 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/TemplateStoreAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/TemplateStoreAction.java @@ -1,21 +1,28 @@ package com.fr.design.actions.community; import com.fr.base.BaseUtils; -import com.fr.design.actions.UpdateAction; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.login.AbstractDesignerSSO; import com.fr.design.mainframe.share.collect.ComponentCollector; import com.fr.design.menu.MenuKeySet; -import com.fr.design.utils.BrowseUtils; -import com.fr.general.CloudCenter; import javax.swing.KeyStroke; -import java.awt.event.ActionEvent; /** * created by Harrison on 2020/03/24 **/ public class TemplateStoreAction extends AbstractDesignerSSO { - + + /** + * 云中心组件商城模板在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Market_Template"; + + /** + * 云中心组件商城模板默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Market_Template_Default"; + public TemplateStoreAction() { this.setMenuKeySet(TEMPLATE); @@ -47,6 +54,6 @@ public class TemplateStoreAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { ComponentCollector.getInstance().collectTepMenuEnterClick(); - return CloudCenter.getInstance().acquireUrlByKind("design.market.template", "https://market.fanruan.com/template"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT); } } diff --git a/designer-base/src/main/java/com/fr/design/actions/community/UpAction.java b/designer-base/src/main/java/com/fr/design/actions/community/UpAction.java index 05022ecf8..e0c640483 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/UpAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/UpAction.java @@ -1,14 +1,24 @@ package com.fr.design.actions.community; import com.fr.base.BaseUtils; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.login.AbstractDesignerSSO; import com.fr.design.menu.MenuKeySet; -import com.fr.general.CloudCenter; import javax.swing.KeyStroke; public class UpAction extends AbstractDesignerSSO { + /** + * 云中心工单中心在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Bbs_Update"; + + /** + * 云中心工单中心默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Bbs_Update_Default"; + public UpAction() { this.setMenuKeySet(UPDATE); this.setName(getMenuKeySet().getMenuName()); @@ -18,7 +28,7 @@ public class UpAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.update", "http://bbs.fanruan.com/forum.php?mod=collection&action=view&ctid=10"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY ,PROPS_LINK_KEY_DEFAULT); } public static final MenuKeySet UPDATE = new MenuKeySet() { diff --git a/designer-base/src/main/java/com/fr/design/actions/community/WorkOrderCenterAction.java b/designer-base/src/main/java/com/fr/design/actions/community/WorkOrderCenterAction.java index d1168eca7..03e634a4a 100644 --- a/designer-base/src/main/java/com/fr/design/actions/community/WorkOrderCenterAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/community/WorkOrderCenterAction.java @@ -1,7 +1,7 @@ package com.fr.design.actions.community; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; -import com.fr.general.CloudCenter; /** * @Description 工单中心 @@ -9,6 +9,17 @@ import com.fr.general.CloudCenter; * @Date 2021/3/8 14:02 **/ public class WorkOrderCenterAction extends UpAction { + + /** + * 云中心工单中心在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Work_Order_Center"; + + /** + * 云中心工单中心默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Work_Order_Center_Default"; + public WorkOrderCenterAction() { this.setSmallIcon("/com/fr/design/images/bbs/workOrderCenter"); this.setName(Toolkit.i18nText("Fine-Design_Basic_Commuinity_Work_Order_Center")); @@ -16,6 +27,6 @@ public class WorkOrderCenterAction extends UpAction { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind("bbs.work.order.center", "https://service.fanruan.com/ticket"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java b/designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java index 33761a92e..e38a39895 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java @@ -68,7 +68,7 @@ public class SwitchExistEnv extends MenuDef { EnvChangeEntrance.getInstance().chooseEnv(envName); } else { SaveSomeTemplatePane saveSomeTemplatePane = new SaveSomeTemplatePane(true); - if (saveSomeTemplatePane.showSavePane()) { + if (saveSomeTemplatePane.showSavePane(true)) { // 用户模板保存后,才进行切换目录操作 EnvChangeEntrance.getInstance().switch2Env(envName); } 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 51a390c82..1a4bccfa4 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 @@ -1,9 +1,9 @@ package com.fr.design.actions.help; +import com.fr.design.i18n.LocaleLinkProvider; 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.stable.CommonUtils; @@ -18,6 +18,16 @@ import java.awt.event.KeyEvent; public class TutorialAction extends AbstractDesignerSSO { + /** + * 云中心社区帮助文档在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Help"; + + /** + * 云中心社区帮助文档默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Help_Default"; + public TutorialAction() { this.setMenuKeySet(HELP_TUTORIAL); this.setName(getMenuKeySet().getMenuName()); @@ -28,7 +38,7 @@ public class TutorialAction extends AbstractDesignerSSO { @Override public String getJumpUrl() { - return CloudCenter.getInstance().acquireUrlByKind(createDocKey(), "http://help.finereport.com"); + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); } // 生成帮助文档 sitecenter key, help.zh_CN.10 diff --git a/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java b/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java index b3a076a92..af9850172 100644 --- a/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java +++ b/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java @@ -5,14 +5,17 @@ import com.fr.base.TableData; import com.fr.base.svg.IconUtils; import com.fr.data.MultiResultTableData; import com.fr.data.TableDataSource; +import com.fr.data.impl.DBTableData; import com.fr.design.DesignModelAdapter; import com.fr.design.actions.UpdateAction; import com.fr.design.data.datapane.TableDataCreatorProducer; import com.fr.design.data.datapane.TableDataNameObjectCreator; import com.fr.design.data.datapane.TableDataSourceOP; import com.fr.design.data.datapane.TableDataTree; +import com.fr.design.data.datapane.auth.TableDataAuthHelper; import com.fr.design.data.tabledata.ResponseDataSourceChange; import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +import com.fr.design.data.tabledata.tabledatapane.loading.TableDataLoadingPane; import com.fr.design.data.tabledata.wrapper.MultiResultTableDataWrapper; import com.fr.design.data.tabledata.wrapper.TableDataWrapper; import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; @@ -42,6 +45,8 @@ import javax.swing.DefaultCellEditor; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.tree.TreeCellEditor; @@ -51,6 +56,7 @@ import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; +import java.util.Collection; import java.util.EventObject; import java.util.HashMap; import java.util.HashSet; @@ -449,7 +455,45 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp storeProcedureDataWrapper.previewData(MultiResultTableDataWrapper.PREVIEW_ALL); } } else { - ((TableDataWrapper) data).previewData(); + TableDataWrapper wrapper = ((TableDataWrapper) data); + if (TableDataAuthHelper.needCheckAuthWhenEdit(wrapper.getTableData())) { + // 先打开一个Loading面板 + TableDataLoadingPane loadingPane = new TableDataLoadingPane(); + BasicDialog loadingDialog = loadingPane.showLargeWindow(SwingUtilities.getWindowAncestor(BasicTableDataTreePane.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); + wrapper.previewData(); + } 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 { + wrapper.previewData(); + } } } catch (Exception ex) { 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 5134e88c8..2354007e1 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 @@ -32,6 +32,7 @@ import com.fr.file.TableDataConfig; import com.fr.general.ComparatorUtils; import com.fr.general.data.DataModel; import com.fr.general.data.TableDataException; +import com.fr.general.sql.sqlnote.SqlNoteConstants; import com.fr.log.FineLoggerFactory; import com.fr.module.ModuleContext; import com.fr.script.Calculator; @@ -571,6 +572,7 @@ public abstract class DesignTableDataManager { parameter.setValue(parameterMap.get(parameter.getName())); } } + addTemplateInfoIfNeed(parameterMap); return DataOperator.getInstance().previewTableData(TableDataSourceTailor.extractTableData(tableDataSource), tabledata, parameterMap, rowCount); } catch (Exception e) { throw new TableDataException(e.getMessage(), e); @@ -590,6 +592,12 @@ public abstract class DesignTableDataManager { } } + private static void addTemplateInfoIfNeed(Map parameterMap) { + if (JTemplate.isValid(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate())) { + parameterMap.put(SqlNoteConstants.SQL_NOTE_TEMPLATE, HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getEditingFILE().getPath()); + } + } + private static boolean needInputParams(boolean mustInputParameters, ParameterProvider[] parameters) { if (mustInputParameters && ArrayUtils.isNotEmpty(parameters)) { return true; @@ -667,6 +675,7 @@ public abstract class DesignTableDataManager { if (needLoadingBar) { MultiResultTableDataWrapper.loadingBar.start(); } + addTemplateInfoIfNeed(parameterMap); return DataOperator.getInstance().previewMultiResultTableData(tableData, parameterMap, 0); } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java index f3df21df9..0106654e8 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java @@ -6,6 +6,7 @@ import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.ilable.ActionLabel; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.esd.common.CacheConstants; @@ -29,8 +30,8 @@ import java.net.URI; import java.text.ParseException; import java.util.ArrayList; import java.util.Collections; -import java.util.List; import java.util.Date; +import java.util.List; /** * @author rinoux @@ -38,7 +39,18 @@ import java.util.Date; * Created by rinoux on 2020/7/22 */ public class ESDStrategyConfigPane extends BasicBeanPane { - private static final String CRON_HELP_URL = "http://help.fanruan.com/finereport/doc-view-693.html"; + + /** + * 云中心定时调度执行频率表达式设定帮助文档链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Cron_Help"; + + /** + * 云中心定时调度执行频率表达式设定帮助文档默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Cron_Help_Default"; + + private static final String CRON_HELP_URL = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); private UIRadioButton selectAutoUpdate; private UIRadioButton selectBySchema; private UICheckBox shouldEvolve; diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java index 0a00f3704..3c5c2b82a 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java @@ -589,7 +589,7 @@ public abstract class DatabaseConnectionPane dataMaskMark = LocaleCenter.getMark(DataMaskMark.class); + URL url = new URL(dataMaskMark.getValue()); Desktop.getDesktop().browse(url.toURI()); } catch (Exception e) { FineLoggerFactory.getLogger().error(e, "open browse of table data desensitization help document failed for {}", e.getMessage()); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java index c0239c8fa..c4996d539 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java @@ -11,12 +11,12 @@ import com.fr.design.dialog.DialogActionAdapter; 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.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.design.parameter.ParameterInputPane; import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.general.CloudCenter; import com.fr.general.GeneralContext; import com.fr.log.FineLoggerFactory; import com.fr.plugin.injectable.PluginModule; @@ -63,6 +63,16 @@ public class PreviewPerformedSqlPane extends JDialog implements ActionListener { private UILabel imageLabel; + /** + * 云中心防止sql注入帮助文档链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design_Basic_Sql_Injection_Prevention_Help"; + + /** + * 云中心防止sql注入帮助文档默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design_Basic_Sql_Injection_Prevention_Help_Default"; + public PreviewPerformedSqlPane(Frame frame, String sql) { this(frame, sql, null, null, false); } @@ -84,7 +94,7 @@ public class PreviewPerformedSqlPane extends JDialog implements ActionListener { JLabel label = new JLabel(Toolkit.i18nText("Fine-Design_Basic_Preview_Performed_Sql_Message") + Toolkit.i18nText("Fine-Design_Basic_Sql_Injection_Prevention") + Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Back_Message")); messagePanel.add(label); } else { - MessageWithLink message = new MessageWithLink(Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Front_Message"), Toolkit.i18nText("Fine-Design_Basic_Sql_Injection_Prevention"), CloudCenter.getInstance().acquireConf(Toolkit.i18nText("Fine-Design_Basic_Sql_Injection_Prevention_Help"), "https://help.fanruan.com/finereport/doc-view-2219.html"), Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Back_Message")); + MessageWithLink message = new MessageWithLink(Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Front_Message"), Toolkit.i18nText("Fine-Design_Basic_Sql_Injection_Prevention"), LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT), Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Back_Message")); messagePanel.add(message); } // 提示图标 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 index fc5f957f6..8fe64dc29 100644 --- 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 @@ -2,6 +2,7 @@ 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.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; import com.fr.plugin.error.PluginErrorCode; import com.fr.plugin.manage.control.PluginTaskResult; @@ -16,7 +17,19 @@ public class PluginCallBackHelper { 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"); + + /** + * 云中心第三方插件安装失败说明帮助文档在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_LINK"; + + /** + * 云中心第三方插件安装失败说明帮助文档默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_LINK_Default"; + + + private static final String HELP_DOCUMENT_LINK = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); /** 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 86820aa22..f895a4f5b 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 @@ -268,7 +268,8 @@ public class HistoryTemplateListCache implements CallbackEvent { boolean replaceWithJVirtualTemplate = overTemplate.getEditingFILE().exists() && overTemplate.isALLSaved() && overTemplate != editingTemplate - && overTemplate.checkEnable(); + && overTemplate.checkEnable() + && overTemplate.supportCache(); if (replaceWithJVirtualTemplate) { closeVirtualSelectedReport(overTemplate); historyList.set(i, new JVirtualTemplate(overTemplate.getEditingFILE())); @@ -297,7 +298,9 @@ public class HistoryTemplateListCache implements CallbackEvent { int index = iterator.nextIndex(); if (size == index + 1 && index > 0) { //如果删除的是后一个Tab,则定位到前一个 - MultiTemplateTabPane.getInstance().setSelectedIndex(index - 1); + MultiTemplateTabPane.getInstance().setSelectedIndex( + MultiTemplateTabPane.getInstance().calNextShowJTemplateIndex(index - 1)); + } } } diff --git a/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabMenuFactory.java b/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabMenuFactory.java new file mode 100644 index 000000000..6210f7ba6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabMenuFactory.java @@ -0,0 +1,349 @@ +package com.fr.design.file; + +import com.fr.base.svg.IconUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.imenu.UIMenuItem; +import com.fr.design.gui.imenu.UIScrollPopUpMenu; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.utils.TemplateUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.collections.CollectionUtils; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 右侧下拉菜单的工厂类 + * @author Carlson + * @since 11.0 + * created on 2023-04-14 + **/ +public class MultiTemplateTabMenuFactory { + + private static final Icon CLOSE = IconUtils.readIcon("/com/fr/design/standard/close/close"); + private static final Icon MOUSE_OVER_CLOSE = IconUtils.readIcon("/com/fr/design/standard/close/close_mouseover.svg"); + private static final Icon MOUSE_PRESS_CLOSE = IconUtils.readIcon("/com/fr/design/standard/close/close_press.svg"); + + private static final int ITEM_SIZE = 25; + + private UIScrollPopUpMenu menu = null; + + private static MultiTemplateTabMenuFactory INSTANCE = new MultiTemplateTabMenuFactory(); + + private MultiTemplateTabMenuFactory() { + + } + + /** + * 返回右侧下拉菜单的工厂类 + * @return + */ + public static MultiTemplateTabMenuFactory getInstance() { + return INSTANCE; + } + + /** + * tab上的下拉菜单 + */ + public UIScrollPopUpMenu createMenu() { + menu = new UIScrollPopUpMenu(); + menu.setBorder(BorderFactory.createEmptyBorder(-3, 3, 3, 0)); + + menu.add(initCloseOther()); + menu.add(createEmptyRow()); + menu.addSeparator(); + menu.add(createEmptyRow()); + menu.add(createCategory(Toolkit.i18nText("Fine-Design_Basic_Tab_Current_Category_Templates"))); + Component[] items = createCurrentCategory(); + for (Component item : items) { + menu.add(item); + } + items = createOtherCategory(); + if (items.length > 0) { + menu.addSeparator(); + menu.add(createEmptyRow()); + menu.add(createCategory(Toolkit.i18nText("Fine-Design_Basic_Tab_Other_Category_Templates"))); + for (Component item : items) { + menu.add(item); + } + } + Dimension dimension = menu.getPreferredSize(); + dimension.width += ITEM_SIZE; + menu.setPreferredSize(dimension); + return menu; + } + + /** + * 关闭其它按钮 + */ + private UIMenuItem initCloseOther() { + UIMenuItem closeOther = new UIMenuItem(Toolkit.i18nText("Fine-Design_Basic_Tab_Close_Other_Templates_Of_Current_Category")); + closeOther.setHorizontalAlignment(SwingConstants.CENTER); + Dimension dimension = closeOther.getPreferredSize(); + dimension.height = ITEM_SIZE; + closeOther.setPreferredSize(dimension); + String currentOperator = getCurrentTabOperatorType(); + closeOther.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + MultiTemplateTabPane.getInstance().closeOtherByOperatorType(currentOperator); + } + }); + if (MultiTemplateTabPane.getInstance().getOpenedJTemplatesByOperator(currentOperator).size() <= 1) { + closeOther.setEnabled(false); + } + return closeOther; + } + + + /** + * 美观用 + */ + private JPanel createEmptyRow() { + return new JPanel() { + @Override + public Dimension getPreferredSize() { + Dimension d = super.getPreferredSize(); + d.height = 1; + return d; + } + }; + } + + /** + * 模板分类item + */ + private UIButton createCategory(String categoryName) { + UIButton button = new UIButton(categoryName); + button.setBorderPainted(false); + button.setExtraPainted(false); + button.setPreferredSize(new Dimension(menu.getWidth(), ITEM_SIZE)); + button.setOpaque(true); + button.setBackground(UIConstants.NORMAL_BACKGROUND); + button.setHorizontalAlignment(SwingConstants.LEFT); + button.setForeground(UIConstants.FLESH_BLUE); + return button; + } + + /** + * 创建 当前分类模板 item数组 + */ + private Component[] createCurrentCategory() { + return createListDownItem(MultiTemplateTabPane.getInstance().getOpenedJTemplatesByOperator(getCurrentTabOperatorType())); + } + + private String getCurrentTabOperatorType(){ + JTemplate jTemplate= HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + return jTemplate.getTemplateTabOperatorType(); + } + + /** + * 创建 其它分类模板 item数组 + */ + private Component[] createOtherCategory() { + String currentOperator = getCurrentTabOperatorType(); + List> openedTemplates = new ArrayList<>(); + Map>> map = MultiTemplateTabPane.getInstance().getOpenedJTemplatesByCategory(); + for (Map.Entry>> entry : map.entrySet()) { + if (!StringUtils.equals(currentOperator, entry.getKey())) { + openedTemplates.addAll(entry.getValue()); + } + } + return createListDownItem(openedTemplates); + } + + /** + * 根据template列表创建多个item + */ + private Component[] createListDownItem(List> openedTemplates) { + if (!CollectionUtils.isEmpty(openedTemplates)) { + Component[] templates = new Component[openedTemplates.size()]; + for (int i = 0; i < openedTemplates.size(); i++) { + templates[i] = createListDownMenuItem(openedTemplates.get(i)); + } + return templates; + } + return new Component[0]; + } + + /** + * 根据template对象创建item + */ + private Component createListDownMenuItem(JTemplate template) { + JPanel jPanel = new JPanel(); + jPanel.setPreferredSize(new Dimension(menu.getWidth(), ITEM_SIZE)); + jPanel.setLayout(new BorderLayout()); + + MenuItemButtonGroup menuItemButtonGroup = new MenuItemButtonGroup(template); + if (template == HistoryTemplateListCache.getInstance().getCurrentEditingTemplate()) { + menuItemButtonGroup.templateButton.setForeground(UIConstants.FLESH_BLUE); + } + + jPanel.add(menuItemButtonGroup.iconButton, BorderLayout.WEST); + jPanel.add(menuItemButtonGroup.templateButton, BorderLayout.CENTER); + jPanel.add(menuItemButtonGroup.closeButton, BorderLayout.EAST); + + return jPanel; + } + + /** + * menu的item由模板图标、模板名、模板关闭按钮组成 + */ + private class MenuItemButtonGroup { + + private final UIButton iconButton; + private final UIButton templateButton; + private final UIButton closeButton; + + public MenuItemButtonGroup(JTemplate template) { + iconButton = createIconButton(template); + templateButton = createTemplateButton(template); + closeButton = createCloseButton(); + initListener(template); + } + + /** + * item[0] 模板图标按钮初始化 + */ + private UIButton createIconButton(JTemplate template) { + UIButton button = new UIButton(template.getIcon(), template.getIcon(), template.getIcon()); + button.setPreferredSize(new Dimension(ITEM_SIZE, ITEM_SIZE)); + button.setOpaque(true); + button.setBackground(UIConstants.NORMAL_BACKGROUND); + return button; + } + + /** + * item[1] 切换模板按钮初始化 + */ + private UIButton createTemplateButton(JTemplate template) { + UIButton button = new UIButton(TemplateUtils.createLockeTemplatedName(template, template.getTemplateName())); + button.setBorderPainted(false); + button.setExtraPainted(false); + button.setPreferredSize(new Dimension(menu.getWidth() - ITEM_SIZE * 2, ITEM_SIZE)); + button.setOpaque(true); + button.setBackground(UIConstants.NORMAL_BACKGROUND); + button.setHorizontalAlignment(SwingConstants.LEFT); + return button; + } + + /** + * item[2] 关闭模板图标按钮初始化 + */ + private UIButton createCloseButton() { + UIButton button = new UIButton(CLOSE, MOUSE_OVER_CLOSE, MOUSE_PRESS_CLOSE); + button.setPreferredSize(new Dimension(ITEM_SIZE, ITEM_SIZE)); + button.setOpaque(true); + button.setBackground(UIConstants.NORMAL_BACKGROUND); + button.setVisible(false); + return button; + } + + private void initListener(JTemplate template) { + initIconButtonListener(); + initTemplateButtonListener(template); + initCloseButtonListener(template); + } + + /** + * item[0] 模板图标按钮鼠标事件 + */ + private void initIconButtonListener() { + iconButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + fireMouseEnteredEvent(); + } + + @Override + public void mouseExited(MouseEvent e) { + fireMouseExitedEvent(); + } + }); + } + + /** + * item[1] 切换模板按钮鼠标事件 + */ + private void initTemplateButtonListener(JTemplate template) { + templateButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + menu.setVisible(false); + MultiTemplateTabPane.getInstance().switchJTemplate(template); + } + + @Override + public void mouseEntered(MouseEvent e) { + fireMouseEnteredEvent(); + } + + @Override + public void mouseExited(MouseEvent e) { + fireMouseExitedEvent(); + } + }); + } + + /** + * item[2] 关闭模板按钮鼠标事件 + */ + private void initCloseButtonListener(JTemplate template) { + closeButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + menu.setVisible(false); + MultiTemplateTabPane.getInstance().setIsCloseCurrent(template == HistoryTemplateListCache.getInstance().getCurrentEditingTemplate()); + MultiTemplateTabPane.getInstance().closeFormat(template); + MultiTemplateTabPane.getInstance().closeSpecifiedTemplate(template); + } + + @Override + public void mouseEntered(MouseEvent e) { + fireMouseEnteredEvent(); + } + + @Override + public void mouseExited(MouseEvent e) { + fireMouseExitedEvent(); + } + }); + } + + /** + * mouse移入item范围 + */ + private void fireMouseEnteredEvent() { + iconButton.setBackground(UIConstants.HOVER_BLUE); + templateButton.setBackground(UIConstants.HOVER_BLUE); + closeButton.setBackground(UIConstants.HOVER_BLUE); + closeButton.setVisible(true); + } + + /** + * mouse移出item范围 + */ + private void fireMouseExitedEvent() { + iconButton.setBackground(UIConstants.NORMAL_BACKGROUND); + templateButton.setBackground(UIConstants.NORMAL_BACKGROUND); + closeButton.setBackground(UIConstants.NORMAL_BACKGROUND); + closeButton.setVisible(false); + } + + } + +} diff --git a/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java b/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java index 8e302fd97..9236deb4a 100644 --- a/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java +++ b/designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java @@ -1,7 +1,6 @@ package com.fr.design.file; -import com.fr.base.BaseUtils; import com.fr.base.GraphHelper; import com.fr.base.svg.IconUtils; import com.fr.base.vcs.DesignerMode; @@ -19,7 +18,6 @@ import com.fr.design.mainframe.JTemplate; import com.fr.design.mainframe.TemplateSavingChecker; import com.fr.design.mainframe.manager.search.TemplateTreeSearchManager; import com.fr.design.utils.DesignUtils; -import com.fr.design.utils.TemplateUtils; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.utils.gui.GUIPaintUtils; import com.fr.design.worker.WorkerManager; @@ -42,11 +40,11 @@ import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; -import javax.swing.JPanel; import javax.swing.JSeparator; import javax.swing.MenuElement; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; +import javax.swing.ToolTipManager; import javax.swing.plaf.basic.BasicMenuItemUI; import java.awt.AWTEvent; import java.awt.AlphaComposite; @@ -70,6 +68,8 @@ import java.awt.geom.Line2D; import java.awt.geom.Path2D; import java.awt.geom.RoundRectangle2D; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import static com.fr.design.dialog.FineJOptionPane.showConfirmDialog; import static javax.swing.JOptionPane.OK_CANCEL_OPTION; @@ -213,6 +213,35 @@ public class MultiTemplateTabPane extends JComponent { }); } + + /** + * 模板可以关闭的条件 + */ + class CloseCondition { + private CloseOption closeOption; + + public CloseCondition(CloseOption closeOption) { + this.closeOption = closeOption; + } + + /** + * 判断模板是否可以关闭,两个条件:1、是否满足CloseOption里面的条件(在左侧、在右侧等)2、是否和当前正在编辑模板属于同一种模板tab操作类型 + * @param closeJTemplate + * @param tplIndex + * @param i + * @return + */ + public boolean shouldClose(JTemplate closeJTemplate, int tplIndex, int i) { + boolean matchOption = this.closeOption.shouldClose(tplIndex, i); + JTemplate currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (!JTemplate.isValid(currentTemplate)) { + return matchOption; + } + return matchOption && ComparatorUtils.equals(closeJTemplate.getTemplateTabOperatorType(), + currentTemplate.getTemplateTabOperatorType()); + } + } + enum CloseOption { Left(Toolkit.i18nText("Fine-Design_Close_templates_To_The_Left")) { @Override @@ -323,29 +352,34 @@ public class MultiTemplateTabPane extends JComponent { @Override public void actionPerformed(ActionEvent e) { - SaveSomeTemplatePane saveSomeTempaltePane = new SaveSomeTemplatePane(false); - if (saveSomeTempaltePane.showSavePane()) { + //只有关闭所有模板才需要判断当前模板,关闭左侧、右侧、其他都不需要 + SaveSomeTemplatePane saveSomeTemplatePane = new SaveSomeTemplatePane(option == CloseOption.All); + CloseCondition closeCondition = new CloseCondition(option); + if (saveSomeTemplatePane.showSavePane(closeCondition, false)) { JTemplate[] templates = new JTemplate[openedTemplate.size()]; for (int i = 0; i < openedTemplate.size(); i++) { templates[i] = openedTemplate.get(i); } JTemplate currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - closeTemplate(templates, currentTemplate); + closeTemplate(closeCondition, templates, currentTemplate); - if (option == CloseOption.All) { + if (openedTemplate.size() == 0) { DesignerContext.getDesignerFrame().addAndActivateJTemplate(); + } else if (option == CloseOption.All){ + //openedTemplate(0)是JVirtualTemplate时需重新打开 + openedTemplate.get(0).activeOldJTemplate(); } else { - DesignerContext.getDesignerFrame().activateJTemplate(currentTemplate); + currentTemplate.activeOldJTemplate(); } MultiTemplateTabPane.getInstance().repaint(); } } - private void closeTemplate(JTemplate[] templates, JTemplate currentTemplate) { + private void closeTemplate(CloseCondition closeCondition, JTemplate[] templates, JTemplate currentTemplate) { for (int i = 0; i < templates.length; i++) { - if (option.shouldClose(tplIndex, i)) { + if (closeCondition.shouldClose(templates[i], tplIndex, i)) { JTemplate jTemplate = templates[i]; if (jTemplate == currentTemplate) { currentTemplate = option == CloseOption.All ? null : templates[tplIndex]; @@ -378,6 +412,46 @@ public class MultiTemplateTabPane extends JComponent { return openedTemplate.get(selectedIndex); } + /** + * 关闭所有指定模板tab操作类型的模板 + * @param operatorType + */ + public void closeOtherByOperatorType(String operatorType){ + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + SaveSomeTemplatePane saveSomeTempaltePane = new SaveSomeTemplatePane(false); + if (saveSomeTempaltePane.showSavePane()) { + List> openedTemplate = HistoryTemplateListCache.getInstance().getHistoryList(); + + JTemplate[] templates = new JTemplate[openedTemplate.size()]; + for (int i = 0; i < openedTemplate.size(); i++) { + templates[i] = openedTemplate.get(i); + } + closeTemplate(templates, currentEditingTemplate, operatorType); + + DesignerContext.getDesignerFrame().activateJTemplate(currentEditingTemplate); + MultiTemplateTabPane.getInstance().repaint(); + } + } + + /** + * 关闭指定的非当前编辑模板 + * @param templates + * @param operatorType + */ + private static void closeTemplate(JTemplate[] templates, JTemplate currentEditingTemplate, String operatorType) { + for (int i = 0; i < templates.length; i++) { + JTemplate jTemplate = templates[i]; + boolean needClose = ComparatorUtils.equals(operatorType, jTemplate.getTemplateTabOperatorType()) + && jTemplate != currentEditingTemplate; + if (!needClose) { + continue; + } + MultiTemplateTabPane.getInstance().closeFormat(jTemplate); + HistoryTemplateListCache.getInstance().closeSelectedReport(jTemplate); + MultiTemplateTabPane.getInstance().closeAndFreeLock(jTemplate); + } + } + /** * 关闭掉当前已打开文件列表中指定的文件 @@ -478,11 +552,7 @@ public class MultiTemplateTabPane extends JComponent { private String tempalteShowName(JTemplate template) { - String name = TemplateUtils.createLockeTemplatedName(template, template.getTemplateName()); - if (!template.isSaved() && !name.endsWith(" *")) { - name += " *"; - } - return name; + return template.getTabShowName(template); } /** @@ -500,40 +570,7 @@ public class MultiTemplateTabPane extends JComponent { private void showListDown() { - - UIScrollPopUpMenu menu = new UIScrollPopUpMenu(); - menu.setBorder(BorderFactory.createEmptyBorder(-3, 3, 3, 0)); - menu.add(initCloseOther()); - JSeparator separator = new JSeparator() { - @Override - public Dimension getPreferredSize() { - Dimension d = super.getPreferredSize(); - d.height = 1; - return d; - } - }; - menu.add(new JPanel() { - @Override - public Dimension getPreferredSize() { - Dimension d = super.getPreferredSize(); - d.height = 1; - return d; - } - }); - separator.setForeground(UIConstants.LINE_COLOR); - menu.add(separator); - menu.add(new JPanel() { - @Override - public Dimension getPreferredSize() { - Dimension d = super.getPreferredSize(); - d.height = 1; - return d; - } - }); - UIMenuItem[] items = createListDownTemplate(); - for (int i = 0; i < items.length; i++) { - menu.add(items[i]); - } + UIScrollPopUpMenu menu = MultiTemplateTabMenuFactory.getInstance().createMenu(); GUICoreUtils.showPopupMenu(menu, MultiTemplateTabPane.getInstance(), MultiTemplateTabPane.getInstance().getWidth() - menu.getPreferredSize().width, getY() - 1 + getHeight()); } @@ -583,6 +620,9 @@ public class MultiTemplateTabPane extends JComponent { //从可以开始展示在tab面板上的tab开始画 for (int i = minPaintIndex; i <= maxPaintIndex; i++) { JTemplate template = openedTemplate.get(i); + if (!showJTemplateTab(template)){ + continue; + } Icon icon = template.getIcon(); String name = tempalteShowName(template); //如果tab名字的长度大于最大能显示的英文字符长度,则进行省略号处理 @@ -717,13 +757,67 @@ public class MultiTemplateTabPane extends JComponent { minPaintIndex = 0; maxPaintIndex = openedTemplate.size() - 1; } + //需要根据每个tab的宽度重新check下实际的maxPaintIndex和minPaintIndex + checkActualPaintIndex(); + } + + /** + * 先计算出需要补充的tab个数 + * @return + */ + private int calTabCountComplemented(){ + int a = 0; + for (int i = minPaintIndex; i <= maxPaintIndex; i++) { + JTemplate template = openedTemplate.get(i); + if (!showJTemplateTab(template)) { + a++; + } + } + return a; + } + + + /** + * 由于可能存在宽度为0的tab,所以这边需要重新check下,先往后补,再往前补 + */ + private void checkActualPaintIndex(){ + int tabCount = calTabCountComplemented(); + if (tabCount == 0){ + return; + } + if (maxPaintIndex < openedTemplate.size() - 1) { + for (int i = maxPaintIndex + 1; i < openedTemplate.size(); i++) { + JTemplate template = openedTemplate.get(i); + if (showJTemplateTab(template)) { + tabCount--; + } + maxPaintIndex++; + if (tabCount == 0){ + return; + } + } + } + if (minPaintIndex > 0){ + for (int i = minPaintIndex - 1; i >= 0; i--) { + JTemplate template = openedTemplate.get(i); + if (showJTemplateTab(template)) { + tabCount--; + } + minPaintIndex--; + if (tabCount == 0){ + return; + } + } + } } //个数小于最多能容纳的个数的情况下,看看宽度每个要画多少 private void calculateRealAverageWidth(double maxwidth, int templateNum) { + JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + List> showTemplates = getOpenedJTemplatesByOperator(jTemplate.getTemplateTabOperatorType()); - int num = openedTemplate.size() > templateNum ? templateNum : openedTemplate.size(); + int num = Math.min(showTemplates.size(), templateNum); realWidth = (int) (maxwidth / (num)); if (realWidth > MAXWIDTH) { realWidth = MAXWIDTH; @@ -932,7 +1026,7 @@ public class MultiTemplateTabPane extends JComponent { activePrevTemplateAfterClose(); } - private void closeAndFreeLock(@Nonnull JTemplate template) { + public void closeAndFreeLock(@Nonnull JTemplate template) { FILE file = template.getEditingFILE(); // 只有是环境内的文件,才执行释放锁 if (file != null && file.isEnvFile()) { @@ -986,9 +1080,12 @@ public class MultiTemplateTabPane extends JComponent { // selectIndex 没有变化,但是对应的模板已经变成了前一张模板 if (closeIconIndex == selectedIndex || isCloseCurrent) { // 如果当前关闭的模板在最右侧,那么预览上一个,防止数组越界 + // 关闭的模板是当前选中的模板时,需要重新计算下一个待展示的模板的index if (selectedIndex >= maxPaintIndex) { // selectIndex 不会 <0 因为如果关闭的是打开的最后一个模板,那么关闭之后 openedTemplate.isEmpty() = true - selectedIndex--; + selectedIndex = calNextShowJTemplateIndex(selectedIndex - 1); + } else { + selectedIndex = calNextShowJTemplateIndex(selectedIndex); } isCloseCurrent = false; } @@ -1005,6 +1102,26 @@ public class MultiTemplateTabPane extends JComponent { } } + /** + * 计算下一个可以展示的模板index + * @param currentIndex + * @return + */ + public int calNextShowJTemplateIndex(int currentIndex) { + //先看是否有可以展示的模板 + for (int i = currentIndex; i >= 0; i--) { + if (showJTemplateTab(openedTemplate.get(i))) { + return i; + } + } + for (int i = currentIndex; i >= 0; i--) { + if (!showJTemplateTab(openedTemplate.get(i))) { + return i; + } + } + return -1; + } + private boolean isOverCloseIcon(int evtX) { boolean isOverCloseIcon = false; @@ -1027,7 +1144,7 @@ public class MultiTemplateTabPane extends JComponent { private int getTemplateIndex(int evtX) { int textX = 0; for (int i = minPaintIndex; i <= maxPaintIndex; i++) { - int textWidth = realWidth; + int textWidth = showJTemplateTab(openedTemplate.get(i)) ? realWidth : 0; if (evtX >= textX && evtX < textX + textWidth) { return i; } @@ -1089,6 +1206,7 @@ public class MultiTemplateTabPane extends JComponent { private class MultiTemplateTabMouseListener implements MouseListener { + private boolean oldLightWeightPopupEnabled; /** * 鼠标进入 @@ -1097,7 +1215,8 @@ public class MultiTemplateTabPane extends JComponent { */ @Override public void mouseEntered(MouseEvent e) { - // do nothing + this.oldLightWeightPopupEnabled = ToolTipManager.sharedInstance().isLightWeightPopupEnabled(); + ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false); } /** @@ -1107,6 +1226,9 @@ public class MultiTemplateTabPane extends JComponent { */ @Override public void mouseExited(MouseEvent e) { + ToolTipManager.sharedInstance().setEnabled(false); + ToolTipManager.sharedInstance().setEnabled(true); + ToolTipManager.sharedInstance().setLightWeightPopupEnabled(this.oldLightWeightPopupEnabled); listDownMode = LIST_DOWN; closeIconIndex = -1; mouseOveredIndex = -1; @@ -1184,29 +1306,44 @@ public class MultiTemplateTabPane extends JComponent { //没有点击关闭和ListDown按钮,则切换到点击的模板处 closeIconIndex = -1; clodeMode = CLOSE; - int tempSelectedIndex = selectedIndex; - if (selectedIndex != getTemplateIndex(evtX) && getTemplateIndex(evtX) != -1) { - openedTemplate.get(selectedIndex).stopEditing(); - selectedIndex = getTemplateIndex(evtX); - //如果在权限编辑情况下,不允许切换到表单类型的工作簿 - if (DesignerMode.isAuthorityEditing() && !openedTemplate.get(selectedIndex).isJWorkBook()) { - DesignerContext.getDesignerFrame().addAndActivateJTemplate(openedTemplate.get(tempSelectedIndex)); - FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Form_Authority_Edited_Cannot_Be_Supported") - + "!", Toolkit.i18nText("Fine-Design_Basic_Alert"), JOptionPane.WARNING_MESSAGE); - MultiTemplateTabPane.this.repaint(); - return; - } - JTemplate evtXTemplate = openedTemplate.get(getTemplateIndex(evtX)); - evtXTemplate.activeNewJTemplate(); - } + switchJTemplate(getTemplateIndex(evtX)); isShowList = false; } MultiTemplateTabPane.this.repaint(); - - } + } + /** + * 切换到指定模板 + * @param jTemplate + */ + public void switchJTemplate(JTemplate jTemplate) { + int switchIndex = this.openedTemplate.indexOf(jTemplate); + if (switchIndex >= 0) { + switchJTemplate(switchIndex); + } + } + /** + * 切换到指定index + * @param switchIndex + */ + private void switchJTemplate(int switchIndex){ + int tempSelectedIndex = selectedIndex; + if (selectedIndex != switchIndex && switchIndex != -1) { + openedTemplate.get(selectedIndex).stopEditing(); + selectedIndex = switchIndex; + //如果在权限编辑情况下,不允许切换到表单类型的工作簿 + if (DesignerMode.isAuthorityEditing() && !openedTemplate.get(selectedIndex).isJWorkBook()) { + DesignerContext.getDesignerFrame().addAndActivateJTemplate(openedTemplate.get(tempSelectedIndex)); + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Form_Authority_Edited_Cannot_Be_Supported") + + "!", Toolkit.i18nText("Fine-Design_Basic_Alert"), JOptionPane.WARNING_MESSAGE); + MultiTemplateTabPane.this.repaint(); + return; + } + JTemplate evtXTemplate = openedTemplate.get(switchIndex); + evtXTemplate.activeNewJTemplate(); + } } private boolean checkCurrentClose(JTemplate template) { @@ -1251,5 +1388,34 @@ public class MultiTemplateTabPane extends JComponent { } } + /** + * 判断是否显示在tab栏上 + * @param jTemplate + * @return + */ + private boolean showJTemplateTab(JTemplate jTemplate){ + JTemplate current = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + return ComparatorUtils.equals(current.getTemplateTabOperatorType(), jTemplate.getTemplateTabOperatorType()); + } + + /** + * 获取tab操作类型的模板 + * @param operator + * @return + */ + public List> getOpenedJTemplatesByOperator(String operator) { + return openedTemplate.stream().filter((jTemplate) -> ComparatorUtils.equals(jTemplate.getTemplateTabOperatorType(), operator)) + .collect(Collectors.toList()); + } + + /** + * 根据tab操作类型进行分类 + * @return + */ + public Map>> getOpenedJTemplatesByCategory() { + return openedTemplate.stream() + .collect(Collectors.groupingBy(JTemplate::getTemplateTabOperatorType)); + } + } diff --git a/designer-base/src/main/java/com/fr/design/file/NewTemplatePane.java b/designer-base/src/main/java/com/fr/design/file/NewTemplatePane.java index dae921a1c..81f82e78c 100644 --- a/designer-base/src/main/java/com/fr/design/file/NewTemplatePane.java +++ b/designer-base/src/main/java/com/fr/design/file/NewTemplatePane.java @@ -81,11 +81,19 @@ public abstract class NewTemplatePane extends JComponent implements MouseListene } if (isOverNewIcon(evtX) && newWorkBookIconMode != GRAY_NEW_CPT) { newWorkBookIconMode = getMousePressNew(); - DesignerContext.getDesignerFrame().addAndActivateJTemplate(); + createNewTemplate(); } this.repaint(); } + + /** + * 新建模板 + */ + protected void createNewTemplate() { + DesignerContext.getDesignerFrame().addAndActivateJTemplate(); + } + /** *鼠标松开 * @param e 事件 diff --git a/designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java b/designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java index 72945b31c..0bdd48b35 100644 --- a/designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java +++ b/designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java @@ -17,6 +17,7 @@ import com.fr.design.mainframe.JTemplate; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; @@ -47,6 +48,7 @@ public class SaveSomeTemplatePane extends BasicPane { /** * 支持自定义设置 dialog的父窗口 + * * @param isNeedTojudgeCurrent * @param parent */ @@ -79,11 +81,14 @@ public class SaveSomeTemplatePane extends BasicPane { this.isJudgeCurrentEditingTemplate = isNeedTojudgeCurrent; } - private void initTemplatesChoosePane() { + + private void initTemplatesChoosePane(boolean judgeJTemplateMustSave) { templatesChoosePane.setBorder(BorderFactory.createTitledBorder("")); for (int i = 0; i < unSavedTemplate.size(); i++) { templateCheckBoxes[i] = new UICheckBox(unSavedTemplate.get(i).getEditingFILE().getName()); templateCheckBoxes[i].setSelected(true); + boolean needSave = judgeJTemplateMustSave && unSavedTemplate.get(i).needSaveBeforeSwitchEnv(); + templateCheckBoxes[i].setEnabled(!needSave); } final UIList templatesList = new UIList(templateCheckBoxes); @@ -103,7 +108,10 @@ public class SaveSomeTemplatePane extends BasicPane { boolean isSelected = chooseAllCheckBox.isSelected(); for (int i = 0; i < templatesList.getModel().getSize(); i++) { UICheckBox checkBox = (UICheckBox) templatesList.getModel().getElementAt(i); - checkBox.setSelected(isSelected); + boolean mustSaveBeforeSwitchEnv = judgeJTemplateMustSave && unSavedTemplate.get(i).needSaveBeforeSwitchEnv(); + checkBox.setSelected(mustSaveBeforeSwitchEnv || isSelected); + templateCheckBoxes[i].setEnabled(!mustSaveBeforeSwitchEnv); + } templatesList.repaint(); } @@ -116,8 +124,10 @@ public class SaveSomeTemplatePane extends BasicPane { if (index < 0) { return; } + boolean mustSaveBeforeSwitchEnv = judgeJTemplateMustSave + && unSavedTemplate.get(index).needSaveBeforeSwitchEnv(); UICheckBox checkBox = (UICheckBox) templatesList.getModel().getElementAt(index); - checkBox.setSelected(!checkBox.isSelected()); + checkBox.setSelected(mustSaveBeforeSwitchEnv ||!checkBox.isSelected()); //根据templateCheckBoxes中的选择情况来更新全选框的状态 int selectedCount = calculateSelectedNum(); @@ -139,7 +149,7 @@ public class SaveSomeTemplatePane extends BasicPane { /** * 获取templateCheckBoxes中状态为选中状态的CheckBox数量 - * */ + */ private int calculateSelectedNum() { int count = 0; for (UICheckBox checkBox : templateCheckBoxes) { @@ -152,7 +162,28 @@ public class SaveSomeTemplatePane extends BasicPane { public boolean showSavePane() { - populate(); + return showSavePane(false); + } + + /** + * 显示保存模板提醒面板 + * + * @param judgeJTemplateMustSave 模板是否必须保存 + * @return + */ + public boolean showSavePane(boolean judgeJTemplateMustSave) { + return showSavePane(null, judgeJTemplateMustSave); + } + + /** + * 显示保存模板提醒面板 + * + * @param option 具体关闭操作 + * @param judgeJTemplateMustSave 模板是否必须保存 + * @return + */ + public boolean showSavePane(@Nullable MultiTemplateTabPane.CloseCondition option, boolean judgeJTemplateMustSave) { + initAndPopulate(option, judgeJTemplateMustSave); //如果有未保存的文件 ,则跳出保存对话框,选择要存储的项目 if (!unSavedTemplate.isEmpty()) { dialog.setVisible(true); @@ -162,19 +193,26 @@ public class SaveSomeTemplatePane extends BasicPane { return isAllSaved; } - public void populate() { - java.util.List> opendedTemplate = HistoryTemplateListPane.getInstance().getHistoryList(); + protected java.util.List> getOpenedTemplatesToProcess(){ + return HistoryTemplateListPane.getInstance().getHistoryList(); + } + + private void initAndPopulate(@Nullable MultiTemplateTabPane.CloseCondition option, boolean judgeJTemplateMustSave) { + java.util.List> opendedTemplate = getOpenedTemplatesToProcess(); JTemplate currentTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + int currentIndex = opendedTemplate.indexOf(currentTemplate); for (int i = 0; i < opendedTemplate.size(); i++) { - if (isneedToAdd(opendedTemplate.get(i), currentTemplate)) { + //满足关闭条件的才继续判断文件是否发生了改动 + boolean needClose = option == null || option.shouldClose(opendedTemplate.get(i), currentIndex, i); + if (needClose && isneedToAdd(opendedTemplate.get(i), currentTemplate)) { unSavedTemplate.add(opendedTemplate.get(i)); } } templateCheckBoxes = new UICheckBox[unSavedTemplate.size()]; - initTemplatesChoosePane(); + initTemplatesChoosePane(judgeJTemplateMustSave); } - private boolean isneedToAdd(JTemplate template, JTemplate currentTemplate) { + protected boolean isneedToAdd(JTemplate template, JTemplate currentTemplate) { //所有模板都判断是不是保存 if (isJudgeCurrentEditingTemplate) { return !template.isALLSaved(); @@ -194,7 +232,7 @@ public class SaveSomeTemplatePane extends BasicPane { specifiedTemplate.stopEditing(); return specifiedTemplate.saveTemplate(); } - FineLoggerFactory.getLogger().info( com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Template_Already_Saved", specifiedTemplate.getEditingFILE().getName())); + FineLoggerFactory.getLogger().info(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Template_Already_Saved", specifiedTemplate.getEditingFILE().getName())); return true; } diff --git a/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java b/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java index ee05422ca..93cdc4e4e 100644 --- a/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java @@ -17,16 +17,19 @@ import com.fr.stable.Nameable; import com.fr.stable.StringUtils; import com.fr.stable.core.PropertyChangeAdapter; -import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import javax.swing.ListCellRenderer; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -343,21 +346,46 @@ public abstract class JListControlPane extends JControlPane implements ListContr } protected class NameableListCellRenderer extends - DefaultListCellRenderer { + JPanel implements ListCellRenderer { + + private final JLabel textLabel; + private final JLabel iconLabel; + + /** + * JList默认单元格渲染器的选中背景色 + */ + private final Color selectedBgColor = new Color(65, 155, 249); + protected NameableListCellRenderer() { + setLayout(new BorderLayout()); + this.textLabel = new JLabel(); + this.iconLabel = new JLabel(); + add(this.textLabel, BorderLayout.CENTER); + add(this.iconLabel, BorderLayout.WEST); + this.iconLabel.setBackground(Color.WHITE); + //iconLabel和textLabel的背景颜色不会被JList背景颜色覆盖,开发者自定义 + this.textLabel.setOpaque(true); + this.iconLabel.setOpaque(true); + } + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - super.getListCellRendererComponent(list, value, index, isSelected, - cellHasFocus); if (value instanceof ListModelElement) { ListModelElement element = ((ListModelElement) value); Nameable nameable = element.wrapper; - this.setText(nameable.getName()); + this.textLabel.setText(nameable.getName()); boolean iconSet = false; + if(isSelected) { + this.textLabel.setBackground(selectedBgColor); + this.textLabel.setForeground(Color.WHITE); + } else { + this.textLabel.setBackground(Color.WHITE); + this.textLabel.setForeground(Color.BLACK); + } for (NameableCreator creator : JListControlPane.this.creators()) { if (creator.menuIcon() != null && creator.acceptObject2Populate(nameable) != null) { - this.setIcon(creator.menuIcon()); + this.iconLabel.setIcon(creator.menuIcon()); this.setToolTipText(creator.createTooltip()); iconSet = true; break; @@ -369,8 +397,16 @@ public abstract class JListControlPane extends JControlPane implements ListContr } return this; } - } + /** + * 改造后兼容子类NoIconNameableListCellRenderer使用,添加此setIcon函数 + * + * @param icon 图标,可为null + */ + public void setIcon(Icon icon) { + this.iconLabel.setIcon(icon); + } + } @Override public BasicBeanPane createPaneByCreators(NameableCreator creator) { return Reflect.on(creator.getUpdatePane()).create().get(); 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 ed07ecc2d..47581fb62 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 @@ -28,14 +28,7 @@ import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import java.awt.AlphaComposite; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; +import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.lang.reflect.Constructor; @@ -146,7 +139,7 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li } this.checkButtonEnabled(); refreshEventListWrapperPane(); - this.checkGroupPaneSize(); + this.updateGroupPaneSize(contentPane); isPopulating = false; } @@ -214,7 +207,7 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li nameEdList.addModNameActionListener(new ModNameActionListener() { @Override public void nameModed(int index, String oldName, String newName) { - checkGroupPaneSize(); + updateGroupPaneSize(contentPane); saveSettings(); } }); @@ -304,24 +297,30 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li public void onAddItem(NameableCreator creator) { updateSelectedNameList(creator); getCommonHandlers().onAddItem(creator); - checkGroupPaneSize(); + updateGroupPaneSize(contentPane); } @Override public void onRemoveItem() { getCommonHandlers().onRemoveItem(); refreshEventListWrapperPane(); - checkGroupPaneSize(); + updateGroupPaneSize(contentPane); } @Override public void onCopyItem() { getCommonHandlers().onCopyItem(); - checkGroupPaneSize(); + updateGroupPaneSize(contentPane); } - private void checkGroupPaneSize() { + /** + * 根据父面板更新对应的面板宽度 + * (如果小于父面板的宽度就填充到与父面板宽度一致) + * + * @param parentPane 父面板 + */ + private void updateGroupPaneSize(JPanel parentPane) { int width = 180; Iterator> iterator = nameEdListMap.entrySet().iterator(); while (iterator.hasNext()) { @@ -331,7 +330,9 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li width = Math.max(width, calculateUIListMaxCellWidth(uiList.getModel(), uiList.getFontMetrics(uiList.getFont()))); } iterator = nameEdListMap.entrySet().iterator(); - width += 30; + //contentPane是外层的Panel,如果不进行判断的话宽度就可能会小于contentPanel,右侧会有空隙 + //所以需要判断一下,如果外层比较宽就取外层的宽度,防止空隙出现 + width = Math.max(width + 30, parentPane == null ? 0 : parentPane.getWidth()); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); ListWrapperPane wrapperPane = entry.getValue(); diff --git a/designer-base/src/main/java/com/fr/design/gui/ilist/JNameEdList.java b/designer-base/src/main/java/com/fr/design/gui/ilist/JNameEdList.java index c12a22505..f4c3cfe92 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ilist/JNameEdList.java +++ b/designer-base/src/main/java/com/fr/design/gui/ilist/JNameEdList.java @@ -11,15 +11,20 @@ import com.fr.stable.core.PropertyChangeAdapter; import javax.swing.ListModel; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; -import java.util.ArrayList; -import java.util.Vector; import java.awt.Component; import java.awt.Rectangle; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; +import java.util.ArrayList; +import java.util.Vector; public class JNameEdList extends UIList implements CellEditorListener { - private static final int ICON_WIDTH = 20; + + /** + * 原值为20,设计器图标由png替换为svg之后JNameEdList的icon大小为16x16 + * 重命名是会出现左侧一部分带有背景色的渲染 + */ + private static final int ICON_WIDTH = 16; private boolean editable = true; // kunsnat: 是否强制ListName是数字 (int型) diff --git a/designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java b/designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java index cc49820de..0fb3706af 100644 --- a/designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java @@ -16,6 +16,7 @@ import com.fr.design.gui.frpane.UIPercentDragPane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icombobox.LineComboBox; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; @@ -26,8 +27,8 @@ import com.fr.design.style.color.NewColorSelectBox; import com.fr.env.utils.DesignerInteractionHistory; import com.fr.general.Background; import com.fr.general.IOUtils; -import com.fr.i18n.UrlI18nManager; import com.fr.general.act.BorderPacker; +import com.fr.i18n.UrlI18nManager; import com.fr.stable.Constants; import com.fr.stable.GraphDrawHelper; import com.fr.stable.ProjectLibrary; @@ -78,7 +79,18 @@ import java.util.Arrays; public class TranslucentBorderSpecialPane extends AbstractBorderPackerPane implements UIObserver { private final int SETTING_LABEL_WIDTH = 60; private final Style DEFAULT_IMAGE_LAYOUT_STYLE = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_DEFAULT); - private final String TWEAK_NINE_POINT_HELP_URL = "https://help.fanruan.com/finereport/doc-view-4135.html"; + + /** + * 云中心点九图帮助文档在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Nine_Patch"; + + /** + * 云中心点九图帮助文档默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Nine_Patch_Default"; + + private final String TWEAK_NINE_POINT_HELP_URL = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); private UIObserverListener uiObserverListener; diff --git a/designer-base/src/main/java/com/fr/design/i18n/LocaleLinkProvider.java b/designer-base/src/main/java/com/fr/design/i18n/LocaleLinkProvider.java new file mode 100644 index 000000000..4a819069a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/i18n/LocaleLinkProvider.java @@ -0,0 +1,47 @@ +package com.fr.design.i18n; + +import com.fr.general.CloudCenter; +import com.fr.stable.StringUtils; + +/** + * 国际化链接获取工具 + * 根据配置文件key获取云中心key对应的链接或者默认链接 + * + * @author obo + * @since 11.0 + * Created on 2023/4/7 + */ +public final class LocaleLinkProvider { + + private LocaleLinkProvider(){}; + + /** + * 单一实例 + */ + private static final LocaleLinkProvider INSTANCE = new LocaleLinkProvider(); + + /** + * 返回LocaleLinkProvider的单一实例 + * + * @return LocaleLinkProvider单一实例 + */ + public static LocaleLinkProvider getInstance(){ + return INSTANCE; + } + + /** + * 根据配置文件项中的key获取链接 + * + * @param propsKey 配置项key + * @param defaultKey 默认链接项key + * @return 对应的生成器 + */ + public String getLink(String propsKey, String defaultKey) { + String cloudKey = DesignI18nImpl.getInstance().i18nText(propsKey); + String url = CloudCenter.getInstance().acquireUrlByKind(cloudKey); + if(StringUtils.isEmpty(url)) { + return DesignI18nImpl.getInstance().i18nText(defaultKey); + } + return url; + } +} diff --git a/designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java b/designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java index 8e8ef45b9..74b159620 100644 --- a/designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java +++ b/designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java @@ -14,11 +14,11 @@ import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextarea.UITextArea; import com.fr.design.gui.itextfield.PlaceholderTextField; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; import com.fr.design.javascript.jsapi.JSAPITreeHelper; import com.fr.design.javascript.jsapi.JSAPIUserObject; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.general.CloudCenter; import com.fr.general.ComparatorUtils; import com.fr.general.http.HttpToolbox; import com.fr.json.JSONArray; @@ -26,6 +26,26 @@ import com.fr.json.JSONException; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.SwingWorker; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; @@ -50,24 +70,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -import javax.swing.BorderFactory; -import javax.swing.DefaultListCellRenderer; -import javax.swing.DefaultListModel; -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTree; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; +import java.util.concurrent.ExecutionException; public class JSContentWithDescriptionPane extends JSContentPane implements KeyListener { @@ -117,6 +120,15 @@ public class JSContentWithDescriptionPane extends JSContentPane implements KeyLi private static final String RELOAD_CARD = "reloadCard"; private static final String DOC_LIST_CARD = "docListCard"; + /** + * 云中心Js高级编辑器帮助链接前缀在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Js_Editor"; + + /** + * 云中心Js高级编辑器帮助链接前缀在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Js_Editor_Default"; public JSContentWithDescriptionPane(String[] args) { this.setLayout(new BorderLayout()); //=============================== @@ -352,27 +364,51 @@ public class JSContentWithDescriptionPane extends JSContentPane implements KeyLi private void doHelpDocumentSearch() { Object value = interfaceNameList.getSelectedValue(); if (value != null) { - String url = CloudCenter.getInstance().acquireUrlByKind("af.doc_search", DOCUMENT_SEARCH_URL) + value.toString(); - try { - String result = HttpToolbox.get(url); - JSONObject jsonObject = new JSONObject(result); - JSONArray jsonArray = jsonObject.optJSONArray("list"); - if (jsonArray != null) { - DefaultListModel helpDOCModel = (DefaultListModel) helpDOCList.getModel(); - helpDOCModel.clear(); - for (int i = 0; i < jsonArray.length(); i++) { - JSONObject resultJSONObject = jsonArray.optJSONObject(i); - String docURL = resultJSONObject.optString("url"); - String name = resultJSONObject.optString("title").trim(); - HelpDocument helpDocument = new HelpDocument(docURL, name); - helpDOCModel.addElement(helpDocument); + new SwingWorker, Void>() { + @Override + protected List doInBackground() { + List helpDocuments = new ArrayList<>(); + updateHelpDocuments(value, helpDocuments); + return helpDocuments; + } + + @Override + protected void done() { + try { + List helpDocuments = get(); + DefaultListModel helpDOCModel = (DefaultListModel) helpDOCList.getModel(); + helpDOCModel.clear(); + for (HelpDocument helpDocument : helpDocuments) { + helpDOCModel.addElement(helpDocument); + } + } catch (InterruptedException | ExecutionException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); } } - } catch (JSONException e) { - FineLoggerFactory.getLogger().debug(e.getMessage(), e); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); + + }.execute(); + } + } + + private void updateHelpDocuments(Object value, List helpDocuments) { + String url = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT) + value.toString(); + try { + String result = HttpToolbox.get(url); + JSONObject jsonObject = new JSONObject(result); + JSONArray jsonArray = jsonObject.optJSONArray("list"); + if (jsonArray != null) { + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject resultJSONObject = jsonArray.optJSONObject(i); + String docURL = resultJSONObject.optString("url"); + String name = resultJSONObject.optString("title").trim(); + HelpDocument helpDocument = new HelpDocument(docURL, name); + helpDocuments.add(helpDocument); + } } + } catch (JSONException e) { + FineLoggerFactory.getLogger().debug(e.getMessage(), e); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); } } diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/BbsRegisterMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/BbsRegisterMark.java index afe1c8eef..dfa425a3c 100644 --- a/designer-base/src/main/java/com/fr/design/locale/impl/BbsRegisterMark.java +++ b/designer-base/src/main/java/com/fr/design/locale/impl/BbsRegisterMark.java @@ -1,13 +1,8 @@ package com.fr.design.locale.impl; -import com.fr.general.CloudCenter; -import com.fr.general.GeneralContext; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.general.locale.LocaleMark; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - /** * @author hades * @version 10.0 @@ -15,24 +10,19 @@ import java.util.Map; */ public class BbsRegisterMark implements LocaleMark { - private final Map map = new HashMap<>(); - private static final String BBS_REGISTER_CN = CloudCenter.getInstance().acquireUrlByKind("bbs.register", "https://id.fanruan.com/register/register.php?clueSource=activityfr"); - private static final String BBS_REGISTER_TW = CloudCenter.getInstance().acquireUrlByKind("bbs.register", "https://id.fanruan.com/register/register.php?clueSource=activityfr"); - private static final String BBS_REGISTER_EN = CloudCenter.getInstance().acquireUrlByKind("bbs.register.en_US", "https://id.fanruan.com/en/register/register.php"); - private static final String BBS_REGISTER_KR = CloudCenter.getInstance().acquireUrlByKind("bbs.register.en_US", "https://id.fanruan.com/en/register/register.php"); - private static final String BBS_REGISTER_JP = CloudCenter.getInstance().acquireUrlByKind("bbs.register.en_US", "https://id.fanruan.com/en/register/register.php"); + /** + * 云中心新账户中心链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_New_Account_Center"; - public BbsRegisterMark() { - map.put(Locale.CHINA, BBS_REGISTER_CN); - map.put(Locale.KOREA, BBS_REGISTER_KR); - map.put(Locale.JAPAN, BBS_REGISTER_JP); - map.put(Locale.US, BBS_REGISTER_EN); - map.put(Locale.TAIWAN, BBS_REGISTER_TW); - } + /** + * 云中心新账户中心链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_New_Account_Center_Default"; + public BbsRegisterMark() {} @Override public String getValue() { - String result = map.get(GeneralContext.getLocale()); - return result == null ? BBS_REGISTER_EN : result; + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); } } diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/BbsResetMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/BbsResetMark.java index 27db28e41..49092d4f2 100644 --- a/designer-base/src/main/java/com/fr/design/locale/impl/BbsResetMark.java +++ b/designer-base/src/main/java/com/fr/design/locale/impl/BbsResetMark.java @@ -1,13 +1,8 @@ package com.fr.design.locale.impl; -import com.fr.general.CloudCenter; -import com.fr.general.GeneralContext; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.general.locale.LocaleMark; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - /** * @author hades * @version 10.0 @@ -15,24 +10,21 @@ import java.util.Map; */ public class BbsResetMark implements LocaleMark { - private final Map map = new HashMap<>(); - private static final String BBS_RESET_CN = CloudCenter.getInstance().acquireUrlByKind("bbs.reset", "https://id.fanruan.com/forget/forget.php?clue=activityfr"); - private static final String BBS_RESET_TW = CloudCenter.getInstance().acquireUrlByKind("bbs.reset", "https://id.fanruan.com/forget/forget.php?clue=activityfr"); - private static final String BBS_RESET_EN = CloudCenter.getInstance().acquireUrlByKind("bbs.reset.en_US", "https://id.fanruan.com/en/forget/forget.php"); - private static final String BBS_RESET_KR = CloudCenter.getInstance().acquireUrlByKind("bbs.reset.en_US", "https://id.fanruan.com/en/forget/forget.php"); - private static final String BBS_RESET_JP = CloudCenter.getInstance().acquireUrlByKind("bbs.reset.en_US", "https://id.fanruan.com/en/forget/forget.php"); - public BbsResetMark() { - map.put(Locale.CHINA, BBS_RESET_CN); - map.put(Locale.KOREA, BBS_RESET_KR); - map.put(Locale.JAPAN, BBS_RESET_JP); - map.put(Locale.US, BBS_RESET_EN); - map.put(Locale.TAIWAN, BBS_RESET_TW); - } + /** + * 云中心老账户中心链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Account_Center"; + + /** + * 云中心老账户中心链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Account_Center_Default"; + + public BbsResetMark() {} @Override public String getValue() { - String result = map.get(GeneralContext.getLocale()); - return result == null ? BBS_RESET_EN : result; + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); } } diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/BbsSpaceMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/BbsSpaceMark.java index 999c73284..a0b21d271 100644 --- a/designer-base/src/main/java/com/fr/design/locale/impl/BbsSpaceMark.java +++ b/designer-base/src/main/java/com/fr/design/locale/impl/BbsSpaceMark.java @@ -1,13 +1,8 @@ package com.fr.design.locale.impl; -import com.fr.general.CloudCenter; -import com.fr.general.GeneralContext; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.general.locale.LocaleMark; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - /** * @author hades * @version 10.0 @@ -15,25 +10,20 @@ import java.util.Map; */ public class BbsSpaceMark implements LocaleMark { - private final Map map = new HashMap<>(); - private static final String BBS_SPACE_CN = CloudCenter.getInstance().acquireUrlByKind("bbs.default", "http://bbs.fanruan.com/home.php?mod=space&do=pm"); - private static final String BBS_SPACE_TW = CloudCenter.getInstance().acquireUrlByKind("bbs.default", "http://bbs.fanruan.com/home.php?mod=space&do=pm"); - private static final String BBS_SPACE_EN = CloudCenter.getInstance().acquireUrlByKind("bbs.default.en_US", "https://community.finereport.com/home.php?mod=space&do=pm"); - private static final String BBS_SPACE_KR = CloudCenter.getInstance().acquireUrlByKind("bbs.default.en_US", "https://community.finereport.com/home.php?mod=space&do=pm"); - private static final String BBS_SPACE_JP = CloudCenter.getInstance().acquireUrlByKind("bbs.default.en_US", "https://community.finereport.com/home.php?mod=space&do=pm"); + /** + * 云中心帆软社区消息中心链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Message_Center"; - public BbsSpaceMark() { - map.put(Locale.CHINA, BBS_SPACE_CN); - map.put(Locale.KOREA, BBS_SPACE_KR); - map.put(Locale.JAPAN, BBS_SPACE_JP); - map.put(Locale.US, BBS_SPACE_EN); - map.put(Locale.TAIWAN, BBS_SPACE_TW); - } + /** + * 云中心帆软社区消息中心链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Message_Center_Default"; + + public BbsSpaceMark() {} @Override public String getValue() { - String result = map.get(GeneralContext.getLocale()); - return result == null ? BBS_SPACE_EN : result; + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); } - } diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/DataMaskMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/DataMaskMark.java new file mode 100644 index 000000000..11312657b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/locale/impl/DataMaskMark.java @@ -0,0 +1,30 @@ +package com.fr.design.locale.impl; + +import com.fr.design.i18n.LocaleLinkProvider; +import com.fr.general.locale.LocaleMark; + + +/** + * 根据图片信息生成获取国际化服务器图标工具 + * + * @author obo + * @since 11.0 + * Created on 2023/4/19 + */ +public class DataMaskMark implements LocaleMark { + + /** + * 云中心数据脱敏帮助链接链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Data_Mask"; + + /** + * 云中心数据脱敏默认帮助链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design_Report_Desensitization_Help_Document_Url"; + + @Override + public String getValue() { + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); + } +} diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/LineEngineMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/LineEngineMark.java new file mode 100644 index 000000000..ebb5fd09a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/locale/impl/LineEngineMark.java @@ -0,0 +1,28 @@ +package com.fr.design.locale.impl; + +import com.fr.design.i18n.LocaleLinkProvider; +import com.fr.general.locale.LocaleMark; + +/** + * 根据国际化获取启用行式引擎执行层式报表帮助文档链接 + * + * @author obo + * @since 11.0 + * Created on 2023/4/19 + */ +public class LineEngineMark implements LocaleMark { + + /** + * 云中心启用行式引擎执行层式报表帮助链接链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Line_Engine"; + + /** + * 云中心启用行式引擎执行层式报表默认帮助链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Line_Engine_Default"; + @Override + public String getValue() { + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); + } +} diff --git a/designer-base/src/main/java/com/fr/design/locale/impl/VideoMark.java b/designer-base/src/main/java/com/fr/design/locale/impl/VideoMark.java index 2521c82c2..571c5e02e 100644 --- a/designer-base/src/main/java/com/fr/design/locale/impl/VideoMark.java +++ b/designer-base/src/main/java/com/fr/design/locale/impl/VideoMark.java @@ -16,7 +16,7 @@ public class VideoMark implements LocaleMark { private Map map = new HashMap<>(); private static final String VIDEO_EN = CloudCenter.getInstance().acquireUrlByKind("bbs.video.en_US", "http://www.finereport.com/en/Learning-path"); - private static final String VIDEO_CN = CloudCenter.getInstance().acquireUrlByKind("bbs.video.zh_CN", "https://edu.fanruan.com/video?class1=16&class2=0"); + private static final String VIDEO_CN = CloudCenter.getInstance().acquireUrlByKind("bbs.video.zh_CN", "https://home.fanruan.com/finereport/video"); private static final String VIDEO_TW = CloudCenter.getInstance().acquireUrlByKind("bbs.video.zh_TW", "http://www.finereport.com/tw/video"); public VideoMark() { diff --git a/designer-base/src/main/java/com/fr/design/login/DesignerLoginBridge.java b/designer-base/src/main/java/com/fr/design/login/DesignerLoginBridge.java index 4d0ba8a41..4789cc4f9 100644 --- a/designer-base/src/main/java/com/fr/design/login/DesignerLoginBridge.java +++ b/designer-base/src/main/java/com/fr/design/login/DesignerLoginBridge.java @@ -5,6 +5,7 @@ import com.fr.design.bridge.exec.JSCallback; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.gui.ilable.ActionLabel; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.locale.impl.BbsResetMark; @@ -23,15 +24,16 @@ import com.fr.log.FineLoggerFactory; import com.teamdev.jxbrowser.chromium.Browser; import com.teamdev.jxbrowser.chromium.JSFunction; import com.teamdev.jxbrowser.chromium.JSObject; + +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URI; import java.util.Map; import java.util.Set; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; /** * @author Lanlan @@ -40,6 +42,16 @@ import javax.swing.SwingUtilities; */ public class DesignerLoginBridge { + /** + * 云中心组件商城模板在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Market_Template"; + + /** + * 云中心组件商城模板默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Market_Template_Default"; + private Map params; public static DesignerLoginBridge getBridge(Browser browser, Map params) { @@ -71,7 +83,7 @@ public class DesignerLoginBridge { getHyperlinkPane( com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Guide_Login_Success_Title"), com.fr.design.i18n.Toolkit.i18nText("Fine-Designer_Guide_Login_Success_Hyperlink_Text"), - CloudCenter.getInstance().acquireUrlByKind("designer.premium.template", "https://market.fanruan.com/template") + LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT) ) ); } else if (source == DesignerLoginSource.BBS_JUMP) { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java index b18b34652..3cceff5a7 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java @@ -230,12 +230,11 @@ public class CenterRegionContainerPane extends JPanel { // 颜色,字体那些按钮的工具栏 toolbarPane.add(toolbarComponent = ad.resetToolBar(toolbarComponent, plus), BorderLayout.CENTER); - if (strategy.hasToolBarPane(plus)) { - this.add(toolbarPane, BorderLayout.NORTH); - } else { - this.remove(toolbarPane); + JPanel customNorthPane = strategy.customNorthPane(toolbarPane,plus); + if (!isExist(customNorthPane)){ + this.removeNorth(); + this.add(customNorthPane, BorderLayout.NORTH); } - if (strategy.hasTemplateTabPane(plus)) { eastCenterPane.add(templateTabPane, BorderLayout.CENTER); } else { @@ -250,6 +249,26 @@ public class CenterRegionContainerPane extends JPanel { resetByDesignMode(); } + private void removeNorth(){ + Component[] components = this.getComponents(); + for(Component c : components){ + if (c!= centerTemplateCardPane){ + this.remove(c); + } + } + } + + + private boolean isExist(JPanel customNorthPane) { + Component[] components = this.getComponents(); + for (Component component : components) { + if (component == customNorthPane) { + return true; + } + } + return false; + } + private void resetByDesignMode() { if (DesignModeContext.isDuchampMode()) { eastPane.remove(largeToolbar); @@ -292,4 +311,11 @@ public class CenterRegionContainerPane extends JPanel { return toolbarComponentState; } + /** + * 重置下RegionContainerpane + */ + public void resetCenterRegionContainerPane(){ + templateTabPane.add(MultiTemplateTabPane.getInstance(), BorderLayout.CENTER); + } + } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DefaultToolKitConfig.java b/designer-base/src/main/java/com/fr/design/mainframe/DefaultToolKitConfig.java index 305c44aa2..73daf052f 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DefaultToolKitConfig.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DefaultToolKitConfig.java @@ -2,6 +2,8 @@ package com.fr.design.mainframe; import com.fr.design.base.mode.DesignModeContext; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; +import javax.swing.JPanel; + public class DefaultToolKitConfig implements ToolKitConfigStrategy { @Override @@ -18,4 +20,10 @@ public class DefaultToolKitConfig implements ToolKitConfigStrategy { public boolean hasToolBarPane(ToolBarMenuDockPlus plus) { return plus.hasToolBarPane(); } + + @Override + public JPanel customNorthPane(JPanel toolBarPane, ToolBarMenuDockPlus plus) { + CenterRegionContainerPane.getInstance().resetCenterRegionContainerPane(); + return toolBarPane; + } } 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 e88d0c946..150c4302f 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 @@ -852,7 +852,7 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta if (jt == null || jt.getEditingFILE() == null) { return; } - if (currentTemplateDeactivateFail()) { + if (currentTemplateDeactivateFail(jt)) { return; } jt.addJTemplateActionListener(this); @@ -877,7 +877,7 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta if (jt == null || jt.getEditingFILE() == null) { return; } - if (currentTemplateDeactivateFail()) { + if (currentTemplateDeactivateFail(jt)) { return; } getCenterTemplateCardPane().showJTemplate(jt); @@ -939,9 +939,9 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta * * @return 是否停用失败 */ - private boolean currentTemplateDeactivateFail() { + private boolean currentTemplateDeactivateFail(JTemplate jt) { JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); - return currentEditingTemplate != null && !currentEditingTemplate.deactivateTemplate(); + return currentEditingTemplate != null && !currentEditingTemplate.deactivateTemplate(jt); } 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 0082e091f..7977b8202 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 @@ -58,9 +58,12 @@ import com.fr.design.module.DesignModuleFactory; import com.fr.design.preview.PagePreview; import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.DesignUtils; +import com.fr.design.utils.TemplateUtils; 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.worker.save.type.SaveType; +import com.fr.design.worker.save.type.SaveTypeWorker; import com.fr.design.write.submit.DBManipulationInWidgetEventPane; import com.fr.design.write.submit.DBManipulationPane; import com.fr.event.EventDispatcher; @@ -118,6 +121,8 @@ import java.util.concurrent.Callable; * 报表设计和表单设计的编辑区域(设计器编辑的IO文件) */ public abstract class JTemplate> extends TargetComponent implements ToolBarMenuDockPlus, DesignerProxy, JTemplateSave, TabChangeListener, ThemedTemplate { + + private static final String DEFAULT_TAB_OPERATOR = "DefaultTabOperator"; // TODO ALEX_SEP editingFILE这个属性一定要吗?如果非要不可,有没有可能保证不为null private static final int PREDEFINED_ICON_WIDTH = 27; @@ -1368,6 +1373,17 @@ public abstract class JTemplate> } + /** + * 将要激活打开其他模板,使当前模板灭活 + * 默认 do nothing 返回true + * + * @return true:成功停用当前模板 + */ + public boolean deactivateTemplate(JTemplate jTemplate) { + //兼容调用老的接口 + return deactivateTemplate(); + } + /** * 返回当前支持的超链界面pane * @@ -1687,24 +1703,7 @@ public abstract class JTemplate> if (!editingFILE.exists()) { return saveAs(showLoc); } - - CallbackSaveWorker worker = new CallbackSaveWorker(new Callable() { - @Override - public Boolean call() throws Exception { - return saveRealFileByWorker(); - } - }, this); - - worker.addSuccessCallback(new Runnable() { - @Override - public void run() { - callBackForSave(); - //在保存后的回调中执行预编译流程 - CptCompileUtil.compile(JTemplate.this); - } - }); - - return worker; + return getSaveCallBackSaveWorker(); } /** @@ -1750,6 +1749,8 @@ public abstract class JTemplate> } } + + private CallbackSaveWorker saveAs(boolean showLoc) { FILE editingFILE = this.getEditingFILE(); if (editingFILE == null) { @@ -1771,7 +1772,6 @@ public abstract class JTemplate> // 目标文件 editingFILE = fileChooser.getSelectedFILE(); } - FILE finalEditingFILE = editingFILE; CallbackSaveWorker worker = new CallbackSaveWorker(new Callable() { @Override @@ -1872,10 +1872,95 @@ public abstract class JTemplate> return saveAs(true); } + /** + * 获取保存用到的saveWorker + */ + private CallbackSaveWorker getSaveCallBackSaveWorker() { + CallbackSaveWorker worker = new CallbackSaveWorker(new Callable() { + @Override + public Boolean call() throws Exception { + return saveRealFileByWorker(); + } + }, this); + + worker.addSuccessCallback(new Runnable() { + @Override + public void run() { + callBackForSave(); + //在保存后的回调中执行预编译流程 + CptCompileUtil.compile(JTemplate.this); + } + }); + return worker; + } + + /** + * 获取保存的类别执行的callable + */ + private Callable getSaveTypeCallable() { + return () -> { + fireJTemplateSaveBefore(); + FILE editingFILE = getEditingFILE(); + // carl:editingFILE没有,当然不存了,虽然不会有这种情况 + if (editingFILE == null) { + return SaveType.TypeEnum.EMPTY; + } + // 检查一下editingFILE是不是已存在的文件,如果不存在则用saveAs + if (!editingFILE.exists()) { + return SaveType.TypeEnum.SAVE_AS; + } + return SaveType.TypeEnum.SAVE; + }; + } + + /** + * 根据保存类型获取对应的saveWorker + * + * @param saveType 保存类型 + */ + private CallbackSaveWorker getSaveTypeWorker(SaveType saveType) { + CallbackSaveWorker callbackSaveWorker; + switch (saveType.getType()) { + case EMPTY: + callbackSaveWorker = new EmptyCallBackSaveWorker(); + break; + case SAVE: + callbackSaveWorker = getSaveCallBackSaveWorker(); + break; + default: + callbackSaveWorker = saveAs(true); + } + return callbackSaveWorker; + } + + + @Override public void saveDirectly() { - CallbackSaveWorker worker = save(); - worker.start(getRuntimeId()); + new SaveTypeWorker(getSaveTypeCallable(), this) { + @Override + protected void done() { + try { + SaveType saveType = get(); + CallbackSaveWorker callbackSaveWorker = getSaveTypeWorker(saveType); + //告诉一下后面执行的saveWorker,当前判断文件是否存在的操作是否已经进行了开始转圈的那个等待动画,避免重复 + callbackSaveWorker.setSlowly(saveType.isSlowly()); + callbackSaveWorker.start(getRuntimeId()); + //如果是空也就是不保存,需要恢复一下界面(如果saveTypeWorker里进行了操作的话) + if (callbackSaveWorker instanceof EmptyCallBackSaveWorker) { + setSaving(false); + if (saveType.isSlowly()) { + if (ComparatorUtils.equals(getName(), HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getName())) { + DesignerContext.getDesignerFrame().getCenterTemplateCardPane().hideCover(); + } + } + DesignerFrameFileDealerPane.getInstance().stateChange(); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + }.start(); } @Override @@ -1979,7 +2064,7 @@ public abstract class JTemplate> public void setDesignerUIMode() { DesignerUIModeConfig.getInstance().setAbsoluteMeasureUIMode(); } - + /** * 判断当前的模板是否是有效的模板 * @@ -1989,4 +2074,50 @@ public abstract class JTemplate> public static boolean isValid(JTemplate jt) { return jt != null && jt != JNullTemplate.NULL; } + + /** + * 获取此模板所使用的tab栏操作类型 + * @return + */ + public String getTemplateTabOperatorType(){ + return DEFAULT_TAB_OPERATOR; + } + + /** + * 当前模板是否可以被保存 + * @return 是/否 + */ + public boolean canBeSaved(){ + return true; + } + + /** + * 当前的模板是否支持缓存 + * + * @return 是/否 + */ + public boolean supportCache(){ + return true; + } + + /** + * 获取此模板在tab栏中显示的名称 + * @return + */ + public String getTabShowName(JTemplate jTemplate){ + String name = TemplateUtils.createLockeTemplatedName(jTemplate, jTemplate.getTemplateName()); + if (!jTemplate.isSaved() && !name.endsWith(" *")) { + name += " *"; + } + return name; + } + + /** + * 切换环境之前是否需要保存 + * @return + */ + public boolean needSaveBeforeSwitchEnv(){ + return false; + } + } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/ToolKitConfigStrategy.java b/designer-base/src/main/java/com/fr/design/mainframe/ToolKitConfigStrategy.java index 67b1409b3..f2feff804 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/ToolKitConfigStrategy.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/ToolKitConfigStrategy.java @@ -2,6 +2,9 @@ package com.fr.design.mainframe; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; +import javax.swing.JPanel; + + public interface ToolKitConfigStrategy { /** @@ -24,4 +27,11 @@ public interface ToolKitConfigStrategy { * @return */ boolean hasToolBarPane(ToolBarMenuDockPlus plus); + /** + * 定制工具栏 + * @param toolBarPane + * @param plus + * @return + */ + JPanel customNorthPane(JPanel toolBarPane, ToolBarMenuDockPlus plus); } 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 0671ed1b6..8274b6535 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 @@ -4,10 +4,10 @@ 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.DesignSizeI18nManager; +import com.fr.design.i18n.LocaleLinkProvider; 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 javax.swing.BorderFactory; @@ -39,17 +39,27 @@ public class CheckFontInfoDialog extends JDialog implements ActionListener { private UILabel directUiLabel; private UILabel detailLabel; + /** + * 云中心插件管理帮助文档在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Server_Install_Font"; + + /** + * 云中心插件管理默认帮助文档在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Server_Install_Font_Default"; + public CheckFontInfoDialog(Frame parent, String areaText) { super(parent,true); //提示信息 JPanel imagePanel = new JPanel(); imageLabel = new UILabel(IOUtils.readIcon("com/fr/design/images/warnings/warning32.png")); imagePanel.add(imageLabel); - + String link = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); 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")); + link); 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/toolbar/ToolBarMenuDock.java b/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java index 3c75eff39..3372e2ad1 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 @@ -42,6 +42,7 @@ import com.fr.design.actions.server.GlobalTableDataAction; import com.fr.design.actions.server.PlatformManagerAction; import com.fr.design.actions.server.PluginManagerAction; import com.fr.design.base.mode.DesignModeContext; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.file.NewTemplatePane; import com.fr.design.fun.MenuHandler; import com.fr.design.fun.OemProcessor; @@ -275,7 +276,10 @@ public abstract class ToolBarMenuDock { insertTemplateExtendMenu(plus, menuDefs); // 添加模板菜单 - menuList.addAll(Arrays.asList(menuDefs)); + // 如果是JNullTemplate不能添加模板菜单,之前没有这个JNullTemplate所以没考虑 + if (JTemplate.isValid(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate())) { + menuList.addAll(Arrays.asList(menuDefs)); + } // 添加服务器菜单 if (WorkContext.getCurrent() != null && WorkContext.getCurrent().isRoot()) { diff --git a/designer-base/src/main/java/com/fr/design/update/actions/NewFeatureAction.java b/designer-base/src/main/java/com/fr/design/update/actions/NewFeatureAction.java index 56db4cee9..320a2a23d 100644 --- a/designer-base/src/main/java/com/fr/design/update/actions/NewFeatureAction.java +++ b/designer-base/src/main/java/com/fr/design/update/actions/NewFeatureAction.java @@ -1,9 +1,8 @@ package com.fr.design.update.actions; -import com.fr.common.util.Strings; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.utils.BrowseUtils; -import com.fr.general.CloudCenter; import com.fr.log.FineLoggerFactory; import java.awt.event.ActionEvent; @@ -16,17 +15,22 @@ import java.awt.event.ActionListener; * */ public class NewFeatureAction implements ActionListener { + /** + * 云中心更新日志索引在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Latest_Update_Detail"; - public static String DEFAULT_UPDATE_DETAIL_URL = "https://help.fanruan.com/finereport/doc-view-4699.html"; + /** + * 云中心更新日志索引默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Latest_Update_Detail_Default"; + + public static String DEFAULT_UPDATE_DETAIL_URL = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); @Override public void actionPerformed(ActionEvent e) { try { - String url = CloudCenter.getInstance().acquireConf("fr.latest.update.detil"); - if (Strings.isEmpty(url)) { - url = DEFAULT_UPDATE_DETAIL_URL; - } - BrowseUtils.browser(url); + BrowseUtils.browser(DEFAULT_UPDATE_DETAIL_URL); } catch (Exception ex) { FineLoggerFactory.getLogger().error(ex.getMessage()); } diff --git a/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java b/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java index f3d062946..9b426b5c8 100644 --- a/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java @@ -24,6 +24,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.SwingWorker; import java.io.OutputStream; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -44,7 +46,7 @@ public class TemplateUtils { * @param openNewTemplate 是否需要在创建后打开模板 */ public static void createAndOpenTemplate(String prefix, FILE file, boolean createByEditingTemplate, boolean openNewTemplate) { - createAndOpenTemplate(prefix, file, createByEditingTemplate, openNewTemplate, () -> {}); + createAndOpenTemplate(prefix, file, createByEditingTemplate, openNewTemplate, null); } /** @@ -66,15 +68,33 @@ public class TemplateUtils { Runnable doAfterCreateTemplate; //判断一下要保存的文件是否已打开 int index = HistoryTemplateListCache.getInstance().contains(file); - if (index == -1) { - doAfterCreateTemplate = () -> {}; - } else { - JTemplate template = HistoryTemplateListCache.getInstance().getHistoryList().get(index); - doAfterCreateTemplate = () -> HistoryTemplateListCache.getInstance().closeSelectedReport(template); + JTemplate template = null; + if (index != -1) { + template = HistoryTemplateListCache.getInstance().getHistoryList().get(index); } - createAndOpenTemplate0(file, oldPath, createByEditingTemplate, openNewTemplate, doAfterCreateTemplate); + createAndOpenTemplate0(file, oldPath, createByEditingTemplate, openNewTemplate, template); } + /** + * 创建新的模板文件并打开模板,并在创建备份模板成功后执行doAfterCreate + * + * @param prefix 模板文件名称前缀 + * @param file 模板文件 + * @param createByEditingTemplate 是否根据 当前编辑模板 来创建新模板 + * 为true时以CurrentEditingTemplate为准创建新模板 + * 为false时以传入的File文件为准创建新模板,此文件可以不是编辑状态 + * @param openNewTemplate 是否需要在创建后打开模板 + * @param template 备份成功后需要关闭的模板 + */ + public static void createAndOpenTemplate(String prefix, FILE file, boolean createByEditingTemplate, boolean openNewTemplate, @Nullable JTemplate template) { + String oldPath = file.getPath(); + file = getSavedFile(prefix, file); + if (file == null) { + return; + } + + createAndOpenTemplate0(file, oldPath, createByEditingTemplate, openNewTemplate, template); + } /** * 返回值可以为null, 为null表示没有点击保存按钮或者传递进来的文件file本身不满足格式要求 @@ -111,31 +131,17 @@ public class TemplateUtils { } /** - * 创建新的模板文件并打开模板,并在创建备份模板成功后执行doAfterCreate + * 生成备份模板 * - * @param prefix 模板文件名称前缀 - * @param file 模板文件 + * @param file saveAs的模板文件 * @param createByEditingTemplate 是否根据 当前编辑模板 来创建新模板 * 为true时以CurrentEditingTemplate为准创建新模板 * 为false时以传入的File文件为准创建新模板,此文件可以不是编辑状态 - * @param openNewTemplate 是否需要在创建后打开模板 - * @param doAfterCreateTemplate 创建备份模板成功后调用 + * @param oldPath 被saveAs的文件路径 */ - public static void createAndOpenTemplate(String prefix, FILE file, boolean createByEditingTemplate, boolean openNewTemplate, Runnable doAfterCreateTemplate) { - String oldPath = file.getPath(); - file = getSavedFile(prefix, file); - if (file == null) { - return; - } - - createAndOpenTemplate0(file, oldPath, createByEditingTemplate, openNewTemplate, doAfterCreateTemplate); - } - - private static void createAndOpenTemplate0(FILE file, String oldPath, boolean createByEditingTemplate, boolean openNewTemplate, Runnable doAfterCreateTemplate) { - new SwingWorker() { - - @Override - protected Boolean doInBackground() throws Exception { + private static CompletableFuture createTemplate(FILE file, String oldPath, boolean createByEditingTemplate) { + return CompletableFuture.supplyAsync(() -> { + try { // 读取模板数据 byte[] content = getTemplateData(createByEditingTemplate, oldPath); OutputStream out = null; @@ -144,7 +150,7 @@ public class TemplateUtils { boolean saveAsLock = WorkContext.getCurrent().get(TplOperator.class).saveAs(file.getPath()); if (!saveAsLock) { // 加锁失败时,直接返回 - return false; + throw new RuntimeException("[RemoteDesign] back up template file failed"); } out = file.asOutputStream(); out.write(content); @@ -159,20 +165,43 @@ public class TemplateUtils { } } return true; + } catch (Exception e) { + SaveFailureHandler.getInstance().process(e); + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return false; } + }); + } + /** + * 打开saveAs的新模板并关闭指定的旧模板 + * + * @param file 模板文件 + * @param openNewTemplate 是否需要打开新模板 + * @param template 需要关闭的模板 + */ + private static void openNewTemplateAndCloseOldTemplate(FILE file, boolean openNewTemplate, @Nullable JTemplate template) { + new SwingWorker() { + @Override + protected Boolean doInBackground() throws Exception { + if (JTemplate.isValid(template)) { + //给要关闭的模板解锁 + WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(template.getPath()); + return true; + } + return false; + } @Override protected void done() { try { - if (!get()) { - throw new Exception("[RemoteDesign] back up template file failed"); + if (get()) { + //模板释放锁成功后关闭该模板 + HistoryTemplateListCache.getInstance().closeSelectedReport(template); } - // 创建备份成功后,关闭原模板 - doAfterCreateTemplate.run(); if (openNewTemplate) { DesignerContext.getDesignerFrame().openTemplate(file); } - // 备份成功刷新下目录树 展示出来备份的模板 + // 刷新下目录树 TemplateTreePane.getInstance().refresh(); } catch (Exception e) { SaveFailureHandler.getInstance().process(e); @@ -182,6 +211,15 @@ public class TemplateUtils { }.execute(); } + private static void createAndOpenTemplate0(FILE file, String oldPath, boolean createByEditingTemplate, boolean openNewTemplate, @Nullable JTemplate template) { + createTemplate(file, oldPath, createByEditingTemplate).thenApply((Function) aBoolean -> { + if (aBoolean) { + openNewTemplateAndCloseOldTemplate(file, openNewTemplate, template); + } + return null; + }); + } + /** * 读取模板文件数据 * diff --git a/designer-base/src/main/java/com/fr/design/widget/btn/ButtonConstants.java b/designer-base/src/main/java/com/fr/design/widget/btn/ButtonConstants.java index 9be9a8fba..3efc320d8 100644 --- a/designer-base/src/main/java/com/fr/design/widget/btn/ButtonConstants.java +++ b/designer-base/src/main/java/com/fr/design/widget/btn/ButtonConstants.java @@ -44,4 +44,20 @@ public class ButtonConstants { StableFactory.getMarkedClass(BridgeMark.SUBMIT_BUTTON, Widget.class), StableFactory.getMarkedClass(BridgeMark.TREE_NODE_TOGGLE_BUTTON, Widget.class) }; + + public static final String[] TYPES_BUTTON_NO_FREE = { + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Common"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Utils_Insert_Row"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Delete_Row"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Button_Type_Parameter_Submit"), + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Widget_TreeNode") + }; + + public static final Class[] CLASSES_BUTTON_NO_FREE = { + Button.class, + StableFactory.getMarkedClass(BridgeMark.APPEND_ROW_BUTTON, Widget.class), + StableFactory.getMarkedClass(BridgeMark.DELETE_ROW_BUTTON, Widget.class), + StableFactory.getMarkedClass(BridgeMark.SUBMIT_BUTTON, Widget.class), + StableFactory.getMarkedClass(BridgeMark.TREE_NODE_TOGGLE_BUTTON, Widget.class) + }; } diff --git a/designer-base/src/main/java/com/fr/design/widget/btn/ButtonDetailPane.java b/designer-base/src/main/java/com/fr/design/widget/btn/ButtonDetailPane.java index 63d678577..2b73a3fe7 100644 --- a/designer-base/src/main/java/com/fr/design/widget/btn/ButtonDetailPane.java +++ b/designer-base/src/main/java/com/fr/design/widget/btn/ButtonDetailPane.java @@ -1,11 +1,9 @@ package com.fr.design.widget.btn; +import com.fr.design.beans.BasicBeanPane; import com.fr.design.gui.icombobox.DictionaryComboBox; import com.fr.design.dialog.BasicPane; -import com.fr.design.widget.btn.ButtonConstants; import com.fr.form.ui.Button; - - import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.event.ActionEvent; @@ -13,6 +11,7 @@ import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; + /** * Created by IntelliJ IDEA. * Author : Richer @@ -22,7 +21,7 @@ import java.util.List; */ public abstract class ButtonDetailPane extends BasicPane { private List ls = new ArrayList(); - + protected final List> extraPaneList = new ArrayList<>(); @Override public String title4PopupWindow() { return com.fr.design.i18n.Toolkit.i18nText("Button"); @@ -49,7 +48,10 @@ public abstract class ButtonDetailPane extends BasicPane { public abstract Class classType(); protected DictionaryComboBox createButtonTypeComboBox() { - final DictionaryComboBox dictionaryComboBox = new DictionaryComboBox(ButtonConstants.CLASSES4BUTTON, ButtonConstants.TYPES4BUTTON, false); + return createButtonTypeComboBox(false); + } + + private DictionaryComboBox initDictionaryComboBox(DictionaryComboBox dictionaryComboBox) { dictionaryComboBox.setSelectedItem(classType()); dictionaryComboBox.addActionListener(new ActionListener() { @Override @@ -59,4 +61,14 @@ public abstract class ButtonDetailPane extends BasicPane { }); return dictionaryComboBox; } + + protected DictionaryComboBox createButtonTypeComboBox(Boolean containsExtraPane) { + final DictionaryComboBox dictionaryComboBox; + if (!containsExtraPane) { + dictionaryComboBox = new DictionaryComboBox(ButtonConstants.CLASSES4BUTTON, ButtonConstants.TYPES4BUTTON, false); + } else { + dictionaryComboBox = new DictionaryComboBox(ButtonConstants.CLASSES_BUTTON_NO_FREE, ButtonConstants.TYPES_BUTTON_NO_FREE, false); + } + return initDictionaryComboBox(dictionaryComboBox); + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/widget/btn/ButtonWithHotkeysDetailPane.java b/designer-base/src/main/java/com/fr/design/widget/btn/ButtonWithHotkeysDetailPane.java index b75aeaa81..d146c7309 100644 --- a/designer-base/src/main/java/com/fr/design/widget/btn/ButtonWithHotkeysDetailPane.java +++ b/designer-base/src/main/java/com/fr/design/widget/btn/ButtonWithHotkeysDetailPane.java @@ -6,6 +6,7 @@ import javax.swing.*; import com.fr.design.designer.IntervalConstants; import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.gui.icombobox.DictionaryComboBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.layout.FRGUIPaneFactory; @@ -42,8 +43,9 @@ public abstract class ButtonWithHotkeysDetailPane extends Butt JPanel labelPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); iconPane = new AccessibleIconEditor(); labelPane.add(iconPane); + Component comp = createCenterPane(); Component[][] n_components = { - {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Button_Type")), createButtonTypeComboBox()}, + {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Button_Type")), createCustomButtonTypeComboBox()}, {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Button_Name")), buttonNameTextField = new UITextField()}, {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Button_Icon")), iconPane}, {new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Button_Hot_keys")), hotkeysTextField = new UITextField()}, @@ -52,7 +54,6 @@ public abstract class ButtonWithHotkeysDetailPane extends Butt JPanel panel = TableLayoutHelper.createGapTableLayoutPane(n_components, rowSize, columnSize, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1); panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); advancePane.add(panel, BorderLayout.NORTH); - Component comp = createCenterPane(); if(comp != null ) { advancePane.add(comp,BorderLayout.CENTER); } @@ -63,6 +64,13 @@ public abstract class ButtonWithHotkeysDetailPane extends Butt protected abstract Component createCenterPane(); + /** + * 判断是按钮控件下拉框的种类:1.有自定义按钮 2.无自定义按钮 + */ + protected DictionaryComboBox createCustomButtonTypeComboBox() { + return createButtonTypeComboBox(); + } + @Override public void populate(T button) { if (button == null) { 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 index 42ef95978..9ab897d7e 100644 --- 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 @@ -119,8 +119,8 @@ public class SaveFailureHandler implements ThrowableHandler { new FileNodeFILE(new FileNode(template.getPath(), false)), true, true, - // 创建并打开备份模板后,关闭原模板,无需释放原模板锁(因为已经被超管手动清除了) - () -> HistoryTemplateListCache.getInstance().closeSelectedReport(template)); + //另存之后需要关闭的模板 + template); } } } @@ -141,8 +141,8 @@ public class SaveFailureHandler implements ThrowableHandler { new FileNodeFILE(new FileNode(template.getPath(), false)), true, true, - // 创建并打开备份模板后,关闭原模板,无需释放原模板锁(锁定信息不一致 = 此用户模板锁信息已被清除) - () -> HistoryTemplateListCache.getInstance().closeSelectedReport(template)); + //另存之后需要关闭的模板 + template); } } } 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 60d797c3e..83b7c50d4 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 @@ -5,12 +5,16 @@ import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrameFileDealerPane; import com.fr.design.mainframe.EastRegionContainerPane; import com.fr.design.mainframe.JTemplate; +import com.fr.design.ui.util.UIUtil; import com.fr.design.worker.WorkerManager; +import com.fr.design.worker.save.type.SaveTypeWorker; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; + import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; + +import com.fr.third.org.apache.commons.lang3.time.StopWatch; + import javax.swing.SwingWorker; /** @@ -34,6 +38,14 @@ public class SaveWorker extends SwingWorker { private boolean slowly; + public boolean isSlowly() { + return slowly; + } + + public void setSlowly(boolean slowly) { + this.slowly = slowly; + } + public SaveWorker(Callable callable, JTemplate template) { this.callable = callable; this.template = template; @@ -47,10 +59,11 @@ public class SaveWorker extends SwingWorker { @Override protected void done() { try { - success = get(); + success = get(); } catch (Exception e) { processResult(); FineLoggerFactory.getLogger().error(e.getMessage(), e); + WorkerManager.getInstance().removeWorker(taskName); SaveFailureHandler.getInstance().process(e); return; } @@ -62,6 +75,7 @@ public class SaveWorker extends SwingWorker { // 恢复界面 if (slowly && ComparatorUtils.equals(this.template.getName(), HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getName())) { DesignerContext.getDesignerFrame().getCenterTemplateCardPane().hideCover(); + slowly = false; } DesignerFrameFileDealerPane.getInstance().stateChange(); WorkerManager.getInstance().removeWorker(taskName); @@ -69,21 +83,29 @@ public class SaveWorker extends SwingWorker { public void start(String taskName) { this.taskName = taskName; + StopWatch stopWatch = StopWatch.createStarted(); this.template.setSaving(true); this.execute(); // worker纳入管理 WorkerManager.getInstance().registerWorker(taskName, this); - try { - this.get(TIME_OUT, TimeUnit.MILLISECONDS); - } catch (TimeoutException timeoutException) { - slowly = true; - // 开始禁用 - EastRegionContainerPane.getInstance().updateAllPropertyPane(); - DesignerContext.getDesignerFrame().getCenterTemplateCardPane().showCover(); - DesignerFrameFileDealerPane.getInstance().stateChange(); - } catch (Exception exception) { - FineLoggerFactory.getLogger().error(exception.getMessage(), exception); - WorkerManager.getInstance().removeWorker(taskName); - } + SaveTypeWorker.SAVE_TYPE_POOL.execute(() -> { + while (true) { + if (stopWatch.getTime() > TIME_OUT || isDone()) { + if (!isDone()) { + slowly = true; + UIUtil.invokeLaterIfNeeded(() -> { + // 开始禁用 + if (slowly) { + EastRegionContainerPane.getInstance().updateAllPropertyPane(); + DesignerContext.getDesignerFrame().getCenterTemplateCardPane().showCover(); + DesignerFrameFileDealerPane.getInstance().stateChange(); + } + }); + } + stopWatch.stop(); + break; + } + } + }); } } diff --git a/designer-base/src/main/java/com/fr/design/worker/save/type/SaveType.java b/designer-base/src/main/java/com/fr/design/worker/save/type/SaveType.java new file mode 100644 index 000000000..63cf6c4c7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/worker/save/type/SaveType.java @@ -0,0 +1,50 @@ +package com.fr.design.worker.save.type; + +/** + * 保存的类别 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/4/14 + */ +public class SaveType { + + private TypeEnum type; + //保存时间是否慢(是否展示了保存中的UI界面) + private boolean slowly; + + public TypeEnum getType() { + return type; + } + + public void setType(TypeEnum saveType) { + this.type = saveType; + } + + public boolean isSlowly() { + return slowly; + } + + public void setSlowly(boolean slowly) { + this.slowly = slowly; + } + + /** + * 保存类型:save or saveAs or empty + */ + public enum TypeEnum { + /** + * 保存 + */ + SAVE, + /** + * 另存 + */ + SAVE_AS, + /** + * 空保存 + */ + EMPTY; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/worker/save/type/SaveTypeWorker.java b/designer-base/src/main/java/com/fr/design/worker/save/type/SaveTypeWorker.java new file mode 100644 index 000000000..d415537eb --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/worker/save/type/SaveTypeWorker.java @@ -0,0 +1,81 @@ +package com.fr.design.worker.save.type; + + +import com.fr.concurrent.FineExecutors; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrameFileDealerPane; +import com.fr.design.mainframe.EastRegionContainerPane; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.ui.util.UIUtil; +import com.fr.third.org.apache.commons.lang3.time.StopWatch; + +import javax.swing.SwingWorker; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; + +/** + * 判断保存类别时执行的worker + * + * @author John.Ying + * @since 11.0 + * Created on 2023/4/14 + */ +public class SaveTypeWorker extends SwingWorker { + + public static final ExecutorService SAVE_TYPE_POOL = FineExecutors.newSingleThreadExecutor(); + + private final Callable callable; + + private static final int TIME_OUT = 400; + + private final JTemplate template; + + private final SaveType saveType; + + + + public SaveTypeWorker(Callable callable, JTemplate template) { + this.callable = callable; + this.template = template; + this.saveType = new SaveType(); + } + + @Override + protected SaveType doInBackground() throws Exception { + this.saveType.setType(callable.call()); + return this.saveType; + } + + @Override + protected void done() { + + } + + /** + * 启动saveTypeWorker + */ + public void start() { + StopWatch stopWatch = StopWatch.createStarted(); + this.template.setSaving(true); + this.execute(); + SAVE_TYPE_POOL.execute(() -> { + while (true) { + //大于最大等待时间或者worker已经完成该线程都要结束循环 + if (stopWatch.getTime() > TIME_OUT || isDone()) { + //如果是大于最大等待时间结束的,就需要进行等待中界面的覆盖 + if (!isDone()) { + saveType.setSlowly(true); + UIUtil.invokeLaterIfNeeded(() -> { + // 开始禁用 + EastRegionContainerPane.getInstance().updateAllPropertyPane(); + DesignerContext.getDesignerFrame().getCenterTemplateCardPane().showCover(); + DesignerFrameFileDealerPane.getInstance().stateChange(); + }); + } + stopWatch.stop(); + break; + } + } + }); + } +} diff --git a/designer-base/src/main/java/com/fr/env/RemoteDesignLocaleMark.java b/designer-base/src/main/java/com/fr/env/RemoteDesignLocaleMark.java index 877a9224b..dd9532361 100644 --- a/designer-base/src/main/java/com/fr/env/RemoteDesignLocaleMark.java +++ b/designer-base/src/main/java/com/fr/env/RemoteDesignLocaleMark.java @@ -1,11 +1,7 @@ package com.fr.env; -import com.fr.general.CloudCenter; -import com.fr.general.GeneralContext; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.general.locale.LocaleMark; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; /** * @author hades @@ -14,23 +10,21 @@ import java.util.Map; */ public class RemoteDesignLocaleMark implements LocaleMark { - private Map map = new HashMap<>(); - private static final String REMOTE_DESIGN_CN = CloudCenter.getInstance().acquireUrlByKind("help.remote.design.zh_CN", "https://help.fanruan.com/finereport/doc-view-3925.html"); - private static final String REMOTE_DESIGN_EN = CloudCenter.getInstance().acquireUrlByKind("help.remote.design.en_US", "https://help.fanruan.com/finereport-en/doc-view-3862.html"); + /** + * 云中心远程设计常见问题链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Remote_Design_Question"; + /** + * 云中心远程设计常见问题链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Remote_Design_Question_Default"; - public RemoteDesignLocaleMark() { - map.put(Locale.CHINA, REMOTE_DESIGN_CN); - map.put(Locale.KOREA, REMOTE_DESIGN_EN); - map.put(Locale.JAPAN, REMOTE_DESIGN_EN); - map.put(Locale.US, REMOTE_DESIGN_EN); - map.put(Locale.TAIWAN, REMOTE_DESIGN_CN); - } + public RemoteDesignLocaleMark() {} @Override public String getValue() { - String result = map.get(GeneralContext.getLocale()); - return result == null ? REMOTE_DESIGN_CN : result; + return LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); } } 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 fd4b98e33..a0b07bd2c 100644 --- a/designer-base/src/main/java/com/fr/env/SyncFailedPluginsDialog.java +++ b/designer-base/src/main/java/com/fr/env/SyncFailedPluginsDialog.java @@ -6,25 +6,18 @@ 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.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.design.utils.gui.GUICoreUtils; -import com.fr.general.CloudCenter; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; import com.fr.general.IOUtils; import com.fr.json.JSONArray; import com.fr.json.JSONObject; import com.fr.stable.StringUtils; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.Locale; + import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JDialog; @@ -33,6 +26,14 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.UIManager; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Locale; /** * @author pengda @@ -47,6 +48,16 @@ public class SyncFailedPluginsDialog extends JDialog { private RestartHelper restartHelper = new RestartHelper(); private UIButton restartButton; private boolean show = false; + + /** + * 云中心插件管理帮助文档在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Plugin_Management"; + + /** + * 云中心插件管理默认帮助文档在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Plugin_Management_Default"; public SyncFailedPluginsDialog(JFrame parent, JSONArray syncFailedPlugins) { super(parent, true); JPanel body = FRGUIPaneFactory.createBorderLayout_L_Pane(); @@ -62,7 +73,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")); + LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT)); messageWithLink.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.env.SyncFailedPluginsDialog.messageWithLink")); messagePane.add(messageWithLink); diff --git a/designer-base/src/main/java/com/fr/env/detect/base/DetectorConstants.java b/designer-base/src/main/java/com/fr/env/detect/base/DetectorConstants.java index 4e4592dcd..61f08c344 100644 --- a/designer-base/src/main/java/com/fr/env/detect/base/DetectorConstants.java +++ b/designer-base/src/main/java/com/fr/env/detect/base/DetectorConstants.java @@ -1,13 +1,33 @@ package com.fr.env.detect.base; +import com.fr.design.i18n.LocaleLinkProvider; + /** * created by Harrison on 2022/05/25 **/ public class DetectorConstants { + /** + * 云中心FineDB异常检测帮助文档在配置文件中对应的配置文件key + */ + private static final String FINE_DB_HELP_PROPS_LINK_KEY = "Fine-Design-CloudCenter_FineDB_Exception_Check"; + + /** + * 云中心FineDB异常检测帮助文档默认链接在配置文件中对应的配置文件key + */ + private static final String FINE_DB_HELP_PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_FineDB_Exception_Check_Default"; + + /** + * 云中心FineDB异常检测帮助文档在配置文件中对应的配置文件key + */ + private static final String JAR_HELP_PROPS_LINK_KEY = "Fine-Design-CloudCenter_Jar_Exception_Check"; + + /** + * 云中心FineDB异常检测帮助文档默认链接在配置文件中对应的配置文件key + */ + private static final String JAR_HELP_PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Jar_Exception_Check_Default"; + public static final String JAR_HELP_LINK = LocaleLinkProvider.getInstance().getLink(JAR_HELP_PROPS_LINK_KEY, JAR_HELP_PROPS_LINK_KEY_DEFAULT);; - public static final String JAR_HELP_LINK = "https://help.fanruan.com/finereport/doc-view-4700.html?source=3"; - - public static final String FINE_DB_HELP_LINK = "https://help.fanruan.com/finereport/doc-view-4701.html?source=3"; + public static final String FINE_DB_HELP_LINK = LocaleLinkProvider.getInstance().getLink(FINE_DB_HELP_PROPS_LINK_KEY, FINE_DB_HELP_PROPS_LINK_KEY_DEFAULT); public static final String SEPARATOR = "、"; public static final String BR_TAG = "
"; diff --git a/designer-base/src/main/java/com/fr/file/FILEChooserPane.java b/designer-base/src/main/java/com/fr/file/FILEChooserPane.java index 0561319db..66b9d12d3 100644 --- a/designer-base/src/main/java/com/fr/file/FILEChooserPane.java +++ b/designer-base/src/main/java/com/fr/file/FILEChooserPane.java @@ -129,6 +129,10 @@ public class FILEChooserPane extends BasicPane { public static final int JOPTIONPANE_CANCEL_OPTION = 3; + public static final String SEPARATOR_STRING = "/"; + + public static final char SEPARATOR_CHAR = '/'; + /** * alex:之所以在Pattern那里加个+,是因为有些路径会有两个甚至多个分隔符放在一起 @@ -1466,10 +1470,17 @@ public class FILEChooserPane extends BasicPane { for (int i = 0; i < this.buttonList.size(); i++) { this.buttonList.get(i).setForeground(null); if (((SetDirectoryAction) this.buttonList.get(i).getAction()).getDir() != null - && this.buttonList.get(i).getAction() instanceof SetDirectoryAction - && (ComparatorUtils.equals(((SetDirectoryAction) this.buttonList.get(i).getAction()).getDir().getPath(), dir.getPath()))) { - - this.buttonList.get(i).setForeground(Color.BLUE); + && this.buttonList.get(i).getAction() instanceof SetDirectoryAction) { + String actionPath = ((SetDirectoryAction) this.buttonList.get(i).getAction()).getDir().getPath(); + String dirPath = dir.getPath(); + //如果是报表环境,button的Action最后会跟上"/",这个是特意处理的,但是对应代码没有说明原因,不做修改 + //FILE的getPath不会带"/",这边针对这种情况加个处理,不建议直接改FILE + if (actionPath.endsWith(SEPARATOR_STRING) && !dirPath.endsWith(SEPARATOR_STRING)) { + dirPath = dirPath + SEPARATOR_STRING; + } + if (ComparatorUtils.equals(actionPath, dirPath)) { + this.buttonList.get(i).setForeground(Color.BLUE); + } } } } @@ -1479,7 +1490,7 @@ public class FILEChooserPane extends BasicPane { } public void populate(FILE dir) { - if (popDir != null && dir != null && popDir.toString().indexOf(dir.toString()) == 0) { + if (checkOnlyHighLight(dir)) { highLightButton(dir); return; } @@ -1530,6 +1541,24 @@ public class FILEChooserPane extends BasicPane { highLightButton(dir); } + /** + * 检查是不是只需要设置高亮即可 + * + * @param dir FILE + * @return 如果还要进行别的设置就返回false,如果只需要更新下高亮(通过点击上面的路径才会只需要更新高亮),返回true + */ + private boolean checkOnlyHighLight(FILE dir) { + if (popDir == null || dir == null) { + return false; + } + String popDirStr = popDir.toString(); + String dirStr = dir.toString(); + //前缀匹配是不够的,还要看下前缀匹配的下一位是不是'/' + //否则"test"和"test副本"明明不属于同个路径逻辑,也只更新高亮,应该是"test"和"test/副本"这样才可以通过 + //如果通过了indexOf的检查,因为不会存在相同的路径,popDirStr只会比dirStr大,看一下前缀匹配的下一位是不是'/',如果不是就得更新路径文本,不能只设置高亮 + return popDirStr.indexOf(dirStr) == 0 && popDirStr.length() > dirStr.length() && popDirStr.charAt(dirStr.length()) == SEPARATOR_CHAR; + } + // doLayout @Override public void doLayout() { diff --git a/designer-base/src/main/resources/com/fr/design/config/default b/designer-base/src/main/resources/com/fr/design/config/default index f808a8237..b32330282 100644 --- a/designer-base/src/main/resources/com/fr/design/config/default +++ b/designer-base/src/main/resources/com/fr/design/config/default @@ -1 +1,2 @@ Fine-Designer_Login=i7hP48WAcuTrmxfN +Fine-Designer_Reu_Share_CERTIFICATE_PUBLIC_KEY=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtsz62CPSWXZE/IYZRiAuTSZkw1WOwer8+JFktK0uKLAUuQoBr+UjAMFtRA8W7JgKMDwZy/2liEAiXEOSPU/hrdV8DtT541LnGi1X/hXiRwuttPWYN3L2GYm/d5blU+FBNwghBIrdAxXTzYBc6P4KL/oYXnMdTIrkz8tYkG3QoFQIDAQAB \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/data/BasicTableDataUtilsTest.java b/designer-base/src/test/java/com/fr/design/data/BasicTableDataUtilsTest.java index 7391924ac..a5721a36a 100644 --- a/designer-base/src/test/java/com/fr/design/data/BasicTableDataUtilsTest.java +++ b/designer-base/src/test/java/com/fr/design/data/BasicTableDataUtilsTest.java @@ -50,19 +50,19 @@ public class BasicTableDataUtilsTest extends TestCase { TableDataSource source = EasyMock.mock(TableDataSource.class); TableData tableData = EasyMock.mock(TableData.class); EasyMock.expect(source.getTableData("ds1")).andReturn(tableData).anyTimes(); - EasyMock.expect(source.getTableData("test-ds1")).andReturn(tableData).anyTimes(); - EasyMock.expect(source.getTableData("test-ds11")).andReturn(null).anyTimes(); + EasyMock.expect(source.getTableData("test_ds1")).andReturn(tableData).anyTimes(); + EasyMock.expect(source.getTableData("test_ds11")).andReturn(null).anyTimes(); EasyMock.replay(source, tableData); - Assert.assertEquals("test-ds1", BasicTableDataUtils.getTableDataName(true, source, "ds1", "test", false)); - Assert.assertEquals("test-ds11", BasicTableDataUtils.getTableDataName(false, source, "ds1", "test", false)); + Assert.assertEquals("test_ds1", BasicTableDataUtils.getTableDataName(true, source, "ds1", "test", false)); + Assert.assertEquals("test_ds11", BasicTableDataUtils.getTableDataName(false, source, "ds1", "test", false)); source = EasyMock.mock(TableDataSource.class); EasyMock.expect(source.getTableData("ds1")).andReturn(null).anyTimes(); - EasyMock.expect(source.getTableData("test-ds1")).andReturn(null).anyTimes(); + EasyMock.expect(source.getTableData("test_ds1")).andReturn(null).anyTimes(); EasyMock.replay(source); - Assert.assertEquals("test-ds1", BasicTableDataUtils.getTableDataName(true, source, "ds1", "test", false)); + Assert.assertEquals("test_ds1", BasicTableDataUtils.getTableDataName(true, source, "ds1", "test", false)); Assert.assertEquals("ds1", BasicTableDataUtils.getTableDataName(false, source, "ds1", "test", false)); - Assert.assertEquals("test-ds1", BasicTableDataUtils.getTableDataName(false, source, "ds1", "test", true)); + Assert.assertEquals("test_ds1", BasicTableDataUtils.getTableDataName(false, source, "ds1", "test", true)); } diff --git a/designer-base/src/test/java/com/fr/design/data/DesignTableDataManagerTest.java b/designer-base/src/test/java/com/fr/design/data/DesignTableDataManagerTest.java index 9a5ce7b8c..1a23555f6 100644 --- a/designer-base/src/test/java/com/fr/design/data/DesignTableDataManagerTest.java +++ b/designer-base/src/test/java/com/fr/design/data/DesignTableDataManagerTest.java @@ -23,7 +23,7 @@ import java.util.HashMap; import java.util.Map; @RunWith(PowerMockRunner.class) -@PrepareForTest({TableDataFactory.class, StoreProcedure.class, TableDataConfig.class, ProcedureConfig.class}) +@PrepareForTest({TableDataFactory.class, StoreProcedure.class, TableDataConfig.class, ProcedureConfig.class, TemplateTableDataWrapper.class}) @SuppressStaticInitializationFor({"com.fr.design.data.tabledata.wrapper.TableDataFactory"}) public class DesignTableDataManagerTest { 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 4efe977ff..297245960 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 @@ -9,6 +9,7 @@ import com.fr.base.chart.BaseChartCollection; import com.fr.chart.chartattr.ChartCollection; import com.fr.chart.charttypes.ChartTypeManager; import com.fr.chartx.attr.ChartProvider; +import com.fr.decision.webservice.v10.map.geojson.helper.GEOJSONHelper; import com.fr.design.ChartTypeInterfaceManager; import com.fr.design.designer.TargetComponent; import com.fr.design.gui.chart.BaseChartPropertyPane; @@ -19,6 +20,7 @@ import com.fr.design.utils.gui.GUICoreUtils; import javax.swing.BorderFactory; import javax.swing.Icon; +import javax.swing.SwingWorker; import java.awt.BorderLayout; import java.awt.Component; 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 bdd3608c9..5b17494da 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 @@ -154,24 +154,23 @@ public class VanChartHyperLinkPane extends VanChartUIListControlPane { } HashMap paneMap = getHyperlinkMap(); - //安装平台内打开插件时,添加相应按钮 - Set providers = ExtraDesignClassManager.getInstance().getArray(HyperlinkProvider.XML_TAG); java.util.List list = refreshList(paneMap); + Map creators = new ListMap<>(); int size = list.size(); - NameObjectCreator[] creators = new NameObjectCreator[size + providers.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); } + //安装平台内打开插件时, 添加/替换 相应按钮 + Set providers = ExtraDesignClassManager.getInstance().getArray(HyperlinkProvider.XML_TAG); for (HyperlinkProvider provider : providers) { NameableCreator creator = provider.createHyperlinkCreator(); if (creator != null) { - creators[size] = new NameObjectCreator(creator.menuName(), creator.getHyperlink(), creator.getUpdatePane()); - size++; + creators.put(creator.menuName(), new NameObjectCreator(creator.menuName(), creator.getHyperlink(), creator.getUpdatePane())); } } - - refreshNameableCreator(creators); + refreshNameableCreator(creators.values().toArray(new NameObjectCreator[0])); } public void populate(Plot plot) { @@ -303,7 +302,7 @@ public class VanChartHyperLinkPane extends VanChartUIListControlPane { @Override protected void initCreatorsFilter() { - this.creatorsFilter = nameableCreator -> { + this.creatorsFilter = nameableCreator -> { Class clazz = nameableCreator.getHyperlink(); JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); if (!JTemplate.isValid(template)) { diff --git a/designer-chart/src/main/java/com/fr/van/chart/multilayer/data/MultiPiePlotTableDataContentPane.java b/designer-chart/src/main/java/com/fr/van/chart/multilayer/data/MultiPiePlotTableDataContentPane.java index b32ea4b67..ba8d24929 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/multilayer/data/MultiPiePlotTableDataContentPane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/multilayer/data/MultiPiePlotTableDataContentPane.java @@ -58,6 +58,9 @@ public class MultiPiePlotTableDataContentPane extends AbstractTableDataContentPa //将数据列名保存下来,在update时会删除层级名列表,需要用保存的list重新初始化新的层级名列表 private List columnNameList; + //汇总方式求和的索引 + public static final int SUM_INDEX = 2; + public MultiPiePlotTableDataContentPane() { } @@ -241,7 +244,8 @@ public class MultiPiePlotTableDataContentPane extends AbstractTableDataContentPa for (UIComboBox uiComboBox : levelNameList) { clearBoxItems(uiComboBox); } - clearBoxItems(calculateCombox); + //默认选求和 + calculateCombox.setSelectedIndex(SUM_INDEX); refreshCenterPane(); } diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XNumberEditor.java b/designer-form/src/main/java/com/fr/design/designer/creator/XNumberEditor.java index 15cd30c6f..fc359976e 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XNumberEditor.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XNumberEditor.java @@ -91,15 +91,15 @@ public class XNumberEditor extends XWrapperedFieldEditor { } } - @Override + @Override protected JComponent initEditor() { setBorder(FIELDBORDER); return this; } - @Override - protected String getIconName() { - return "number_field_16.png"; - } + @Override + protected String getIconName() { + return "number_field_16.png"; + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/Jump2DetailAction.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/Jump2DetailAction.java index 9df031382..b4d546727 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/Jump2DetailAction.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/Jump2DetailAction.java @@ -1,17 +1,11 @@ package com.fr.design.mainframe.share.ui.actions; -import com.fr.design.actions.UpdateAction; -import com.fr.design.gui.imenu.UIMenuItem; -import com.fr.design.gui.imenu.UIMenuItemUI; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; -import com.fr.design.mainframe.share.ui.constants.ColorConstants; import com.fr.design.mainframe.share.ui.online.CarouselStateManger; import com.fr.stable.StringUtils; import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.SwingConstants; -import java.awt.Color; import java.awt.Desktop; import java.awt.event.ActionEvent; import java.io.IOException; @@ -24,7 +18,18 @@ import java.net.URISyntaxException; * Created by Starryi on 2021/9/28 */ public class Jump2DetailAction extends SharedComponentPopupAction { - private static final String ONLINE_WIDGET_DETAIL_FORMATTED_URL = "https://market.fanruan.com/reuse/%s"; + + /** + * 云中心组件市场组件详情在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Market_Detail"; + + /** + * 云中心组件市场组件详情默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Market_Detail_Default"; + + private static final String ONLINE_WIDGET_DETAIL_FORMATTED_URL = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); private final String id; public Jump2DetailAction(String id) { diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java index b4d3bcc68..e7b60ce92 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java @@ -2,35 +2,30 @@ package com.fr.design.mainframe.share.ui.online; import com.fr.base.BaseUtils; import com.fr.base.Style; -import com.fr.config.constant.Constant; import com.fr.design.dialog.BasicPane; import com.fr.design.form.util.FontTransformUtil; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.share.ui.base.LoadingPane; import com.fr.design.mainframe.share.ui.base.MouseClickListener; import com.fr.design.mainframe.share.ui.online.mini.MiniComponentShopDialog; import com.fr.design.mainframe.share.util.OnlineShopUtils; -import com.fr.design.mainframe.theme.edit.ui.LabelUtils; import com.fr.form.share.bean.OnlineShareWidget; import com.fr.general.FRFont; import com.fr.general.IOUtils; import com.fr.log.FineLoggerFactory; -import com.fr.stable.Constants; import com.fr.stable.StringUtils; import javax.swing.BorderFactory; -import javax.swing.BoxLayout; import javax.swing.JPanel; -import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.SwingWorker; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; -import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FlowLayout; @@ -47,7 +42,18 @@ import java.util.concurrent.ExecutionException; * Created by kerry on 2020-10-16 */ public class OnlineWidgetRepoPane extends BasicPane { - private static final String MARKET_URL = "https://market.fanruan.com/reuse"; + + /** + * 云中心组件市场在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Market"; + + /** + * 云中心组件市场默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Market_Default"; + + private static final String MARKET_URL = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); private static List[] sharableWidgets; private OnlineWidgetTabPane componentTabPane; private boolean isShowPackagePanel = false; 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 a814dfa0a..a451a9bee 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 @@ -3,6 +3,7 @@ package com.fr.design.mainframe.share.util; import com.fr.base.theme.FormTheme; import com.fr.design.DesignerEnvManager; import com.fr.design.extra.PluginConstants; +import com.fr.design.login.config.DefaultLoginKeys; import com.fr.form.share.base.CancelCheck; import com.fr.form.share.constants.ShareComponentConstants; import com.fr.ftp.util.Base64; @@ -45,10 +46,7 @@ import java.util.Set; * created by Harrison on 2020/05/27 **/ public class DownloadUtils { - private static final String CERTIFICATE_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtsz62CPSWXZE/IYZRiAuTSZkw\n" + - "1WOwer8+JFktK0uKLAUuQoBr+UjAMFtRA8W7JgKMDwZy/2liEAiXEOSPU/hrdV8D\n" + - "tT541LnGi1X/hXiRwuttPWYN3L2GYm/d5blU+FBNwghBIrdAxXTzYBc6P4KL/oYX\n" + - "nMdTIrkz8tYkG3QoFQIDAQAB"; + private static final String CERTIFICATE_PUBLIC_KEY = DefaultLoginKeys.getInstance().getKey("Fine-Designer_Reu_Share_CERTIFICATE_PUBLIC_KEY"); private static String getReusesUrl() { return StableUtils.pathJoin(OnlineShopUtils.getReuInfoPath(), "file/download"); diff --git a/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java b/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java index 86e3f4998..a794a7bd6 100644 --- a/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java @@ -368,12 +368,11 @@ public class RootDesignDefinePane extends AbstractDataModify { wParameterLayout.setParamsFireStopEdit(fireAfterEditor.isSelected()); JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); jTemplate.needAddTemplateIdAttr(useParamsTemplate.isSelected()); - wParameterLayout.setBackground((Background) background.getValue()); if (extraPaneList.isEmpty()) { - background.setValue(wParameterLayout.getBackground()); + wParameterLayout.setBackground((Background) background.getValue()); } else { for (BasicBeanPane pane : extraPaneList) { - pane.populateBean(wParameterLayout); + pane.updateBean(wParameterLayout); } } //设置参数模板面板的高度 diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/btn/AbstractExtraButtonPane.java b/designer-form/src/main/java/com/fr/design/widget/ui/btn/AbstractExtraButtonPane.java new file mode 100644 index 000000000..67b8e4d26 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/widget/ui/btn/AbstractExtraButtonPane.java @@ -0,0 +1,126 @@ +package com.fr.design.widget.ui.btn; + +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.dialog.BasicPane; +import com.fr.design.fun.WidgetAdvancedPaneProvider; +import com.fr.design.gui.icombobox.DictionaryComboBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.widget.btn.ButtonWithHotkeysDetailPane; +import com.fr.form.ui.Button; +import com.fr.general.GeneralContext; +import com.fr.plugin.observer.PluginEvent; +import com.fr.plugin.observer.PluginEventListener; +import org.jetbrains.annotations.Nullable; + +import javax.swing.JPanel; +import java.awt.Component; +import java.util.Set; + + + +/** + * 用来处理额外的按钮属性 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/4/19 + */ +public abstract class AbstractExtraButtonPane extends ButtonWithHotkeysDetailPane { + protected JPanel extraPane; + protected boolean containsExtraPane; + protected static double F = TableLayout.FILL; + protected static double P = TableLayout.PREFERRED; + + protected void initExtraPane() { + initPluginListener(); + refreshExtraAdvancedPane(classType()); + } + + + /** + * 根据按钮类别判断需要返回什么类型的属性界面 + */ + protected void refreshExtraAdvancedPane(Class cls) { + extraPaneList.clear(); + boolean containsExtraPane = false; + Set> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG); + for (WidgetAdvancedPaneProvider provider : providers) { + if (!provider.accept(cls)) { + continue; + } + insertShortCut(provider.getInsertPosition(extraPaneList.size()), provider.createExtraAdvancedPane()); + containsExtraPane = true; + } + if (containsExtraPane) { + extraPane = FRGUIPaneFactory.createYBoxEmptyBorderPane(); + for (BasicBeanPane pane : extraPaneList) { + extraPane.add(pane); + } + } + this.containsExtraPane = containsExtraPane; + + } + + protected void initPluginListener() { + GeneralContext.listenPluginRunningChanged(new PluginEventListener() { + @Override + public void on(PluginEvent event) { + refreshExtraAdvancedPane(classType()); + } + }, pluginContext -> pluginContext.getRuntime().contain(WidgetAdvancedPaneProvider.XML_TAG)); + } + + /** + * 插入配置项面板 + * + * @param index 插入的位置 + * @param pane 配置项面板 + */ + protected void insertShortCut(int index, BasicBeanPane pane) { + int size = extraPaneList.size(); + index = Math.min(index, size); + extraPaneList.add(index, pane); + } + + @Override + public void populate(T button) { + super.populate(button); + for (BasicBeanPane pane : extraPaneList) { + pane.populateBean(button); + } + } + + @Override + public T update() { + T button = super.update(); + for (BasicBeanPane pane : extraPaneList) { + pane.updateBean(button); + } + return button; + } + + + @Override + protected DictionaryComboBox createCustomButtonTypeComboBox() { + return createButtonTypeComboBox(containsExtraPane); + } + + /** + * 生成额外的属性界面 + */ + protected Component createExtraPane(@Nullable BasicPane pane) { + initExtraPane(); + Component[][] components = new Component[][]{ + new Component[]{pane, null}, + new Component[]{extraPane, null} + }; + double[] rowSize = {P, P}; + double[] columnSize = {P, F}; + int[][] rowCount = {{1, 1},{1, 1}}; + return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, 10, 7); + } + +} diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/btn/FormSubmitButtonDetailPane.java b/designer-form/src/main/java/com/fr/design/widget/ui/btn/FormSubmitButtonDetailPane.java index acc2e76c4..77a735df5 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/btn/FormSubmitButtonDetailPane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/btn/FormSubmitButtonDetailPane.java @@ -1,22 +1,21 @@ package com.fr.design.widget.ui.btn; import com.fr.form.parameter.FormSubmitButton; -import com.fr.design.widget.btn.ButtonWithHotkeysDetailPane; import java.awt.*; /** - * Created by IntelliJ IDEA. - * Author : Richer - * Version: 6.5.6 - * Date : 11-11-15 - * Time : 下午6:25 + * 提交参数按钮 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/4/19 */ -public class FormSubmitButtonDetailPane extends ButtonWithHotkeysDetailPane { +public class FormSubmitButtonDetailPane extends AbstractExtraButtonPane { @Override protected Component createCenterPane() { - return null; + return createExtraPane(null); } @Override @@ -37,4 +36,5 @@ public class FormSubmitButtonDetailPane extends ButtonWithHotkeysDetailPane
extends AbstractDataMod protected UITextField labelNameTextField; private final List> extraPaneList = new ArrayList<>(); private JPanel extraPane; + protected boolean containsExtraPane; public ButtonDefinePane(XCreator creator){ super(creator); @@ -63,7 +64,7 @@ public abstract class ButtonDefinePane extends AbstractDataMod private void refreshAdvancedPane() { extraPaneList.clear(); - boolean containsExtraPane = false; + containsExtraPane = false; Set> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG); for (WidgetAdvancedPaneProvider provider : providers) { if (!provider.accept(creator)) { diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/FreeButtonDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/FreeButtonDefinePane.java index 843f402f0..16a31b85e 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/FreeButtonDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/FreeButtonDefinePane.java @@ -41,10 +41,13 @@ public class FreeButtonDefinePane extends ButtonDefinePane { } public void populateSubButtonPane(FreeButton e) { + if (containsExtraPane) { + return; + } backgroundCompPane.populate(e); frFontPane.setVisible(e.isCustomStyle()); fontLabel.setVisible(e.isCustomStyle()); - if(e.isCustomStyle()){ + if (e.isCustomStyle()) { FRFont frFont = e.getFont(); if (frFont != null) { frFontPane.populateBean(e.getFont()); @@ -54,12 +57,14 @@ public class FreeButtonDefinePane extends ButtonDefinePane { public FreeButton updateSubButtonPane() { FreeButton freeButton = (FreeButton) creator.toData(); - backgroundCompPane.update(freeButton); - frFontPane.setVisible(freeButton.isCustomStyle()); - fontLabel.setVisible(freeButton.isCustomStyle()); - if(freeButton.isCustomStyle()){ - FRFont frFont = freeButton.getFont() == null ? FRFont.getInstance() : freeButton.getFont(); - freeButton.setFont(frFontPane.update(frFont)); + if (!containsExtraPane) { + backgroundCompPane.update(freeButton); + frFontPane.setVisible(freeButton.isCustomStyle()); + fontLabel.setVisible(freeButton.isCustomStyle()); + if (freeButton.isCustomStyle()) { + FRFont frFont = freeButton.getFont() == null ? FRFont.getInstance() : freeButton.getFont(); + freeButton.setFont(frFontPane.update(frFont)); + } } return freeButton; } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/WidgetCardTagBoundPane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/WidgetCardTagBoundPane.java index 22d544c1a..66ae39cd6 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/WidgetCardTagBoundPane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/WidgetCardTagBoundPane.java @@ -29,7 +29,7 @@ public class WidgetCardTagBoundPane extends WidgetBoundPane { @Override public void initBoundPane() { - cardTagWidth = new UIBoundSpinner(0, Integer.MAX_VALUE, 1); + cardTagWidth = new UIBoundSpinner(0, Integer.MAX_VALUE, 1, 0); cardTagWidth.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Coords_And_Size")); this.add(WidgetBoundsPaneFactory.createCardTagBoundPane(cardTagWidth)); } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ElementCaseDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ElementCaseDefinePane.java index bdd5b7d35..b9c84e5be 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ElementCaseDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ElementCaseDefinePane.java @@ -22,7 +22,6 @@ import com.fr.design.mainframe.WidgetPropertyPane; import com.fr.design.mainframe.mobile.ui.MobileCollapsedStyleExpandPane; import com.fr.design.mainframe.mobile.ui.MobileComboBoxDialogEditor; import com.fr.form.ui.ElementCaseEditor; - import com.fr.form.ui.mobile.MobileCollapsedStyle; import com.fr.stable.StringUtils; @@ -30,7 +29,9 @@ import javax.swing.BorderFactory; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SwingConstants; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; /** * 报表块-移动端属性面板 @@ -123,7 +124,6 @@ public class ElementCaseDefinePane extends MobileWidgetDefinePane { panelWrapper.add(panel, BorderLayout.NORTH); UIExpandablePane folderPane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Fit"), 280, 20, panelWrapper); this.add(folderPane, BorderLayout.NORTH); - this.bingListeners2Widgets(); this.setGlobalNames(); this.repaint(); } @@ -165,7 +165,6 @@ public class ElementCaseDefinePane extends MobileWidgetDefinePane { @Override public void populate(FormDesigner designer) { this.designer = designer; - this.addAttributeChangeListener(changeListener); ElementCaseEditor elementCaseEditor = (ElementCaseEditor) xCreator.toData(); this.hComboBox.setSelectedItem(new Item(elementCaseEditor.getHorziontalAttr().description(), elementCaseEditor.getHorziontalAttr())); this.vComboBox.setSelectedItem(new Item(elementCaseEditor.getVerticalAttr().description(), elementCaseEditor.getVerticalAttr())); @@ -178,6 +177,8 @@ public class ElementCaseDefinePane extends MobileWidgetDefinePane { this.mobileCollapsedStyleEditor.setStyle(elementCaseEditor.getMobileCollapsedStyle()); fix(elementCaseEditor.getMobileCollapsedStyle()); this.mobileCollapsedStyleEditor.setSelected(elementCaseEditor.getMobileCollapsedStyle().isCollapsedWork()); + this.bingListeners2Widgets(); + this.addAttributeChangeListener(changeListener); } /** @@ -191,7 +192,6 @@ public class ElementCaseDefinePane extends MobileWidgetDefinePane { @Override public void update() { - DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified(); // 触发设计器保存按钮亮起来 String globalName = this.getGlobalName(); switch (globalName) { case "hComboBox": @@ -220,6 +220,7 @@ public class ElementCaseDefinePane extends MobileWidgetDefinePane { style.setCollapsedWork(this.mobileCollapsedStyleEditor.isSelectedCustom() && !FormDesignerUtils.isInAbsoluteLayout(xCreator)); ((ElementCaseEditor) xCreator.toData()).setMobileCollapsedStyle(style); } + DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified(); // 触发设计器保存按钮亮起来 } private void setGlobalNames() { diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ScanCodeMobileDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ScanCodeMobileDefinePane.java index a9876b7a3..71c35574a 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ScanCodeMobileDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ScanCodeMobileDefinePane.java @@ -10,6 +10,7 @@ import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.FormDesigner; import com.fr.design.widget.ui.designer.mobile.component.MobileTextFieldInputSettingPane; import com.fr.form.ui.TextEditor; + import java.awt.BorderLayout; diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileTextFieldInputSettingPane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileTextFieldInputSettingPane.java index 75d924e53..fb9daa30f 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileTextFieldInputSettingPane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileTextFieldInputSettingPane.java @@ -2,12 +2,16 @@ package com.fr.design.widget.ui.designer.mobile.component; import com.fr.base.mobile.MobileScanCodeAttr; import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.ibutton.UIRadioButton; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.VerticalFlowLayout; + +import javax.swing.ButtonGroup; +import javax.swing.JPanel; import java.awt.BorderLayout; import java.awt.FlowLayout; -import javax.swing.JPanel; /** * @author hades @@ -20,15 +24,28 @@ public class MobileTextFieldInputSettingPane extends BasicBeanPane { + UICheckBox source = (UICheckBox) e.getSource(); + // 更新面板是否可见 + updateNfcContentTypePane(source.isSelected(), nfcContentTypePane.getSelectedType()); + }); settingPane.add(manualInputCheckBox); settingPane.add(scanCodeCheckBox); settingPane.add(nfcInputCheckBox); + settingPane.add(nfcContentTypePane); + // 初始状态,内容类型面板不可见 + nfcContentTypePane.setVisible(false); this.add(settingPane, BorderLayout.NORTH); } @@ -37,6 +54,7 @@ public class MobileTextFieldInputSettingPane extends BasicBeanPane"; diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java index 9879ac53a..5ac64d401 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java @@ -20,6 +20,7 @@ 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.locale.impl.DataMaskMark; import com.fr.design.mainframe.EastRegionContainerPane; import com.fr.design.mainframe.JTemplate; import com.fr.design.mainframe.cell.settingpane.desensitization.CellDesensitizationGroupsPane; @@ -28,6 +29,8 @@ import com.fr.design.utils.gui.UIComponentUtils; import com.fr.design.widget.FRWidgetFactory; import com.fr.general.ComparatorUtils; import com.fr.general.FRFont; +import com.fr.general.locale.LocaleCenter; +import com.fr.general.locale.LocaleMark; import com.fr.report.cell.TemplateCellElement; import com.fr.report.cell.cellattr.CellDesensitizationAttr; import com.fr.report.cell.cellattr.CellGUIAttr; @@ -156,10 +159,11 @@ public class CellOtherSetPane extends AbstractCellAttrPane { // 带超链的提示信息 UILabel label = new UILabel(); + LocaleMark dataMaskMark = LocaleCenter.getMark(DataMaskMark.class); MessageWithLink hyperlink = new MessageWithLink( Toolkit.i18nText("Fine-Design_Report_Desensitization_Tip"), Toolkit.i18nText("Fine-Design_Report_Desensitization_Hyperlink"), - Toolkit.i18nText("Fine-Design_Report_Desensitization_Help_Document_Url"), + dataMaskMark.getValue(), StringUtils.EMPTY, label.getBackground(), label.getFont(), diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java b/designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java index d8f7265f7..3ceef3ae2 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java @@ -7,6 +7,7 @@ import com.fr.design.dialog.FineJOptionPane; import com.fr.design.env.DesignerWorkspaceInfo; import com.fr.design.env.DesignerWorkspaceInfoContext; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; @@ -17,7 +18,6 @@ import com.fr.design.mainframe.toast.ToastMsgDialog; import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.BrowseUtils; import com.fr.event.EventDispatcher; -import com.fr.general.CloudCenter; import com.fr.log.FineLoggerFactory; import com.fr.serialization.SerializerHelper; import com.fr.stable.ArrayUtils; @@ -32,6 +32,7 @@ import com.fr.workspace.WorkContext; import com.fr.workspace.Workspace; import com.fr.workspace.base.WorkspaceConstants; import com.fr.workspace.connect.WorkspaceConnectionInfo; +import com.fr.workspace.engine.exception.WorkspaceConnectionException; import com.fr.workspace.server.socket.CustomLogEvent; import com.fr.workspace.server.socket.LogEventConverter; import io.socket.client.IO; @@ -58,7 +59,17 @@ public class DesignerSocketIO { Disconnecting } - private static final String WEBSOCKET_HELP_DOC = CloudCenter.getInstance().acquireUrlByKind("websocketConnect", "https://help.fanruan.com/finereport/doc-view-2512.html"); + /** + * 云中心特殊字符导出在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_WebSocket"; + + /** + * 云中心特殊字符导出默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_WebSocket_Default"; + + private static final String WEBSOCKET_HELP_DOC = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); private static final String HTTPS = "https"; private static final String HTTP = "http"; private static Socket socket = null; @@ -261,6 +272,11 @@ public class DesignerSocketIO { httpGet.setConfig(requestConfig); try { CloseableHttpResponse response = httpclient.execute(httpGet); + if (isErrorStatus(response.getStatusLine().getStatusCode())) { + //这边nginx做负载,服务器被kill掉,返回的是502,不会抛错,导致checkRPCConnect通过 + //针对500-600的错误码加个判断,其他类型的状态码暂不考虑,如果有遇到再处理,不然怕影响范围大 + throw new WorkspaceConnectionException("Response " + response.getStatusLine().toString()); + } } catch (Exception e) { FineLoggerFactory.getLogger().error(e, e.getMessage()); return false; @@ -268,6 +284,23 @@ public class DesignerSocketIO { return true; } + /** + * 错误状态码 + * 5xx(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。代码 说明 + * 500 (服务器内部错误) 服务器遇到错误,无法完成请求。 + * 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。 + * 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。 + * 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。 + * 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 + * 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。 + * + * @param status 错误状态码 + * @return 是否是错误状态码 + */ + private static boolean isErrorStatus(int status) { + return status >= 500 && status <= 600; + } + //配置变更监听器 private static final Emitter.Listener modifyConfig = new Emitter.Listener() { @Override diff --git a/designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java b/designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java index 5fe52560d..4da3b89e8 100644 --- a/designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java +++ b/designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java @@ -6,10 +6,10 @@ 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.i18n.LocaleLinkProvider; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.BrowseUtils; -import com.fr.general.CloudCenter; import com.fr.io.attr.ReportExportAttr; import com.fr.transaction.Configurations; import com.fr.transaction.WorkerFacade; @@ -30,7 +30,17 @@ import java.awt.event.ActionListener; */ public class ExportUniversalPane extends BasicPane { - private static final String HELP_URL = CloudCenter.getInstance().acquireUrlByKind("help.alt_font.zh_CN", "https://help.fanruan.com/finereport/doc-view-4707.html"); + /** + * 云中心特殊字符导出在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Alt_Font_Export"; + + /** + * 云中心特殊字符导出默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Alt_Font_Export_Default"; + + private static final String HELP_URL = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT); private UICheckBox specialCharacterExport; // 密码支持公式 diff --git a/designer-realize/src/main/java/com/fr/design/report/ReportEnginePane.java b/designer-realize/src/main/java/com/fr/design/report/ReportEnginePane.java index 15dd2a3ea..380809faf 100644 --- a/designer-realize/src/main/java/com/fr/design/report/ReportEnginePane.java +++ b/designer-realize/src/main/java/com/fr/design/report/ReportEnginePane.java @@ -11,14 +11,15 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.locale.impl.LineEngineMark; import com.fr.design.mainframe.DesignerContext; import com.fr.design.widget.FRWidgetFactory; -import com.fr.general.SiteCenter; +import com.fr.general.locale.LocaleCenter; +import com.fr.general.locale.LocaleMark; import com.fr.log.FineLoggerFactory; import com.fr.report.core.ReportUtils; import com.fr.report.stable.LayerReportAttr; import com.fr.report.worksheet.WorkSheet; -import com.fr.stable.ProductConstants; import javax.swing.AbstractButton; import javax.swing.BorderFactory; @@ -203,7 +204,8 @@ public class ReportEnginePane extends BasicBeanPane { @Override public void mouseClicked(MouseEvent e) { try { - Desktop.getDesktop().browse(new URI(SiteCenter.getInstance().acquireUrlByKind("standard.doc", ProductConstants.WEBSITE_URL))); + LocaleMark lineEngineMark = LocaleCenter.getMark(LineEngineMark.class); + Desktop.getDesktop().browse(new URI(lineEngineMark.getValue())); } catch (IOException | URISyntaxException ex) { FineLoggerFactory.getLogger().error("io exception or not find website", ex); } diff --git a/designer-realize/src/main/java/com/fr/design/webattr/EventPane.java b/designer-realize/src/main/java/com/fr/design/webattr/EventPane.java index 8c11bc592..347d94283 100644 --- a/designer-realize/src/main/java/com/fr/design/webattr/EventPane.java +++ b/designer-realize/src/main/java/com/fr/design/webattr/EventPane.java @@ -5,8 +5,11 @@ import com.fr.design.actions.UpdateAction; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.i18n.Toolkit; import com.fr.design.javascript.ListenerEditPane; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; import com.fr.design.menu.MenuDef; import com.fr.design.menu.ToolBarDef; import com.fr.design.widget.EventCreator; @@ -238,6 +241,23 @@ public class EventPane extends BasicPane { } public void actionPerformed(ActionEvent e) { + JTemplate jTemplate = DesignerContext.getDesignerFrame().getSelectedJTemplate(); + if (!JTemplate.isValid(jTemplate)) { + //如果当前没打开模板就跳出弹窗 + Object[] options = new Object[]{Toolkit.i18nText("Fine-Design_Basic_Button_OK")}; + FineJOptionPane.showOptionDialog( + EventPane.this, + Toolkit.i18nText("Fine-Design_Please_Open_Template_First"), + Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"), + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + options, + options[0] + ); + //如果不支持就直接返回,不提供事件功能 + return ; + } String[] def = WebContent.getDefaultArg(menuName[j]); final ListenerEditPane listenerPane = def == null ? new ListenerEditPane() : new ListenerEditPane(def); Listener lis = new Listener(menuName[j], new JavaScriptImpl()); diff --git a/designer-realize/src/main/java/com/fr/design/widget/ui/btn/AppendRowButtonDefinePane.java b/designer-realize/src/main/java/com/fr/design/widget/ui/btn/AppendRowButtonDefinePane.java index dbf650b7e..981295a1e 100644 --- a/designer-realize/src/main/java/com/fr/design/widget/ui/btn/AppendRowButtonDefinePane.java +++ b/designer-realize/src/main/java/com/fr/design/widget/ui/btn/AppendRowButtonDefinePane.java @@ -2,19 +2,23 @@ package com.fr.design.widget.ui.btn; import com.fr.base.IconManager; + + + import com.fr.report.web.button.write.AppendRowButton; -import com.fr.design.widget.btn.ButtonWithHotkeysDetailPane; + import java.awt.*; + /** - * Created by IntelliJ IDEA. - * Author : Richer - * Version: 6.5.6 - * Date : 11-11-15 - * Time : 下午8:02 + * 插入行按钮 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/4/19 */ -public class AppendRowButtonDefinePane extends ButtonWithHotkeysDetailPane { +public class AppendRowButtonDefinePane extends AbstractExtraButtonPane { private DefineAppendColumnRowPane defineColumnRowPane; // @Override @@ -26,7 +30,8 @@ public class AppendRowButtonDefinePane extends Button @Override protected Component createCenterPane() { - return defineColumnRowPane = new DefineAppendColumnRowPane(); + defineColumnRowPane = new DefineAppendColumnRowPane(); + return createExtraPane(defineColumnRowPane); } @Override @@ -55,4 +60,5 @@ public class AppendRowButtonDefinePane extends Button public Class classType() { return AppendRowButton.class; } + } diff --git a/designer-realize/src/main/java/com/fr/design/widget/ui/btn/DefaultButtonDetailPane.java b/designer-realize/src/main/java/com/fr/design/widget/ui/btn/DefaultButtonDetailPane.java index e7f621ccb..84239e904 100644 --- a/designer-realize/src/main/java/com/fr/design/widget/ui/btn/DefaultButtonDetailPane.java +++ b/designer-realize/src/main/java/com/fr/design/widget/ui/btn/DefaultButtonDetailPane.java @@ -1,20 +1,25 @@ package com.fr.design.widget.ui.btn; + import com.fr.form.ui.Button; import com.fr.form.ui.FreeButton; -import com.fr.design.widget.btn.ButtonWithHotkeysDetailPane; + import java.awt.*; + /** - * Created by IntelliJ IDEA. Author : Richer Version: 6.5.6 Date : 11-11-15 Time - * : 下午6:24 + * 普通按钮 + * + * @author John.Ying + * @since 11.0 + * Created on 2023/4/19 */ -public class DefaultButtonDetailPane extends ButtonWithHotkeysDetailPane