Browse Source

Merge pull request #12116 in DESIGN/design from final/11.0 to persist/11.0

* commit '4ba221c73a40ee92e8e87412dac47be7dcbc6d6f': (114 commits)
  REPORT-95731 多层饼图、矩形树图的汇总方式下拉项为空
  REPORT-95731 多层饼图、矩形树图的汇总方式下拉项为空
  REPORT-95156 review修改
  REPORT-95156 【FR设计器】报表块取消勾选移动端"组件可选中",改变组件位置,撤销异常 【问题原因】 ElementCaseDefinePane 初始化panel的时候默认给了个true,导致拖动的时候,触发面板刷新检查的时候,组件未选中这个checkbox识别成了状态发生了变化,undoState记录的状态就不太对。 【改动思路】 两种改法: 初始化的时候,要根据传进来的FormDesigner来渲染checkbox数据。 组件初始化监听事件的位置不要放在初始化位置,参考图表块,放在pupolate时,保持一致。(选这个) 关于一次撤销导致两种状态发生变化的问题,是由于记录undo状态的位置靠前,导致新的状态还没有变化,就被记录了,把这个位置移动下。
  REPORT-95362 fix:tab上的toolTip被截断
  REPORT-95367 fix:关闭icon模糊
  REPORT-95068 && REPORT-95197 && REPORT-95194  && REPORT-95401 && REPORT-95218 && REPORT-94999  合并到final
  REPORT-95337 & REPORT-95265 fix: 设计器预览数据集的模板信息携带修改 & sql注释先单独处理一下sqlserver的存储过程
  REPORT-95337 & REPORT-95265 fix: 设计器预览数据集的模板信息携带修改 & sql注释先单独处理一下sqlserver的存储过程
  REPORT-90546 把设计器和平台调用的方法区分开
  REPORT-90546 把设计器和平台调用的方法区分开
  REPORT-94476 设计器中按上方向键后上面的单元格被清空--注释
  REPORT-94476 设计器中按上方向键后上面的单元格被清空
  改一下方法名称
  REPORT-94510 决策报表-tab块组件大小设置0-样式设置"菜单式"-预览模板空白
  REPORT-91253 FR源码中存在密钥硬编码
  REPORT-94504 关闭所有模板,当前模板是否有未保存内容没有校验,模板内容有丢失风险
  添加注释
  REPORT-94400【FVS支持多开】来回切换fvs模板,tab栏会晃动
  REPORT-94379 控件显示增强插件安装启用后,部分控件的样式设置有问题
  ...
fix-lag
superman 2 years ago
parent
commit
6605f27c61
  1. 4
      designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java
  2. 16
      designer-base/src/main/java/com/fr/design/actions/community/BBSAction.java
  3. 16
      designer-base/src/main/java/com/fr/design/actions/community/BugAction.java
  4. 15
      designer-base/src/main/java/com/fr/design/actions/community/CenterAction.java
  5. 18
      designer-base/src/main/java/com/fr/design/actions/community/CusDemandAction.java
  6. 16
      designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java
  7. 16
      designer-base/src/main/java/com/fr/design/actions/community/NeedAction.java
  8. 16
      designer-base/src/main/java/com/fr/design/actions/community/QuestionAction.java
  9. 17
      designer-base/src/main/java/com/fr/design/actions/community/SignAction.java
  10. 15
      designer-base/src/main/java/com/fr/design/actions/community/StudyPlanAction.java
  11. 15
      designer-base/src/main/java/com/fr/design/actions/community/TechSolutionAction.java
  12. 17
      designer-base/src/main/java/com/fr/design/actions/community/TemplateStoreAction.java
  13. 14
      designer-base/src/main/java/com/fr/design/actions/community/UpAction.java
  14. 15
      designer-base/src/main/java/com/fr/design/actions/community/WorkOrderCenterAction.java
  15. 2
      designer-base/src/main/java/com/fr/design/actions/file/SwitchExistEnv.java
  16. 14
      designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java
  17. 46
      designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java
  18. 9
      designer-base/src/main/java/com/fr/design/data/DesignTableDataManager.java
  19. 16
      designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java
  20. 6
      designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java
  21. 7
      designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/common/DesensitizationOpenPane.java
  22. 14
      designer-base/src/main/java/com/fr/design/data/datapane/preview/sql/PreviewPerformedSqlPane.java
  23. 15
      designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginCallBackHelper.java
  24. 7
      designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java
  25. 349
      designer-base/src/main/java/com/fr/design/file/MultiTemplateTabMenuFactory.java
  26. 308
      designer-base/src/main/java/com/fr/design/file/MultiTemplateTabPane.java
  27. 10
      designer-base/src/main/java/com/fr/design/file/NewTemplatePane.java
  28. 60
      designer-base/src/main/java/com/fr/design/file/SaveSomeTemplatePane.java
  29. 50
      designer-base/src/main/java/com/fr/design/gui/controlpane/JListControlPane.java
  30. 31
      designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java
  31. 11
      designer-base/src/main/java/com/fr/design/gui/ilist/JNameEdList.java
  32. 16
      designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java
  33. 47
      designer-base/src/main/java/com/fr/design/i18n/LocaleLinkProvider.java
  34. 110
      designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java
  35. 32
      designer-base/src/main/java/com/fr/design/locale/impl/BbsRegisterMark.java
  36. 34
      designer-base/src/main/java/com/fr/design/locale/impl/BbsResetMark.java
  37. 34
      designer-base/src/main/java/com/fr/design/locale/impl/BbsSpaceMark.java
  38. 30
      designer-base/src/main/java/com/fr/design/locale/impl/DataMaskMark.java
  39. 28
      designer-base/src/main/java/com/fr/design/locale/impl/LineEngineMark.java
  40. 2
      designer-base/src/main/java/com/fr/design/locale/impl/VideoMark.java
  41. 20
      designer-base/src/main/java/com/fr/design/login/DesignerLoginBridge.java
  42. 36
      designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java
  43. 8
      designer-base/src/main/java/com/fr/design/mainframe/DefaultToolKitConfig.java
  44. 8
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java
  45. 173
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  46. 10
      designer-base/src/main/java/com/fr/design/mainframe/ToolKitConfigStrategy.java
  47. 16
      designer-base/src/main/java/com/fr/design/mainframe/check/CheckFontInfoDialog.java
  48. 6
      designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java
  49. 20
      designer-base/src/main/java/com/fr/design/update/actions/NewFeatureAction.java
  50. 104
      designer-base/src/main/java/com/fr/design/utils/TemplateUtils.java
  51. 16
      designer-base/src/main/java/com/fr/design/widget/btn/ButtonConstants.java
  52. 22
      designer-base/src/main/java/com/fr/design/widget/btn/ButtonDetailPane.java
  53. 12
      designer-base/src/main/java/com/fr/design/widget/btn/ButtonWithHotkeysDetailPane.java
  54. 8
      designer-base/src/main/java/com/fr/design/worker/save/SaveFailureHandler.java
  55. 52
      designer-base/src/main/java/com/fr/design/worker/save/SaveWorker.java
  56. 50
      designer-base/src/main/java/com/fr/design/worker/save/type/SaveType.java
  57. 81
      designer-base/src/main/java/com/fr/design/worker/save/type/SaveTypeWorker.java
  58. 28
      designer-base/src/main/java/com/fr/env/RemoteDesignLocaleMark.java
  59. 31
      designer-base/src/main/java/com/fr/env/SyncFailedPluginsDialog.java
  60. 24
      designer-base/src/main/java/com/fr/env/detect/base/DetectorConstants.java
  61. 39
      designer-base/src/main/java/com/fr/file/FILEChooserPane.java
  62. 1
      designer-base/src/main/resources/com/fr/design/config/default
  63. 14
      designer-base/src/test/java/com/fr/design/data/BasicTableDataUtilsTest.java
  64. 2
      designer-base/src/test/java/com/fr/design/data/DesignTableDataManagerTest.java
  65. 2
      designer-chart/src/main/java/com/fr/design/mainframe/ChartPropertyPane.java
  66. 17
      designer-chart/src/main/java/com/fr/van/chart/custom/component/VanChartHyperLinkPane.java
  67. 6
      designer-chart/src/main/java/com/fr/van/chart/multilayer/data/MultiPiePlotTableDataContentPane.java
  68. 10
      designer-form/src/main/java/com/fr/design/designer/creator/XNumberEditor.java
  69. 21
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/Jump2DetailAction.java
  70. 20
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java
  71. 6
      designer-form/src/main/java/com/fr/design/mainframe/share/util/DownloadUtils.java
  72. 5
      designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java
  73. 126
      designer-form/src/main/java/com/fr/design/widget/ui/btn/AbstractExtraButtonPane.java
  74. 16
      designer-form/src/main/java/com/fr/design/widget/ui/btn/FormSubmitButtonDetailPane.java
  75. 3
      designer-form/src/main/java/com/fr/design/widget/ui/designer/ButtonDefinePane.java
  76. 19
      designer-form/src/main/java/com/fr/design/widget/ui/designer/FreeButtonDefinePane.java
  77. 2
      designer-form/src/main/java/com/fr/design/widget/ui/designer/component/WidgetCardTagBoundPane.java
  78. 11
      designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ElementCaseDefinePane.java
  79. 1
      designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ScanCodeMobileDefinePane.java
  80. 87
      designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileTextFieldInputSettingPane.java
  81. 14
      designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITReplaceWestPanel.java
  82. 6
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/CellOtherSetPane.java
  83. 37
      designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java
  84. 14
      designer-realize/src/main/java/com/fr/design/report/ExportUniversalPane.java
  85. 8
      designer-realize/src/main/java/com/fr/design/report/ReportEnginePane.java
  86. 20
      designer-realize/src/main/java/com/fr/design/webattr/EventPane.java
  87. 22
      designer-realize/src/main/java/com/fr/design/widget/ui/btn/AppendRowButtonDefinePane.java
  88. 16
      designer-realize/src/main/java/com/fr/design/widget/ui/btn/DefaultButtonDetailPane.java
  89. 17
      designer-realize/src/main/java/com/fr/design/widget/ui/btn/DeleteRowButtonDefinePane.java
  90. 15
      designer-realize/src/main/java/com/fr/design/widget/ui/btn/FreeButtonDetailPane.java
  91. 21
      designer-realize/src/main/java/com/fr/design/widget/ui/btn/TreeNodeToogleButtonDefinePane.java
  92. 1
      designer-realize/src/main/java/com/fr/design/widget/ui/mobile/ScanCodeMobilePane.java
  93. 24
      designer-realize/src/main/java/com/fr/grid/GridKeyAction.java

4
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;
}

16
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() {

16
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() {

15
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() {

18
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);
}

16
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() {

16
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() {

16
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() {

17
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() {

15
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);
}
}

15
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() {

17
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);
}
}

14
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() {

15
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);
}
}

2
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);
}

14
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

46
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<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
// 获取无权限连接名称集合
Collection<String> 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) {

9
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<String, Object> 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);
}

16
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<StrategyConfig> {
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;

6
designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java

@ -589,7 +589,7 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
} else {
path = driverPath;
}
if(JarFileParseUtil.hasDuplicateDriver(con.getDriver(), path)) {
if(hasDuplicateDriver(con.getDriver(), path)) {
testResult.setForeground(Color.RED);
testResult.setText(Toolkit.i18nText("Fine_Designer_Driver_Conflict"));
} else {
@ -605,7 +605,9 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
return xBorderPanel;
}
private boolean hasDuplicateDriver(String driver, String folder) {
return JarFileParseUtil.hasDuplicateDriver(driver, folder);
}
}
}

7
designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/common/DesensitizationOpenPane.java

@ -8,10 +8,12 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.locale.impl.DataMaskMark;
import com.fr.general.locale.LocaleCenter;
import com.fr.general.locale.LocaleMark;
import com.fr.log.FineLoggerFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
@ -58,7 +60,8 @@ public class DesensitizationOpenPane extends JPanel {
@Override
public void mouseClicked(MouseEvent event) {
try {
URL url = new URL(Toolkit.i18nText("Fine-Design_Report_Desensitization_Help_Document_Url"));
LocaleMark<String> 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());

14
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);
}
// 提示图标

15
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);
/**

7
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));
}
}
}

349
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<JTemplate<?, ?>> openedTemplates = new ArrayList<>();
Map<String, List<JTemplate<?, ?>>> map = MultiTemplateTabPane.getInstance().getOpenedJTemplatesByCategory();
for (Map.Entry<String, List<JTemplate<?, ?>>> entry : map.entrySet()) {
if (!StringUtils.equals(currentOperator, entry.getKey())) {
openedTemplates.addAll(entry.getValue());
}
}
return createListDownItem(openedTemplates);
}
/**
* 根据template列表创建多个item
*/
private Component[] createListDownItem(List<JTemplate<?, ?>> 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);
}
}
}

308
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<JTemplate<?, ?>> 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<JTemplate<?, ?>> 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<JTemplate<?, ?>> getOpenedJTemplatesByOperator(String operator) {
return openedTemplate.stream().filter((jTemplate) -> ComparatorUtils.equals(jTemplate.getTemplateTabOperatorType(), operator))
.collect(Collectors.toList());
}
/**
* 根据tab操作类型进行分类
* @return
*/
public Map<String, List<JTemplate<?, ?>>> getOpenedJTemplatesByCategory() {
return openedTemplate.stream()
.collect(Collectors.groupingBy(JTemplate::getTemplateTabOperatorType));
}
}

10
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 事件

60
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<JTemplate<?, ?>> opendedTemplate = HistoryTemplateListPane.getInstance().getHistoryList();
protected java.util.List<JTemplate<?, ?>> getOpenedTemplatesToProcess(){
return HistoryTemplateListPane.getInstance().getHistoryList();
}
private void initAndPopulate(@Nullable MultiTemplateTabPane.CloseCondition option, boolean judgeJTemplateMustSave) {
java.util.List<JTemplate<?, ?>> 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;
}

50
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<Object> {
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();

31
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<Map.Entry<String, ListWrapperPane>> 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<String, ListWrapperPane> entry = iterator.next();
ListWrapperPane wrapperPane = entry.getValue();

11
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型)

16
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;

47
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;
}
}

110
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<List<HelpDocument>, Void>() {
@Override
protected List<HelpDocument> doInBackground() {
List<HelpDocument> helpDocuments = new ArrayList<>();
updateHelpDocuments(value, helpDocuments);
return helpDocuments;
}
@Override
protected void done() {
try {
List<HelpDocument> 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<HelpDocument> 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);
}
}

32
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<String> {
private final Map<Locale, String> 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);
}
}

34
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<String> {
private final Map<Locale, String> 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);
}
}

34
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<String> {
private final Map<Locale, String> 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);
}
}

30
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<String> {
/**
* 云中心数据脱敏帮助链接链接在配置文件中对应的配置文件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);
}
}

28
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<String> {
/**
* 云中心启用行式引擎执行层式报表帮助链接链接在配置文件中对应的配置文件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);
}
}

2
designer-base/src/main/java/com/fr/design/locale/impl/VideoMark.java

@ -16,7 +16,7 @@ public class VideoMark implements LocaleMark<String> {
private Map<Locale, String> 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() {

20
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<String, String> params;
public static DesignerLoginBridge getBridge(Browser browser, Map<String, String> 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) {

36
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);
}
}

8
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;
}
}

8
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);
}

173
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<T extends BaseBook, U extends BaseUndoState<?>> extends TargetComponent<T> 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<T extends BaseBook, U extends BaseUndoState<?>>
}
/**
* 将要激活打开其他模板使当前模板灭活
* 默认 do nothing 返回true
*
* @return true成功停用当前模板
*/
public boolean deactivateTemplate(JTemplate jTemplate) {
//兼容调用老的接口
return deactivateTemplate();
}
/**
* 返回当前支持的超链界面pane
*
@ -1687,24 +1703,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
if (!editingFILE.exists()) {
return saveAs(showLoc);
}
CallbackSaveWorker worker = new CallbackSaveWorker(new Callable<Boolean>() {
@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<T extends BaseBook, U extends BaseUndoState<?>>
}
}
private CallbackSaveWorker saveAs(boolean showLoc) {
FILE editingFILE = this.getEditingFILE();
if (editingFILE == null) {
@ -1771,7 +1772,6 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
// 目标文件
editingFILE = fileChooser.getSelectedFILE();
}
FILE finalEditingFILE = editingFILE;
CallbackSaveWorker worker = new CallbackSaveWorker(new Callable<Boolean>() {
@Override
@ -1872,10 +1872,95 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
return saveAs(true);
}
/**
* 获取保存用到的saveWorker
*/
private CallbackSaveWorker getSaveCallBackSaveWorker() {
CallbackSaveWorker worker = new CallbackSaveWorker(new Callable<Boolean>() {
@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<SaveType.TypeEnum> 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
@ -1989,4 +2074,50 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
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;
}
}

10
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);
}

16
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);

6
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()) {

20
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());
}

104
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<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
private static CompletableFuture<Boolean> 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<Boolean, Void>() {
@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<Boolean, Void>) aBoolean -> {
if (aBoolean) {
openNewTemplateAndCloseOldTemplate(file, openNewTemplate, template);
}
return null;
});
}
/**
* 读取模板文件数据
*

16
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)
};
}

22
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<T extends Button> extends BasicPane {
private List<ChangeListener> ls = new ArrayList<ChangeListener>();
protected final List<BasicBeanPane<T>> extraPaneList = new ArrayList<>();
@Override
public String title4PopupWindow() {
return com.fr.design.i18n.Toolkit.i18nText("Button");
@ -49,7 +48,10 @@ public abstract class ButtonDetailPane<T extends Button> 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<T extends Button> 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);
}
}

12
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<T extends Button> 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<T extends Button> 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<T extends Button> extends Butt
protected abstract Component createCenterPane();
/**
* 判断是按钮控件下拉框的种类1.有自定义按钮 2.无自定义按钮
*/
protected DictionaryComboBox createCustomButtonTypeComboBox() {
return createButtonTypeComboBox();
}
@Override
public void populate(T button) {
if (button == null) {

8
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);
}
}
}

52
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<Boolean, Void> {
private boolean slowly;
public boolean isSlowly() {
return slowly;
}
public void setSlowly(boolean slowly) {
this.slowly = slowly;
}
public SaveWorker(Callable<Boolean> callable, JTemplate<?, ?> template) {
this.callable = callable;
this.template = template;
@ -47,10 +59,11 @@ public class SaveWorker extends SwingWorker<Boolean, Void> {
@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<Boolean, Void> {
// 恢复界面
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<Boolean, Void> {
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;
}
}
});
}
}

50
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;
}
}

81
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<SaveType, Void> {
public static final ExecutorService SAVE_TYPE_POOL = FineExecutors.newSingleThreadExecutor();
private final Callable<SaveType.TypeEnum> callable;
private static final int TIME_OUT = 400;
private final JTemplate<?, ?> template;
private final SaveType saveType;
public SaveTypeWorker(Callable<SaveType.TypeEnum> 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;
}
}
});
}
}

28
designer-base/src/main/java/com/fr/env/RemoteDesignLocaleMark.java vendored

@ -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<String> {
private Map<Locale, String> 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);
}
}

31
designer-base/src/main/java/com/fr/env/SyncFailedPluginsDialog.java vendored

@ -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);

24
designer-base/src/main/java/com/fr/env/detect/base/DetectorConstants.java vendored

@ -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";
public static final String JAR_HELP_LINK = "https://help.fanruan.com/finereport/doc-view-4700.html?source=3";
/**
* 云中心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 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 = "<br/>";

39
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() {

1
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

14
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));
}

2
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 {

2
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;

17
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<HyperlinkProvider> providers = ExtraDesignClassManager.getInstance().getArray(HyperlinkProvider.XML_TAG);
java.util.List<UIMenuNameableCreator> list = refreshList(paneMap);
Map<String, NameObjectCreator> 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<HyperlinkProvider> 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<? extends JavaScript> clazz = nameableCreator.getHyperlink();
JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (!JTemplate.isValid(template)) {

6
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();
}

10
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";
}
}

21
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) {

20
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<OnlineShareWidget>[] sharableWidgets;
private OnlineWidgetTabPane componentTabPane;
private boolean isShowPackagePanel = false;

6
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");

5
designer-form/src/main/java/com/fr/design/parameter/RootDesignDefinePane.java

@ -368,12 +368,11 @@ public class RootDesignDefinePane extends AbstractDataModify<WParameterLayout> {
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<WParameterLayout> pane : extraPaneList) {
pane.populateBean(wParameterLayout);
pane.updateBean(wParameterLayout);
}
}
//设置参数模板面板的高度

126
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<T extends Button> extends ButtonWithHotkeysDetailPane<T> {
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<WidgetAdvancedPaneProvider<T>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<T> provider : providers) {
if (!provider.accept(cls)) {
continue;
}
insertShortCut(provider.getInsertPosition(extraPaneList.size()), provider.createExtraAdvancedPane());
containsExtraPane = true;
}
if (containsExtraPane) {
extraPane = FRGUIPaneFactory.createYBoxEmptyBorderPane();
for (BasicBeanPane<T> 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<T> 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<T> pane : extraPaneList) {
pane.populateBean(button);
}
}
@Override
public T update() {
T button = super.update();
for (BasicBeanPane<T> 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);
}
}

16
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<FormSubmitButton> {
public class FormSubmitButtonDetailPane extends AbstractExtraButtonPane<FormSubmitButton> {
@Override
protected Component createCenterPane() {
return null;
return createExtraPane(null);
}
@Override
@ -37,4 +36,5 @@ public class FormSubmitButtonDetailPane extends ButtonWithHotkeysDetailPane<Form
public Class classType() {
return FormSubmitButton.class;
}
}

3
designer-form/src/main/java/com/fr/design/widget/ui/designer/ButtonDefinePane.java

@ -35,6 +35,7 @@ public abstract class ButtonDefinePane<T extends Button> extends AbstractDataMod
protected UITextField labelNameTextField;
private final List<BasicBeanPane<T>> extraPaneList = new ArrayList<>();
private JPanel extraPane;
protected boolean containsExtraPane;
public ButtonDefinePane(XCreator creator){
super(creator);
@ -63,7 +64,7 @@ public abstract class ButtonDefinePane<T extends Button> extends AbstractDataMod
private void refreshAdvancedPane() {
extraPaneList.clear();
boolean containsExtraPane = false;
containsExtraPane = false;
Set<WidgetAdvancedPaneProvider<T>> providers = ExtraDesignClassManager.getInstance().getArray(WidgetAdvancedPaneProvider.XML_TAG);
for (WidgetAdvancedPaneProvider<T> provider : providers) {
if (!provider.accept(creator)) {

19
designer-form/src/main/java/com/fr/design/widget/ui/designer/FreeButtonDefinePane.java

@ -41,10 +41,13 @@ public class FreeButtonDefinePane extends ButtonDefinePane<FreeButton> {
}
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<FreeButton> {
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;
}

2
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));
}

11
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() {

1
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;

87
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<MobileScanCod
private final UICheckBox scanCodeCheckBox;
private final UICheckBox nfcInputCheckBox;
/**
* NFC内容类型面板
*/
private final NfcContentTypePane nfcContentTypePane = new NfcContentTypePane();
public MobileTextFieldInputSettingPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
JPanel settingPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 5);
manualInputCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Mobile_Manual_Input"), true);
scanCodeCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Mobile_Scan_Code_Input"), true);
nfcInputCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Mobile_NFC_Input"), false);
nfcInputCheckBox.addChangeListener(e -> {
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<MobileScanCod
manualInputCheckBox.setSelected(ob.isSupportManual());
scanCodeCheckBox.setSelected(ob.isSupportScan());
nfcInputCheckBox.setSelected(ob.isSupportNFC());
updateNfcContentTypePane(ob.isSupportNFC(), ob.getNfcContentType());
}
@Override
@ -50,6 +68,18 @@ public class MobileTextFieldInputSettingPane extends BasicBeanPane<MobileScanCod
ob.setSupportManual(manualInputCheckBox.isSelected());
ob.setSupportScan(scanCodeCheckBox.isSelected());
ob.setSupportNFC(nfcInputCheckBox.isSelected());
ob.setNfcContentType(nfcContentTypePane.getSelectedType());
}
/**
* 更新NFC内容类型面板可见选项
*
* @param visible 是否可见
* @param contentType 内容类型
*/
private void updateNfcContentTypePane(boolean visible, MobileScanCodeAttr.NFCContentType contentType) {
nfcContentTypePane.setVisible(visible);
nfcContentTypePane.setSelectedType(contentType);
}
@ -58,4 +88,59 @@ public class MobileTextFieldInputSettingPane extends BasicBeanPane<MobileScanCod
return null;
}
/**
* NFC内容类型面板封装
*/
private class NfcContentTypePane extends JPanel {
/**
* 类型-卡片内容
*/
private UIRadioButton contentTypeButton;
/**
* 类型-UID
*/
private UIRadioButton uidTypeButton;
NfcContentTypePane() {
VerticalFlowLayout layout = new VerticalFlowLayout();
layout.setAlignLeft(true);
this.setLayout(layout);
contentTypeButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Mobile_NFC_Content_Type_Content"));
uidTypeButton = new UIRadioButton(Toolkit.i18nText("Fine-Design_Mobile_NFC_Content_Type_UID"));
contentTypeButton.setSelected(true);
uidTypeButton.setSelected(false);
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(contentTypeButton);
buttonGroup.add(uidTypeButton);
this.add(contentTypeButton);
this.add(uidTypeButton);
}
/**
* 根据NFCContentType设置Button的选中状态
*
* @param contentType
*/
void setSelectedType(MobileScanCodeAttr.NFCContentType contentType) {
contentTypeButton.setSelected(contentType == MobileScanCodeAttr.NFCContentType.CONTENT);
uidTypeButton.setSelected(contentType == MobileScanCodeAttr.NFCContentType.UID);
}
/**
* 获取当前选中Button代表的NFCContentType
*
* @return
*/
MobileScanCodeAttr.NFCContentType getSelectedType() {
return uidTypeButton.isSelected() ?
MobileScanCodeAttr.NFCContentType.UID :
MobileScanCodeAttr.NFCContentType.CONTENT;
}
}
}

14
designer-realize/src/main/java/com/fr/design/actions/replace/ui/ITReplaceWestPanel.java

@ -4,10 +4,10 @@ import com.fr.base.svg.IconUtils;
import com.fr.design.actions.replace.info.Info;
import com.fr.design.gui.ibutton.UIToggleButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.ui.base.MouseClickListener;
import com.fr.design.utils.BrowseUtils;
import com.fr.general.CloudCenter;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
@ -35,7 +35,17 @@ public class ITReplaceWestPanel {
private UIToggleButton contentButton;
private UIToggleButton settingButton;
private static final Icon HELP_ICON = IconUtils.readIcon("com/fr/design/images/buttonicon/replace_help.svg");
private static final String HELP_URL = CloudCenter.getInstance().acquireUrlByKind("design.replace.help", "https://help.fanruan.com/finereport/doc-view-4954.html?source=3");
/**
* 云中心定时调度执行频率表达式设定帮助文档链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design-CloudCenter_Template_Level_Search_Replace";
/**
* 云中心定时调度执行频率表达式设定帮助文档默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design-CloudCenter_Template_Level_Search_Replace_Default";
private static final String HELP_URL = LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT);
private static final int FILL_COUNT = 11;
public static final int LEFT_WIDTH = 100;
public static final String CONTENT_TEXT = "<html><font color = 'rgb(255,255,255)'>" + Toolkit.i18nText("Fine-Design_Basic_Templates_Content") + "</font></html>";

6
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<String> 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(),

37
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

14
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;
// 密码支持公式

8
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<LayerReportAttr> {
@Override
public void mouseClicked(MouseEvent e) {
try {
Desktop.getDesktop().browse(new URI(SiteCenter.getInstance().acquireUrlByKind("standard.doc", ProductConstants.WEBSITE_URL)));
LocaleMark<String> 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);
}

20
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());

22
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<T extends AppendRowButton> extends ButtonWithHotkeysDetailPane<AppendRowButton> {
public class AppendRowButtonDefinePane<T extends AppendRowButton> extends AbstractExtraButtonPane<AppendRowButton> {
private DefineAppendColumnRowPane defineColumnRowPane;
// @Override
@ -26,7 +30,8 @@ public class AppendRowButtonDefinePane<T extends AppendRowButton> extends Button
@Override
protected Component createCenterPane() {
return defineColumnRowPane = new DefineAppendColumnRowPane();
defineColumnRowPane = new DefineAppendColumnRowPane();
return createExtraPane(defineColumnRowPane);
}
@Override
@ -55,4 +60,5 @@ public class AppendRowButtonDefinePane<T extends AppendRowButton> extends Button
public Class classType() {
return AppendRowButton.class;
}
}

16
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<Button> {
public class DefaultButtonDetailPane extends AbstractExtraButtonPane<Button> {
@Override
protected Component createCenterPane() {
return null;
return createExtraPane(null);
}
@Override
@ -27,4 +32,5 @@ public class DefaultButtonDetailPane extends ButtonWithHotkeysDetailPane<Button>
public Class classType() {
return Button.class;
}
}

17
designer-realize/src/main/java/com/fr/design/widget/ui/btn/DeleteRowButtonDefinePane.java

@ -3,23 +3,23 @@ package com.fr.design.widget.ui.btn;
import com.fr.base.IconManager;
import com.fr.report.web.button.write.DeleteRowButton;
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:04
* 删除行按钮
*
* @author John.Ying
* @since 11.0
* Created on 2023/4/19
*/
public class DeleteRowButtonDefinePane<T extends DeleteRowButton> extends ButtonWithHotkeysDetailPane<DeleteRowButton> {
public class DeleteRowButtonDefinePane<T extends DeleteRowButton> extends AbstractExtraButtonPane<DeleteRowButton> {
private DefineDeleteColumnRowPane ddcp;
@Override
protected Component createCenterPane() {
return ddcp = new DefineDeleteColumnRowPane();
ddcp = new DefineDeleteColumnRowPane();
return createExtraPane(ddcp);
}
@Override
@ -48,4 +48,5 @@ public class DeleteRowButtonDefinePane<T extends DeleteRowButton> extends Button
ddcp.update(btn);
return btn;
}
}

15
designer-realize/src/main/java/com/fr/design/widget/ui/btn/FreeButtonDetailPane.java

@ -1,17 +1,23 @@
package com.fr.design.widget.ui.btn;
import java.awt.Component;
import com.fr.form.ui.FreeButton;
import com.fr.design.widget.btn.ButtonWithHotkeysDetailPane;
import com.fr.form.ui.FreeButton;
public class FreeButtonDetailPane extends ButtonWithHotkeysDetailPane<FreeButton> {
/**
* 自定义按钮
*
* @author John.Ying
* @since 11.0
* Created on 2023/4/19
*/
public class FreeButtonDetailPane extends AbstractExtraButtonPane<FreeButton> {
private ButtonSytleDefinedPane buttonSytleDefinedPane;
@Override
protected Component createCenterPane() {
buttonSytleDefinedPane = new ButtonSytleDefinedPane();
return buttonSytleDefinedPane;
return createExtraPane(buttonSytleDefinedPane);
}
@Override
@ -35,4 +41,5 @@ public class FreeButtonDetailPane extends ButtonWithHotkeysDetailPane<FreeButton
public Class classType() {
return FreeButton.class;
}
}

21
designer-realize/src/main/java/com/fr/design/widget/ui/btn/TreeNodeToogleButtonDefinePane.java

@ -9,19 +9,18 @@ import com.fr.design.layout.TableLayoutHelper;
import com.fr.form.ui.Button;
import com.fr.report.web.button.form.TreeNodeToggleButton;
import com.fr.design.widget.btn.ButtonDetailPane;
import javax.swing.*;
import java.awt.*;
/**
* Created by IntelliJ IDEA.
* Author : Richer
* Version: 6.5.6
* Date : 11-11-15
* Time : 下午7:45
* 树节点按钮
*
* @author John.Ying
* @since 11.0
* Created on 2023/4/19
*/
public class TreeNodeToogleButtonDefinePane<T extends TreeNodeToggleButton> extends ButtonDetailPane<Button> {
public class TreeNodeToogleButtonDefinePane<T extends TreeNodeToggleButton> extends AbstractExtraButtonPane<Button> {
public TreeNodeToogleButtonDefinePane() {
initComponents();
@ -33,8 +32,9 @@ public class TreeNodeToogleButtonDefinePane<T extends TreeNodeToggleButton> exte
double p = TableLayout.PREFERRED;
double rowSize[] = {p};
double columnSize[] = {p, f};
initExtraPane();
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()},
};
JPanel panel = TableLayoutHelper.createGapTableLayoutPane(n_components, rowSize, columnSize, IntervalConstants.INTERVAL_L2, 8);
JPanel borderPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
@ -45,6 +45,11 @@ public class TreeNodeToogleButtonDefinePane<T extends TreeNodeToggleButton> exte
}
@Override
protected Component createCenterPane() {
return null;
}
@Override
public TreeNodeToggleButton update() {
return createButton();

1
designer-realize/src/main/java/com/fr/design/widget/ui/mobile/ScanCodeMobilePane.java

@ -8,6 +8,7 @@ import com.fr.design.widget.mobile.WidgetMobilePane;
import com.fr.design.widget.ui.designer.mobile.component.MobileTextFieldInputSettingPane;
import com.fr.form.ui.TextEditor;
import com.fr.form.ui.Widget;
import java.awt.BorderLayout;

24
designer-realize/src/main/java/com/fr/grid/GridKeyAction.java

@ -69,28 +69,26 @@ public class GridKeyAction extends AbstractAction {
} else if ("right".equals(actionKey)) {
selectionMove(ReportConstants.MOVE_DIRECTION_RIGHT);
} else if ("up".equals(actionKey)) {
selectionMove(ReportConstants.MOVE_DIRECTION_UP);
directKeyPressed(ReportConstants.MOVE_DIRECTION_UP);
} else if ("down".equals(actionKey)) {
selectionMove(ReportConstants.MOVE_DIRECTION_DOWN);
directKeyPressed(ReportConstants.MOVE_DIRECTION_DOWN);
} else if ("enter".equals(actionKey)) {
enterKeyPressed();
directKeyPressed(ReportConstants.MOVE_DIRECTION_DOWN);
} else if ("tab".equals(actionKey)) {
tabKeyPressed();
directKeyPressed(ReportConstants.MOVE_DIRECTION_RIGHT);
}
}
private void enterKeyPressed() {
if (grid.isCellEditing()) {
grid.stopEditing();
}
selectionMove(ReportConstants.MOVE_DIRECTION_DOWN);
}
private void tabKeyPressed() {
/**
* 传入方向进行单元格的方向移动
*
* @param direction 方向
*/
private void directKeyPressed(int direction) {
if (grid.isCellEditing()) {
grid.stopEditing();
}
selectionMove(ReportConstants.MOVE_DIRECTION_RIGHT);
selectionMove(direction);
}
/**

Loading…
Cancel
Save