Browse Source

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

* commit '75c997eb4d01e7269156386ff83e7a3a1b1fcdff': (41 commits)
  REPORT-77217 ConnectionProvider-修改之后数据连接信息无法保存 【问题原因】产生假保存的原因是,在保存的时候会判断现有的Connection与以前存储的Connection是否有不同,如果不同就代表需要更新。实际上插件中的Connection相关类没有写equals方法,然后新旧Connection被认为是相同了,就没有走后面的更新配置的逻辑 【改动方案】拉rinoux、vito、hugh一起沟通了下方案,暂时主代码里做个兼容,让主代码内置的两种Connection去判断是否要更新,其余的Connection(插件Connection)都必须更新 【review建议】
  REPORT-75991 插件完整性校验,弹窗链接帮助文档说明 【问题原因】安全类需求,将原来仅对官方插件开启的 插件完整性校验,扩大到了 第三方插件。但弹窗不明确,对于用户侧没有闭环,需要添加帮助文档链接,帮助用户清楚前因后果与解决方案。 【改动方案】1.提示文案内容修改;2.提示中存在超链接,将插件这边因为"插件完整性校验"而失败的弹窗单独处理了下,由原本的JOptionPane修改为JEditorPane 【review建议】其它的弹窗暂时没有变动的需求,跟产品沟通过了,如果以后有必要统一的时候再来统一处理
  REPORT-76635 数据集参数默认值为空的情况下,组合图条件属性内容错乱
  REPORT-76370 提供一个数据连接前置检查接口&写错了应该是远程调用
  REPORT-76370 提供一个数据连接前置检查接口&设计器数据连接保存
  fix
  REPORT-74340 设计器菜单栏-登录,密码输错超过100次,没有错误提示
  REPORT-76259 【迭代】【数据连接面板为空】概率出现编辑数据集一直加载中 根据评审意见修改下,不特地分出两个方法了
  REPORT-76259 【迭代】【数据连接面板为空】概率出现编辑数据集一直加载中 【问题原因】远程设计下,数据集面板的初始化中有两个耗时操作(下拉框取数据连接、TableViewList根据下拉框值取连接对应的所有表),对应两个SwingWorker,设为A和B;数据集面板本身的展示过程也对应一个SwingWorker(需要查询此连接是否有权限),设为C;当C执行完后,会在done方法里调用数据集面板的setVisible方法以让它展示,如果此时A和B才执行完doInbackground,准备执行done的时候(done的执行是invokeLater的),C的面板先显示了,会导致它们的done方法会被已经显示的模态dialog给阻塞住,从而无法完成面板数据更新 【改动思路】将setVisible方法用invokeLater包一层,让A和B的done方法不被阻塞 【review建议】无
  REPORT-75752 兼容下旧插件
  REPORT-75752 表格辅助线的功能从frm扩展到dashboard
  REPORT-76403 【迭代】更新日志-更新内容为空,报错Unparseable date: "null" 1、兼容下更新日志的缓存 2、昨天提交到feature的,没合的,提交到release
  REPORT-75575 design feat:fvs支持服务器全局参数
  REPORT-76403【迭代】更新日志-更新内容为空,报错Unparseable date: "null" 1、处理下异常
  REPORT-76403【迭代】更新日志-更新内容为空,报错Unparseable date: "null" 1、规范下代码
  REPORT-76403【迭代】更新日志-更新内容为空,报错Unparseable date: "null" 1、兼容下本地缓存更新日志的逻辑
  REPORT-72828 启动页配置项屏蔽
  REPORT-76291 【迭代】【数据连接为空】次管查看无权限的数据集,没有提示 【问题原因】获取数据连接名称的方式错了,误写成了获取数据集名称,因此判断成了有权限 【改动思路】改用正确方式获取数据连接的名称 【review建议】无
  REPORT-75919 【迭代】更新日志-交互问题 1、修改交互
  REPORT-76174 【迭代】【数据连接面板为空】数据表搜索框-交互问题 【问题原因】1. 开发的时候没做这个TextField鼠标悬浮变色的功能;2. 部分代码质量问题 【改动思路】1. 加上悬浮变色边框的逻辑;2. 代码质量问题修改 【review建议】无
  ...
fix-lag
superman 2 years ago
parent
commit
498cf0ece8
  1. 24
      designer-base/src/main/java/com/fr/base/function/UITerminator.java
  2. 45
      designer-base/src/main/java/com/fr/design/DesignerEnvManager.java
  3. 27
      designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java
  4. 4
      designer-base/src/main/java/com/fr/design/actions/file/PreferenceAction.java
  5. 114
      designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java
  6. 148
      designer-base/src/main/java/com/fr/design/components/loading/LoadingPane.java
  7. 107
      designer-base/src/main/java/com/fr/design/components/tooltip/ModernToolTip.java
  8. 5
      designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java
  9. 42
      designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java
  10. 15
      designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java
  11. 52
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  12. 57
      designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java
  13. 38
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java
  14. 48
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java
  15. 113
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java
  16. 16
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java
  17. 54
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java
  18. 23
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/SwitchableTableDataPane.java
  19. 54
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TableDataLoadingPane.java
  20. 45
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TipsPane.java
  21. 3
      designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java
  22. 3
      designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java
  23. 3
      designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java
  24. 3
      designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java
  25. 70
      designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginCallBackHelper.java
  26. 86
      designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginTaskResultErrorDialog.java
  27. 2
      designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java
  28. 2
      designer-base/src/main/java/com/fr/design/gui/ibutton/UITabGroup.java
  29. 19
      designer-base/src/main/java/com/fr/design/gui/ilable/ActionLabel.java
  30. 3
      designer-base/src/main/java/com/fr/design/gui/itooltip/UIToolTip.java
  31. 7
      designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/TreeAttrChangeListener.java
  32. 50
      designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/TreeRootPane.java
  33. 47
      designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java
  34. 33
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java
  35. 23
      designer-base/src/main/java/com/fr/design/mainframe/DesignerUIModeConfig.java
  36. 6
      designer-base/src/main/java/com/fr/design/mainframe/JDashboard.java
  37. 108
      designer-base/src/main/java/com/fr/design/mainframe/TransparentPane.java
  38. 5
      designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java
  39. 11
      designer-base/src/main/java/com/fr/design/notification/NotificationCenter.java
  40. 143
      designer-base/src/main/java/com/fr/design/plugin/remind/PluginErrorDesignReminder.java
  41. 211
      designer-base/src/main/java/com/fr/design/plugin/remind/PluginInvalidateRemindDialog.java
  42. 6
      designer-base/src/main/java/com/fr/design/plugin/remind/PluginStartFailedRemindDialog.java
  43. 34
      designer-base/src/main/java/com/fr/design/update/actions/NewFeatureAction.java
  44. 201
      designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java
  45. 6
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTable.java
  46. 6
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableCellRender.java
  47. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTextAreaCellRender.java
  48. 11
      designer-base/src/main/java/com/fr/design/utils/ColorUtils.java
  49. 29
      designer-base/src/main/java/com/fr/design/utils/DesignUtils.java
  50. 87
      designer-base/src/main/java/com/fr/design/widget/component/ReturnTypePane.java
  51. 79
      designer-base/src/main/java/com/fr/start/BaseDesigner.java
  52. 77
      designer-base/src/main/java/com/fr/start/common/DesignerOpenEmptyPanel.java
  53. 55
      designer-base/src/main/java/com/fr/start/common/DesignerStartupConfig.java
  54. 176
      designer-base/src/main/java/com/fr/start/common/DesignerStartupContext.java
  55. 32
      designer-base/src/main/java/com/fr/start/common/DesignerStartupExecutor.java
  56. 20
      designer-base/src/main/java/com/fr/start/common/DesignerStartupPool.java
  57. 51
      designer-base/src/main/java/com/fr/start/common/DesignerStartupUtil.java
  58. 0
      designer-base/src/main/java/com/fr/start/module/StartupArgs.java
  59. 17
      designer-base/src/main/java/com/fr/startup/ui/StartupPageConstants.java
  60. 111
      designer-base/src/main/java/com/fr/startup/ui/StartupPageModel.java
  61. 40
      designer-base/src/main/java/com/fr/startup/ui/StartupPageUtil.java
  62. 339
      designer-base/src/main/java/com/fr/startup/ui/StartupPageWindow.java
  63. 501
      designer-base/src/main/java/com/fr/startup/ui/StartupPageWorkspacePanel.java
  64. 49
      designer-base/src/main/java/com/fr/startup/ui/StartupWorkspaceBean.java
  65. 2
      designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties
  66. 2
      designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties
  67. 2
      designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties
  68. 3
      designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties
  69. 2
      designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties
  70. 1
      designer-base/src/main/resources/com/fr/design/login/lib/locale/login_en_US.js
  71. 1
      designer-base/src/main/resources/com/fr/design/login/lib/locale/login_ja_JP.js
  72. 1
      designer-base/src/main/resources/com/fr/design/login/lib/locale/login_ko_KR.js
  73. 1
      designer-base/src/main/resources/com/fr/design/login/lib/locale/login_zh_CN.js
  74. 1
      designer-base/src/main/resources/com/fr/design/login/lib/locale/login_zh_TW.js
  75. 2
      designer-base/src/main/resources/com/fr/design/login/login.js
  76. 3
      designer-base/src/main/resources/com/fr/design/standard/system/add.svg
  77. 3
      designer-base/src/main/resources/com/fr/design/standard/system/add_hover.svg
  78. 32
      designer-base/src/main/resources/com/fr/design/standard/system/cpt.svg
  79. 14
      designer-base/src/main/resources/com/fr/design/standard/system/error_tips.svg
  80. 4
      designer-base/src/main/resources/com/fr/design/standard/system/home_folder.svg
  81. 6
      designer-base/src/main/resources/com/fr/design/standard/system/remote_connect.svg
  82. 18
      designer-base/src/main/resources/com/fr/design/startup/create_new_template.svg
  83. 11
      designer-base/src/main/resources/com/fr/design/startup/local_server_background_28.svg
  84. 11
      designer-base/src/main/resources/com/fr/design/startup/local_server_background_36.svg
  85. 3
      designer-base/src/main/resources/com/fr/design/startup/more.svg
  86. 3
      designer-base/src/main/resources/com/fr/design/startup/more_hover.svg
  87. 12
      designer-base/src/main/resources/com/fr/design/startup/remote_server_background_28.svg
  88. 18
      designer-base/src/main/resources/com/fr/design/startup/remote_server_background_36.svg
  89. 3
      designer-base/src/main/resources/com/fr/design/startup/show_less.svg
  90. 3
      designer-base/src/main/resources/com/fr/design/startup/show_more.svg
  91. 33
      designer-base/src/test/java/com/fr/design/EnvChangeEntranceTest.java
  92. 72
      designer-base/src/test/java/com/fr/design/plugin/remind/PluginErrorDesignReminderTest.java
  93. 2
      designer-base/src/test/java/com/fr/design/utils/DevDebugUtils.java
  94. 6
      designer-base/src/test/java/com/fr/design/utils/DevUtils.java
  95. 32
      designer-base/src/test/java/com/fr/startup/ui/StartupPageWindowTest.java
  96. 27
      designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ColSelectedWithSummaryMethodEditor.java
  97. 5
      designer-chart/src/main/java/com/fr/van/chart/custom/other/VanChartCustomPlotConditionAttrTabPane.java
  98. 20
      designer-form/src/main/java/com/fr/design/fit/common/NewUIModeAutoChangeLine.java
  99. 69
      designer-form/src/main/java/com/fr/design/fit/common/NewUIModeRotationDraw.java
  100. 29
      designer-form/src/main/java/com/fr/design/mainframe/JForm.java
  101. Some files were not shown because too many files have changed in this diff Show More

24
designer-base/src/main/java/com/fr/base/function/UITerminator.java

@ -0,0 +1,24 @@
package com.fr.base.function;
import com.fr.design.utils.DesignUtils;
import com.fr.runtime.FineRuntime;
/**
* UI 终止动作
*
* created by Harrison on 2022/07/14
**/
public abstract class UITerminator {
public void run() {
// 先执行必须的逻辑
FineRuntime.start();
DesignUtils.initLookAndFeel();
// 在执行核心逻辑
doRun();
}
protected abstract void doRun();
}

45
designer-base/src/main/java/com/fr/design/DesignerEnvManager.java

@ -55,6 +55,7 @@ import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLTools;
import com.fr.stable.xml.XMLWriter;
import com.fr.stable.xml.XMLableReader;
import com.fr.start.common.DesignerStartupConfig;
import com.fr.third.apache.logging.log4j.core.appender.FileAppender;
import com.fr.third.apache.logging.log4j.core.layout.PatternLayout;
import com.fr.third.org.apache.commons.io.FilenameUtils;
@ -189,6 +190,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private VcsConfigManager vcsConfigManager = VcsConfigManager.getInstance();
private DesignerStartupConfig designerStartupConfig = DesignerStartupConfig.getInstance();
public static final String CAS_CERTIFICATE_PATH = "certificatePath";
public static final String CAS_CERTIFICATE_PASSWORD = "certificatePass";
@ -1001,6 +1004,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.language = locale;
}
public boolean isStartupPageEnabled() {
return this.designerStartupConfig.isEnabled();
}
public void setStartupPageEnabled(boolean enabled) {
this.designerStartupConfig.setEnabled(enabled);
}
/**
* 返回环境名称迭代器
*/
@ -1120,22 +1131,25 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.CurrentDirectoryPrefix = prefix;
}
public List<String> getRecentOpenedFilePathList4Env(String envName) {
/**
* 返回最近打开的文件路径列表
*/
public List<String> getRecentOpenedFilePathList() {
if (StringUtils.isEmpty(getCurEnvName())) {
if (StringUtils.isEmpty(envName)) {
return tempRecentOpenedFilePathList;
} else {
if (!recentOpenedFileListMap.containsKey(getCurEnvName())) {
recentOpenedFileListMap.put(getCurEnvName(), tempRecentOpenedFilePathList);
if (!recentOpenedFileListMap.containsKey(envName)) {
recentOpenedFileListMap.put(envName, tempRecentOpenedFilePathList);
}
}
return recentOpenedFileListMap.get(envName);
}
return recentOpenedFileListMap.get(getCurEnvName());
/**
* 返回最近打开的文件路径列表
*/
public List<String> getRecentOpenedFilePathList() {
return this.getRecentOpenedFilePathList4Env(getCurEnvName());
}
/**
@ -1829,6 +1843,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
readHttpsParas(reader);
} else if (name.equals(EnvDetectorConfig.XML_TAG)) {
readEnvDetectorConfig(reader);
} else if (name.equals(DesignerStartupConfig.XML_TAG)) {
readStartupConfig(reader);
} else if (name.equals("AlphaFineConfigManager")) {
readAlphaFineAttr(reader);
} else if (name.equals("RecentColors")) {
@ -1870,6 +1886,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
reader.readXMLObject(this.envDetectorConfig);
}
private void readStartupConfig(XMLableReader reader) {
reader.readXMLObject(this.designerStartupConfig);
}
private void readHttpsParas(XMLableReader reader) {
String tempVal;
if ((tempVal = reader.getAttrAsString(CAS_CERTIFICATE_PATH, null)) != null) {
@ -2084,6 +2104,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
writeHttpsParas(writer);
writeAlphaFineAttr(writer);
writeEnvDetectorConfig(writer);
writeStartupConfig(writer);
writeRecentColor(writer);
writeOpenDebug(writer);
writeDesignerPushUpdateAttr(writer);
@ -2134,6 +2155,12 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
}
}
private void writeStartupConfig(XMLPrintWriter writer) {
if (this.designerStartupConfig != null) {
this.designerStartupConfig.writeXML(writer);
}
}
//写入uuid
private void writeUUID(XMLPrintWriter writer) {
writer.startTAG("uuid");

27
designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java

@ -1,7 +1,7 @@
package com.fr.design;
import com.fr.common.report.ReportState;
import com.fr.decision.webservice.v10.plugin.helper.PluginErrorRemindHandler;
import com.fr.design.plugin.remind.PluginErrorDesignReminder;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
@ -35,7 +35,6 @@ import com.fr.process.engine.core.FineProcessContext;
import com.fr.rpc.Result;
import com.fr.stable.AssistUtils;
import com.fr.stable.StringUtils;
import com.fr.env.PluginErrorRemindDialog;
import com.fr.start.server.ServerTray;
import com.fr.workspace.WorkContext;
import com.fr.workspace.WorkContextCallback;
@ -139,7 +138,7 @@ public class EnvChangeEntrance {
if (template != null) {
template.refreshToolArea();
}
pluginErrorRemind();
PluginErrorDesignReminder.getInstance().remindStartFailedPlugins();
} catch (Exception exception) {
// 失败的处理
WorkspaceExceptionHandler.getInstance().handleInSwitch(exception, selectedEnv);
@ -245,28 +244,6 @@ public class EnvChangeEntrance {
}
}
/**
* 插件启动错误信息提示
*/
public void pluginErrorRemind() {
if (!WorkContext.getCurrent().isLocal()) {
return;
}
String content = PluginErrorRemindHandler.pluginErrorContent();
if (StringUtils.isNotEmpty(content)) {
// 该操作需要在当前awt操作之后执行,使用SwingUtilities.invokeLater将其置于awt操作对列末尾
// 若使用UIUtil.invokeLaterIfNeeded,会立即执行,影响其他UI操作
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
PluginErrorRemindDialog dialog = new PluginErrorRemindDialog(DesignerContext.getDesignerFrame(), content);
dialog.setVisible(true);
}
});
}
}
/**
* 判断是否需要做版本验证判断依据为
* 1选择的环境为远程环境

4
designer-base/src/main/java/com/fr/design/actions/file/PreferenceAction.java

@ -40,7 +40,9 @@ public class PreferenceAction extends UpdateAction {
DesignerEnvManager.loadLogSetting();
DesignerEnvManager.getEnvManager().saveXMLFile();
JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
jt.refreshToolArea();
if (jt != null) {
jt.refreshToolArea();
}
preferencePane.showRestartDialog();
DesignerFrameFileDealerPane.getInstance().refreshDockingView();
}

114
designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java

@ -14,9 +14,11 @@ import com.fr.design.gui.frpane.UITabbedPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UIColorButton;
import com.fr.design.gui.ibutton.UINoThemeColorButton;
import com.fr.design.gui.ibutton.UIRadioButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icombobox.UIDictionaryComboBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ifilechooser.FileChooserArgs;
import com.fr.design.gui.ifilechooser.FileChooserFactory;
import com.fr.design.gui.ifilechooser.FileChooserProvider;
@ -26,6 +28,7 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.iprogressbar.UIProgressBarUI;
import com.fr.design.gui.ispinner.UISpinner;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.jdk.JdkVersion;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
@ -42,8 +45,10 @@ import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.general.Inter;
import com.fr.general.log.Log4jConfig;
import com.fr.io.attr.ImageExportAttr;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.report.ReportConfigManager;
import com.fr.stable.Constants;
import com.fr.stable.os.OperatingSystem;
import com.fr.third.apache.logging.log4j.Level;
@ -52,19 +57,24 @@ import com.fr.transaction.Worker;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.vcs.VcsOperator;
import com.fr.workspace.server.vcs.git.config.GcConfig;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.BorderLayout;
@ -177,6 +187,7 @@ public class PreferencePane extends BasicPane {
private UICheckBox vcsEnableCheckBox;
private UICheckBox saveCommitCheckBox;
private UICheckBox useIntervalCheckBox;
private UICheckBox startupPageEnabledCheckBox;
private IntegerEditor saveIntervalEditor;
private UICheckBox gcEnableCheckBox;
private UIButton gcButton;
@ -190,6 +201,14 @@ public class PreferencePane extends BasicPane {
private Timer gcProgressTimer;
private UIButton gcOkButton = new UIButton(i18nText("Fine-Design_Report_OK"));
private UIRadioButton previewResolutionBtnS;
private UIRadioButton previewResolutionBtnM;
private UIRadioButton previewRenderSpeed;
private UIRadioButton previewRenderQuality;
private static final int DPI_SCALE_S = 1;
private static final int DPI_SCALE_M = 2;
public PreferencePane() {
this.initComponents();
}
@ -201,9 +220,13 @@ public class PreferencePane extends BasicPane {
UITabbedPane jtabPane = new UITabbedPane();
JPanel generalPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
jtabPane.addTab(i18nText("Fine-Design_Basic_General"), generalPane);
UIScrollPane generalScrollPane = patchScroll(generalPane);
jtabPane.addTab(i18nText("Fine-Design_Basic_General"), generalScrollPane);
JPanel advancePane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
jtabPane.addTab(i18nText("Fine-Design_Basic_Advanced"), advancePane);
UIScrollPane adviceScrollPane = patchScroll(advancePane);
jtabPane.addTab(i18nText("Fine-Design_Basic_Advanced"), adviceScrollPane);
contentPane.add(jtabPane, BorderLayout.NORTH);
createFunctionPane(generalPane);
@ -219,6 +242,8 @@ public class PreferencePane extends BasicPane {
createLanPane(generalPane);
// 先屏蔽下
// createStartupPagePane(generalPane);
createLengthPane(advancePane);
createServerPane(advancePane);
@ -274,6 +299,7 @@ public class PreferencePane extends BasicPane {
JPanel imageCompressPanel = FRGUIPaneFactory.createVerticalTitledBorderPane(i18nText("Fine-Design_Template_Preview_Performance"));
imageCompressPanelCheckBox = new UICheckBox(i18nText("Fine-Design_Image_Compress"));
imageCompressPanel.add(imageCompressPanelCheckBox);
imageCompressPanel.add(createImageExportSettingPane());
advancePane.add(imageCompressPanel);
JPanel designerStartupOption = FRGUIPaneFactory.createTitledBorderPane(i18nText("Fine-Design_Startup_Option"));
@ -282,6 +308,42 @@ public class PreferencePane extends BasicPane {
advancePane.add(designerStartupOption);
}
private JPanel createImageExportSettingPane() {
previewResolutionBtnS = new UIRadioButton(i18nText("Fine-Design_Image_Export_SD"), true);
previewResolutionBtnM = new UIRadioButton(i18nText("Fine-Design_Image_Export_HD"));
ButtonGroup previewResolutionBtnGroup = new ButtonGroup();
previewResolutionBtnGroup.add(previewResolutionBtnS);
previewResolutionBtnGroup.add(previewResolutionBtnM);
previewRenderSpeed = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Speed_Priority"));
previewRenderQuality = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Quality_First"));
ButtonGroup previewRenderGroup = new ButtonGroup();
previewRenderGroup.add(previewRenderQuality);
previewRenderGroup.add(previewRenderSpeed);
JPanel imageExportSettingPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
JComponent[][] templateComps = {
{new UILabel(Toolkit.i18nText("Fine-Design_Report_Engine_Enlarge_Or_Reduce") + ":"), this.previewResolutionBtnS, this.previewResolutionBtnM},
{new UILabel(Toolkit.i18nText("Fine-Design_Image_Export_Rendering_Quality") + ":"), this.previewRenderQuality, this.previewRenderSpeed},
};
imageExportSettingPane.add(
TableLayoutHelper.createGapTableLayoutPane(
templateComps,
new double[]{TableLayout.FILL, TableLayout.FILL},
new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL},
20, 0),
BorderLayout.CENTER);
imageExportSettingPane.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
return imageExportSettingPane;
}
@NotNull
private UIScrollPane patchScroll(JPanel generalPane) {
UIScrollPane generalPanelWithScroll = new UIScrollPane(generalPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
generalPanelWithScroll.setBorder(new EmptyBorder(0, 0, 0, 0));
generalPanelWithScroll.setPreferredSize(new Dimension(generalPane.getWidth(), 600));
return generalPanelWithScroll;
}
private void createVcsSettingPane(JPanel generalPane) {
JPanel vcsPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(i18nText("Fine-Design_Vcs_Title"));
generalPane.add(vcsPane);
@ -589,6 +651,21 @@ public class PreferencePane extends BasicPane {
return languageComboBox;
}
private void createStartupPagePane(JPanel generalPane) {
// ben:选择版本语言;
JPanel startupPagePaneWrapper = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane();
JPanel startupPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane("启动页配置");
generalPane.add(startupPagePaneWrapper);
startupPagePaneWrapper.add(startupPane);
startupPageEnabledCheckBox = new UICheckBox("启动设计器时,自动打开启动页");
startupPane.add(startupPageEnabledCheckBox);
UILabel descLabel = new UILabel("注意:若在远程环境下直接关闭,再次启动时,启动速度会变慢");
descLabel.setForeground(new Color(51, 51, 52, (int)Math.round(0.5 * 255)));
startupPane.add(descLabel);
}
private String getDisplayShortCut(String shotrCut) {
return shotrCut.replace(TYPE, DISPLAY_TYPE).replace(BACK_SLASH, DISPLAY_BACK_SLASH).replace(SLASH, DISPLAY_SLASH)
.replace(CONTROL, DISPLAY_CONTROL).replace(OPEN_BRACKET, DISPLAY_OPEN_BRACKET).replace(CLOSE_BRACKET, DISPLAY_CLOSE_BRACKET)
@ -757,7 +834,27 @@ public class PreferencePane extends BasicPane {
this.startWithEmptyFile.setSelected(designerEnvManager.isStartWithEmptyFile());
this.imageCompressPanelCheckBox.setSelected(designerEnvManager.isImageCompress());
ImageExportAttr attr = ReportConfigManager.getProviderInstance().getImageExportAttr();
if (attr.getPreviewRenderQuality() == ImageExportAttr.RENDER_SPEED) {
previewRenderSpeed.setSelected(true);
} else {
previewRenderQuality.setSelected(true);
}
if (attr.getPreviewResolutionScale() == DPI_SCALE_S) {
previewResolutionBtnS.setSelected(true);
} else {
previewResolutionBtnM.setSelected(true);
}
boolean enabled = WorkContext.getCurrent().isLocal() || WorkContext.getCurrent().isRoot();
previewRenderSpeed.setEnabled(enabled);
previewRenderQuality.setEnabled(enabled);
previewResolutionBtnS.setEnabled(enabled);
previewResolutionBtnM.setEnabled(enabled);
this.cloudAnalyticsDelayCheckBox.setSelected(designerEnvManager.isCloudAnalyticsDelay());
// this.startupPageEnabledCheckBox.setSelected(designerEnvManager.isStartupPageEnabled());
}
private int chooseCase(int sign) {
@ -824,6 +921,7 @@ public class PreferencePane extends BasicPane {
vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected());
vcsConfigManager.setSaveCommit(this.saveCommitCheckBox.isSelected());
vcsConfigManager.setUseInterval(this.useIntervalCheckBox.isSelected());
// designerEnvManager.setStartupPageEnabled(this.startupPageEnabledCheckBox.isSelected());
Configurations.update(new Worker() {
@Override
public void run() {
@ -883,6 +981,18 @@ public class PreferencePane extends BasicPane {
}
});
ImageExportAttr attr = ReportConfigManager.getProviderInstance().getImageExportAttr();
if (previewRenderSpeed.isSelected()) {
attr.setPreviewRenderQuality(ImageExportAttr.RENDER_SPEED);
} else {
attr.setPreviewRenderQuality(ImageExportAttr.RENDER_QUALITY);
}
if (previewResolutionBtnS.isSelected()) {
attr.setPreviewResolutionScale(DPI_SCALE_S);
} else {
attr.setPreviewResolutionScale(DPI_SCALE_M);
}
}
// 如果语言设置改变了,则显示重启对话框

148
designer-base/src/main/java/com/fr/design/components/loading/LoadingPane.java

@ -0,0 +1,148 @@
package com.fr.design.components.loading;
import javax.swing.JComponent;
import javax.swing.Timer;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/4/12
*/
public class LoadingPane extends JComponent implements ActionListener {
private AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
private volatile boolean mIsRunning;
private volatile boolean mIsFadingOut;
private Timer mTimer;
private int mAngle;
private int mFadeCount;
private int mFadeLimit = 15;
private int lines = 12;
private int maxAngle = 360;
private int angleAdd = 30;
public LoadingPane() {
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// do nothing
}
});
setLayout(getCoverLayout());
setBackground(null);
setOpaque(false);
}
protected LayoutManager getCoverLayout() {
return new LayoutManager() {
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return parent.getPreferredSize();
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return null;
}
@Override
public void layoutContainer(Container parent) {
}
@Override
public void addLayoutComponent(String name, Component comp) {
}
};
}
@Override
public void paint(Graphics g) {
int w = this.getWidth();
int h = this.getHeight();
super.paint(g);
if (!mIsRunning) {
return;
}
Graphics2D g2 = (Graphics2D) g.create();
float fade = (float) mFadeCount / (float) mFadeLimit;
Composite urComposite = g2.getComposite();
g2.setComposite(composite);
g2.fillRect(0, 0, w, h);
g2.setComposite(urComposite);
int s = Math.min(w, h) / 50;
int cx = w / 2;
int cy = h / 2;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(s / 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2.setPaint(Color.BLACK);
g2.rotate(Math.PI * mAngle / 180, cx, cy);
for (int i = 0; i < lines; i++) {
float scale = (11.0f - (float) i) / 11.0f;
g2.drawLine(cx + s, cy, cx + s * 2, cy);
g2.rotate(-Math.PI / 6, cx, cy);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, scale * fade));
}
g2.dispose();
}
@Override
public void actionPerformed(ActionEvent e) {
if (mIsRunning) {
repaint();
mAngle += angleAdd;
if (mAngle >= maxAngle) {
mAngle = 0;
}
if (mIsFadingOut) {
if (--mFadeCount == 0) {
mIsRunning = false;
mTimer.stop();
}
} else if (mFadeCount < mFadeLimit) {
mFadeCount++;
}
}
}
public void start() {
if (mIsRunning) {
return;
}
mIsRunning = true;
mIsFadingOut = false;
mFadeCount = 0;
int fps = 24;
int tick = 1000 / fps;
mTimer = new Timer(tick, this);
mTimer.start();
}
public void stop() {
mIsRunning = false;
mIsFadingOut = true;
}
}

107
designer-base/src/main/java/com/fr/design/components/tooltip/ModernToolTip.java

@ -0,0 +1,107 @@
package com.fr.design.components.tooltip;
import com.fr.base.GraphHelper;
import com.fr.design.gui.itooltip.UIToolTip;
import com.fr.log.FineLoggerFactory;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JToolTip;
import javax.swing.SwingUtilities;
import javax.swing.plaf.ToolTipUI;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Enumeration;
import java.util.Vector;
/**
* 现代化的 UIToolTip
* <a href="https://kms.fineres.com/pages/viewpage.action?pageId=416850313">设计文档</a>
*
* created by Harrison on 2022/07/09
**/
public class ModernToolTip extends UIToolTip {
public ModernToolTip() {
super();
setUI(new ModernToolTipUI());
}
private class ModernToolTipUI extends ToolTipUI {
private String[] strs;
private Icon icon;
private boolean needPaint;
public void paint(Graphics g, JComponent c) {
if (!needPaint) {
return;
}
FontMetrics metrics = GraphHelper.getFontMetrics(c.getFont());
Dimension size = c.getSize();
int width = size.width;
int height = size.height;
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(51, 51, 52, (int) Math.round(0.7 * 255)));
g2.fillRoundRect(0, 0, width, height, 0, 0);
g2.setColor(Color.WHITE);
if (strs != null) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_DEFAULT);
for (int i = 0; i < strs.length; i++) {
g2.drawString(strs[i], icon.getIconWidth() + 6, (metrics.getHeight()) * (i + 1));
}
}
}
@Override
public Dimension getPreferredSize(JComponent c) {
FontMetrics metrics = GraphHelper.getFontMetrics(c.getFont());
String tipText = ((JToolTip) c).getTipText();
icon = ((UIToolTip)c).getIcon();
needPaint = true;
if (tipText == null) {
if(icon.getIconWidth() == -1) {
needPaint = false;
}
tipText = " ";
}
BufferedReader br = new BufferedReader(new StringReader(tipText));
String line;
int maxWidth = 0;
Vector<String> v = new Vector<String>();
try {
while ((line = br.readLine()) != null) {
int width = SwingUtilities.computeStringWidth(metrics, line);
maxWidth = (maxWidth < width) ? width : maxWidth;
v.addElement(line);
}
} catch (IOException ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
int lines = v.size();
if (lines < 1) {
strs = null;
lines = 1;
} else {
strs = new String[lines];
int i = 0;
for (Enumeration<String> e = v.elements(); e.hasMoreElements(); i++) {
strs[i] = e.nextElement();
}
}
int height = metrics.getHeight() * lines;
return new Dimension(maxWidth + icon.getIconWidth() + 10, Math.max(height, icon.getIconHeight()) + 6);
}
}
}

5
designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java

@ -16,6 +16,11 @@ public enum DesignerLaunchStatus implements Event<Null> {
*/
WORKSPACE_INIT_COMPLETE,
/**
* 设计器模块初始化开始
*/
DESIGNER_INIT_STARTED,
/**
* 设计器模块启动完成
*/

42
designer-base/src/main/java/com/fr/design/data/MapCompareUtils.java

@ -16,6 +16,8 @@ public final class MapCompareUtils {
/**
* 对比两个map 查找出相比origother中有哪些是新增的删除的或者被修改的并分别进行处理
*
* 对比时默认用equals方法来判断是否为 EntryEventKind#UPDATED
*
* @param orig 原始map
* @param other 参考的新map
* @param eventHandler 有区别时的事件处理器
@ -24,12 +26,29 @@ public final class MapCompareUtils {
*/
public static <K, V> void contrastMapEntries(@NotNull Map<K, V> orig, @NotNull Map<K, V> other, @NotNull EventHandler<K, V> eventHandler) {
contrastMapEntries(orig, other, eventHandler, UpdateRule.DEFAULT);
}
/**
* 对比两个map 查找出相比origother中有哪些是新增的删除的或者被修改的并分别进行处理
*
* 对比时用自定义的规则来判断是否为 EntryEventKind#UPDATED
*
* @param orig 原始map
* @param other 参考的新map
* @param eventHandler 有区别时的事件处理器
* @param updateRule 自定义的Update事件判定规则
* @param <K>
* @param <V>
*/
public static <K, V> void contrastMapEntries(@NotNull Map<K, V> orig, @NotNull Map<K, V> other, @NotNull EventHandler<K, V> eventHandler, @NotNull UpdateRule<K, V> updateRule) {
Map<K, V> copiedOrig = new LinkedHashMap<>(orig);
other.forEach((k, v) -> {
V existedV = copiedOrig.remove(k);
if (existedV != null) {
if (!v.equals(existedV)) {
if (updateRule.needUpdate(existedV, v)) {
eventHandler.on(EntryEventKind.UPDATED, k, v);
}
} else {
@ -41,10 +60,31 @@ public final class MapCompareUtils {
}
/**
* 事件处理器对应比较后的三种结果的事件处理
* @param <K>
* @param <V>
*/
public interface EventHandler<K, V> {
void on(EntryEventKind entryEventKind, K k, V v);
}
/**
* 数据被修改(EntryEventKind.UPDATED) 的判定规则
* @param <K>
* @param <V>
*/
public interface UpdateRule<K, V> {
EntryEventKind eventKind = EntryEventKind.UPDATED;
UpdateRule DEFAULT = new UpdateRule() {};
default boolean needUpdate(V origin, V v) {
return !v.equals(origin);
}
}
public enum EntryEventKind {
ADDED,
REMOVED,

15
designer-base/src/main/java/com/fr/design/data/datapane/ESDStrategyConfigPane.java

@ -133,7 +133,7 @@ public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
ob = StrategyConfigHelper.createStrategyConfig(true, false, true);
}
this.strategyConfig = ob;
this.updateInterval.setText(ob.getUpdateInterval() <= 0 ? "0" : String.format("%.0f", ob.getUpdateInterval() / (double) CacheConstants.MILLIS_OF_MINUTE));
this.updateInterval.setText(ob.getUpdateInterval() <= 0 ? "0" : String.valueOf(ob.getUpdateInterval() / (double) CacheConstants.MILLIS_OF_MINUTE));
this.schemaTime.setText(StringUtils.join(",", ob.getUpdateSchema().toArray(new String[0])));
this.shouldEvolve.setSelected(ob.shouldEvolve());
this.selectBySchema.setSelected(ob.isScheduleBySchema());
@ -185,7 +185,6 @@ public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
this.schemaTimeCheckTips.setVisible(true);
throw new IllegalArgumentException("[ESD]Update schema time interval is to short.");
}
} else {
Collections.addAll(schemaTimes, text.split(","));
}
@ -200,8 +199,15 @@ public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
String interval = this.updateInterval.getText();
if (checkUpdateInterval(interval)) {
long intervalMillis = StringUtils.isEmpty(interval) ? 0 : (long) (Double.parseDouble(interval) * CacheConstants.MILLIS_OF_MINUTE);
config.setUpdateInterval(intervalMillis);
if (intervalMillis >= CacheConstants.MILLIS_OF_MINUTE) {
config.setUpdateInterval(intervalMillis);
} else {
this.updateIntervalCheckTips.setText(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Time_Interval_Too_Short"));
this.updateIntervalCheckTips.setVisible(true);
throw new IllegalArgumentException("[ESD]Update schema time interval is to short.");
}
} else {
this.updateIntervalCheckTips.setText(InterProviderFactory.getDesignI18nProvider().i18nText("Fine-Design_ESD_Error_Time_Format"));
this.updateIntervalCheckTips.setVisible(true);
throw new IllegalArgumentException("[ESD]Error update interval format.");
}
@ -220,7 +226,7 @@ public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
private boolean checkUpdateInterval(String intervalValue) {
try {
return !StringUtils.isEmpty(intervalValue) && !(Integer.parseInt(intervalValue) <= 0);
return !StringUtils.isEmpty(intervalValue) && !(Double.parseDouble(intervalValue) <= 0);
} catch (NumberFormatException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
@ -228,6 +234,7 @@ public class ESDStrategyConfigPane extends BasicBeanPane<StrategyConfig> {
return false;
}
private boolean checkCornTimeInterval (String cronText) {
// 判断后两次更新时间间隔,如果小于1分钟就返回false
try {

52
designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java

@ -13,6 +13,7 @@ import com.fr.design.data.BasicTableDataTreePane;
import com.fr.design.data.BasicTableDataUtils;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.StrategyConfigAttrUtils;
import com.fr.design.data.datapane.auth.TableDataAuthHelper;
import com.fr.design.data.datapane.management.clip.TableDataTreeClipboard;
import com.fr.design.data.datapane.management.search.pane.TableDataSearchRemindPane;
import com.fr.design.data.datapane.management.search.pane.TreeSearchToolbarPane;
@ -22,6 +23,7 @@ import com.fr.design.data.tabledata.StoreProcedureWorkerListener;
import com.fr.design.data.tabledata.paste.TableDataFollowingPasteUtils;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.TableDataLoadingPane;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
@ -39,7 +41,6 @@ import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.i18n.Toolkit;
import com.fr.design.icon.IconPathConstants;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.menu.LineSeparator;
@ -87,6 +88,7 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@ -485,7 +487,11 @@ public class TableDataTreePane extends BasicTableDataTreePane {
doPropertyChange(dg, tdNamePanel, oldName);
}
});
dg.setVisible(true);
// 有些数据集(DBTableData)面板的初始化过程中是包含了SwingWorker处理(查询数据连接、查表等)的
// 如果这里直接setVisible,可能阻塞SwingWorker的done方法,导致面板渲染出现问题
SwingUtilities.invokeLater(() -> {
dg.setVisible(true);
});
}
@Override
@ -1017,8 +1023,46 @@ public class TableDataTreePane extends BasicTableDataTreePane {
AbstractTableDataPane<?> tableDataPane = wrapper.creatTableDataPane();
//下面创建creatTableDataPane后会直接populate,所以populate时不能用后设置的一些参数,比如name
dgEdit(tableDataPane, dsName, false);
if (TableDataAuthHelper.needCheckAuthWhenEdit(wrapper.getTableData())) {
// 先打开一个Loading面板
TableDataLoadingPane loadingPane = new TableDataLoadingPane();
BasicDialog loadingDialog = loadingPane.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.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);
dgEdit(tableDataPane, dsName, false);
} else {
// 无权限时,给出无权限提示
loadingPane.switchTo(TableDataLoadingPane.NO_AUTH_PANE_NAME);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error("loading connection error in remote design", e.getMessage());
// 查询权限失败时,给出报错提示
loadingPane.switchTo(TableDataLoadingPane.ERROR_NAME);
}
}
}.execute();
loadingDialog.setVisible(true);
} else {
// 无需检查权限时,直接打开数据库查询编辑面板
//下面创建creatTableDataPane后会直接populate,所以populate时不能用后设置的一些参数,比如name
dgEdit(tableDataPane, dsName, false);
}
}
}

57
designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java

@ -0,0 +1,57 @@
package com.fr.design.data.datapane.auth;
import com.fr.base.TableData;
import com.fr.data.impl.Connection;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.NameDatabaseConnection;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.connection.DBConnectAuth;
import java.util.Collection;
import java.util.Collections;
/**
* 数据连接权限相关的工具类
* @author Yvan
*/
public class TableDataAuthHelper {
/**
* 编辑数据集时是否需要检查权限
* @param tableData
* @return
*/
public static boolean needCheckAuthWhenEdit(TableData tableData) {
// 远程设计下,编辑DBTableData时需要判断权限
return !WorkContext.getCurrent().isLocal() && tableData instanceof DBTableData;
}
/**
* 获取无权限数据连接集合
* 远程下需要调用RPC为耗时操作谨慎使用
* @return
*/
public static Collection<String> getNoAuthConnections() {
// 获取无权限连接集合
Collection<String> noAuthConnections = WorkContext.getCurrent().get(DBConnectAuth.class).getNoAuthConnections();
return noAuthConnections == null ? Collections.emptyList() : noAuthConnections;
}
/**
* 通过数据集获取其数据连接的名称
*
* 注意
* 1. Connection接口本身是不提供名称的只有我们内部为了使用方便将其包装成了NameDataBaseConnection
* 如果不是NameDataBaseConnection类型则无名称因此这里只能用判断类型的方式获取名称
* 2. 仅支持DBTableData获取连接名
* @return
*/
public static String getConnectionNameByDBTableData(DBTableData tableData) {
Connection database = tableData.getDatabase();
if (database instanceof NameDatabaseConnection) {
return ((NameDatabaseConnection) database).getName();
}
return StringUtils.EMPTY;
}
}

38
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java

@ -138,18 +138,34 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
if (connection instanceof NameDatabaseConnection) {
this.setSelectedItem(((NameDatabaseConnection) connection).getName());
} else {
String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection();
if (StringUtils.isNotBlank(s)) {
// 之前的写法有多线程问题,nameList异步尚未初始化完成的时候,这里可能无法匹配设置数据连接名称,导致DBTableDataPane打开后连接面板空白
// 这里的需求无非是设置上一次使用的数据连接,做个简单检查这个连接是否存在即可,存在就设置
if (nameList.contains(s)) {
this.setSelectedItem(s);
}
}
// alex:如果这个ComboBox还是没有选中,那么选中第一个
if (StringUtils.isBlank(this.getSelectedItem()) && this.getConnectionSize() > 0) {
this.setSelectedItem(this.getConnection(0));
setRecentConnection();
}
}
/**
* 下拉框选项设置成最近选择的connection如果最近选择不存在则选择列表中的第一个
*/
protected void setRecentConnection() {
String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection();
if (StringUtils.isNotBlank(s)) {
// 之前的写法有多线程问题,nameList异步尚未初始化完成的时候,这里可能无法匹配设置数据连接名称,导致DBTableDataPane打开后连接面板空白
// 这里的需求无非是设置上一次使用的数据连接,做个简单检查这个连接是否存在即可,存在就设置
if (nameList.contains(s)) {
this.setSelectedItem(s);
}
}
// alex:如果这个ComboBox还是没有选中,那么选中第一个
if (StringUtils.isBlank(this.getSelectedItem()) && this.getConnectionSize() > 0) {
this.setSelectedItem(this.getConnection(0));
}
}
/**
* 是否无选中状态空白item也视为无选中
* @return
*/
protected boolean isSelectedItemEmpty() {
String selectedItem = this.getSelectedItem();
return selectedItem == null || StringUtils.equals(selectedItem, EMPTY.toString());
}
}

48
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java

@ -1,12 +1,12 @@
package com.fr.design.data.datapane.connect;
import com.fr.base.TemplateUtils;
import com.fr.config.RemoteConfigEvent;
import com.fr.data.core.db.JDBCSecurityChecker;
import com.fr.data.impl.Connection;
import com.fr.data.impl.ConnectionBean;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.impl.JNDIDatabaseConnection;
import com.fr.data.metric.utils.DatabaseConnectionMetricHandler;
import com.fr.data.operator.DataOperator;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.data.MapCompareUtils;
import com.fr.design.dialog.BasicDialog;
@ -186,27 +186,53 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
case ADDED:
case UPDATED:
addedOrUpdatedConnections.add(new ConnectionBean(s, StringUtils.EMPTY, connection));
if (connection instanceof JDBCDatabaseConnection) {
DatabaseConnectionMetricHandler.handleSaveConnection((JDBCDatabaseConnection) connection, null);
}
default:
break;
}
}, new MapCompareUtils.UpdateRule<String, Connection>() {
@Override
public boolean needUpdate(Connection origin, Connection connection) {
return needUpdate0(origin, connection);
}
/**
* 是否需要更新处理
* 1. Connection本身equals为false代表字段修改
* 2. 非内置的Connection即插件提供的Connection
* todo 原本一个equals方法就可以搞定但是插件里面没有实现equals结果导致不能正确判断只能主代码里做兼容很恶心先记个todo以后看有没有办法改掉
* @param origin
* @param connection
* @return
*/
private boolean needUpdate0(Connection origin, Connection connection) {
return !connection.equals(origin) || !isEmbedConnection(connection);
}
/**
* 是否是主工程里内置的Connection
* @return
*/
private boolean isEmbedConnection(Connection connection) {
return connection instanceof JDBCDatabaseConnection || connection instanceof JNDIDatabaseConnection;
}
});
this.checkSecurity(addedOrUpdatedConnections);
this.validateConnections(addedOrUpdatedConnections);
this.alterConnections(removedConnNames, addedOrUpdatedConnections);
}
private void checkSecurity(List<ConnectionBean> addedOrUpdatedConnections) throws Exception {
private void validateConnections(List<ConnectionBean> addedOrUpdatedConnections) throws Exception {
for (ConnectionBean connectionBean : addedOrUpdatedConnections) {
Connection connection = connectionBean.getConnection();
if (connection instanceof JDBCDatabaseConnection) {
try {
JDBCSecurityChecker.checkURL(TemplateUtils.render(((JDBCDatabaseConnection) connection).getURL()));
JDBCSecurityChecker.checkValidationQuery(((JDBCDatabaseConnection) connection).getDbcpAttr().getValidationQuery());
} catch (SQLException e) {
throw new SQLException(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Invalid_Config", connectionBean.getName()) + ", " + e.getMessage(), e.getCause());
}
try {
DataOperator.getInstance().validateConnectionSettings(connection);
} catch (Exception e) {
throw new SQLException(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Invalid_Config", connectionBean.getName()) + ", " + e.getMessage(), e.getCause());
}
}

113
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java

@ -1,26 +1,32 @@
package com.fr.design.data.datapane.connect;
import com.fr.base.BaseUtils;
import com.fr.base.svg.IconUtils;
import com.fr.data.core.db.TableProcedure;
import com.fr.data.impl.AbstractDatabaseConnection;
import com.fr.data.impl.Connection;
import com.fr.design.border.UIRoundedBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.SwitchableTableDataPane;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ilist.TableViewList;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.general.GeneralContext;
import com.fr.stable.ArrayUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.ToolTipManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@ -45,7 +51,39 @@ public class ConnectionTableProcedurePane extends BasicPane {
private java.util.List<DoubleClickSelectedNodeOnTreeListener> listeners = new java.util.ArrayList<DoubleClickSelectedNodeOnTreeListener>();
public ConnectionTableProcedurePane() {
init(null);
}
/**
* 传入父容器
* @param parent
*/
public ConnectionTableProcedurePane(SwitchableTableDataPane parent) {
init(parent);
}
private void init(SwitchableTableDataPane parent) {
this.setLayout(new BorderLayout(4, 4));
// 初始化数据连接下拉框
initConnectionComboBox(parent);
// 初始化中间的面板
JPanel centerPane = initCenterPane();
this.add(connectionComboBox, BorderLayout.NORTH);
this.add(centerPane, BorderLayout.CENTER);
this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height));
addKeyMonitor();
}
private JPanel initCenterPane() {
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
// 搜索面板
centerPane.add(createSearchPane(), BorderLayout.NORTH);
// 数据库表视图面板
centerPane.add(createTableViewBorderPane(), BorderLayout.CENTER);
return centerPane;
}
private void initConnectionComboBox(SwitchableTableDataPane parent) {
connectionComboBox = new ConnectionComboBoxPanel(com.fr.data.impl.Connection.class) {
@Override
@ -60,10 +98,34 @@ public class ConnectionTableProcedurePane extends BasicPane {
search(true);
}
}
@Override
protected void afterRefreshItems() {
// 刷新完成后,如果未选中(在nameList初始化完成之前可能会出现),则尝试再次设置
if (isSelectedItemEmpty()) {
setRecentConnection();
}
// 获取数据连接之后,让父容器切换面板
if (parent != null) {
parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME);
}
}
@Override
protected void refreshItemsError() {
// 获取数据连接出现错误时,也让父容器从Loading面板切换至内容面板
if (parent != null) {
parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME);
}
}
};
connectionComboBox.addComboBoxActionListener(filter);
}
private JPanel createTableViewBorderPane() {
tableViewList = new TableViewList();
ToolTipManager.sharedInstance().registerComponent(tableViewList);
connectionComboBox.addComboBoxActionListener(filter);
tableViewList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() >= 2) {
@ -80,23 +142,50 @@ public class ConnectionTableProcedurePane extends BasicPane {
}
}
});
JPanel filterPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
UIScrollPane tableViewListPane = new UIScrollPane(tableViewList);
tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
JPanel tableViewBorderPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
tableViewBorderPane.add(tableViewListPane, BorderLayout.CENTER);
JPanel checkBoxgroupPane = createCheckBoxgroupPane();
if (checkBoxgroupPane != null) {
filterPane.add(createCheckBoxgroupPane(), BorderLayout.NORTH);
tableViewBorderPane.add(createCheckBoxgroupPane(), BorderLayout.SOUTH);
}
return tableViewBorderPane;
}
/**
* 创建搜索Panel用于搜索表或视图
* @return
*/
private JPanel createSearchPane() {
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane();
JPanel searchPane = new JPanel(new BorderLayout(10, 0));
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR));
searchPane.setBackground(Color.WHITE);
searchField = new UITextField();
searchPane.add(searchField, BorderLayout.CENTER);
searchField.setBorderPainted(false);
searchField.setPlaceholder(Toolkit.i18nText("Fine-Design_Basic_Table_Search"));
searchField.getDocument().addDocumentListener(searchListener);
filterPane.add(searchPane, BorderLayout.CENTER);
UIScrollPane tableViewListPane = new UIScrollPane(tableViewList);
tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
this.add(connectionComboBox, BorderLayout.NORTH);
this.add(tableViewListPane, BorderLayout.CENTER);
this.add(filterPane, BorderLayout.SOUTH);
this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height));
addKeyMonitor();
searchField.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
super.mouseEntered(e);
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.CHECKBOX_HOVER_SELECTED));
}
@Override
public void mouseExited(MouseEvent e) {
super.mouseExited(e);
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR));
}
});
// 搜索图标
UILabel searchLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/search"));
searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
searchPane.add(searchField, BorderLayout.CENTER);
searchPane.add(searchLabel, BorderLayout.EAST);
panel.add(searchPane, BorderLayout.CENTER);
return panel;
}
protected void filter(Connection connection, String conName, List<String> nameList) {

16
designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java

@ -127,10 +127,12 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() + 1);
itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() - 1);
}
afterRefreshItems();
} catch (Exception e) {
if (!(e instanceof CancellationException)) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
refreshItemsError();
}
}
@ -160,6 +162,20 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
*/
protected abstract java.util.Iterator<String> items();
/**
* 刷新ComboBox.items之后
*/
protected void afterRefreshItems() {
// 空实现,供子类重写
}
/**
* 刷新ComboBox.items时出现异常
*/
protected void refreshItemsError() {
// 空实现,供子类重写
}
/*
* 弹出对话框编辑Items
*/

54
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java

@ -20,6 +20,8 @@ import com.fr.design.data.datapane.preview.sql.PreviewPerformedSqlPane;
import com.fr.design.data.datapane.sqlpane.SQLEditPane;
import com.fr.design.data.tabledata.strategy.StrategyConfigHandler;
import com.fr.design.data.tabledata.tabledatapane.db.StrategyConfigFrom;
import com.fr.design.data.tabledata.tabledatapane.loading.SwitchableTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.TipsPane;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
@ -36,6 +38,7 @@ import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants;
import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.menu.SeparatorDef;
import com.fr.design.menu.ToolBarDef;
@ -70,6 +73,7 @@ import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
@ -86,7 +90,7 @@ import java.util.List;
* @version 10.0
* Created by rinoux on 2020/7/22
*/
public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
public class DBTableDataPane extends AbstractTableDataPane<DBTableData> implements SwitchableTableDataPane {
private static final int BOTTOM = 6;
private static final String PREVIEW_BUTTON = Toolkit.i18nText("Fine-Design_Basic_Preview");
@ -109,14 +113,42 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
private StrategyConfigHandler<DBTableData> configHandler;
private CardLayout card;
/** 数据库查询面板真正的内容面板 */
private JPanel contentPane;
/** 加载中面板 */
private JPanel loadingPane;
public DBTableDataPane() {
initCards();
initContentPane();
}
/**
* 初始化内容面板
*/
protected void initContentPane() {
init();
initMainSplitPane();
}
/**
* 初始化cardLayout以及LoadingPane等并且布局切到LoadingPane
*/
protected void initCards() {
card = new CardLayout();
setLayout(card);
loadingPane = new TipsPane(true);
contentPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
add(LOADING_PANE_NAME, loadingPane);
add(CONTENT_PANE_NAME, contentPane);
switchTo(LOADING_PANE_NAME);
}
private void init() {
setLayout(new BorderLayout(4, 4));
contentPane.setLayout(new BorderLayout(4, 4));
this.sqlTextPane = new SQLEditPane();
this.sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
@ -130,7 +162,7 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
editorPane = new UITableEditorPane<>(model);
this.connectionTableProcedurePane = new ConnectionTableProcedurePane() {
this.connectionTableProcedurePane = new ConnectionTableProcedurePane(this) {
@Override
protected void filter(Connection connection, String conName, List<String> nameList) {
connection.addConnection(nameList, conName, new Class[]{
@ -231,7 +263,21 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.connectionTableProcedurePane, sqlSplitPane);
mainSplitPane.setBorder(BorderFactory.createLineBorder(GUICoreUtils.getTitleLineBorderColor()));
mainSplitPane.setOneTouchExpandable(true);
add(mainSplitPane, BorderLayout.CENTER);
contentPane.add(mainSplitPane, BorderLayout.CENTER);
}
@Override
public void switchTo(String panelName) {
try {
if (panelName != null) {
card.show(this, panelName);
}
} catch (IllegalArgumentException ingore) {
// 有些直接继承此面板或者替换掉此面板的插件,在未适配此功能时会出现报错,因为不是CardLayout,无法切换,这里处理下
FineLoggerFactory.getLogger().info("cannot switch pane by {}", this.getClass().getName());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private boolean isPreviewOrRefreshButton(FocusEvent e) {

23
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/SwitchableTableDataPane.java

@ -0,0 +1,23 @@
package com.fr.design.data.tabledata.tabledatapane.loading;
/**
* 可切换的DBTableData对应的数据集面板需要使用CardLayout布局
* 主要是给插件适配用的
* @author Yvan
*/
public interface SwitchableTableDataPane {
/** Loading面板 */
String LOADING_PANE_NAME = "Loading";
/** 内容面板 */
String CONTENT_PANE_NAME = "Content";
/**
* 根据面板名称切换面板
* @param paneName 面板名称
*/
void switchTo(String paneName);
}

54
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TableDataLoadingPane.java

@ -0,0 +1,54 @@
package com.fr.design.data.tabledata.tabledatapane.loading;
import com.fr.design.dialog.BasicPane;
import com.fr.design.i18n.Toolkit;
import javax.swing.JPanel;
import java.awt.CardLayout;
/**
* @author Yvan
*/
public class TableDataLoadingPane extends BasicPane {
/** Loading面板 */
public static final String LOADING_PANE_NAME = "Loading";
/** 无权限提示面板 */
public static final String NO_AUTH_PANE_NAME = "NoAuthority";
/** 错误提示面板 */
public static final String ERROR_NAME = "Error";
private CardLayout card;
/** 加载中面板 */
private JPanel loadingPane;
/** 错误提示面板 */
private JPanel errorPane;
/** 数据连接无权限面板 */
private JPanel noAuthorityPane;
public TableDataLoadingPane() {
initPanes();
}
private void initPanes() {
card = new CardLayout();
this.setLayout(card);
loadingPane = new TipsPane(true);
errorPane = new TipsPane(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Error"));
noAuthorityPane = new TipsPane(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_No_Auth"));
add(LOADING_PANE_NAME, loadingPane);
add(NO_AUTH_PANE_NAME, noAuthorityPane);
add(ERROR_NAME, errorPane);
switchTo(LOADING_PANE_NAME);
}
public void switchTo(String panelName) {
card.show(this, panelName);
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query");
}
}

45
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TipsPane.java

@ -0,0 +1,45 @@
package com.fr.design.data.tabledata.tabledatapane.loading;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
/**
* 提示面板支持自定义提示支持进度条配置可选
* @author Yvan
*/
public class TipsPane extends JPanel {
/**
* 默认提示
*/
private static final String LOADING = Toolkit.i18nText("Fine-Design_Basic_Loading_And_Waiting");
public TipsPane () {
this(LOADING, false);
}
public TipsPane (String tip) {
this(tip, false);
}
public TipsPane (boolean needProgressBar) {
this(LOADING, needProgressBar);
}
public TipsPane (String tips, boolean needProgressBar) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
UILabel tipsLabel = new UILabel(tips, SwingConstants.CENTER);
this.add(tipsLabel, BorderLayout.CENTER);
if (needProgressBar) {
JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
this.add(progressBar, BorderLayout.SOUTH);
}
}
}

3
designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java

@ -3,6 +3,7 @@ package com.fr.design.extra.exe.callback;
import com.fr.design.bridge.exec.JSCallback;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.extra.PluginOperateUtils;
import com.fr.design.extra.exe.callback.handle.PluginCallBackHelper;
import com.fr.design.i18n.Toolkit;
import com.fr.log.FineLoggerFactory;
@ -73,7 +74,7 @@ public class InstallFromDiskCallback extends AbstractPluginTaskCallback {
}else {
jsCallback.execute("failed");
FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Plugin_Install_Failed"));
FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE);
PluginCallBackHelper.showErrorMessage(result, pluginInfo);
}
}
}

3
designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java

@ -4,6 +4,7 @@ import com.fr.design.bridge.exec.JSCallback;
import com.fr.design.bridge.exec.JSExecutor;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.extra.PluginOperateUtils;
import com.fr.design.extra.exe.callback.handle.PluginCallBackHelper;
import com.fr.design.i18n.Toolkit;
import com.fr.log.FineLoggerFactory;
@ -63,7 +64,7 @@ public class InstallOnlineCallback extends AbstractDealPreTaskCallback {
} else {
jsCallback.execute("failed");
FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Plugin_Install_Failed"));
FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE);
PluginCallBackHelper.showErrorMessage(result, pluginInfo);
}
}

3
designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java

@ -3,6 +3,7 @@ package com.fr.design.extra.exe.callback;
import com.fr.design.bridge.exec.JSCallback;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.extra.PluginOperateUtils;
import com.fr.design.extra.exe.callback.handle.PluginCallBackHelper;
import com.fr.design.i18n.Toolkit;
import com.fr.log.FineLoggerFactory;
@ -72,7 +73,7 @@ public class UpdateFromDiskCallback extends AbstractPluginTaskCallback {
}else {
jsCallback.execute("failed");
FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Plugin_Update_Failed"));
FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE);
PluginCallBackHelper.showErrorMessage(result, pluginInfo);
}
}
}

3
designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java

@ -3,6 +3,7 @@ package com.fr.design.extra.exe.callback;
import com.fr.design.bridge.exec.JSCallback;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.extra.PluginOperateUtils;
import com.fr.design.extra.exe.callback.handle.PluginCallBackHelper;
import com.fr.design.i18n.Toolkit;
import com.fr.log.FineLoggerFactory;
@ -38,7 +39,7 @@ public class UpdateOnlineCallback extends AbstractDealPreTaskCallback {
} else {
jsCallback.execute("failed");
FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Plugin_Update_Failed"));
FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE);
PluginCallBackHelper.showErrorMessage(result, pluginInfo);
}
}
}

70
designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginCallBackHelper.java

@ -0,0 +1,70 @@
package com.fr.design.extra.exe.callback.handle;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.dialog.link.MessageWithLink;
import com.fr.design.i18n.Toolkit;
import com.fr.plugin.error.PluginErrorCode;
import com.fr.plugin.manage.control.PluginTaskResult;
/**
* 帮助处理插件操作安装更新等的弹窗
* @author Yvan
*/
public class PluginCallBackHelper {
private static final String NEW_LINE_TAG = "<br/>";
private static final String REFERENCE = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_Reference");
private static final String HELP_DOCUMENT_NAME = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_NAME");
private static final String CONNECTOR = "-";
private static final String HELP_DOCUMENT_LINK = Toolkit.i18nText("Fine-Design_Basic_Plugin_File_Validate_HELP_DOCUMENT_LINK");
/**
* 展示插件操作失败后的提示弹窗
* @param result
* @param pluginInfo
*/
public static void showErrorMessage(PluginTaskResult result, String pluginInfo) {
// 单独处理下插件完整性校验失败的提示
if (PluginCallBackHelper.needHandleInvalidatePackage(result)) {
MessageWithLink messageWithLink = PluginCallBackHelper.generate4InvalidatePackage(pluginInfo);
PluginTaskResultErrorDialog resultDialog = new PluginTaskResultErrorDialog(null, messageWithLink);
resultDialog.showResult();
} else {
FineJOptionPane.showMessageDialog(null, pluginInfo, Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"), FineJOptionPane.ERROR_MESSAGE);
}
}
/**
* 判断是否需要处理 插件安装包校验失败 导致的安装失败任务
* @param result
* @return
*/
private static boolean needHandleInvalidatePackage(PluginTaskResult result) {
return !result.isSuccess() && result.getCode() == PluginErrorCode.InstallPackageValidateFailed;
}
/**
* 根据插件原始报错信息构建MessageWithLink
* @param originInfo
* @return
*/
private static MessageWithLink generate4InvalidatePackage(String originInfo) {
return new MessageWithLink(getSupplementaryMessage(originInfo), HELP_DOCUMENT_NAME, HELP_DOCUMENT_LINK);
}
/**
* 根据插件原始报错信息获取增加了补充说明后的信息
* @param originInfo
* @return
*/
private static String getSupplementaryMessage(String originInfo) {
return new StringBuilder()
.append(originInfo)
.append(NEW_LINE_TAG)
.append(REFERENCE)
.append(CONNECTOR)
.toString();
}
}

86
designer-base/src/main/java/com/fr/design/extra/exe/callback/handle/PluginTaskResultErrorDialog.java

@ -0,0 +1,86 @@
package com.fr.design.extra.exe.callback.handle;
import com.fr.base.svg.IconUtils;
import com.fr.design.dialog.link.MessageWithLink;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.utils.gui.GUICoreUtils;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* 当前仅处理Error提示之后有需要再扩展
* @author Yvan
*/
public class PluginTaskResultErrorDialog extends JDialog {
private static final Dimension LABEL = new Dimension(60, 90);
private JPanel contentPane;
private UILabel errorLabel;
private UIButton confirmButton;
private MessageWithLink messageWithLink;
public PluginTaskResultErrorDialog(Frame parent, MessageWithLink messageWithLink) {
super(parent, true);
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Plugin_Warning"));
this.messageWithLink = messageWithLink;
initContentPane();
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.setResizable(false);
this.add(contentPane, BorderLayout.CENTER);
this.setSize(new Dimension( 380, 160));
GUICoreUtils.centerWindow(this);
}
/**
* 初始化内容面板
*/
private void initContentPane() {
this.contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
// error图标
errorLabel = new UILabel(IconUtils.readIcon("/com/fr/design/standard/system/error_tips.svg"));
errorLabel.setPreferredSize(LABEL);
errorLabel.setBorder(BorderFactory.createEmptyBorder(10, 20, 40, 20));
// 提示内容
JPanel messagePane = FRGUIPaneFactory.createBorderLayout_S_Pane();
messagePane.add(errorLabel, BorderLayout.WEST);
messagePane.add(messageWithLink, BorderLayout.CENTER);
messagePane.setBorder(BorderFactory.createEmptyBorder(20, 10, 0, 10));
this.contentPane.add(messagePane, BorderLayout.CENTER);
// 确定按钮
confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Button_OK"));
confirmButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
hideResult();
}
});
JPanel confirmPane = new JPanel(new VerticalFlowLayout());
confirmPane.add(confirmButton);
confirmPane.setBorder(BorderFactory.createEmptyBorder(0, 160, 10, 0));
this.contentPane.add(confirmPane, BorderLayout.SOUTH);
}
public void showResult() {
this.setVisible(true);
}
public void hideResult() {
this.setVisible(false);
}
}

2
designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java

@ -296,7 +296,7 @@ public class UIButtonGroup<T> extends JPanel implements GlobalNameObserver, UIOb
return selectedIndex;
}
protected void setSelectedIndex(int newSelectedIndex, boolean fireChanged) {
public void setSelectedIndex(int newSelectedIndex, boolean fireChanged) {
if (selectedIndex != newSelectedIndex) {
selectedIndex = newSelectedIndex;
for (int i = 0; i < labelButtonList.size(); i++) {

2
designer-base/src/main/java/com/fr/design/gui/ibutton/UITabGroup.java

@ -63,7 +63,7 @@ public class UITabGroup extends UIButtonGroup<Integer> {
}
@Override
protected void setSelectedIndex(int newSelectedIndex, boolean fireChanged) {
public void setSelectedIndex(int newSelectedIndex, boolean fireChanged) {
super.setSelectedIndex(newSelectedIndex, false);
tabChanged(newSelectedIndex);
}

19
designer-base/src/main/java/com/fr/design/gui/ilable/ActionLabel.java

@ -14,11 +14,18 @@ import java.awt.event.MouseEvent;
public class ActionLabel extends UILabel {
private ActionListener actionListener;
private Color color;
// 文字是否有下划线
private boolean drawUnderLine = true;
public ActionLabel(String text) {
this(text, Color.blue);
}
public ActionLabel(String text, boolean drawUnderLine) {
this(text, Color.blue);
this.drawUnderLine = drawUnderLine;
}
public ActionLabel(String text, Color color) {
super(text);
this.color = color;
@ -39,7 +46,9 @@ public class ActionLabel extends UILabel {
super.paintComponent(_gfx);
_gfx.setColor(this.color);
_gfx.drawLine(0, this.getHeight() - 1, this.getWidth(), this.getHeight() - 1);
if (drawUnderLine) {
_gfx.drawLine(0, this.getHeight() - 1, this.getWidth(), this.getHeight() - 1);
}
}
private MouseInputAdapter mouseInputAdapter = new MouseInputAdapter() {
@ -95,4 +104,12 @@ public class ActionLabel extends UILabel {
}
}
};
public boolean isDrawUnderLine() {
return drawUnderLine;
}
public void setDrawUnderLine(boolean drawUnderLine) {
this.drawUnderLine = drawUnderLine;
}
}

3
designer-base/src/main/java/com/fr/design/gui/itooltip/UIToolTip.java

@ -67,6 +67,9 @@ public class UIToolTip extends JToolTip{
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
Container container = getComponent();
if (container == null) {
return;
}
while (!ComparatorUtils.equals(container.getClass(), UIScrollPane.class)) {
if (container.getParent() == null) {
break;

7
designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/TreeAttrChangeListener.java

@ -0,0 +1,7 @@
package com.fr.design.gui.itree.refreshabletree;
import com.fr.data.impl.TreeAttr;
public interface TreeAttrChangeListener {
void doChange(TreeAttr treeAttr);
}

50
designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/TreeRootPane.java

@ -10,21 +10,24 @@ import javax.swing.BoxLayout;
import javax.swing.JPanel;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
public class TreeRootPane extends BasicPane {
private final List<TreeAttrChangeListener> listeners = new ArrayList<>();
// 是否支持多选(checkBoxTree)
//private JCheckBox multipleSelection;
private UICheckBox checkTypeCheckBox;
private final UICheckBox checkTypeCheckBox;
// richer:加载的方式,支持异步加载和完全加载
private UICheckBox loadTypeCheckBox;
private final UICheckBox loadTypeCheckBox;
private UICheckBox layerTypeCheckBox;
private final UICheckBox layerTypeCheckBox;
private UICheckBox returnFullPathCheckBox;
private final UICheckBox returnFullPathCheckBox;
public TreeRootPane() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
@ -41,13 +44,6 @@ public class TreeRootPane extends BasicPane {
checkTypePane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
loadTypeCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Widget_Load_By_Async"));
loadTypeCheckBox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
loadTypeCheckBox.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
UICheckBox checkBox = (UICheckBox) e.getSource();
doLoadTypeChange(checkBox.isSelected());
}
});
loadTypePane.add(loadTypeCheckBox);
this.add(loadTypePane);
@ -63,11 +59,27 @@ public class TreeRootPane extends BasicPane {
checkTypePane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
returnFullPathPane.add(returnFullPathCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tree_Return_Full_Path")));
returnFullPathCheckBox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
addCheckBoxListener();
this.add(returnFullPathPane);
}
private void addCheckBoxListener() {
loadTypeCheckBox.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
UICheckBox checkBox = (UICheckBox) e.getSource();
doLoadTypeChange(checkBox.isSelected());
}
});
checkTypeCheckBox.addActionListener(event->fireTreeAttrChangeListener());
loadTypeCheckBox.addActionListener(event->fireTreeAttrChangeListener());
layerTypeCheckBox.addActionListener(event->fireTreeAttrChangeListener());
returnFullPathCheckBox.addActionListener(event->fireTreeAttrChangeListener());
}
private void doLoadTypeChange(Boolean selected) {
//给埋点插件提供一个方法,埋埋点用
}
@ -82,6 +94,7 @@ public class TreeRootPane extends BasicPane {
loadTypeCheckBox.setSelected(treeAttr.isAjax());
layerTypeCheckBox.setSelected(treeAttr.isSelectLeafOnly());
returnFullPathCheckBox.setSelected(treeAttr.isReturnFullPath());
fireTreeAttrChangeListener();
}
public TreeAttr update() {
@ -93,4 +106,17 @@ public class TreeRootPane extends BasicPane {
return treeAttr;
}
public void addTreeAttrChangeListener(TreeAttrChangeListener listener) {
listeners.add(listener);
}
public void fireTreeAttrChangeListener() {
TreeAttr treeAttr = new TreeAttr();
treeAttr.setMultipleSelection(checkTypeCheckBox.isSelected());
treeAttr.setAjax(loadTypeCheckBox.isSelected());
treeAttr.setSelectLeafOnly(layerTypeCheckBox.isSelected());
treeAttr.setReturnFullPath(returnFullPathCheckBox.isSelected());
listeners.forEach(listener -> listener.doChange(treeAttr));
}
}

47
designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java

@ -13,6 +13,9 @@ import javax.swing.JRadioButton;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.LayoutManager;
@ -149,6 +152,50 @@ public class FRGUIPaneFactory {
return new FRGridLayout(nColumn);
}
/**
* centerBody 为中心创建一个布局
* 只有当且仅当有一个组件且希望组件 上下左右 居中时使用
* @param centerBody 中心组件
* @return 布局方式
*/
public static LayoutManager createCenterLayout(JComponent centerBody) {
final double yFactor = 0.30;
return new LayoutManager() {
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return centerBody.getPreferredSize();
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return null;
}
@Override
public void layoutContainer(Container parent) {
int width = parent.getParent().getWidth();
int height = parent.getParent().getHeight();
// 这个时候大小是不确定的
int bodyWidth = centerBody.getPreferredSize().width;
int bodyHeight = centerBody.getPreferredSize().height;
int labelX = (width - bodyWidth) / 2;
int labelY = (int) ((height - bodyHeight) * yFactor);
centerBody.setBounds(labelX, labelY, bodyWidth, bodyHeight);
}
@Override
public void addLayoutComponent(String name, Component comp) {
}
};
}
/**
* 创建一个带标题边框面板
*

33
designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java

@ -29,17 +29,16 @@ import com.fr.design.fun.impl.AbstractTemplateTreeShortCutProvider;
import com.fr.design.gui.iprogressbar.ProgressDialog;
import com.fr.design.gui.iscrollbar.UIScrollBar;
import com.fr.design.i18n.Toolkit;
import com.fr.design.lock.LockInfoDialog;
import com.fr.design.mainframe.share.mini.MiniShopDisposingChecker;
import com.fr.design.mainframe.share.mini.MiniShopNativeTaskManager;
import com.fr.design.mainframe.toolbar.ToolBarMenuDock;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.design.menu.ShortCut;
import com.fr.design.os.impl.MacOsAddListenerAction;
import com.fr.design.os.impl.SupportOSImpl;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.design.utils.TemplateUtils;
import com.fr.design.lock.LockInfoDialog;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.event.EventDispatcher;
import com.fr.exception.DecryptTemplateException;
import com.fr.exception.TplLockedException;
@ -60,11 +59,11 @@ import com.fr.stable.os.OperatingSystem;
import com.fr.stable.os.support.OSSupportCenter;
import com.fr.stable.project.ProjectConstants;
import com.fr.start.OemHandler;
import com.fr.start.common.DesignerOpenEmptyPanel;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import com.fr.workspace.connect.WorkspaceConnectionInfo;
import java.util.UUID;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JFrame;
@ -103,6 +102,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
public class DesignerFrame extends JFrame implements JTemplateActionListener, TargetModifiedListener {
@ -171,7 +171,10 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
return;
}
//关闭前当前模板 停止编辑
HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().stopEditing();
JTemplate<?, ?> currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (currentEditingTemplate != null) {
currentEditingTemplate.stopEditing();
}
SaveSomeTemplatePane saveSomeTemplatePane = new SaveSomeTemplatePane(true);
// 全部保存成功才退出
if (saveSomeTemplatePane.showSavePane()) {
@ -303,9 +306,14 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
public void resizeFrame() {
HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().setComposite();
JTemplate<?, ?> currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (currentEditingTemplate != null) {
currentEditingTemplate.setComposite();
}
reCalculateFrameSize();
HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().doResize();
if (currentEditingTemplate != null) {
currentEditingTemplate.doResize();
}
}
@Deprecated
@ -799,6 +807,17 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
}
}
public void showEmptyJTemplate() {
DesignerOpenEmptyPanel designerOpenEmptyPanel = new DesignerOpenEmptyPanel();
BorderLayout layout = (BorderLayout) basePane.getLayout();
basePane.remove(layout.getLayoutComponent(BorderLayout.CENTER));
basePane.remove(layout.getLayoutComponent(BorderLayout.EAST));
basePane.add(designerOpenEmptyPanel, BorderLayout.CENTER);
layeredPane.repaint();
}
/**
* 添加新建模板, 并激活.
*/

23
designer-base/src/main/java/com/fr/design/mainframe/DesignerUIModeConfig.java

@ -1,8 +1,11 @@
package com.fr.design.mainframe;
import com.fr.base.AutoChangeLineProvider;
import com.fr.base.DefaultAutoChangeLine;
import com.fr.base.ScreenResolution;
import com.fr.design.fun.ReportLengthUNITProvider;
import com.fr.design.unit.UnitConvertUtil;
import com.fr.form.fit.NewUIModeAutoChangeLine;
import com.fr.general.ComparatorUtils;
import com.fr.stable.Constants;
@ -58,6 +61,14 @@ public class DesignerUIModeConfig {
return mode.parseLengthUNIT(unitType);
}
/**
* 获取不同模式下的换行逻辑
* @return AutoChangeLineProvider
*/
public AutoChangeLineProvider getAutoChangeLineStrategy() {
return mode.getAutoChangeLineStrategy();
}
/**
* 获取不同模式下的屏幕分辨率
*
@ -75,6 +86,11 @@ public class DesignerUIModeConfig {
return UnitConvertUtil.parseLengthUNIT(unitType);
}
@Override
public AutoChangeLineProvider getAutoChangeLineStrategy() {
return new DefaultAutoChangeLine();
}
@Override
protected int getScreenResolution() {
return ScreenResolution.getScreenResolution();
@ -87,6 +103,11 @@ public class DesignerUIModeConfig {
return new PXReportLengthUNIT();
}
@Override
public AutoChangeLineProvider getAutoChangeLineStrategy() {
return new NewUIModeAutoChangeLine();
}
@Override
protected int getScreenResolution() {
return Constants.DEFAULT_WEBWRITE_AND_SCREEN_RESOLUTION;
@ -96,6 +117,8 @@ public class DesignerUIModeConfig {
protected abstract ReportLengthUNITProvider parseLengthUNIT(int unitType);
public abstract AutoChangeLineProvider getAutoChangeLineStrategy();
protected abstract int getScreenResolution();

6
designer-base/src/main/java/com/fr/design/mainframe/JDashboard.java

@ -1,5 +1,9 @@
package com.fr.design.mainframe;
import com.fr.report.worksheet.FormElementCase;
import java.awt.Rectangle;
/**
* @author Starryi
* @version 1.0
@ -7,4 +11,6 @@ package com.fr.design.mainframe;
*/
public interface JDashboard {
void switchToDashBoardEditor();
Rectangle getElementCaseRectangle(FormElementCase elementCase);
}

108
designer-base/src/main/java/com/fr/design/mainframe/TransparentPane.java

@ -1,58 +1,30 @@
package com.fr.design.mainframe;
import com.fr.design.components.loading.LoadingPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import javax.swing.Timer;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.Timer;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/4/12
*/
public class TransparentPane extends JComponent implements ActionListener {
public class TransparentPane extends LoadingPane {
private UILabel label;
private AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
private volatile boolean mIsRunning;
private volatile boolean mIsFadingOut;
private Timer mTimer;
private int mAngle;
private int mFadeCount;
private int mFadeLimit = 15;
private int lines = 12;
private int maxAngle = 360;
private int angleAdd = 30;
private double prec = 0.56;
public TransparentPane() {
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// do nothing
}
});
setLayout(getCoverLayout());
setBackground(null);
setOpaque(false);
super();
label = new UILabel(Toolkit.i18nText("Fine-Design_Saving_Template_Tip"));
add(label);
}
@ -91,72 +63,4 @@ public class TransparentPane extends JComponent implements ActionListener {
};
}
@Override
public void paint(Graphics g) {
int w = this.getWidth();
int h = this.getHeight();
super.paint(g);
if (!mIsRunning) {
return;
}
Graphics2D g2 = (Graphics2D) g.create();
float fade = (float) mFadeCount / (float) mFadeLimit;
Composite urComposite = g2.getComposite();
g2.setComposite(composite);
g2.fillRect(0, 0, w, h);
g2.setComposite(urComposite);
int s = Math.min(w, h) / 50;
int cx = w / 2;
int cy = h / 2;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(s / 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2.setPaint(Color.BLACK);
g2.rotate(Math.PI * mAngle / 180, cx, cy);
for (int i = 0; i < lines; i++) {
float scale = (11.0f - (float) i) / 11.0f;
g2.drawLine(cx + s, cy, cx + s * 2, cy);
g2.rotate(-Math.PI / 6, cx, cy);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, scale * fade));
}
g2.dispose();
}
@Override
public void actionPerformed(ActionEvent e) {
if (mIsRunning) {
repaint();
mAngle += angleAdd;
if (mAngle >= maxAngle) {
mAngle = 0;
}
if (mIsFadingOut) {
if (--mFadeCount == 0) {
mIsRunning = false;
mTimer.stop();
}
} else if (mFadeCount < mFadeLimit) {
mFadeCount++;
}
}
}
public void start() {
if (mIsRunning) {
return;
}
mIsRunning = true;
mIsFadingOut = false;
mFadeCount = 0;
int fps = 24;
int tick = 1000 / fps;
mTimer = new Timer(tick, this);
mTimer.start();
}
public void stop() {
mIsRunning = false;
mIsFadingOut = true;
}
}

5
designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java

@ -502,10 +502,7 @@ public abstract class ToolBarMenuDock {
addPluginManagerAction(menuDef);
menuDef.addShortCut(new FunctionManagerAction());
if (!DesignModeContext.isDuchampMode()) {
menuDef.addShortCut(new GlobalParameterAction());
}
menuDef.addShortCut(new GlobalParameterAction());
}

11
designer-base/src/main/java/com/fr/design/notification/NotificationCenter.java

@ -2,6 +2,8 @@ package com.fr.design.notification;
import com.fr.design.notification.ui.NotificationCenterPane;
import com.fr.stable.StringUtils;
import java.util.ArrayList;
import java.util.List;
@ -30,6 +32,15 @@ public class NotificationCenter {
NotificationCenterPane.getNotificationCenterPane().refreshButton();
}
/**
* 通过messageId删除消息
* @param messageID
*/
public void removeNotificationByMessageID(String messageID) {
notifications.removeIf(notification -> StringUtils.equals(notification.getMessageId(), messageID));
NotificationCenterPane.getNotificationCenterPane().refreshButton();
}
public Notification getNotification(int index){
return notifications.get(index);
}

143
designer-base/src/main/java/com/fr/design/plugin/remind/PluginErrorDesignReminder.java

@ -0,0 +1,143 @@
package com.fr.design.plugin.remind;
import com.fr.design.dialog.NotificationDialogAction;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.notification.Notification;
import com.fr.design.notification.NotificationCenter;
import com.fr.plugin.error.PluginErrorRemindHandler;
import com.fr.plugin.error.PluginErrorReminder;
import com.fr.stable.StringUtils;
import com.fr.stable.collections.CollectionUtils;
import com.fr.workspace.WorkContext;
import javax.swing.SwingUtilities;
import java.util.List;
/**
* 插件错误信息提醒-设计器模块
*
* @author Yvan
*/
public class PluginErrorDesignReminder implements PluginErrorReminder {
private static final String MESSAGE_ID = "plugin-invalidate-remind";
public static final String COMMA = "、";
public static final String COLON = ":";
public static final String NEW_LINE_TAG = "<br/>";
private static final int MAX_PLUGIN_NAME_PER_LINE = 3;
private static class Holder {
private static final PluginErrorDesignReminder INSTANCE = new PluginErrorDesignReminder();
}
private PluginErrorDesignReminder() {}
public static PluginErrorDesignReminder getInstance() {
return Holder.INSTANCE;
}
@Override
public void remindStartFailedPlugins() {
if (!WorkContext.getCurrent().isLocal()) {
return;
}
String content = PluginErrorRemindHandler.pluginErrorContent();
if (StringUtils.isNotEmpty(content)) {
// 该操作需要在当前awt操作之后执行,使用SwingUtilities.invokeLater将其置于awt操作对列末尾
// 若使用UIUtil.invokeLaterIfNeeded,会立即执行,影响其他UI操作
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
PluginStartFailedRemindDialog dialog = new PluginStartFailedRemindDialog(DesignerContext.getDesignerFrame(), content);
dialog.setVisible(true);
}
});
}
}
@Override
public void remindInvalidatePlugins() {
if (!WorkContext.getCurrent().isLocal()) {
return;
}
// 获取失效插件名称列表
List<String> embedPluginNames = PluginErrorRemindHandler.getInvalidateEmbedPluginNames();
if (!CollectionUtils.isEmpty(embedPluginNames)) {
// 构建消息
String message = generateMessageContent(embedPluginNames);
Notification notification = generateNotification(message, embedPluginNames);
// 添加消息
NotificationCenter.getInstance().addNotification(notification);
}
}
/**
* 构建消息内容
* @param invalidatePluginNames
* @return
*/
private String generateMessageContent(List<String> invalidatePluginNames) {
return new StringBuilder()
.append(Toolkit.i18nText("Fine-Design_Plugin_Embed_Notice"))
.append(COLON)
.append(NEW_LINE_TAG)
.append(NEW_LINE_TAG)
.append(dealWithPluginNames(invalidatePluginNames))
.append(NEW_LINE_TAG)
.append(NEW_LINE_TAG)
.append(Toolkit.i18nText("Fine-Design_Plugin_Embed_Description"))
.append(NEW_LINE_TAG)
.toString();
}
/**
* 处理消息中的插件名称展示
* 由于Notification那边展示的弹窗是随消息宽度变化的所以插件名称很多时会变得很长这里做个分行
* @return
* @param invalidatePluginNames
*/
public String dealWithPluginNames(List<String> invalidatePluginNames) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < invalidatePluginNames.size(); i++) {
String pluginName = invalidatePluginNames.get(i);
builder.append(pluginName);
if (i != invalidatePluginNames.size() - 1) {
builder.append(i % MAX_PLUGIN_NAME_PER_LINE == (MAX_PLUGIN_NAME_PER_LINE - 1) ? NEW_LINE_TAG : COMMA);
}
}
return builder.toString();
}
/**
* 构建通知对象
* @param message
* @param invalidatePluginNames
* @return
*/
private Notification generateNotification(String message, List<String> invalidatePluginNames) {
return new Notification(
MESSAGE_ID,
Notification.WARNING_MESSAGE,
message,
new NotificationDialogAction() {
@Override
public String name() {
return "plugin-invalidate-remind-show";
}
@Override
public void doClick() {
PluginInvalidateRemindDialog remindDialog = new PluginInvalidateRemindDialog(
DesignerContext.getDesignerFrame(),
invalidatePluginNames,
PluginErrorRemindHandler.getInvalidateEmbedPluginMarkers(),
MESSAGE_ID);
remindDialog.setVisible(true);
}
}
);
}
}

211
designer-base/src/main/java/com/fr/design/plugin/remind/PluginInvalidateRemindDialog.java

@ -0,0 +1,211 @@
package com.fr.design.plugin.remind;
import com.fr.common.util.Collections;
import com.fr.design.actions.UpdateAction;
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.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.notification.NotificationCenter;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.context.PluginMarker;
import com.fr.plugin.manage.PluginManager;
import com.fr.plugin.manage.control.PluginTaskCallback;
import com.fr.plugin.manage.control.PluginTaskResult;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
/**
* @author Yvan
*/
public class PluginInvalidateRemindDialog extends JDialog implements ActionListener{
/**
* 因内置而失效的插件Marker列表
*/
private List<PluginMarker> pluginMarkers;
/**
* 因内置而失效的插件名称列表
*/
private List<String> pluginNames;
/**
* 本弹窗对应的消息的id
* 方便弹窗逻辑执行完之后删除通知中心的消息
*/
private String messageID;
public PluginInvalidateRemindDialog(Frame parent, List<String> pluginNames, List<PluginMarker> pluginMarkers, String messageId) {
super(parent, true);
this.pluginMarkers = pluginMarkers;
this.pluginNames = pluginNames;
this.messageID = messageId;
// 标题
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"));
this.setResizable(false);
this.add(initTopPane(), BorderLayout.NORTH);
this.add(initCenterPanel(), BorderLayout.CENTER);
this.add(initBottomPanel(), BorderLayout.SOUTH);
this.setSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.plugin.remind.PluginInvalidateRemindDialog.dialog"));
GUICoreUtils.centerWindow(this);
}
/**
* 上层的面板用于解释插件内置
* @return
*/
private JPanel initTopPane() {
JPanel topPane = FRGUIPaneFactory.createBorderLayout_L_Pane();
// 图标面板
JPanel imagePanel = new JPanel();
Icon icon = IOUtils.readIcon("com/fr/design/images/warnings/icon_WarningIcon_normal.png");
UILabel imageLabel = new UILabel();
imageLabel.setIcon(icon);
imagePanel.add(imageLabel);
imagePanel.setBorder(BorderFactory.createEmptyBorder(20, 10, 0, 10));
JPanel verticalPanel = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true);
UILabel noticeLabel = new UILabel(Toolkit.i18nText("Fine-Design_Plugin_Embed_Notice"));
noticeLabel.setFont(FRFont.getInstance().applySize(16));
UILabel adviceLabel = new UILabel(Toolkit.i18nText("Fine-Design_Plugin_Embed_Advice"));
UILabel descriptionLabel = new UILabel(Toolkit.i18nText("Fine-Design_Plugin_Embed_Description"));
verticalPanel.add(noticeLabel);
verticalPanel.add(adviceLabel);
verticalPanel.add(descriptionLabel);
topPane.add(imagePanel, BorderLayout.WEST);
topPane.add(verticalPanel, BorderLayout.CENTER);
topPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 20));
return topPane;
}
/**
* 中层面板用于展示内置插件列表
* @return
*/
private JPanel initCenterPanel() {
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_L_Pane();
// "插件列表"标签面板
UILabel textLabel = new UILabel(Toolkit.i18nText("Fine-Design_Plugin_Embed_List"));
textLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
JTextPane textPane = new JTextPane();
textPane.setEditable(false);
textPane.setBackground(Color.WHITE);
SimpleAttributeSet attributeSet = new SimpleAttributeSet();
StyleConstants.setLineSpacing(attributeSet, 0.5f);
textPane.setParagraphAttributes(attributeSet, true);
textPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
textPane.setText(generatePluginListText(pluginNames));
JScrollPane scrollPane = new JScrollPane(textPane);
centerPane.add(textLabel, BorderLayout.NORTH);
centerPane.add(scrollPane, BorderLayout.CENTER);
centerPane.setBorder(BorderFactory.createEmptyBorder(20, 10, 0, 10));
centerPane.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane"));
return centerPane;
}
/**
* 生成中间面板展示的插件列表
* @param pluginNames
* @return
*/
private String generatePluginListText(List<String> pluginNames) {
String space = " ";
StringBuilder sb = new StringBuilder();
for (String pluginName : pluginNames) {
sb.append(space).append(pluginName).append("\n");
}
return sb.toString();
}
/**
* 底层面板用于处理用户操作
* @return
*/
private JPanel initBottomPanel() {
JPanel bottomPane = FRGUIPaneFactory.createBorderLayout_L_Pane();
UIButton ignore = new UIButton(Toolkit.i18nText("Fine-Design_Plugin_Embed_Ignore"));
UIButton delete = new UIButton(Toolkit.i18nText("Fine-Design_Plugin_Embed_Delete_Plugins"));
UILabel emptyLabel = new UILabel();
ignore.addActionListener(this);
delete.addActionListener(new DeleteEmbedPluginsAction(this));
bottomPane.add(ignore, BorderLayout.WEST);
bottomPane.add(emptyLabel, BorderLayout.CENTER);
bottomPane.add(delete, BorderLayout.EAST);
return bottomPane;
}
@Override
public void actionPerformed(ActionEvent e) {
this.dispose();
}
private class DeleteEmbedPluginsAction extends UpdateAction {
private JDialog dialog;
DeleteEmbedPluginsAction(JDialog dialog) {
this.dialog = dialog;
}
@Override
public void actionPerformed(ActionEvent e) {
this.dialog.dispose();
// 删除插件
deleteEmbedPlugins(pluginMarkers);
// 删除消息
NotificationCenter.getInstance().removeNotificationByMessageID(messageID);
}
/**
* 删除插件
* @param toDelete
*/
private void deleteEmbedPlugins(List<PluginMarker> toDelete) {
if (Collections.isEmpty(toDelete)) {
return;
}
for (PluginMarker pluginMarker : toDelete) {
// 删除插件
PluginManager.getController().uninstall(pluginMarker, false, new PluginTaskCallback() {
@Override
public void done(PluginTaskResult result) {
// 输出结果日志
FineLoggerFactory.getLogger().info(
"Detele Embed Plugin(id = {}, version = {}) {}",
pluginMarker.getPluginID(),
pluginMarker.getVersion(), result.isSuccess() ? "Succeeded" : "Failed");
}
});
}
}
}
}

6
designer-base/src/main/java/com/fr/env/PluginErrorRemindDialog.java → designer-base/src/main/java/com/fr/design/plugin/remind/PluginStartFailedRemindDialog.java

@ -1,4 +1,4 @@
package com.fr.env;
package com.fr.design.plugin.remind;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.actions.UpdateAction;
@ -32,11 +32,11 @@ import java.util.Set;
/**
* 插件启动失败提示窗
*/
public class PluginErrorRemindDialog extends JDialog implements ActionListener {
public class PluginStartFailedRemindDialog extends JDialog implements ActionListener {
private static final String SIM_HEI = "SimHei";
public PluginErrorRemindDialog(Frame parent, String text) {
public PluginStartFailedRemindDialog(Frame parent, String text) {
super(parent, true);
//上面的标签面板
JPanel topPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();

34
designer-base/src/main/java/com/fr/design/update/actions/NewFeatureAction.java

@ -0,0 +1,34 @@
package com.fr.design.update.actions;
import com.fr.common.util.Strings;
import com.fr.design.utils.BrowseUtils;
import com.fr.general.CloudCenter;
import com.fr.log.FineLoggerFactory;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* 帮助-更新升级
* 点击查看新特性
* */
public class NewFeatureAction implements ActionListener {
public static String DEFAULT_UPDATE_DETAIL_URL = "https://help.fanruan.com/finereport/doc-view-4699.html";
@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);
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage());
}
}
}

201
designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java

@ -9,6 +9,7 @@ import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.dialog.UIDialog;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icontainer.UIScrollPane;
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.Toolkit;
@ -16,6 +17,7 @@ import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.update.actions.FileProcess;
import com.fr.design.update.actions.NewFeatureAction;
import com.fr.design.update.domain.UpdateInfoCachePropertyManager;
import com.fr.design.update.utils.UpdateFileUtils;
import com.fr.design.update.ui.widget.LoadingLabel;
@ -57,7 +59,6 @@ import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutionException;
import static com.fr.design.dialog.FineJOptionPane.OPTION_OK_CANCEL;
import static java.nio.charset.StandardCharsets.*;
import static javax.swing.JOptionPane.QUESTION_MESSAGE;
@ -85,7 +86,7 @@ public class UpdateMainDialog extends UIDialog {
private static final String HYPHEN = "-";
private final SimpleDateFormat CHANGELOG_FORMAT = new SimpleDateFormat("M/d/y, h:m:s a", Locale.ENGLISH);
private final SimpleDateFormat UPDATELOG_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
private final SimpleDateFormat UPDATE_INFO_TABLE_FORMAT = new SimpleDateFormat("yyyy.MM.dd");
private JSONObject downloadFileConfig;
@ -93,8 +94,6 @@ public class UpdateMainDialog extends UIDialog {
private LoadingLabel loadingLabel;
//更新按钮
private UIButton updateButton;
//有新版本提示标签
private UILabel updateLabel;
//jar包版本信息面板,包括当前版本和最新版本
private JPanel jarVersionInfoPane;
@ -157,13 +156,8 @@ public class UpdateMainDialog extends UIDialog {
progressBar.setStringPainted(true);
progressBar.setPreferredSize(PROGRESSBAR);
updateLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_New_Version_Available"));
updateLabel.setHorizontalAlignment(SwingConstants.RIGHT);
updateLabel.setVisible(false);
progressBarPane.add(GUICoreUtils.createBorderLayoutPane(
progressBar, BorderLayout.CENTER,
updateLabel, BorderLayout.EAST
progressBar, BorderLayout.CENTER
), BorderLayout.CENTER);
updateActionPane = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{
@ -183,9 +177,9 @@ public class UpdateMainDialog extends UIDialog {
double[] rowUpdatePaneSize = {UPDATE_PANE_ROW_SIZE, TableLayout.PREFERRED, TableLayout.PREFERRED};
double[] columnUpdatePaneSize = {TableLayout.PREFERRED, TableLayout.FILL, TableLayout.PREFERRED};
double[] rowUpdateContentPaneSize = {TableLayout.PREFERRED};
double[] columnUpdateContentPaneSize = {TableLayout.PREFERRED, TableLayout.FILL, TableLayout.PREFERRED};
double[] columnUpdateContentPaneSize = {TableLayout.PREFERRED, TableLayout.FILL};
double[] rowUpdateSubContentPaneSize = {UPDATE_CONTENT_PANE_ROW_SIZE, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, UPDATE_CONTENT_PANE_ROW_SIZE};
double[] columnUpdateSubContentPaneSize = {UPDATE_CONTENT_PANE_COLUMN_SIZE, TableLayout.FILL, TableLayout.PREFERRED};
double[] columnUpdateSubContentPaneSize = {UPDATE_CONTENT_PANE_COLUMN_SIZE, TableLayout.PREFERRED, TableLayout.PREFERRED};
double[] columnUpdateSubContentPaneLabelSize = {UPDATE_CONTENT_PANE_LABEL_COLUMN_SIZE, TableLayout.PREFERRED};
JPanel jarUpdateContentPane = new JPanel();
@ -195,15 +189,15 @@ public class UpdateMainDialog extends UIDialog {
JPanel jarUpdateContentPane2 = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{
new Component[]{new UILabel(), new UILabel(), new UILabel()},
new Component[]{new UILabel(), updateVersionReminderPane, new UILabel()},
new Component[]{new UILabel(), initPaneContent(Color.WHITE, rowUpdateContentPaneSize, columnUpdateSubContentPaneLabelSize, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_JAR_Version")), jarCurrentLabel), new UILabel()},
new Component[]{new UILabel(), initPaneContent(Color.WHITE, rowUpdateContentPaneSize, columnUpdateSubContentPaneLabelSize, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Latest_JAR")), loadingLabel), new UILabel()},
new Component[]{new UILabel(), initPaneContent(Color.WHITE, rowUpdateContentPaneSize, columnUpdateSubContentPaneLabelSize, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_JAR_Version")), jarCurrentLabel), jarRestoreLabel},
new Component[]{new UILabel(), initPaneContent(Color.WHITE, rowUpdateContentPaneSize, columnUpdateSubContentPaneLabelSize, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Latest_JAR")), loadingLabel),
getNewFeatureActionLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Latest_Feature_Detail"))},
new Component[]{new UILabel(), new UILabel(), new UILabel()}
}, rowUpdateSubContentPaneSize, columnUpdateSubContentPaneSize, LayoutConstants.VGAP_LARGE);
jarUpdateContentPane2.setBackground(Color.WHITE);
jarUpdateContentPane.add(jarUpdateContentPane2);
jarVersionInfoPane = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{
new Component[]{new UILabel(), new UILabel(), new UILabel()},
new Component[]{new UILabel(), initPaneContent(getBackground(), rowUpdateContentPaneSize, columnUpdateContentPaneSize, new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_JarUpdate")), new UILabel(), jarRestoreLabel), new UILabel()},
new Component[]{new UILabel(), jarUpdateContentPane, new UILabel()}
}, rowUpdatePaneSize, columnUpdatePaneSize, LayoutConstants.VGAP_LARGE);
}
@ -221,7 +215,7 @@ public class UpdateMainDialog extends UIDialog {
new Component[]{new UILabel(), new UILabel(), new UILabel()}
}, searchRow, searchColumn, LayoutConstants.VGAP_LARGE);
String[] columnNames = {com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Date"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Content"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_SignHeader")};
String[] columnNames = {com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Date"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Version"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Content"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_SignHeader")};
initUpdateInfoTable(columnNames);
UIScrollPane uiScrollPane = new UIScrollPane(updateInfoTable);
@ -232,31 +226,32 @@ public class UpdateMainDialog extends UIDialog {
}
private void initUpdateInfoTable(String[] columnNames) {
int updateTimeColIndex = 0;
int updateTitleColIndex = 1;
int updateSignColIndex = 2;
updateInfoTable = new UpdateInfoTable(columnNames);
updateInfoTable.setShowGrid(false);
updateInfoTable.setCellSelectionEnabled(false);
TableRowSorter<UpdateInfoTableModel> sorter = new TableRowSorter<>(updateInfoTable.getDataModel());
sorter.setSortable(updateTimeColIndex, true);
sorter.setSortable(updateTitleColIndex, false);
sorter.setSortable(updateSignColIndex, false);
sorter.setSortable(UpdateInfoTable.UPDATE_DATE_INDEX, true);
sorter.setSortable(UpdateInfoTable.UPDATE_VERSION_INDEX, true);
sorter.setSortable(UpdateInfoTable.UPDATE_TITLE_INDEX, false);
sorter.setSortable(UpdateInfoTable.SIGN_INDEX, false);
updateInfoTable.setRowSorter(sorter);
List<RowSorter.SortKey> sortKeys = new ArrayList<>();
sortKeys.add(new RowSorter.SortKey(updateTimeColIndex, SortOrder.DESCENDING));
sortKeys.add(new RowSorter.SortKey(UpdateInfoTable.UPDATE_DATE_INDEX, SortOrder.DESCENDING));
sortKeys.add(new RowSorter.SortKey(UpdateInfoTable.UPDATE_VERSION_INDEX, SortOrder.DESCENDING));
sorter.setSortKeys(sortKeys);
updateInfoTable.getTableHeader().setReorderingAllowed(false);
updateInfoTable.getColumnModel().getColumn(updateTimeColIndex).setMaxWidth(UPDATE_INFO_TABLE_HEADER_TIME_WIDTH);
updateInfoTable.getColumnModel().getColumn(updateTimeColIndex).setMinWidth(UPDATE_INFO_TABLE_HEADER_TIME_WIDTH);
updateInfoTable.getColumnModel().getColumn(updateSignColIndex).setMaxWidth(0);
updateInfoTable.getColumnModel().getColumn(updateSignColIndex).setMinWidth(0);
updateInfoTable.getTableHeader().getColumnModel().getColumn(updateSignColIndex).setMaxWidth(0);
updateInfoTable.getTableHeader().getColumnModel().getColumn(updateSignColIndex).setMinWidth(0);
updateInfoTable.getColumnModel().getColumn(UpdateInfoTable.UPDATE_DATE_INDEX).setMaxWidth(UPDATE_INFO_TABLE_HEADER_TIME_WIDTH);
updateInfoTable.getColumnModel().getColumn(UpdateInfoTable.UPDATE_DATE_INDEX).setMinWidth(UPDATE_INFO_TABLE_HEADER_TIME_WIDTH);
updateInfoTable.getColumnModel().getColumn(UpdateInfoTable.UPDATE_VERSION_INDEX).setMaxWidth(UPDATE_INFO_TABLE_HEADER_TIME_WIDTH);
updateInfoTable.getColumnModel().getColumn(UpdateInfoTable.UPDATE_VERSION_INDEX).setMinWidth(UPDATE_INFO_TABLE_HEADER_TIME_WIDTH);
updateInfoTable.getColumnModel().getColumn(UpdateInfoTable.SIGN_INDEX).setMaxWidth(0);
updateInfoTable.getColumnModel().getColumn(UpdateInfoTable.SIGN_INDEX).setMinWidth(0);
updateInfoTable.getTableHeader().getColumnModel().getColumn(UpdateInfoTable.SIGN_INDEX).setMaxWidth(0);
updateInfoTable.getTableHeader().getColumnModel().getColumn(UpdateInfoTable.SIGN_INDEX).setMinWidth(0);
updateInfoTable.getColumn(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Date")).setCellRenderer(new UpdateInfoTableCellRender());
updateInfoTable.getColumn(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Version")).setCellRenderer(new UpdateInfoTableCellRender());
updateInfoTable.getColumn(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Content")).setCellRenderer(new UpdateInfoTextAreaCellRender());
}
@ -300,18 +295,18 @@ public class UpdateMainDialog extends UIDialog {
updateButton.setEnabled(false);
double[] rowSize = {TableLayout.PREFERRED};
double[] colSize = {TableLayout.PREFERRED};
UILabel versionLabel = new UILabel(UpdateConstants.DEFAULT_APP_NAME + StringUtils.BLANK + ProductConstants.VERSION);
versionLabel.setFont(new Font("Default", Font.BOLD, 16));
double[] colSize = {UPDATE_CONTENT_PANE_LABEL_COLUMN_SIZE, TableLayout.PREFERRED};
updateVersionReminderPane = initPaneContent(
Color.WHITE, rowSize, colSize,
new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Designer_Version")),
new UILabel(UpdateConstants.DEFAULT_APP_NAME + StringUtils.BLANK + ProductConstants.VERSION)
Color.WHITE, rowSize, colSize, versionLabel
);
String notInstallVersion = InterProviderFactory.getProvider().getLocText("Fine-Core_Basic_About_No_Build");
String versionBuildNo = GeneralUtils.getVersion() + HYPHEN + GeneralUtils.readBuildNO();
jarCurrentLabel = new UILabel(ComparatorUtils.equals(notInstallVersion, GeneralUtils.readBuildNO()) ? notInstallVersion : versionBuildNo, SwingConstants.CENTER);
UILabel noJarPreviousRevision = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_No_Previous_Version"));
UpdateActionLabel jarRestorePreviousRevision = new UpdateActionLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Restore"), false);
jarRestorePreviousRevision.setForeground(new Color(RESTORE_LABEL_COLOR));
jarRestorePreviousRevision.addActionListener(new ActionListener() {
@ -323,7 +318,7 @@ public class UpdateMainDialog extends UIDialog {
});
//choose RestoreLabel to show
boolean isNeedRestore = ArrayUtils.isNotEmpty(UpdateFileUtils.listBackupVersions());
jarRestoreLabel = isNeedRestore ? jarRestorePreviousRevision : noJarPreviousRevision;
jarRestoreLabel = isNeedRestore ? jarRestorePreviousRevision : null;
}
private void initComponents() {
@ -417,18 +412,25 @@ public class UpdateMainDialog extends UIDialog {
if (downloadFileConfig == null) {
throw new Exception("network error.");
}
HttpGet get = new HttpGet(CloudCenter.getInstance().acquireUrlByKind("changelog10") + "&start=" + lastUpdateCacheTime + "&end=" + getLatestJARTimeStr());
httpClient = HttpToolbox.getHttpClient(CloudCenter.getInstance().acquireUrlByKind("changelog10") + "&start=" + lastUpdateCacheTime + "&end=" + getLatestJARTimeStr());
HttpGet get = new HttpGet(CloudCenter.getInstance().acquireUrlByKind("updatelog") + "?start=" + lastUpdateCacheTime + "&end=" + getLatestJARTimeStr());
httpClient = HttpToolbox.getHttpClient(CloudCenter.getInstance().acquireUrlByKind("updatelog") + "?start=" + lastUpdateCacheTime + "&end=" + getLatestJARTimeStr());
response = httpClient.execute(get);
String responseText = CommonIOUtils.inputStream2String(response.getEntity().getContent(),EncodeConstants.ENCODING_UTF_8).trim();
JSONArray array = JSONArray.create();
//假如返回"-1",说明socket出错了
if (!ComparatorUtils.equals(responseText, "-1")) {
array = new JSONArray(responseText);
JSONObject respObject = new JSONObject(responseText);
if (respObject != null && "success".equals(respObject.get("status"))) {
array = respObject.getJSONArray("data");
}
}
return array;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage());
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
return JSONArray.create();
}
@ -445,7 +447,7 @@ public class UpdateMainDialog extends UIDialog {
updateCachedInfoFile(jsonArray);
} catch (Exception e) {
getUpdateInfoSuccess = true;
FineLoggerFactory.getLogger().error(e.getMessage());
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
}
};
@ -459,7 +461,7 @@ public class UpdateMainDialog extends UIDialog {
}
//从文件中读取缓存的更新信息
private void getCachedUpdateInfo(String keyword) throws Exception {
private void getCachedUpdateInfo(String keyword) {
String cacheInfoPath = getUpdateCacheInfo();
File cacheFile = new File(StableUtils.pathJoin(WorkContext.getCurrent().getPath(), "resources", "offlineres", cacheInfoPath));
if (!ComparatorUtils.equals(lastUpdateCacheState, "success")) {
@ -472,22 +474,27 @@ public class UpdateMainDialog extends UIDialog {
String readStr, updateTimeStr;
while ((readStr = br.readLine()) != null) {
String[] updateInfo = readStr.split("\\t");
if (updateInfo.length == 2) {
updateTimeStr = updateInfo[0];
Date updateTime = CHANGELOG_FORMAT.parse(updateTimeStr);
if (updateInfo.length == 3) {
updateTimeStr = updateInfo[UpdateInfoTable.UPDATE_DATE_INDEX];
Date updateTime = UPDATELOG_FORMAT.parse(updateTimeStr);
//形如 Build#release-2018.07.31.03.03.52.80
String currentNO = GeneralUtils.readBuildNO();
Date curJarDate = UPDATE_INFO_TABLE_FORMAT.parse(currentNO, new ParsePosition(currentNO.indexOf("-") + 1));
if (!ComparatorUtils.equals(keyword, StringUtils.EMPTY)) {
if (!containsKeyword(UPDATE_INFO_TABLE_FORMAT.format(updateTime), keyword) && !containsKeyword(updateInfo[1], keyword)) {
keyword.replace('.','-');
if (!containsKeyword(UPDATELOG_FORMAT.format(updateTime), keyword) && !containsKeyword(updateInfo[UpdateInfoTable.UPDATE_TITLE_INDEX], keyword)) {
continue;
}
}
if (isValidLogInfo(updateInfo[1])) {
updateInfoList.add(new Object[]{UPDATE_INFO_TABLE_FORMAT.format(updateTime), updateInfo[1], updateTime.after(curJarDate)});
if (isValidLogInfo(updateInfo[UpdateInfoTable.UPDATE_TITLE_INDEX]) && curJarDate != null) {
updateInfoList.add(new Object[]{UPDATELOG_FORMAT.format(updateTime), updateInfo[UpdateInfoTable.UPDATE_VERSION_INDEX], updateInfo[UpdateInfoTable.UPDATE_TITLE_INDEX], updateTime.after(curJarDate)});
}
}
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
}
}
@ -516,7 +523,7 @@ public class UpdateMainDialog extends UIDialog {
try (BufferedWriter bufferWriter = new BufferedWriter(writerStream)) {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jo = (JSONObject) jsonArray.get(i);
bufferWriter.write((String) jo.get("update") + '\t' + jo.get("title"));
bufferWriter.write((String) jo.get("updateTime") + '\t' + jo.get("version") + '\t' + jo.get("jiraId") + " " + jo.get("info"));
bufferWriter.newLine();
bufferWriter.flush();
}
@ -531,22 +538,24 @@ public class UpdateMainDialog extends UIDialog {
private ArrayList<Object[]> generateUpdateInfoList(JSONArray jsonArray, String keyword) throws Exception {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jo = (JSONObject) jsonArray.get(i);
String updateTitle = (String) jo.get("title");
String updateTimeStr = (String) jo.get("update");
Date updateTime = CHANGELOG_FORMAT.parse(updateTimeStr);
String updateTitle = (String) jo.get("jiraId") + " " + jo.get("info");
String updateVersionStr = (String) jo.get("version");
String updateTimeStr = (String) jo.get("updateTime");
Date updateTime = UPDATELOG_FORMAT.parse(updateTimeStr);
//形如 Build#release-2018.07.31.03.03.52.80
String currentNO = GeneralUtils.readBuildNO();
Date curJarDate = UPDATE_INFO_TABLE_FORMAT.parse(currentNO, new ParsePosition(currentNO.indexOf("-") + 1));
if (curJarDate == null) {
curJarDate = updateTime;
}
if (!ComparatorUtils.equals(keyword, StringUtils.EMPTY)) {
if (!containsKeyword(UPDATE_INFO_TABLE_FORMAT.format(updateTime), keyword) && !containsKeyword(updateTitle, keyword)) {
if (!ComparatorUtils.equals(keyword, StringUtils.EMPTY) && keyword != null) {
keyword.replace('.', '-');
if (!containsKeyword(UPDATELOG_FORMAT.format(updateTime), keyword) && !containsKeyword(updateTitle, keyword)) {
continue;
}
}
if (isValidLogInfo(updateTitle)) {
updateInfoList.add(new Object[]{UPDATE_INFO_TABLE_FORMAT.format(updateTime), updateTitle, updateTime.after(curJarDate)});
updateInfoList.add(new Object[]{updateTimeStr, updateVersionStr, updateTitle, updateTime.after(curJarDate)});
}
}
return new ArrayList<>(updateInfoList);
@ -579,14 +588,12 @@ public class UpdateMainDialog extends UIDialog {
Date currentDate = (new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss")).parse(currentNO, new ParsePosition(currentNO.indexOf("-") + 1));
if (DateUtils.subtractDate(jarDate, currentDate, DateUtils.SECOND) > 0) {
updateButton.setEnabled(true);
updateLabel.setVisible(true);
loadingLabel.stopLoading(buildNO.contains("-") ? buildNO.substring(buildNO.lastIndexOf("-") + 1) : buildNO);
} else {
loadingLabel.stopLoading(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Updater_Already_Latest_Version"));
}
} else {
updateButton.setEnabled(true);
updateLabel.setVisible(true);
loadingLabel.stopLoading(buildNO.contains("-") ? buildNO.substring(buildNO.lastIndexOf("-") + 1) : buildNO);
}
@ -608,41 +615,7 @@ public class UpdateMainDialog extends UIDialog {
* jar包更新按钮监听器
*/
private void addActionListenerForUpdateBtn() {
updateButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String[] option = {Toolkit.i18nText("Fine-Design_Report_Yes"), Toolkit.i18nText("Fine-Design_Report_No")};
int a = JOptionPane.showOptionDialog(getParent(), Toolkit.i18nText("Fine-Design_Update_Info_Information"),
Toolkit.i18nText("Fine-Design_Update_Info_Title"),JOptionPane.YES_NO_OPTION, QUESTION_MESSAGE, UIManager.getIcon("OptionPane.warningIcon"), option, 1);
if (a == 0) {
progressBar.setVisible(true);
progressBar.setString(Toolkit.i18nText("Fine-Design_Update_Info_Wait_Message"));
UpdateCallBack callBack = new UpdateProgressCallBack(progressBar);
updateButton.setEnabled(false);
updateLabel.setVisible(false);
RestoreResultDialog.deletePreviousPropertyFile();
final String installLib = StableUtils.pathJoin(StableUtils.getInstallHome(), ProjectConstants.LOGS_NAME, UpdateConstants.INSTALL_LIB);
final JFrame frame = DesignerContext.getDesignerFrame();
final RestartHelper helper = new RestartHelper();
FineProcessContext.getParentPipe().fire(FineProcessEngineEvent.DESTROY);
new FileProcess(callBack) {
@Override
public void onDownloadSuccess() {
progressBar.setVisible(false);
deleteForDesignerUpdate(installLib);
helper.restartForUpdate(frame);
}
@Override
public void onDownloadFailed() {
progressBar.setVisible(false);
deleteForDesignerUpdate(installLib);
FineJOptionPane.showMessageDialog(getParent(), Toolkit.i18nText("Fine-Design_Update_Info_Failed_Message"));
helper.restartForUpdate(frame);
}
}.execute();
}
}
});
updateButton.addActionListener(new UpdateAction());
}
private void deleteForDesignerUpdate(String installLib) {
@ -688,6 +661,13 @@ public class UpdateMainDialog extends UIDialog {
return false;
}
private ActionLabel getNewFeatureActionLabel(final String text){
ActionLabel actionLabel = new ActionLabel(text, new Color(RESTORE_LABEL_COLOR));
actionLabel.setDrawUnderLine(false);
actionLabel.addActionListener(new NewFeatureAction());
return actionLabel;
}
/**
* 显示窗口
*/
@ -705,4 +685,41 @@ public class UpdateMainDialog extends UIDialog {
@Override
public void checkValid() throws Exception {
}
private class UpdateAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String[] option = {Toolkit.i18nText("Fine-Design_Report_Yes"), Toolkit.i18nText("Fine-Design_Report_No")};
int a = JOptionPane.showOptionDialog(getParent(), Toolkit.i18nText("Fine-Design_Update_Info_Information"),
Toolkit.i18nText("Fine-Design_Update_Info_Title"),JOptionPane.YES_NO_OPTION, QUESTION_MESSAGE, UIManager.getIcon("OptionPane.warningIcon"), option, 1);
if (a == 0) {
progressBar.setVisible(true);
progressBar.setString(Toolkit.i18nText("Fine-Design_Update_Info_Wait_Message"));
UpdateCallBack callBack = new UpdateProgressCallBack(progressBar);
updateButton.setEnabled(false);
RestoreResultDialog.deletePreviousPropertyFile();
final String installLib = StableUtils.pathJoin(StableUtils.getInstallHome(), ProjectConstants.LOGS_NAME, UpdateConstants.INSTALL_LIB);
final JFrame frame = DesignerContext.getDesignerFrame();
final RestartHelper helper = new RestartHelper();
FineProcessContext.getParentPipe().fire(FineProcessEngineEvent.DESTROY);
new FileProcess(callBack) {
@Override
public void onDownloadSuccess() {
progressBar.setVisible(false);
deleteForDesignerUpdate(installLib);
helper.restartForUpdate(frame);
}
@Override
public void onDownloadFailed() {
progressBar.setVisible(false);
deleteForDesignerUpdate(installLib);
FineJOptionPane.showMessageDialog(getParent(), Toolkit.i18nText("Fine-Design_Update_Info_Failed_Message"));
helper.restartForUpdate(frame);
}
}.execute();
}
}
}
}

6
designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTable.java

@ -10,6 +10,12 @@ import java.util.Vector;
* Created by XINZAI on 2018/8/21.
*/
public class UpdateInfoTable extends JTable {
public static int UPDATE_DATE_INDEX = 0;
public static int UPDATE_VERSION_INDEX = 1;
public static int UPDATE_TITLE_INDEX = 2;
public static int SIGN_INDEX = 3;
private UpdateInfoTableModel dataModel;
public UpdateInfoTable(TableModel dm) {

6
designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableCellRender.java

@ -18,11 +18,11 @@ public class UpdateInfoTableCellRender extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
cell.setBackground((row & 1) != 0 ? new Color(0xf0f0f0) : Color.WHITE);
if ((Boolean) table.getValueAt(row, 2)) {
if ((Boolean) table.getValueAt(row, UpdateInfoTable.SIGN_INDEX)) {
cell.setBackground(new Color(0xdfecfd));
}
if (column == 0) {
//设置首列日期居中显示
if (column == UpdateInfoTable.UPDATE_DATE_INDEX || column == UpdateInfoTable.UPDATE_VERSION_INDEX) {
//设置日期,版本居中显示
setHorizontalAlignment(JLabel.CENTER);
for (int i = 1; row - i >= 0; i++) {

2
designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTextAreaCellRender.java

@ -35,7 +35,7 @@ public class UpdateInfoTextAreaCellRender extends JTextArea implements TableCell
setText(value == null ? "" : value.toString());
setBackground((row & 1) != 0 ? new Color(0xf0f0f0) : Color.WHITE);
if ((Boolean) table.getValueAt(row, 2)) {
if ((Boolean) table.getValueAt(row, UpdateInfoTable.SIGN_INDEX)) {
setBackground(new Color(0xdfecfd));
}
return this;

11
designer-base/src/main/java/com/fr/design/utils/ColorUtils.java

@ -27,4 +27,15 @@ public class ColorUtils {
}
}
}
public static boolean isDarkColor(Color color) {
if(color == null) {
return false;
}
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
int greyLevel = (int)(red * 0.299 + green * 0.587 + blue * 0.114);
return greyLevel < 192;
}
}

29
designer-base/src/main/java/com/fr/design/utils/DesignUtils.java

@ -24,18 +24,16 @@ import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.os.OperatingSystem;
import com.fr.start.ServerStarter;
import com.fr.start.common.DesignerStartupContext;
import com.fr.startup.ui.StartupPageModel;
import com.fr.value.NotNullLazyValue;
import com.fr.workspace.WorkContext;
import org.jetbrains.annotations.NotNull;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
@ -50,6 +48,7 @@ import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -216,6 +215,28 @@ public class DesignUtils {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
DesignerStartupContext context = DesignerStartupContext.getInstance();
// 如果在启动页展示中
if (context.isOnWaiting()) {
FileFILE fileFILE = new FileFILE(f);
// 设置上一次启动模板为
DesignerEnvManager.getEnvManager().setLastOpenFile(fileFILE.getPath());
StartupPageModel model = context.getStartupPageModel();
Optional.ofNullable(model)
.ifPresent((e) -> {
// 执行上一次模板的启动
Runnable openLastTemplateRunnable = e.getOpenLastTemplateRunnable();
openLastTemplateRunnable.run();
});
return;
}
// 如果是在启动中
if (context.isOnStartup()) {
// 之前就有这样的问题
return;
}
// 打开模板
DesignerContext.getDesignerFrame().openTemplate(new FileFILE(f));
}
});

87
designer-base/src/main/java/com/fr/design/widget/component/CheckBoxDictPane.java → designer-base/src/main/java/com/fr/design/widget/component/ReturnTypePane.java

@ -1,32 +1,29 @@
package com.fr.design.widget.component;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.gui.ibutton.UIButtonGroup;
import com.fr.design.gui.ilable.UILabel;
import javax.swing.*;
import com.fr.design.gui.icombobox.DictionaryComboBox;
import com.fr.design.gui.icombobox.DictionaryConstants;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.form.ui.CheckBoxGroup;
import com.fr.form.ui.ComboCheckBox;
import com.fr.form.ui.ReturnTypeProvider;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Component;
public class CheckBoxDictPane extends JPanel {
public class ReturnTypePane extends JPanel {
private DictionaryComboBox delimiterComboBox;
private UIButtonGroup returnTypeComboBox;
private DictionaryComboBox startComboBox;
private DictionaryComboBox endComboBox;
private JPanel returnStringPane;
private final DictionaryComboBox delimiterComboBox;
private final UIButtonGroup returnTypeComboBox;
private final DictionaryComboBox startComboBox;
private final DictionaryComboBox endComboBox;
private final JPanel returnStringPane;
public CheckBoxDictPane() {
public ReturnTypePane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
delimiterComboBox = new DictionaryComboBox(DictionaryConstants.delimiters, DictionaryConstants.delimiterDisplays);
delimiterComboBox.setEditable(true);
@ -36,18 +33,13 @@ public class CheckBoxDictPane extends JPanel {
endComboBox.setEditable(true);
Component[][] components = new Component[][]{
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Delimiter")), delimiterComboBox},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Combo_CheckBox_Start_Symbol")),startComboBox},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Combo_CheckBox_End_Symbol")),endComboBox}
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Combo_CheckBox_Start_Symbol")), startComboBox},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Combo_CheckBox_End_Symbol")), endComboBox}
};
returnStringPane = TableLayoutHelper.createGapTableLayoutPane(components, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W2, IntervalConstants.INTERVAL_L1);
returnTypeComboBox = new UIButtonGroup(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Widget_Array"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_String")});
returnTypeComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
checkVisible(returnTypeComboBox.getSelectedIndex());
}
});
returnTypeComboBox.addActionListener(e -> checkVisible(returnTypeComboBox.getSelectedIndex()));
JPanel headPane = TableLayoutHelper.createGapTableLayoutPane(
new Component[][]{new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Widget_Date_Selector_Return_Type")), returnTypeComboBox}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L2, IntervalConstants.INTERVAL_L1);
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
@ -57,34 +49,33 @@ public class CheckBoxDictPane extends JPanel {
this.add(jPanel);
}
public void checkVisible(int selectIndex){
returnStringPane.setVisible(selectIndex == 1);
public void setReturnType(ReturnType returnType) {
int selectIndex = returnType == ReturnType.ARRAY ? 0 : 1;
returnTypeComboBox.setSelectedIndex(selectIndex,true);
checkVisible(selectIndex);
}
public void populate(ComboCheckBox comboCheckBox) {
this.delimiterComboBox.setSelectedItem(comboCheckBox.getDelimiter());
this.returnTypeComboBox.setSelectedIndex(comboCheckBox.isReturnString() ? 1 : 0);
this.startComboBox.setSelectedItem(comboCheckBox.getStartSymbol());
this.endComboBox.setSelectedItem(comboCheckBox.getEndSymbol());
checkVisible(this.returnTypeComboBox.getSelectedIndex());
public void checkVisible(int selectIndex) {
returnStringPane.setVisible(selectIndex == 1);
}
public void update(ComboCheckBox comboCheckBox) {
comboCheckBox.setDelimiter((String)this.delimiterComboBox.getSelectedItem());
comboCheckBox.setReturnString(this.returnTypeComboBox.getSelectedIndex() != 0);
comboCheckBox.setStartSymbol((String)this.startComboBox.getSelectedItem());
comboCheckBox.setEndSymbol((String)this.endComboBox.getSelectedItem());
public void update(ReturnTypeProvider returnTypeProvider) {
returnTypeProvider.setDelimiter((String) this.delimiterComboBox.getSelectedItem());
returnTypeProvider.setReturnString(this.returnTypeComboBox.getSelectedIndex() != 0);
returnTypeProvider.setStartSymbol((String) this.startComboBox.getSelectedItem());
returnTypeProvider.setEndSymbol((String) this.endComboBox.getSelectedItem());
}
public void populate(CheckBoxGroup checkBoxGroup) {
this.delimiterComboBox.setSelectedItem(checkBoxGroup.getDelimiter());
this.returnTypeComboBox.setSelectedIndex(checkBoxGroup.isReturnString() ? 1 : 0);
this.startComboBox.setSelectedItem(checkBoxGroup.getStartSymbol());
this.endComboBox.setSelectedItem(checkBoxGroup.getEndSymbol());
public void populate(ReturnTypeProvider returnTypeProvider) {
this.delimiterComboBox.setSelectedItem(returnTypeProvider.getDelimiter());
this.returnTypeComboBox.setSelectedIndex(returnTypeProvider.isReturnString() ? 1 : 0);
this.startComboBox.setSelectedItem(returnTypeProvider.getStartSymbol());
this.endComboBox.setSelectedItem(returnTypeProvider.getEndSymbol());
checkVisible(this.returnTypeComboBox.getSelectedIndex());
}
public void update(CheckBoxGroup checkBoxGroup) {
checkBoxGroup.setDelimiter((String)this.delimiterComboBox.getSelectedItem());
checkBoxGroup.setReturnString(this.returnTypeComboBox.getSelectedIndex() != 0);
checkBoxGroup.setStartSymbol((String)this.startComboBox.getSelectedItem());
checkBoxGroup.setEndSymbol((String)this.endComboBox.getSelectedItem());
public enum ReturnType {
STRING,
ARRAY
}
}

79
designer-base/src/main/java/com/fr/start/BaseDesigner.java

@ -3,7 +3,6 @@
*/
package com.fr.start;
import com.fr.base.extension.FileExtension;
import com.fr.common.report.ReportState;
import com.fr.design.DesignerEnvManager;
import com.fr.design.ExtraDesignClassManager;
@ -15,6 +14,7 @@ import com.fr.design.fun.DesignerStartOpenFileProcessor;
import com.fr.design.fun.impl.DesignerStartWithEmptyFile;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.toolbar.ToolBarMenuDock;
import com.fr.design.monitor.DesignerLifecycleMonitorContext;
import com.fr.design.ui.util.UIUtil;
@ -26,18 +26,17 @@ import com.fr.event.Null;
import com.fr.exit.DesignerExiter;
import com.fr.file.FILE;
import com.fr.file.FILEFactory;
import com.fr.file.FileFILE;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.process.ProcessEventPipe;
import com.fr.process.engine.core.CarryMessageEvent;
import com.fr.process.engine.core.FineProcessContext;
import com.fr.stable.OperatingSystem;
import com.fr.start.common.DesignerStartupContext;
import com.fr.start.common.DesignerStartupUtil;
import com.fr.start.event.LazyStartupEvent;
import com.fr.workspace.base.WorkspaceStatus;
import java.awt.Window;
import java.io.File;
import java.lang.reflect.Method;
/**
@ -124,24 +123,14 @@ public abstract class BaseDesigner extends ToolBarMenuDock {
try {
FILE file = null;
if (args != null && args.length > 0) {
// p:需要打开这个报表文件,这个代码不能删除.
for (String arg : args) {
if (ComparatorUtils.equals("demo", arg)) {
file = FILEFactory.createFILE(FILEFactory.ENV_PREFIX + DesignerEnvManager.getEnvManager().getLastOpenFile());
break;
}
File f = new File(arg);
String path = f.getAbsolutePath();
if (isAcceptFilePathEnd(path)) {
file = new FileFILE(f);
}
}
file = DesignerStartupUtil.convertArgs2FILE(args);
} else {
file = FILEFactory.createFILE(FILEFactory.ENV_PREFIX + DesignerEnvManager.getEnvManager().getLastOpenFile());
}
DesignerFrame df = DesignerContext.getDesignerFrame();
isException = openFile(df, isException, file);
df.fireDesignerOpened();
FineLoggerFactory.getLogger().debug("show designer cost {} ms", DesignerStartupContext.getRecorder().getTime());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
if (!isException) {
@ -152,21 +141,6 @@ public abstract class BaseDesigner extends ToolBarMenuDock {
}
}
private boolean isAcceptFilePathEnd(String path) {
FileExtension[] acceptFileExtensions = new FileExtension[]{
FileExtension.CPT, FileExtension.XLS, FileExtension.XLSX, FileExtension.FRM, FileExtension.CHT, FileExtension.VIS
};
for (FileExtension acceptFileExtension : acceptFileExtensions) {
String[] extensions = acceptFileExtension.getExtensions();
for (String extension : extensions) {
if (path.endsWith("." + extension)) {
return true;
}
}
}
return false;
}
private boolean openFile(final DesignerFrame df, boolean isException, FILE file) {
//启动时打开指定文件的接口
@ -183,17 +157,50 @@ public abstract class BaseDesigner extends ToolBarMenuDock {
isException = true;//此时有文件nullpointer异常,执行打开空文件
}
}
openTemplate(df, isException, file);
if (OperatingSystem.isMacOS()) {
enableFullScreenMode(df);
}
JTemplate<?, ?> selectedJTemplate = df.getSelectedJTemplate();
if (selectedJTemplate != null) {
selectedJTemplate.requestGridFocus();
}
return isException;
}
private void openTemplate(DesignerFrame df, boolean isException, FILE file) {
boolean onStartup = DesignerStartupContext.getInstance().isSupport();
if (onStartup) {
DesignerStartupContext context = DesignerStartupContext.getInstance();
if (context.isCreateNew()) {
df.addAndActivateJTemplate();
// 如果没有模板,则需要确认一下
MutilTempalteTabPane.getInstance().setTemTemplate(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate());
return;
}
if (context.isOpenLastFile()) {
if (file != null && file.exists() && !isException) {
df.openTemplate(file);
return;
}
}
if (context.isOpenEmpty()) {
df.showEmptyJTemplate();
return;
}
}
if (file != null && file.exists() && !isException) {
df.openTemplate(file);
} else {
df.addAndActivateJTemplate();
// 如果没有模板,则需要确认一下
MutilTempalteTabPane.getInstance().setTemTemplate(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate());
}
if (OperatingSystem.isMacOS()) {
enableFullScreenMode(df);
}
df.getSelectedJTemplate().requestGridFocus();
return isException;
}
private void enableFullScreenMode(Window window) {

77
designer-base/src/main/java/com/fr/start/common/DesignerOpenEmptyPanel.java

@ -0,0 +1,77 @@
package com.fr.start.common;
import com.fr.base.svg.IconUtils;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.file.MutilTempalteTabPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.DesignSizeI18nManager;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.design.utils.ColorUtils;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* created by Harrison on 2022/07/09
**/
public class DesignerOpenEmptyPanel extends JPanel {
private static final Color BUTTON_COLOR = new Color(63, 155, 249);
private static final int ARC = 4;
private final JPanel body;
public DesignerOpenEmptyPanel() {
this.body = FRGUIPaneFactory.createBorderLayout_S_Pane();
UILabel createIcon = new UILabel(IconUtils.readIcon("/com/fr/design/startup/create_new_template.svg"));
JButton createButton = new JButton(Toolkit.i18nText("Fine-Design_New_Template")) {
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(BUTTON_COLOR);
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), ARC, ARC);
super.paintComponent(g2d);
}
};
createButton.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.start.common.DesignerOpenEmptyPanel.createButton"));
createButton.setForeground(Color.WHITE);
createButton.setBorderPainted(false);
createButton.setContentAreaFilled(false);
createButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DesignerFrame df = DesignerContext.getDesignerFrame();
df.addAndActivateJTemplate();
// 如果没有模板,则需要确认一下
MutilTempalteTabPane.getInstance().setTemTemplate(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate());
}
});
createButton.setBorder(new EmptyBorder(0, 10, 0, 10));
JPanel createButtonPanel = new JPanel(FRGUIPaneFactory.createCenterFlowLayout());
createButtonPanel.add(createButton);
createButtonPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
createButtonPanel.setBackground(Color.WHITE);
this.body.add(createIcon, BorderLayout.NORTH);
this.body.add(createButtonPanel, BorderLayout.SOUTH);
setLayout(FRGUIPaneFactory.createCenterLayout(this.body));
ColorUtils.syncBackground(this, Color.WHITE);
add(this.body);
}
}

55
designer-base/src/main/java/com/fr/start/common/DesignerStartupConfig.java

@ -0,0 +1,55 @@
package com.fr.start.common;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLable;
import com.fr.stable.xml.XMLableReader;
public class DesignerStartupConfig implements XMLable {
public static final String XML_TAG = "DesignerStartupConfig";
private static final long serialVersionUID = -8170289826729582122L;
private static final DesignerStartupConfig INSTANCE = new DesignerStartupConfig();
public static DesignerStartupConfig getInstance() {
return INSTANCE;
}
/**
* 默认值是 false
*/
private boolean enabled = false;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public Object clone() throws CloneNotSupportedException {
DesignerStartupConfig config = new DesignerStartupConfig();
config.setEnabled(true);
return config;
}
@Override
public void readXML(XMLableReader reader) {
if (reader.isAttr()) {
this.setEnabled(reader.getAttrAsBoolean("isEnabled", false));
}
}
@Override
public void writeXML(XMLPrintWriter writer) {
writer.startTAG(XML_TAG);
writer.attr("isEnabled", this.isEnabled());
writer.end();
}
}

176
designer-base/src/main/java/com/fr/start/common/DesignerStartupContext.java

@ -0,0 +1,176 @@
package com.fr.start.common;
import com.fr.design.DesignerEnvManager;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.env.DesignerWorkspaceType;
import com.fr.start.module.StartupArgs;
import com.fr.startup.ui.StartupPageModel;
import com.fr.third.guava.collect.Lists;
import com.fr.third.org.apache.commons.lang3.time.StopWatch;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 启动页上下文
*
* created by Harrison on 2022/06/22
**/
public class DesignerStartupContext {
/**
* 启动参数
*/
private StartupArgs startupArgs;
/**
* 启动数据
*/
private StartupPageModel startupPageModel;
/**
* 是否在起始页打开的等待过程中
*/
private boolean onWaiting = false;
/**
* 是否在启动中
*/
private boolean onStartup = true;
/**
* 是否在预热中
*/
private boolean onWarmup = false;
/**
* 打开上一次的文件
*/
private boolean openLastFile;
/**
* 打开空设计器
*/
private boolean openEmpty;
/**
* 直接创建一个新模板
*/
private boolean createNew;
/**
* 时间记录
*/
private static StopWatch STOP_WATCH = new StopWatch();
public static DesignerStartupContext getInstance() {
return StartupContextHolder.INSTANCE;
}
private static class StartupContextHolder {
private static final DesignerStartupContext INSTANCE = new DesignerStartupContext();
}
public static StopWatch getRecorder() {
return STOP_WATCH;
}
/* 启动模式 */
/**
* 展示启动页
* 1. 判断当前的工作目录数量
* 2. 判断是否是 demo还是打开目标文件
* 3. 功能是否开启
*
* @return /
*/
public boolean isShowStartupPage() {
DesignerEnvManager envManager = DesignerEnvManager.getEnvManager();
Iterator<String> envNameIterator = envManager.getEnvNameIterator();
ArrayList<String> envs = Lists.newArrayList(envNameIterator);
return !startupArgs.isDemo() && DesignerStartupUtil.convertArgs2FILE(startupArgs.get()) == null && !envs.isEmpty() && envManager.isStartupPageEnabled();
}
/* 预热相关 */
public boolean onWarmup() {
return this.onWarmup;
}
public boolean canWarmup() {
String curEnvName = DesignerEnvManager.getEnvManager().getCurEnvName();
DesignerWorkspaceInfo workspaceInfo = DesignerEnvManager.getEnvManager().getWorkspaceInfo(curEnvName);
return workspaceInfo.getType() == DesignerWorkspaceType.Local;
}
public void setStartupPageModel(StartupPageModel startupPageModel) {
this.startupPageModel = startupPageModel;
}
public StartupPageModel getStartupPageModel() {
return startupPageModel;
}
public boolean isOnWaiting() {
return onWaiting;
}
public void setOnWaiting(boolean onWaiting) {
this.onWaiting = onWaiting;
}
public boolean isSupport() {
return onStartup && isShowStartupPage();
}
public boolean isOnStartup() {
return onStartup;
}
public void setOnStartup(boolean onStartup) {
this.onStartup = onStartup;
}
/* 文件相关*/
public boolean isOpenLastFile() {
return this.openLastFile;
}
public boolean isOpenEmpty() {
return this.openEmpty;
}
/* set */
public void setOnWarmup(boolean onWarmup) {
this.onWarmup = onWarmup;
}
public void setOpenLastFile(boolean openLastFile) {
this.openLastFile = openLastFile;
}
public void setOpenEmpty(boolean openEmpty) {
this.openEmpty = openEmpty;
}
public boolean isCreateNew() {
return createNew;
}
public void setCreateNew(boolean createNew) {
this.createNew = createNew;
}
public void setStartupArgs(StartupArgs startupArgs) {
this.startupArgs = startupArgs;
}
}

32
designer-base/src/main/java/com/fr/start/common/DesignerStartupExecutor.java

@ -0,0 +1,32 @@
package com.fr.start.common;
import java.util.ArrayList;
import java.util.List;
/**
* created by Harrison on 2022/07/03
**/
public class DesignerStartupExecutor {
private List<Runnable> warmupTasks = new ArrayList<>();
public void execute(Runnable runnable) {
if (!DesignerStartupContext.getInstance().onWarmup()) {
runnable.run();
}
}
public void reset() {
warmupTasks.clear();
}
public static DesignerStartupExecutor getInstance() {
return DesignerStartupExecutorHolder.INSTANCE;
}
private static class DesignerStartupExecutorHolder {
private static final DesignerStartupExecutor INSTANCE = new DesignerStartupExecutor();
}
}

20
designer-base/src/main/java/com/fr/start/common/DesignerStartupPool.java

@ -0,0 +1,20 @@
package com.fr.start.common;
import com.fr.concurrent.FineExecutors;
import com.fr.concurrent.NamedThreadFactory;
import java.util.concurrent.Executor;
/**
* created by Harrison on 2022/07/03
**/
public class DesignerStartupPool {
private static final Executor COMMON_EXECUTOR = FineExecutors.newCachedThreadPool(new NamedThreadFactory("startup-common"));
public static Executor common() {
return COMMON_EXECUTOR;
}
}

51
designer-base/src/main/java/com/fr/start/common/DesignerStartupUtil.java

@ -0,0 +1,51 @@
package com.fr.start.common;
import com.fr.base.extension.FileExtension;
import com.fr.design.DesignerEnvManager;
import com.fr.file.FILE;
import com.fr.file.FILEFactory;
import com.fr.file.FileFILE;
import com.fr.general.ComparatorUtils;
import org.jetbrains.annotations.Nullable;
import java.io.File;
/**
* created by Harrison on 2022/07/09
**/
public class DesignerStartupUtil {
@Nullable
public static FILE convertArgs2FILE(String[] args) {
// p:需要打开这个报表文件,这个代码不能删除.
FILE file = null;
for (String arg : args) {
if (ComparatorUtils.equals("demo", arg)) {
file = FILEFactory.createFILE(FILEFactory.ENV_PREFIX + DesignerEnvManager.getEnvManager().getLastOpenFile());
break;
}
File f = new File(arg);
String path = f.getAbsolutePath();
if (isAcceptFilePathEnd(path)) {
file = new FileFILE(f);
}
}
return file;
}
private static boolean isAcceptFilePathEnd(String path) {
FileExtension[] acceptFileExtensions = new FileExtension[]{
FileExtension.CPT, FileExtension.XLS, FileExtension.XLSX, FileExtension.FRM, FileExtension.CHT, FileExtension.VIS
};
for (FileExtension acceptFileExtension : acceptFileExtensions) {
String[] extensions = acceptFileExtension.getExtensions();
for (String extension : extensions) {
if (path.endsWith("." + extension)) {
return true;
}
}
}
return false;
}
}

0
designer-realize/src/main/java/com/fr/start/module/StartupArgs.java → designer-base/src/main/java/com/fr/start/module/StartupArgs.java

17
designer-base/src/main/java/com/fr/startup/ui/StartupPageConstants.java

@ -0,0 +1,17 @@
package com.fr.startup.ui;
/**
* created by Harrison on 2022/07/07
**/
public class StartupPageConstants {
/**
* 圆弧长度
*/
public static final int ARC_DIAMETER = 20;
/**
* 内容宽度
*/
public static final int CONTENT_WIDTH = 850;
}

111
designer-base/src/main/java/com/fr/startup/ui/StartupPageModel.java

@ -0,0 +1,111 @@
package com.fr.startup.ui;
import com.fr.design.DesignerEnvManager;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.env.DesignerWorkspaceType;
import com.fr.third.guava.collect.Lists;
import com.fr.workspace.connect.WorkspaceConnectionInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* created by Harrison on 2022/07/06
**/
public class StartupPageModel {
private StartupWorkspaceBean selectWorkspaceInfo;
private List<StartupWorkspaceBean> workspaceInfos = new ArrayList<>();
private Map<String, List<String>> recentFilesMap = new HashMap<>();
private Runnable openLastTemplateRunnable;
private Runnable createNewTemplateRunnable;
private Runnable openEmptyTemplateRunnable;
public static StartupPageModel create() {
DesignerEnvManager envManager = DesignerEnvManager.getEnvManager();
Iterator<String> envNameIterator = envManager.getEnvNameIterator();
List<StartupWorkspaceBean> infos = Lists.newArrayList(envNameIterator)
.stream()
.map((e) -> {
DesignerWorkspaceInfo workspaceInfo = envManager.getWorkspaceInfo(e);
if (workspaceInfo.getType() == DesignerWorkspaceType.Remote) {
WorkspaceConnectionInfo connection = workspaceInfo.getConnection();
return new StartupWorkspaceBean(e, connection.getUrl(), workspaceInfo.getType());
} else {
return new StartupWorkspaceBean(e, workspaceInfo.getPath(), workspaceInfo.getType());
}
})
.collect(Collectors.toList());
Map<String, List<String>> recentFileMap = new HashMap<>();
for (StartupWorkspaceBean info : infos) {
String name = info.getName();
List<String> recentFiles = envManager.getRecentOpenedFilePathList4Env(name);
recentFileMap.put(name, recentFiles);
}
return new StartupPageModel(infos, recentFileMap);
}
public StartupPageModel(List<StartupWorkspaceBean> workspaceInfos, Map<String, List<String>> recentFilesMap) {
this.selectWorkspaceInfo = workspaceInfos.get(0);
this.workspaceInfos = workspaceInfos;
this.recentFilesMap = recentFilesMap;
}
public StartupWorkspaceBean getSelectWorkspaceInfo() {
return selectWorkspaceInfo;
}
public void setSelectWorkspaceInfo(StartupWorkspaceBean selectWorkspaceInfo) {
this.selectWorkspaceInfo = selectWorkspaceInfo;
}
public List<StartupWorkspaceBean> getWorkspaceInfos() {
return workspaceInfos;
}
public void setWorkspaceInfos(List<StartupWorkspaceBean> workspaceInfos) {
this.workspaceInfos = workspaceInfos;
}
public Map<String, List<String>> getRecentFilesMap() {
return recentFilesMap;
}
public void setRecentFilesMap(Map<String, List<String>> recentFilesMap) {
this.recentFilesMap = recentFilesMap;
}
public Runnable getOpenLastTemplateRunnable() {
return openLastTemplateRunnable;
}
public void setOpenLastTemplateRunnable(Runnable openLastTemplateRunnable) {
this.openLastTemplateRunnable = openLastTemplateRunnable;
}
public Runnable getCreateNewTemplateRunnable() {
return createNewTemplateRunnable;
}
public void setCreateNewTemplateRunnable(Runnable createNewTemplateRunnable) {
this.createNewTemplateRunnable = createNewTemplateRunnable;
}
public Runnable getOpenEmptyTemplateRunnable() {
return openEmptyTemplateRunnable;
}
public void setOpenEmptyTemplateRunnable(Runnable openEmptyTemplateRunnable) {
this.openEmptyTemplateRunnable = openEmptyTemplateRunnable;
}
}

40
designer-base/src/main/java/com/fr/startup/ui/StartupPageUtil.java

@ -0,0 +1,40 @@
package com.fr.startup.ui;
import com.fr.base.svg.SVGIcon;
import com.fr.design.env.DesignerWorkspaceType;
import javax.swing.Icon;
/**
* created by Harrison on 2022/07/11
**/
public class StartupPageUtil {
/**
* 获取最近区域的 ICON
*
* @param workspaceBean 工作目录
* @return 图标
*/
public static Icon getIcon4RecentAreaByWorkspace(StartupWorkspaceBean workspaceBean) {
if (workspaceBean.getType() == DesignerWorkspaceType.Local) {
return SVGIcon.readSVGIcon("/com/fr/design/startup/local_server_background_36.svg", 36, 36);
}
return SVGIcon.readSVGIcon("/com/fr/design/startup/remote_server_background_36.svg", 36, 36);
}
/**
* 获取工作目录描述区域的 ICON
*
* @param workspaceBean 工作目录
* @return 图标
*/
public static Icon getIcon4DescAreaByWorkspace(StartupWorkspaceBean workspaceBean) {
if (workspaceBean.getType() == DesignerWorkspaceType.Local) {
return SVGIcon.readSVGIcon("/com/fr/design/startup/local_server_background_28.svg", 28, 28);
}
return SVGIcon.readSVGIcon("/com/fr/design/startup/remote_server_background_28.svg", 28, 28);
}
}

339
designer-base/src/main/java/com/fr/startup/ui/StartupPageWindow.java

@ -0,0 +1,339 @@
package com.fr.startup.ui;
import com.fr.base.svg.IconUtils;
import com.fr.design.DesignerEnvManager;
import com.fr.design.components.loading.LoadingPane;
import com.fr.design.dialog.UIExpandDialog;
import com.fr.design.gui.icontainer.UIScrollPane;
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.ui.util.UIUtil;
import com.fr.design.utils.ColorUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.collections.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.border.EmptyBorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.Map;
/**
* 启动页
* <a href="https://kms.fineres.com/pages/viewpage.action?pageId=416850313">设计文档</a>
* <p>
* created by Harrison on 2022/07/06
**/
public class StartupPageWindow extends JFrame {
private static final int CONTENT_LAYER = 0;
private static final int TRANSPARENT_LAYER = 1;
private static final Color HOVER_COLOR = new Color(65, 155, 249);
private static final Color SEP_COLOR = new Color(224, 224, 225);
private static final int GROUP_WIDTH = 600;
private static final int RECENT_FILE_LIMIT = 6;
private static final int RECENT_FILE_SCROLL = RECENT_FILE_LIMIT + 1;
private static final int WORKSPACE_PANEL_WIDTH = 180;
private static final int TITLE_FONT_SIZE = 24;
private static final int ITEM_VERTICAL_GAP = 5;
private static final Dimension SCREEN_SIZE = new Dimension(1600, 820);
private StartupPageWorkspacePanel workspacePanel;
private JPanel recentOpenPanel;
private JPanel contentPane;
private JPanel body;
private LoadingPane loadingPane = new LoadingPane();
private JLayeredPane layeredPane = new JLayeredPane() {
@Override
public void doLayout() {
for (Component comp : getComponents()) {
comp.setBounds(0, 0, getWidth(), getHeight());
}
}
};
public StartupPageWindow(StartupPageModel pageModel) {
patchUIAction(pageModel);
setLayout(new BorderLayout());
this.body = FRGUIPaneFactory.createBorderLayout_S_Pane();
// Header
UILabel label = new UILabel(Toolkit.i18nText("Fine-Design_Startup_Page_Select_Workspace"));
Font font = label.getFont();
Font titleFont = font.deriveFont(font.getStyle(), TITLE_FONT_SIZE);
label.setFont(titleFont);
JPanel headerPanel = new JPanel();
LayoutManager centerFlowLayout = FRGUIPaneFactory.createCenterFlowLayout();
headerPanel.setLayout(centerFlowLayout);
headerPanel.add(label);
this.body.add(headerPanel, BorderLayout.NORTH);
// Workspace-description
this.workspacePanel = generateWorkspacePanel(pageModel);
this.body.add(workspacePanel, BorderLayout.CENTER);
workspacePanel.setSelectWorkspaceRunnable(new Runnable() {
@Override
public void run() {
JPanel newPanel = generateRecentOpenPanel(pageModel);
body.remove(recentOpenPanel);
recentOpenPanel = newPanel;
body.add(recentOpenPanel, BorderLayout.SOUTH);
validate();
repaint();
}
});
this.recentOpenPanel = generateRecentOpenPanel(pageModel);
this.body.add(recentOpenPanel, BorderLayout.SOUTH);
this.contentPane = new JPanel();
this.contentPane.setLayout(getCenterLayout(body));
this.contentPane.add(this.body, BorderLayout.CENTER);
this.contentPane.setPreferredSize(this.body.getPreferredSize());
this.layeredPane.setName("layered-pane");
this.layeredPane.add(this.contentPane, CONTENT_LAYER);
this.layeredPane.add(this.loadingPane, TRANSPARENT_LAYER);
this.layeredPane.moveToFront(this.contentPane);
add(this.layeredPane, BorderLayout.CENTER);
// Workspace-detail
setSize(SCREEN_SIZE);
repaint();
validate();
revalidate();
GUICoreUtils.centerWindow(this);
}
private void patchUIAction(StartupPageModel pageModel) {
Runnable selectAndOpenLastTemplateRunnable = pageModel.getOpenLastTemplateRunnable();
pageModel.setOpenLastTemplateRunnable(() -> {
enterWorkspace(selectAndOpenLastTemplateRunnable);
});
Runnable createNewTemplateRunnable = pageModel.getCreateNewTemplateRunnable();
pageModel.setCreateNewTemplateRunnable(() -> {
enterWorkspace(createNewTemplateRunnable);
});
Runnable openEmptyTemplateRunnable = pageModel.getOpenEmptyTemplateRunnable();
pageModel.setOpenEmptyTemplateRunnable(() -> {
enterWorkspace(openEmptyTemplateRunnable);
});
}
private void enterWorkspace(Runnable action) {
loadingPane.start();
layeredPane.moveToFront(loadingPane);
SwingWorker<Void, Void> task = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
action.run();
return null;
}
@Override
protected void done() {
try {
Void result = get();
setVisible(false);
} catch (Exception e) {
// 处理错误
UIUtil.invokeLaterIfNeeded(() -> {
UIExpandDialog.Builder()
.owner(StartupPageWindow.this)
.title(Toolkit.i18nText("Fine-Design_Basic_Remote_Env_Try"))
.message(Toolkit.i18nText("Fine-Design_Basic_Connection_Failed"))
.messageType(UIExpandDialog.WARNING_MESSAGE)
.detail(e.getMessage())
.expand(true)
.modal(false)
.build()
.setVisible(true);
});
FineLoggerFactory.getLogger().error(e.getMessage(), e);
layeredPane.moveToFront(contentPane);
} finally {
loadingPane.stop();
}
}
};
task.execute();
}
private JPanel generateRecentOpenPanel(StartupPageModel pageModel) {
JPanel recentOpenPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.WHITE);
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), StartupPageConstants.ARC_DIAMETER, StartupPageConstants.ARC_DIAMETER);
}
};
recentOpenPanel.setLayout(new BorderLayout());
recentOpenPanel.setBorder(BorderFactory.createEmptyBorder(25, 25, 25, 6));
StartupWorkspaceBean workspaceInfo = pageModel.getSelectWorkspaceInfo();
JPanel workspaceWrapperYPanel = new JPanel();
workspaceWrapperYPanel.setName("workspace-wrapper");
{
workspaceWrapperYPanel.setLayout(new VerticalFlowLayout());
JPanel workspaceWrapperXPanel = new JPanel();
workspaceWrapperXPanel.setLayout(new FlowLayout());
workspaceWrapperXPanel.setBorder(BorderFactory.createEmptyBorder());
JPanel workspacePanel = new JPanel();
workspacePanel.setLayout(new BorderLayout(0, 15));
UILabel workspaceIcon = new UILabel(StartupPageUtil.getIcon4RecentAreaByWorkspace(workspaceInfo));
workspacePanel.add(workspaceIcon, BorderLayout.NORTH);
UILabel nameLabel = new UILabel(workspaceInfo.getName());
nameLabel.setHorizontalAlignment(SwingConstants.CENTER);
workspacePanel.add(nameLabel, BorderLayout.SOUTH);
workspaceWrapperXPanel.add(workspacePanel);
Dimension preferredSize = workspaceWrapperXPanel.getPreferredSize();
workspaceWrapperXPanel.setPreferredSize(new Dimension(WORKSPACE_PANEL_WIDTH, (int) preferredSize.getHeight()));
workspaceWrapperYPanel.add(workspaceWrapperXPanel);
}
recentOpenPanel.add(workspaceWrapperYPanel, BorderLayout.WEST);
JPanel separatorPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
{
JSeparator sep = new JSeparator();
sep.setOrientation(JSeparator.VERTICAL);
sep.setForeground(SEP_COLOR);
separatorPanel.add(sep, BorderLayout.CENTER);
}
recentOpenPanel.add(separatorPanel, BorderLayout.CENTER);
JComponent recentOpenGroupPanel = generateRecentOpenGroupPanel(pageModel, workspaceInfo);
recentOpenPanel.add(recentOpenGroupPanel, BorderLayout.EAST);
ColorUtils.syncBackground(recentOpenPanel, Color.WHITE);
Dimension preferredSize = recentOpenPanel.getPreferredSize();
recentOpenPanel.setPreferredSize(new Dimension(StartupPageConstants.CONTENT_WIDTH, (int) preferredSize.getHeight()));
JPanel recentOpenWrapperPanel = new JPanel();
recentOpenWrapperPanel.setName("recentOpenWrapper");
recentOpenWrapperPanel.setLayout(new BorderLayout(0, 0));
recentOpenWrapperPanel.setBorder(new EmptyBorder(0, 0, 0, 20));
recentOpenWrapperPanel.add(recentOpenPanel, BorderLayout.CENTER);
return recentOpenWrapperPanel;
}
@NotNull
private JComponent generateRecentOpenGroupPanel(StartupPageModel pageModel, StartupWorkspaceBean workspaceInfo) {
JPanel recentOpenGroupPanel = new JPanel();
Map<String, List<String>> recentFilesMap = pageModel.getRecentFilesMap();
boolean needScroll = false;
double itemHeight = 0.0d;
if (!CollectionUtils.isEmpty(recentFilesMap)) {
String name = workspaceInfo.getName();
List<String> recentFiles = recentFilesMap.get(name);
if (!CollectionUtils.isEmpty(recentFiles)) {
recentOpenGroupPanel.setLayout(new GridLayout(recentFiles.size(), 1, 50, 5));
needScroll = recentFiles.size() > RECENT_FILE_LIMIT;
for (String recentFile : recentFiles) {
JPanel recentItemPanel = new JPanel();
recentItemPanel.setLayout(new FlowLayout(FlowLayout.LEFT, ITEM_VERTICAL_GAP, 0));
recentItemPanel.add(new UILabel(IconUtils.readIcon("/com/fr/design/standard/system/cpt.svg")));
UILabel recentFileLabel = new UILabel(recentFile);
Color recentFileLabelForeground = recentFileLabel.getForeground();
recentItemPanel.add(recentFileLabel);
recentItemPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
recentFileLabel.setForeground(HOVER_COLOR);
}
@Override
public void mouseExited(MouseEvent e) {
recentFileLabel.setForeground(recentFileLabelForeground);
}
@Override
public void mouseClicked(MouseEvent e) {
DesignerEnvManager.getEnvManager().setLastOpenFile(recentFile);
pageModel.getOpenLastTemplateRunnable().run();
}
});
Dimension preferredSize = recentItemPanel.getPreferredSize();
itemHeight = preferredSize.getHeight();
recentOpenGroupPanel.add(recentItemPanel);
}
}
}
Dimension preferredSize = recentOpenGroupPanel.getPreferredSize();
recentOpenGroupPanel.setPreferredSize(new Dimension(GROUP_WIDTH, (int) preferredSize.getHeight()));
if (needScroll) {
int scrollHeight = (int) Math.round(itemHeight * RECENT_FILE_LIMIT + ITEM_VERTICAL_GAP * (RECENT_FILE_SCROLL));
UIScrollPane scrollPane = new UIScrollPane(recentOpenGroupPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBorder(new EmptyBorder(0, 0, 0, 0));
scrollPane.setPreferredSize(new Dimension(GROUP_WIDTH, scrollHeight));
return scrollPane;
}
return recentOpenGroupPanel;
}
private StartupPageWorkspacePanel generateWorkspacePanel(StartupPageModel pageModel) {
return new StartupPageWorkspacePanel(pageModel);
}
protected LayoutManager getCenterLayout(JComponent centerBody) {
return FRGUIPaneFactory.createCenterLayout(centerBody);
}
}

501
designer-base/src/main/java/com/fr/startup/ui/StartupPageWorkspacePanel.java

@ -0,0 +1,501 @@
package com.fr.startup.ui;
import com.fr.base.svg.IconUtils;
import com.fr.design.components.tooltip.ModernToolTip;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.utils.ColorUtils;
import com.fr.third.guava.collect.Lists;
import org.jetbrains.annotations.NotNull;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JToolTip;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.EmptyBorder;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static com.fr.startup.ui.StartupPageConstants.ARC_DIAMETER;
/**
* created by Harrison on 2022/07/06
**/
public class StartupPageWorkspacePanel extends JPanel {
/* color */
private static final Color SHALLOW_WHITE_COLOR = new Color(248, 250, 254);
private static final Color HOVER_COLOR = new Color(65, 155, 249);
private static final Color PATH_COLOR = new Color(51, 51, 52, (int) Math.round(255 * 0.5));
/* 长度 */
private static final int SCROLL_BAR_WIDTH = 20;
private static final int CONTENT_WIDTH = StartupPageConstants.CONTENT_WIDTH + SCROLL_BAR_WIDTH;
private static final int BORDER_THIN = 2;
private static final int ITEM_VERTICAL_GAP = 20;
private static final int SINGLE_ITEM_HEIGHT = 72;
private static final int SCROLL_HEIGHT = SINGLE_ITEM_HEIGHT * 4 + ITEM_VERTICAL_GAP * 4;
private static final int NAME_LABEL_SIZE = 15;
private static final int PATH_LABEL_SIZE = 10;
private static final Dimension LABEL_DIMENSION = new Dimension(28, 28);
private static final Dimension PATH_DIMENSION = new Dimension(100, 20);
private static final Dimension SELECT_WORKSPACE_DIMENSION = new Dimension(210, 72);
private static final Dimension SELECT_CREATE_DIMENSION = new Dimension(60, 72);
public static final int COLUMN_LIMIT = 3;
/* model */
private final StartupPageModel pageModel;
private final List<List<StartupWorkspaceBean>> partitions;
private Runnable selectWorkspaceRunnable;
private final Runnable createNewTemplateRunnable;
private final Runnable openEmptyTemplateRunnable;
private JComponent contentPanel;
private JPanel tailPanel;
private boolean showMore = true;
public StartupPageWorkspacePanel(StartupPageModel pageModel) {
this.setLayout(new BorderLayout(0, 0));
this.pageModel = pageModel;
List<StartupWorkspaceBean> workspaceInfos = pageModel.getWorkspaceInfos();
this.partitions = Lists.partition(workspaceInfos, COLUMN_LIMIT);
this.contentPanel = generateLimitContentPanel(partitions);
this.add(contentPanel, BorderLayout.NORTH);
this.tailPanel = generateTailPanel();
this.createNewTemplateRunnable = pageModel.getCreateNewTemplateRunnable();
this.openEmptyTemplateRunnable = pageModel.getOpenEmptyTemplateRunnable();
this.add(tailPanel, BorderLayout.SOUTH);
this.repaint();
}
public void showLessContent() {
this.remove(this.contentPanel);
this.contentPanel = generateLimitContentPanel(this.partitions);
this.add(contentPanel, BorderLayout.NORTH);
}
public void showMoreContent() {
this.remove(this.contentPanel);
this.contentPanel = generateUnLimitContentPanel(this.partitions);
this.add(contentPanel, BorderLayout.NORTH);
}
private JComponent generateUnLimitContentPanel(List<List<StartupWorkspaceBean>> partitions) {
JPanel workspaceDescPanel = new JPanel();
workspaceDescPanel.setLayout(new GridLayout(partitions.size(), 1, 0, ITEM_VERTICAL_GAP));
for (List<StartupWorkspaceBean> partition : partitions) {
JPanel partitionPanel = generatePartitionPanel(partition);
workspaceDescPanel.add(partitionPanel);
}
boolean needScroll = partitions.size() > 4;
if (needScroll) {
// 滚动条
UIScrollPane scrollPane = new UIScrollPane(workspaceDescPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBorder(new EmptyBorder(10, 0, 0, 0));
scrollPane.setPreferredSize(new Dimension(CONTENT_WIDTH, SCROLL_HEIGHT));
return scrollPane;
}
return workspaceDescPanel;
}
private JPanel generateLimitContentPanel(List<List<StartupWorkspaceBean>> partitions) {
JPanel workspaceDescPanel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEFT, 0, ITEM_VERTICAL_GAP);
int limit = 2;
for (int i = 0; i < partitions.size(); i++) {
if (i >= limit) {
break;
}
List<StartupWorkspaceBean> partition = partitions.get(i);
JPanel partitionPanel = generatePartitionPanel(partition);
workspaceDescPanel.add(partitionPanel);
}
return workspaceDescPanel;
}
@NotNull
private JPanel generateTailPanel() {
JPanel tailPanel = new JPanel();
{
tailPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
tailPanel.setBorder(new EmptyBorder(0, 0, 0, 20));
JPanel showAllPanel = new JPanel();
showAllPanel.setLayout(new BorderLayout(5, 0));
showAllPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
UILabel fontLabel = new UILabel(Toolkit.i18nText("Fine-Design_Startup_Page_Expand_All"));
fontLabel.setForeground(HOVER_COLOR);
showAllPanel.add(fontLabel, BorderLayout.WEST);
UILabel iconLabel = new UILabel(IconUtils.readIcon("/com/fr/design/startup/show_more.svg"));
showAllPanel.add(iconLabel, BorderLayout.EAST);
Color showAllBackground = showAllPanel.getBackground();
showAllPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
Color hoverColor = new Color(217, 235, 254);
showAllPanel.setBackground(hoverColor);
}
@Override
public void mouseExited(MouseEvent e) {
ColorUtils.syncBackground(showAllPanel, showAllBackground);
}
@Override
public void mousePressed(MouseEvent e) {
if (showMore) {
fontLabel.setText(Toolkit.i18nText("Fine-Design_Startup_Page_Collapse_Workspace"));
iconLabel.setIcon(IconUtils.readIcon("/com/fr/design/startup/show_less.svg"));
showMoreContent();
showMore = !showMore;
} else {
fontLabel.setText(Toolkit.i18nText("Fine-Design_Startup_Page_Expand_All"));
iconLabel.setIcon(IconUtils.readIcon("/com/fr/design/startup/show_more.svg"));
showLessContent();
showMore = !showMore;
}
}
});
tailPanel.add(showAllPanel);
Dimension preferredSize = tailPanel.getPreferredSize();
tailPanel.setPreferredSize(new Dimension(CONTENT_WIDTH, (int) preferredSize.getHeight()));
}
return tailPanel;
}
@NotNull
private JPanel generatePartitionPanel(List<StartupWorkspaceBean> partition) {
JPanel partitionPanel = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 20, 0);;
partitionPanel.setName("partitionPanel");
for (StartupWorkspaceBean workspaceInfo : partition) {
JPanel workspaceItemDesc = FRGUIPaneFactory.createBorderLayout_S_Pane();
layoutSelectWorkspacePanel(workspaceInfo, workspaceItemDesc);
layoutSelectAndCreatePanel(workspaceItemDesc);
partitionPanel.add(workspaceItemDesc);
Dimension preferredSize = partitionPanel.getPreferredSize();
partitionPanel.setPreferredSize(new Dimension(CONTENT_WIDTH, (int) preferredSize.getHeight()));
}
return partitionPanel;
}
private void layoutSelectWorkspacePanel(StartupWorkspaceBean workspaceInfo, JPanel workspaceItemDesc) {
// 选择工作目录
// 图标 / 分隔符 / 说明-进入
// 选择并新建
AtomicReference<Color> borderColorRef = new AtomicReference<>(null);
JPanel selectWorkspacePanel = new JPanel() {
@Override
public JToolTip createToolTip() {
return new ModernToolTip();
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color borderColor = borderColorRef.get();
Color backColor = Color.WHITE;
g2d.setColor(backColor);
// 直角和圆角上下叠合在一起
int rectOffset = 10;
int roundOffset = 15;
// 填充一个直角
g2d.fillRoundRect(0, 0, getWidth() - rectOffset, getHeight(), ARC_DIAMETER, ARC_DIAMETER);
// 填充一个圆角
g2d.fillRoundRect(getWidth() - roundOffset, 0, roundOffset, getHeight(), 0, 0);
paintBorderIfHover(g2d, borderColor, backColor);
}
/**
* 当悬浮的时候将边框展示出来
* 会叠合然后填充中间
*
* |-------
* | A C B
* |-------
*
* 见上面有两种线分别是 A- B-
* 这里会将 A B 叠在一起中间则存在 C然后将 C 的部分扩大一点然后填充上背景
* 则形成下面这种图形
*
* |----
* |----
*
* @param g2d 绘画
* @param borderColor 边框颜色
* @param backColor 背景颜色
*/
private void paintBorderIfHover(Graphics2D g2d, Color borderColor, Color backColor) {
if (borderColor != null) {
g2d.setColor(borderColor);
g2d.setStroke(new BasicStroke(BORDER_THIN));
// 需要一个修正值
int strokeOffset = BORDER_THIN / 2;
// 直角和圆角上下叠合在一起
int rectOffset = 10;
int roundOffset = 15;
// 画一个圆角
int fixRoundWidth = getWidth() - rectOffset;
int fixRoundHeight = getHeight() - BORDER_THIN;
g2d.drawRoundRect(strokeOffset, strokeOffset, fixRoundWidth, fixRoundHeight, ARC_DIAMETER, ARC_DIAMETER);
// 画一个直角
g2d.drawRoundRect(getWidth() - roundOffset, strokeOffset, roundOffset - strokeOffset, getHeight() - BORDER_THIN, 0, 0);
g2d.setColor(backColor);
// 绘制一个矩形,覆盖住多余的相交线
// 需要考虑上下的线宽
int coverHeight = getHeight() - (BORDER_THIN * 2);
// 偏左一点的 fixedX
int fixedX = getWidth() - roundOffset - BORDER_THIN;
// 圆角和直角相交的区域
int coverWidth = 10;
g2d.fillRect(fixedX, BORDER_THIN, coverWidth, coverHeight);
}
}
};
selectWorkspacePanel.setLayout(new BorderLayout(0,0));
selectWorkspacePanel.setToolTipText(Toolkit.i18nText("Fine-Design_Startup_Page_Double_Click_Enter_Workspace"));
selectWorkspacePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
{
JPanel iconPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
iconPanel.setBorder(new EmptyBorder(0, 10, 0, 10));
Icon icon = StartupPageUtil.getIcon4DescAreaByWorkspace(workspaceInfo);
UILabel label = new UILabel(icon);
label.setPreferredSize(LABEL_DIMENSION);
iconPanel.add(label, BorderLayout.CENTER);
selectWorkspacePanel.add(iconPanel, BorderLayout.WEST);
// desc / >箭头
JPanel descPanel = new JPanel();
descPanel.setLayout(FRGUIPaneFactory.createM_BorderLayout());
descPanel.setBorder(new EmptyBorder(0, 10, 0, 0));
JPanel simpleDescPanelWrapper = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.CENTER, 0, 0);
JPanel simpleDescPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
UILabel nameLabel = new UILabel(workspaceInfo.getName());
Font font = nameLabel.getFont();
Font newSizeFont = font.deriveFont(font.getStyle(), NAME_LABEL_SIZE);
nameLabel.setFont(newSizeFont);
Color nameForeground = nameLabel.getForeground();
simpleDescPanel.add(nameLabel,BorderLayout.NORTH);
UILabel pathLabel = new UILabel(workspaceInfo.getPath());
pathLabel.setPreferredSize(PATH_DIMENSION);
Font pathFont = pathLabel.getFont();
pathLabel.setFont(pathFont.deriveFont(pathFont.getStyle(), PATH_LABEL_SIZE));
Color pathColor = PATH_COLOR;
pathLabel.setForeground(pathColor);
simpleDescPanel.add(pathLabel, BorderLayout.SOUTH);
simpleDescPanelWrapper.add(simpleDescPanel);
descPanel.add(simpleDescPanelWrapper, BorderLayout.WEST);
MouseAdapter selectWorkspaceMouseListener = new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
Color hoverColor = HOVER_COLOR;
borderColorRef.set(hoverColor);
nameLabel.setForeground(hoverColor);
pathLabel.setForeground(hoverColor );
selectWorkspacePanel.getParent().repaint();
}
@Override
public void mouseExited(MouseEvent e) {
borderColorRef.set(Color.WHITE);
nameLabel.setForeground(nameForeground);
pathLabel.setForeground(pathColor);
selectWorkspacePanel.getParent().repaint();
}
@Override
public void mousePressed(MouseEvent e) {
int clickCount = e.getClickCount();
if (clickCount == BORDER_THIN) {
pageModel.setSelectWorkspaceInfo(workspaceInfo);
openEmptyTemplateRunnable.run();
return;
}
// selectWorkspaceRunnable
pageModel.setSelectWorkspaceInfo(workspaceInfo);
selectWorkspaceRunnable.run();
}
};
UILabel arrowLabel = new UILabel(IconUtils.readIcon("/com/fr/design/startup/more.svg")) {
@Override
public JToolTip createToolTip() {
return new ModernToolTip();
}
};
arrowLabel.setToolTipText(Toolkit.i18nText("Fine-Design_Startup_Page_Enter_Workspace"));
arrowLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
arrowLabel.setIcon(IconUtils.readIcon("/com/fr/design/startup/more_hover.svg"));
selectWorkspaceMouseListener.mouseEntered(e);
}
@Override
public void mouseExited(MouseEvent e) {
arrowLabel.setIcon(IconUtils.readIcon("/com/fr/design/startup/more.svg"));
selectWorkspaceMouseListener.mouseExited(e);
}
@Override
public void mousePressed(MouseEvent e) {
openEmptyTemplateRunnable.run();
}
});
descPanel.add(arrowLabel, BorderLayout.EAST);
selectWorkspacePanel.add(descPanel, BorderLayout.CENTER);
selectWorkspacePanel.addMouseListener(selectWorkspaceMouseListener);
}
ColorUtils.syncBackground(selectWorkspacePanel, Color.WHITE);
selectWorkspacePanel.setPreferredSize(SELECT_WORKSPACE_DIMENSION);
workspaceItemDesc.add(selectWorkspacePanel, BorderLayout.WEST);
}
private void layoutSelectAndCreatePanel(JPanel workspaceItemDesc) {
// 选择并新建
AtomicReference<Color> borderColorRef = new AtomicReference<>(null);
JPanel selectAndCreatePanel = new JPanel() {
@Override
public JToolTip createToolTip() {
return new ModernToolTip();
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color borderColor = borderColorRef.get();
Color backColor = SHALLOW_WHITE_COLOR;
g2d.setColor(backColor);
// 见 layoutSelectWorkspacePanel 部分的分析
// 直角和圆角上下叠合在一起
int rectOffset = 10;
int roundOffset = 15;
int strokeOffset = BORDER_THIN / 2;
int fixedRoundOffset = roundOffset + strokeOffset;
g2d.fillRoundRect(0, 0, getWidth() - rectOffset, getHeight(), 0, 0);
g2d.fillRoundRect(getWidth() - fixedRoundOffset, 0, roundOffset, getHeight(), ARC_DIAMETER, ARC_DIAMETER);
if (borderColor != null) {
g2d.setColor(borderColor);
g2d.setStroke(new BasicStroke(BORDER_THIN));
// 画画的笔触需要调整一下
g2d.drawRoundRect(strokeOffset, strokeOffset, getWidth() - rectOffset, getHeight() - BORDER_THIN, 0, 0);
g2d.drawRoundRect(getWidth() - fixedRoundOffset, strokeOffset, roundOffset - strokeOffset, getHeight() - BORDER_THIN, ARC_DIAMETER, ARC_DIAMETER);
g2d.setColor(backColor);
int fillWidth = 11;
g2d.fillRect(getWidth() - fixedRoundOffset - BORDER_THIN, BORDER_THIN, fillWidth, getHeight() - BORDER_THIN * 2);
}
}
};
selectAndCreatePanel.setToolTipText(Toolkit.i18nText("Fine-Design_Startup_Page_Enter_Workspace_And_Create"));
selectAndCreatePanel.setBorder(new EmptyBorder(0, 0, 0, 0));
selectAndCreatePanel.setLayout(new BorderLayout());
{
UILabel label = new UILabel(IconUtils.readIcon("/com/fr/design/standard/system/add.svg"));
label.setPreferredSize(new Dimension(ARC_DIAMETER, ARC_DIAMETER));
label.setForeground(HOVER_COLOR);
selectAndCreatePanel.add(label, BorderLayout.CENTER);
selectAndCreatePanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
borderColorRef.set(HOVER_COLOR);
selectAndCreatePanel.getParent().repaint();
label.setIcon(IconUtils.readIcon("/com/fr/design/standard/system/add_hover.svg"));
}
@Override
public void mouseExited(MouseEvent e) {
borderColorRef.set(null);
selectAndCreatePanel.getParent().repaint();
label.setIcon(IconUtils.readIcon("/com/fr/design/standard/system/add.svg"));
}
@Override
public void mousePressed(MouseEvent e) {
createNewTemplateRunnable.run();
}
});
}
ColorUtils.syncBackground(selectAndCreatePanel, Color.GREEN);
selectAndCreatePanel.setPreferredSize(SELECT_CREATE_DIMENSION);
workspaceItemDesc.add(selectAndCreatePanel, BorderLayout.EAST);
}
public void setSelectWorkspaceRunnable(Runnable selectWorkspaceRunnable) {
this.selectWorkspaceRunnable = selectWorkspaceRunnable;
}
}

49
designer-base/src/main/java/com/fr/startup/ui/StartupWorkspaceBean.java

@ -0,0 +1,49 @@
package com.fr.startup.ui;
import com.fr.design.env.DesignerWorkspaceType;
/**
* created by Harrison on 2022/07/07
**/
public class StartupWorkspaceBean {
private String name;
private String path;
private DesignerWorkspaceType type;
public StartupWorkspaceBean(String name, String path, DesignerWorkspaceType type) {
this.name = name;
this.path = path;
this.type = type;
}
public static StartupWorkspaceBean create(String name, String path) {
return new StartupWorkspaceBean(name, path, DesignerWorkspaceType.Local);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public DesignerWorkspaceType getType() {
return type;
}
public void setType(DesignerWorkspaceType type) {
this.type = type;
}
}

2
designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties

@ -19,3 +19,5 @@ com.fr.design.cell.expand.sort.pane=257*185
com.fr.design.sort.rule.item=125*20
com.fr.design.ds.column.sort.pane=250*180
com.fr.design.sort.expand.header.pane=95*10
com.fr.design.plugin.remind.PluginInvalidateRemindDialog.dialog=600*500
com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane=580*369

2
designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties

@ -18,3 +18,5 @@ com.fr.design.cell.expand.sort.pane=257*170
com.fr.design.sort.rule.item=125*20
com.fr.design.ds.column.sort.pane=250*165
com.fr.design.sort.expand.header.pane=95*10
com.fr.design.plugin.remind.PluginInvalidateRemindDialog.dialog=600*500
com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane=580*369

2
designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties

@ -18,3 +18,5 @@ com.fr.design.cell.expand.sort.pane=267*165
com.fr.design.sort.rule.item=125*20
com.fr.design.ds.column.sort.pane=250*180
com.fr.design.sort.expand.header.pane=95*10
com.fr.design.plugin.remind.PluginInvalidateRemindDialog.dialog=600*500
com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane=580*369

3
designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties

@ -15,7 +15,10 @@ com.fr.design.report.fit.firstColumn=80*20
com.fr.design.report.fit.column=100*20
com.fr.design.lock.LockInfoDialog=400*180
com.fr.design.mainframe.ForbiddenPane.refreshButton=68*24
com.fr.start.common.DesignerOpenEmptyPanel.createButton=70*24
com.fr.design.cell.expand.sort.pane=227*155
com.fr.design.sort.rule.item=80*20
com.fr.design.ds.column.sort.pane=220*150
com.fr.design.sort.expand.header.pane=108*10
com.fr.design.plugin.remind.PluginInvalidateRemindDialog.dialog=600*500
com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane=580*369

2
designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties

@ -18,3 +18,5 @@ com.fr.design.cell.expand.sort.pane=227*155
com.fr.design.sort.rule.item=80*20
com.fr.design.ds.column.sort.pane=220*150
com.fr.design.sort.expand.header.pane=108*10
com.fr.design.plugin.remind.PluginInvalidateRemindDialog.dialog=600*500
com.fr.design.plugin.remind.PluginInvalidateRemindDialog.centerPane=580*369

1
designer-base/src/main/resources/com/fr/design/login/lib/locale/login_en_US.js

@ -54,6 +54,7 @@ var Store = {
'Designer-BBS_Username_Is_Register': 'The user has been registered',
'Designer-BBS_Please_Enter_Correct_Phone': 'Please enter the correct phone number',
'Designer-Login_Network_Connected_Failed': 'Network connection failed',
'Designer-Login_Failed_Exceed_Limit': 'Too many password errors, please try again after 24 hours',
}}
window.Store = Store;

1
designer-base/src/main/resources/com/fr/design/login/lib/locale/login_ja_JP.js

@ -54,6 +54,7 @@ var Store = {
'Designer-BBS_Username_Is_Register': 'このユーザは登録済みです。',
'Designer-BBS_Please_Enter_Correct_Phone': '正確な携帯番号を入力してください。',
'Designer-Login_Network_Connected_Failed': 'インターネット接続失敗',
'Designer-Login_Failed_Exceed_Limit': 'パスワードを連続で間違えています。24時間にもう一度試してください。',
}}
window.Store = Store;

1
designer-base/src/main/resources/com/fr/design/login/lib/locale/login_ko_KR.js

@ -54,6 +54,7 @@ var Store = {
'Designer-BBS_Username_Is_Register': 'The user has been registered',
'Designer-BBS_Please_Enter_Correct_Phone': 'Please enter the correct phone number',
'Designer-Login_Network_Connected_Failed': 'Network connection failed',
'Designer-Login_Failed_Exceed_Limit': 'Too many password errors, please try again after 24 hours',
}}
window.Store = Store;

1
designer-base/src/main/resources/com/fr/design/login/lib/locale/login_zh_CN.js

@ -54,6 +54,7 @@ var Store = {
'Designer-BBS_Username_Is_Register': '该用户已被注册',
'Designer-BBS_Please_Enter_Correct_Phone': '请输入正确的手机号',
'Designer-Login_Network_Connected_Failed': '网络连接失败',
'Designer-Login_Failed_Exceed_Limit': '密码错误次数过多,请24小时后重试',
}}
window.Store = Store;

1
designer-base/src/main/resources/com/fr/design/login/lib/locale/login_zh_TW.js

@ -54,6 +54,7 @@ var Store = {
'Designer-BBS_Username_Is_Register': '該帳號已被註冊',
'Designer-BBS_Please_Enter_Correct_Phone': '請輸入正確的手機號',
'Designer-Login_Network_Connected_Failed': '網路連線失敗',
'Designer-Login_Failed_Exceed_Limit': '密碼錯誤次數過多,請24小時後重試',
}}
window.Store = Store;

2
designer-base/src/main/resources/com/fr/design/login/login.js

File diff suppressed because one or more lines are too long

3
designer-base/src/main/resources/com/fr/design/standard/system/add.svg

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 2C9.44772 2 9 2.44772 9 3V9H3C2.44772 9 2 9.44772 2 10C2 10.5523 2.44772 11 3 11H9V17C9 17.5523 9.44772 18 10 18C10.5523 18 11 17.5523 11 17V11H17C17.5523 11 18 10.5523 18 10C18 9.44772 17.5523 9 17 9H11V3C11 2.44772 10.5523 2 10 2Z" fill="#62646E"/>
</svg>

After

Width:  |  Height:  |  Size: 407 B

3
designer-base/src/main/resources/com/fr/design/standard/system/add_hover.svg

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 2C9.44772 2 9 2.44772 9 3V9H3C2.44772 9 2 9.44772 2 10C2 10.5523 2.44772 11 3 11H9V17C9 17.5523 9.44772 18 10 18C10.5523 18 11 17.5523 11 17V11H17C17.5523 11 18 10.5523 18 10C18 9.44772 17.5523 9 17 9H11V3C11 2.44772 10.5523 2 10 2Z" fill="#419BF9"/>
</svg>

After

Width:  |  Height:  |  Size: 407 B

32
designer-base/src/main/resources/com/fr/design/standard/system/cpt.svg

@ -0,0 +1,32 @@
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_1818_57329)">
<mask id="path-1-inside-1_1818_57329" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M21.5 0.5H2.5V22.5H14L21.5 15V0.5Z"/>
</mask>
<path fill-rule="evenodd" clip-rule="evenodd" d="M21.5 0.5H2.5V22.5H14L21.5 15V0.5Z" fill="white"/>
<path d="M2.5 0.5V-0.5H1.5V0.5H2.5ZM21.5 0.5H22.5V-0.5H21.5V0.5ZM2.5 22.5H1.5V23.5H2.5V22.5ZM14 22.5V23.5H14.4142L14.7071 23.2071L14 22.5ZM21.5 15L22.2071 15.7071L22.5 15.4142V15H21.5ZM2.5 1.5H21.5V-0.5H2.5V1.5ZM3.5 22.5V0.5H1.5V22.5H3.5ZM14 21.5H2.5V23.5H14V21.5ZM20.7929 14.2929L13.2929 21.7929L14.7071 23.2071L22.2071 15.7071L20.7929 14.2929ZM20.5 0.5V15H22.5V0.5H20.5Z" fill="#DADADD" mask="url(#path-1-inside-1_1818_57329)"/>
</g>
<path d="M14.5 15.5H20.2929L14.5 21.2929V15.5Z" fill="url(#paint0_linear_1818_57329)" stroke="#DADADD"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.7399 4.05334H10.1201V7.25032H13.7399V14.4595H14.0849C15.6675 14.4595 16.9504 13.182 16.9504 11.6061V7.25032V4.46102C16.9504 4.23584 16.7672 4.05334 16.5411 4.05334H13.7399Z" fill="#41C9FD"/>
<mask id="mask0_1818_57329" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="6" y="4" width="8" height="11">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.5 4.05338V14.4595H13.3303V4.05338L6.5 4.05338V4.05338Z" fill="white"/>
</mask>
<g mask="url(#mask0_1818_57329)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.3304 7.65797H9.71054V4.05338H9.36554C7.78293 4.05338 6.5 5.33085 6.5 6.90681V14.0519C6.5 14.2771 6.68332 14.4595 6.90945 14.4595H9.71054V10.855H13.3304V7.65797Z" fill="#1D7ADC"/>
</g>
<defs>
<filter id="filter0_d_1818_57329" x="1.5" y="0.5" width="21" height="24" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="0.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.2 0 0 0 0 0.2 0 0 0 0 0.203922 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1818_57329"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1818_57329" result="shape"/>
</filter>
<linearGradient id="paint0_linear_1818_57329" x1="14.4445" y1="17.8317" x2="16.4274" y2="19.7415" gradientUnits="userSpaceOnUse">
<stop offset="1" stop-color="white"/>
<stop offset="1" stop-color="#DADADA"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

14
designer-base/src/main/resources/com/fr/design/standard/system/error_tips.svg

@ -0,0 +1,14 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 32H29V0H1V32Z" fill="#DADADD"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 6H29V0H1V6Z" fill="#AEAEAE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M31 23.5C31 28.194 27.194 32 22.5 32C17.806 32 14 28.194 14 23.5C14 18.806 17.806 15 22.5 15C27.194 15 31 18.806 31 23.5Z" fill="#EB1D1F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 11H10V10H8V11Z" fill="#AEAEAE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 11H13V10H11V11Z" fill="#AEAEAE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 11H16V10H14V11Z" fill="#AEAEAE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 11H19V10H17V11Z" fill="#AEAEAE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20 11H22V10H20V11Z" fill="#AEAEAE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.66568 8.03027C6.79422 7.91375 7 8.00496 7 8.17845V12.8216C7 12.995 6.79422 13.0863 6.66568 12.9697L4.10454 10.6482C4.01697 10.5688 4.01697 10.4312 4.10454 10.3518L6.66568 8.03027Z" fill="#AEAEAE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M23.3343 8.03027C23.2058 7.91375 23 8.00496 23 8.17845V12.8216C23 12.995 23.2058 13.0863 23.3343 12.9697L25.8955 10.6482C25.983 10.5688 25.983 10.4312 25.8955 10.3518L23.3343 8.03027Z" fill="#AEAEAE"/>
<path d="M19.4375 20.4375L25.5625 26.5625" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
<path d="M25.5625 20.4375L19.4375 26.5625" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

4
designer-base/src/main/resources/com/fr/design/standard/system/home_folder.svg

@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.90918 4.0003H8.09118L8.00018 3.9093L7.90918 4.0003Z" fill="#DADADD"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.54612 1.954L0.00012207 8.5L1.45412 9.954L2 9.40812V14.5002V15.5002H3H14.001V14.5002V9.40888L14.5461 9.954L16.0001 8.5L9.45412 1.954L8.00012 0.5L6.54612 1.954ZM8.00012 3.408L2.90788 8.50024H3V14.5002H13V8.50024H13.0924L8.00012 3.408ZM10 13.5002H6V9.50024H10V13.5002Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 561 B

6
designer-base/src/main/resources/com/fr/design/standard/system/remote_connect.svg

@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 8C0 12.4183 3.58172 16 8 16C12.4183 16 16 12.4183 16 8C16 3.58172 12.4183 0 8 0C3.58172 0 0 3.58172 0 8ZM15 8C15 11.866 11.866 15 8 15C4.13401 15 1 11.866 1 8C1 4.13401 4.13401 1 8 1C11.866 1 15 4.13401 15 8Z" fill="#333334"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 8C2 12.4183 4.68629 16 8 16C11.3137 16 14 12.4183 14 8C14 3.58172 11.3137 0 8 0C4.68629 0 2 3.58172 2 8ZM13 8C13 11.9183 10.6887 15 8 15C5.31129 15 3 11.9183 3 8C3 4.08172 5.31129 1 8 1C10.6887 1 13 4.08172 13 8Z" fill="#333334"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 8C5 12.4183 6.34315 16 8 16C9.65685 16 11 12.4183 11 8C11 3.58172 9.65685 0 8 0C6.34315 0 5 3.58172 5 8ZM10 8C10 11.8987 8.83702 15 8 15C7.16298 15 6 11.8987 6 8C6 4.10128 7.16298 1 8 1C8.83702 1 10 4.10128 10 8Z" fill="#333334"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 5C3.58172 5 0 6.34315 0 8C0 9.65685 3.58172 11 8 11C12.4183 11 16 9.65685 16 8C16 6.34315 12.4183 5 8 5ZM8 10C4.10128 10 1 8.83702 1 8C1 7.16298 4.10128 6 8 6C11.8987 6 15 7.16298 15 8C15 8.83702 11.8987 10 8 10Z" fill="#333334"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

18
designer-base/src/main/resources/com/fr/design/startup/create_new_template.svg

@ -0,0 +1,18 @@
<svg width="185" height="145" viewBox="0 0 185 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="185" height="145" fill="white"/>
<path d="M94.5598 137C124.825 137 149.36 135.764 149.36 134.24C149.36 132.716 124.825 131.48 94.5598 131.48C64.2946 131.48 39.7598 132.716 39.7598 134.24C39.7598 135.764 64.2946 137 94.5598 137Z" fill="#C9E2F6"/>
<path d="M132.52 33.8198V98.0398C132.518 99.1308 132.082 100.176 131.31 100.947C130.538 101.717 129.491 102.15 128.4 102.15H50.7204C49.6311 102.147 48.5873 101.713 47.8171 100.943C47.0469 100.173 46.613 99.1291 46.6104 98.0398V33.8198H132.52Z" fill="white" stroke="#448EE5" stroke-miterlimit="10"/>
<path d="M132.52 28.62V33.86H46.6104V28.62C46.613 27.5308 47.0469 26.4869 47.8171 25.7167C48.5873 24.9465 49.6311 24.5127 50.7204 24.51H128.4C129.491 24.51 130.538 24.9427 131.31 25.7132C132.082 26.4837 132.518 27.5291 132.52 28.62Z" fill="#B6D9EF" stroke="#448EE5" stroke-miterlimit="10"/>
<path d="M113.4 30.77C114.029 30.77 114.54 30.2596 114.54 29.63C114.54 29.0004 114.029 28.49 113.4 28.49C112.77 28.49 112.26 29.0004 112.26 29.63C112.26 30.2596 112.77 30.77 113.4 30.77Z" fill="#448EE5"/>
<path d="M119.34 30.77C119.97 30.77 120.48 30.2596 120.48 29.63C120.48 29.0004 119.97 28.49 119.34 28.49C118.711 28.49 118.2 29.0004 118.2 29.63C118.2 30.2596 118.711 30.77 119.34 30.77Z" fill="#448EE5"/>
<path d="M125.28 30.77C125.909 30.77 126.42 30.2596 126.42 29.63C126.42 29.0004 125.909 28.49 125.28 28.49C124.65 28.49 124.14 29.0004 124.14 29.63C124.14 30.2596 124.65 30.77 125.28 30.77Z" fill="#448EE5"/>
<path d="M23.01 55.02C24.1201 55.02 25.02 54.1201 25.02 53.01C25.02 51.8999 24.1201 51 23.01 51C21.8999 51 21 51.8999 21 53.01C21 54.1201 21.8999 55.02 23.01 55.02Z" stroke="#448EE5" stroke-miterlimit="10"/>
<path d="M156.01 62.02C157.12 62.02 158.02 61.1201 158.02 60.01C158.02 58.8999 157.12 58 156.01 58C154.9 58 154 58.8999 154 60.01C154 61.1201 154.9 62.02 156.01 62.02Z" stroke="#448EE5" stroke-miterlimit="10"/>
<path d="M142.66 20.32C144.129 20.32 145.32 19.1291 145.32 17.66C145.32 16.1909 144.129 15 142.66 15C141.191 15 140 16.1909 140 17.66C140 19.1291 141.191 20.32 142.66 20.32Z" stroke="#448EE5" stroke-miterlimit="10"/>
<path d="M115.18 45.5H64.1797V61.5H115.18V45.5Z" fill="#C9E2F6"/>
<path d="M81.1797 65.5H64.1797V88.5H81.1797V65.5Z" fill="#C9E2F6"/>
<path d="M115.18 65.5H85.1797V88.5H115.18V65.5Z" fill="#C9E2F6"/>
<circle cx="123" cy="88" r="17.5" fill="white" stroke="#448EE5"/>
<rect x="115" y="87" width="16" height="2" rx="1" fill="#448EE5"/>
<rect x="124" y="80" width="16" height="2" rx="1" transform="rotate(90 124 80)" fill="#448EE5"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

11
designer-base/src/main/resources/com/fr/design/startup/local_server_background_28.svg

@ -0,0 +1,11 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="28" height="28" rx="5" fill="url(#paint0_linear_2006_34286)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.9004 9.62532H14.0995L13.9999 9.52579L13.9004 9.62532Z" fill="#DADADD"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.4097 7.38719L5.25 14.5469L6.84031 16.1372L7.43737 15.5401V21.1096V22.2034H8.53112H20.5635V21.1096V15.541L21.1597 16.1372L22.75 14.5469L15.5903 7.38719L14 5.79688L12.4097 7.38719ZM14 8.9775L8.43036 14.5471H8.53112V21.1096H19.4686V14.5471H19.5696L14 8.9775ZM16.1874 20.0159H11.8124V15.6409H16.1874V20.0159Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_2006_34286" x1="14" y1="-2.69005e-07" x2="25.0526" y2="26.1579" gradientUnits="userSpaceOnUse">
<stop offset="1" stop-color="#00D2FF"/>
<stop offset="1" stop-color="#13BEFF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 921 B

11
designer-base/src/main/resources/com/fr/design/startup/local_server_background_36.svg

@ -0,0 +1,11 @@
<svg width="38" height="38" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="38" height="38" rx="5" fill="url(#paint0_linear_1821_59187)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.8652 13.0629H19.1354L19.0003 12.9279L18.8652 13.0629Z" fill="#DADADD"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.8417 10.0255L7.125 19.7422L9.28328 21.9005L10.0936 21.0902V28.6488V30.1332H11.5779H27.9076V28.6488L27.9076 21.0913L28.7167 21.9005L30.875 19.7422L21.1583 10.0255L19 7.86719L16.8417 10.0255ZM19 12.1838L11.4412 19.7425H11.5779V28.6488H26.4217V19.7425H26.5588L19 12.1838ZM21.9686 27.1644H16.0311V21.2269H21.9686V27.1644Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_1821_59187" x1="19" y1="-3.65078e-07" x2="34" y2="35.5" gradientUnits="userSpaceOnUse">
<stop offset="1" stop-color="#00D2FF"/>
<stop offset="1" stop-color="#13BEFF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 926 B

3
designer-base/src/main/resources/com/fr/design/startup/more.svg

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.6 10C17.6 14.1974 14.1974 17.6 10 17.6C5.80264 17.6 2.4 14.1974 2.4 10C2.4 5.80264 5.80264 2.4 10 2.4C14.1974 2.4 17.6 5.80264 17.6 10ZM19 10C19 14.9706 14.9706 19 10 19C5.02944 19 1 14.9706 1 10C1 5.02944 5.02944 1 10 1C14.9706 1 19 5.02944 19 10ZM14.9578 10.5297C15.106 10.4014 15.1998 10.2118 15.1998 10.0003C15.1998 9.78879 15.106 9.59919 14.9577 9.47083L10.9608 5.9735C10.6698 5.71892 10.2276 5.7484 9.973 6.03935C9.71842 6.3303 9.74791 6.77253 10.0389 7.02711L12.6368 9.3003H4.9998C4.61321 9.3003 4.2998 9.6137 4.2998 10.0003C4.2998 10.3869 4.61321 10.7003 4.9998 10.7003H12.6368L10.0389 12.9735C9.74791 13.2281 9.71842 13.6703 9.973 13.9613C10.2276 14.2522 10.6698 14.2817 10.9608 14.0271L14.9578 10.5297Z" fill="#62646E"/>
</svg>

After

Width:  |  Height:  |  Size: 887 B

3
designer-base/src/main/resources/com/fr/design/startup/more_hover.svg

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.6 10C17.6 14.1974 14.1974 17.6 10 17.6C5.80264 17.6 2.4 14.1974 2.4 10C2.4 5.80264 5.80264 2.4 10 2.4C14.1974 2.4 17.6 5.80264 17.6 10ZM19 10C19 14.9706 14.9706 19 10 19C5.02944 19 1 14.9706 1 10C1 5.02944 5.02944 1 10 1C14.9706 1 19 5.02944 19 10ZM14.9578 10.5297C15.106 10.4014 15.1998 10.2118 15.1998 10.0003C15.1998 9.78879 15.106 9.59919 14.9577 9.47083L10.9608 5.9735C10.6698 5.71892 10.2276 5.7484 9.973 6.03935C9.71842 6.3303 9.74791 6.77253 10.0389 7.02711L12.6368 9.3003H4.9998C4.61321 9.3003 4.2998 9.6137 4.2998 10.0003C4.2998 10.3869 4.61321 10.7003 4.9998 10.7003H12.6368L10.0389 12.9735C9.74791 13.2281 9.71842 13.6703 9.973 13.9613C10.2276 14.2522 10.6698 14.2817 10.9608 14.0271L14.9578 10.5297Z" fill="#419BF9"/>
</svg>

After

Width:  |  Height:  |  Size: 887 B

12
designer-base/src/main/resources/com/fr/design/startup/remote_server_background_28.svg

@ -0,0 +1,12 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="28" height="28" rx="5" fill="url(#paint0_linear_1904_33071)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.1582 14C5.1582 18.8834 9.11695 22.8421 14.0003 22.8421C18.8837 22.8421 22.8424 18.8834 22.8424 14C22.8424 9.11664 18.8837 5.1579 14.0003 5.1579C9.11695 5.1579 5.1582 9.11664 5.1582 14ZM21.7372 14C21.7372 18.2729 18.2733 21.7368 14.0003 21.7368C9.72737 21.7368 6.26347 18.2729 6.26347 14C6.26347 9.72706 9.72737 6.26316 14.0003 6.26316C18.2733 6.26316 21.7372 9.72706 21.7372 14Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.36914 14C7.36914 18.8834 10.3382 22.8421 14.0007 22.8421C17.6632 22.8421 20.6323 18.8834 20.6323 14C20.6323 9.11664 17.6632 5.1579 14.0007 5.1579C10.3382 5.1579 7.36914 9.11664 7.36914 14ZM19.527 14C19.527 18.3307 16.9725 21.7368 14.0007 21.7368C11.029 21.7368 8.4744 18.3307 8.4744 14C8.4744 9.66928 11.029 6.26316 14.0007 6.26316C16.9725 6.26316 19.527 9.66928 19.527 14Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.6846 14C10.6846 18.8834 12.1691 22.8421 14.0004 22.8421C15.8316 22.8421 17.3162 18.8834 17.3162 14C17.3162 9.11664 15.8316 5.1579 14.0004 5.1579C12.1691 5.1579 10.6846 9.11664 10.6846 14ZM16.2109 14C16.2109 18.3091 14.9255 21.7368 14.0004 21.7368C13.0752 21.7368 11.7898 18.3091 11.7898 14C11.7898 9.69089 13.0752 6.26316 14.0004 6.26316C14.9255 6.26316 16.2109 9.69089 16.2109 14Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.0007 10.6842C9.11731 10.6842 5.15856 12.1687 5.15856 14C5.15856 15.8313 9.11731 17.3158 14.0007 17.3158C18.884 17.3158 22.8428 15.8313 22.8428 14C22.8428 12.1687 18.884 10.6842 14.0007 10.6842ZM14.0007 16.2105C9.69156 16.2105 6.26382 14.9251 6.26382 14C6.26382 13.0749 9.69156 11.7895 14.0007 11.7895C18.3098 11.7895 21.7375 13.0749 21.7375 14C21.7375 14.9251 18.3098 16.2105 14.0007 16.2105Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_1904_33071" x1="5.89474" y1="-6.53009e-08" x2="14" y2="28" gradientUnits="userSpaceOnUse">
<stop offset="1" stop-color="#2F8EF1"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

18
designer-base/src/main/resources/com/fr/design/startup/remote_server_background_36.svg

@ -0,0 +1,18 @@
<svg width="36" height="37" viewBox="0 0 36 37" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1821_85375)">
<rect y="0.5" width="36" height="36" rx="5" fill="url(#paint0_linear_1821_85375)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.63184 18.5C6.63184 24.7786 11.7217 29.8684 18.0003 29.8684C24.2789 29.8684 29.3687 24.7786 29.3687 18.5C29.3687 12.2214 24.2789 7.13159 18.0003 7.13159C11.7217 7.13159 6.63184 12.2214 6.63184 18.5ZM27.9476 18.5C27.9476 23.9938 23.494 28.4474 18.0003 28.4474C12.5065 28.4474 8.05289 23.9938 8.05289 18.5C8.05289 13.0062 12.5065 8.55264 18.0003 8.55264C23.494 8.55264 27.9476 13.0062 27.9476 18.5Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.47363 18.5C9.47363 24.7786 13.291 29.8684 17.9999 29.8684C22.7089 29.8684 26.5263 24.7786 26.5263 18.5C26.5263 12.2214 22.7089 7.13159 17.9999 7.13159C13.291 7.13159 9.47363 12.2214 9.47363 18.5ZM25.1052 18.5C25.1052 24.0681 21.8207 28.4474 17.9999 28.4474C14.1792 28.4474 10.8947 24.0681 10.8947 18.5C10.8947 12.9319 14.1792 8.55264 17.9999 8.55264C21.8207 8.55264 25.1052 12.9319 25.1052 18.5Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.7373 18.5C13.7373 24.7786 15.646 29.8684 18.0005 29.8684C20.3549 29.8684 22.2636 24.7786 22.2636 18.5C22.2636 12.2214 20.3549 7.13159 18.0005 7.13159C15.646 7.13159 13.7373 12.2214 13.7373 18.5ZM20.8426 18.5C20.8426 24.0403 19.1899 28.4474 18.0005 28.4474C16.811 28.4474 15.1584 24.0403 15.1584 18.5C15.1584 12.9597 16.811 8.55264 18.0005 8.55264C19.1899 8.55264 20.8426 12.9597 20.8426 18.5Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.0007 14.2369C11.7221 14.2369 6.6323 16.1456 6.6323 18.5C6.6323 20.8545 11.7221 22.7632 18.0007 22.7632C24.2793 22.7632 29.3691 20.8545 29.3691 18.5C29.3691 16.1456 24.2793 14.2369 18.0007 14.2369ZM18.0007 21.3421C12.4604 21.3421 8.05335 19.6895 8.05335 18.5C8.05335 17.3106 12.4604 15.6579 18.0007 15.6579C23.541 15.6579 27.9481 17.3106 27.9481 18.5C27.9481 19.6895 23.541 21.3421 18.0007 21.3421Z" fill="white"/>
</g>
<defs>
<linearGradient id="paint0_linear_1821_85375" x1="7.57895" y1="0.5" x2="18" y2="36.5" gradientUnits="userSpaceOnUse">
<stop offset="1" stop-color="#4BA3FF"/>
<stop offset="1" stop-color="#2F8EF1"/>
</linearGradient>
<clipPath id="clip0_1821_85375">
<rect width="36" height="36" fill="white" transform="translate(0 0.5)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

3
designer-base/src/main/resources/com/fr/design/startup/show_less.svg

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 13L10 7L5 13" stroke="#419BF9" stroke-width="1.5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 191 B

3
designer-base/src/main/resources/com/fr/design/startup/show_more.svg

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 7L10 13L15 7" stroke="#419BF9" stroke-width="1.5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 190 B

33
designer-base/src/test/java/com/fr/design/EnvChangeEntranceTest.java

@ -1,12 +1,12 @@
package com.fr.design;
import com.fr.decision.webservice.v10.plugin.helper.PluginErrorRemindHandler;
import com.fr.design.plugin.remind.PluginErrorDesignReminder;
import com.fr.plugin.error.PluginErrorRemindHandler;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.env.DesignerWorkspaceType;
import com.fr.design.env.LocalDesignerWorkspaceInfo;
import com.fr.design.env.RemoteDesignerWorkspaceInfo;
import com.fr.env.CheckServiceDialog;
import com.fr.env.PluginErrorRemindDialog;
import com.fr.invoke.Reflect;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
@ -108,33 +108,4 @@ public class EnvChangeEntranceTest {
Assert.assertFalse(Reflect.on(entrance).call("isNotRememberPwd", info3).get());
Assert.assertFalse(Reflect.on(entrance).call("isNotRememberPwd", info4).get());
}
@Test
public void testPluginErrorRemind() {
try {
Workspace workspace = EasyMock.mock(Workspace.class);
EasyMock.expect(workspace.isLocal()).andReturn(false).once();
EasyMock.expect(workspace.isLocal()).andReturn(true).once();
PowerMock.mockStatic(WorkContext.class);
EasyMock.expect(WorkContext.getCurrent()).andReturn(workspace).anyTimes();
PowerMock.mockStatic(PluginErrorRemindHandler.class);
EasyMock.expect(PluginErrorRemindHandler.pluginErrorContent()).andReturn("").once();
EasyMock.replay(workspace);
PowerMock.replayAll();
EnvChangeEntrance entrance = EnvChangeEntrance.getInstance();
entrance.pluginErrorRemind();
entrance.pluginErrorRemind();
EasyMock.verify(workspace);
PowerMock.verifyAll();
} catch (Exception e) {
Assert.fail();
}
}
}

72
designer-base/src/test/java/com/fr/design/plugin/remind/PluginErrorDesignReminderTest.java

@ -0,0 +1,72 @@
package com.fr.design.plugin.remind;
import com.fr.plugin.error.PluginErrorRemindHandler;
import com.fr.workspace.WorkContext;
import com.fr.workspace.empty.EmptyWorkspace;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Yvan
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest(PluginErrorRemindHandler.class)
public class PluginErrorDesignReminderTest extends TestCase {
@Before
public void before() {
WorkContext.switchTo(EmptyWorkspace.getInstance());
}
public void testRemindStartFailedPlugins() {
PowerMock.mockStatic(PluginErrorRemindHandler.class);
EasyMock.expect(PluginErrorRemindHandler.pluginErrorContent()).andReturn("").once();
PowerMock.replayAll();
PluginErrorDesignReminder.getInstance().remindStartFailedPlugins();
PowerMock.verifyAll();
}
public void testRemindInvalidatePlugins() {
PowerMock.mockStatic(PluginErrorRemindHandler.class);
EasyMock.expect(PluginErrorRemindHandler.getInvalidateEmbedPluginNames()).andReturn(new ArrayList<>()).once();
PowerMock.replayAll();
PluginErrorDesignReminder.getInstance().remindInvalidatePlugins();
PowerMock.verifyAll();
}
public void testDealWithPluginNames() {
List<String> pluginNames1 = Arrays.asList("1");
String content1 = PluginErrorDesignReminder.getInstance().dealWithPluginNames(pluginNames1);
Assert.assertFalse(content1.contains(PluginErrorDesignReminder.COMMA));
Assert.assertFalse(content1.contains(PluginErrorDesignReminder.NEW_LINE_TAG));
List<String> pluginNames2 = Arrays.asList("1", "2");
String content2 = PluginErrorDesignReminder.getInstance().dealWithPluginNames(pluginNames2);
Assert.assertTrue(content2.contains(PluginErrorDesignReminder.COMMA));
Assert.assertFalse(content2.contains(PluginErrorDesignReminder.NEW_LINE_TAG));
List<String> pluginNames3 = Arrays.asList("1", "2", "3", "4");
String content3 = PluginErrorDesignReminder.getInstance().dealWithPluginNames(pluginNames3);
Assert.assertTrue(content3.contains(PluginErrorDesignReminder.COMMA));
Assert.assertTrue(content3.contains(PluginErrorDesignReminder.NEW_LINE_TAG));
List<String> pluginNames4 = Arrays.asList("1", "2", "3");
String content4 = PluginErrorDesignReminder.getInstance().dealWithPluginNames(pluginNames4);
Assert.assertTrue(content4.contains(PluginErrorDesignReminder.COMMA));
Assert.assertFalse(content4.contains(PluginErrorDesignReminder.NEW_LINE_TAG));
}
}

2
designer-base/src/test/java/com/fr/design/utils/DevDebugUtils.java

@ -7,6 +7,6 @@ public class DevDebugUtils {
public static void main(String[] args) {
org.swingexplorer.Launcher.main(new String[]{"com.fr.design.utils.DevUtils"});
org.swingexplorer.Launcher.main(new String[]{"com.fr.startup.ui.StartupPageWindowTest"});
}
}

6
designer-base/src/test/java/com/fr/design/utils/DevUtils.java

@ -48,6 +48,12 @@ public class DevUtils {
}
public static void show(Runnable runnable) {
DesignUtils.initLookAndFeel();
UIUtil.invokeLaterIfNeeded(runnable);
}
public static void main(String[] args) {
DevUtils.prepare();

32
designer-base/src/test/java/com/fr/startup/ui/StartupPageWindowTest.java

@ -0,0 +1,32 @@
package com.fr.startup.ui;
import com.fr.design.utils.DevUtils;
import com.fr.third.guava.collect.Lists;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StartupPageWindowTest {
public static void main(String[] args) {
DevUtils.show(new Runnable() {
@Override
public void run() {
HashMap<String, List<String>> recentOpenFileMap = new HashMap<>();
recentOpenFileMap.put("111", Lists.newArrayList("111.cpt", "222//3333.cpt","333.cpt", "444.cpt", "555.cpt", "666.cpt"));
StartupPageModel model = new StartupPageModel(Stream.of(
StartupWorkspaceBean.create("111", "222333344455556663333444555566633334445555666"), StartupWorkspaceBean.create("113", "222"),
StartupWorkspaceBean.create("114", "222"), StartupWorkspaceBean.create("115", "222"), StartupWorkspaceBean.create("116", "222"),
StartupWorkspaceBean.create("117", "222"), StartupWorkspaceBean.create("118", "222"), StartupWorkspaceBean.create("119", "222"),
StartupWorkspaceBean.create("121", "222"), StartupWorkspaceBean.create("122", "222"), StartupWorkspaceBean.create("123", "222"),
StartupWorkspaceBean.create("124", "222"), StartupWorkspaceBean.create("125", "222"), StartupWorkspaceBean.create("126", "222")
).collect(Collectors.toList()), recentOpenFileMap);
StartupPageWindow window = new StartupPageWindow(model);
window.setVisible(true);
}
});
}
}

27
designer-chart/src/main/java/com/fr/design/chart/series/SeriesCondition/ColSelectedWithSummaryMethodEditor.java

@ -1,6 +1,10 @@
package com.fr.design.chart.series.SeriesCondition;
import com.fr.chart.chartattr.Chart;
import com.fr.chart.chartattr.ChartCommonCondition;
import com.fr.chart.chartattr.Plot;
import com.fr.chart.chartglyph.ConditionAttr;
import com.fr.chart.chartglyph.ConditionCollection;
import com.fr.data.DSColumnWithSummaryMethod;
import com.fr.data.util.function.AbstractDataFunction;
import com.fr.design.chart.ChartDataHelper;
@ -9,8 +13,11 @@ import com.fr.design.editor.editor.Editor;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.plugin.chart.attr.plot.VanChartPlot;
import com.fr.plugin.chart.custom.VanChartCustomPlot;
import com.fr.plugin.chart.custom.type.CustomPlotType;
import java.awt.Dimension;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
public class ColSelectedWithSummaryMethodEditor extends Editor<DSColumnWithSummaryMethod> {
@ -88,4 +95,24 @@ public class ColSelectedWithSummaryMethodEditor extends Editor<DSColumnWithSumma
return object instanceof DSColumnWithSummaryMethod;
}
public static void update(int index, Plot plot) {
if (plot instanceof VanChartCustomPlot) {
List<VanChartPlot> list = ((VanChartCustomPlot) plot).getCustomPlotList();
VanChartPlot vanChartPlot = list.get(index);
ConditionCollection conditionCollection = vanChartPlot.getConditionCollection();
ConditionAttr[] conditionAttrs = conditionCollection.getAllConditionAttrList();
for (ConditionAttr conditionAttr : conditionAttrs) {
if (conditionAttr.getCondition() instanceof ChartCommonCondition) {
ChartCommonCondition chartCommonCondition = (ChartCommonCondition) conditionAttr.getCondition();
if (chartCommonCondition.getCompare().getValue() instanceof DSColumnWithSummaryMethod) {
DSColumnWithSummaryMethod dsColumnWithSummaryMethod = (DSColumnWithSummaryMethod) chartCommonCondition.getCompare().getValue();
columnNameComboBoxModel.setSelectedItem(dsColumnWithSummaryMethod.getFieldName());
summaryMethodComboBoxModel.setSelectedItem(ChartCommonCondition.FORMAT_MAP.get(String.valueOf(dsColumnWithSummaryMethod.getDataFunction().getFormula())));
return;
}
}
}
}
}
}

5
designer-chart/src/main/java/com/fr/van/chart/custom/other/VanChartCustomPlotConditionAttrTabPane.java

@ -93,9 +93,8 @@ public class VanChartCustomPlotConditionAttrTabPane extends VanChartCustomPlotTa
CustomPlotType plotType = CustomPlotFactory.getCustomType(chartPlot);
VanChartRichEditorPane.refreshCustomChartTableFieldNames(chart, plotType);
ColSelectedWithSummaryMethodEditor.refreshCustomChartTableFieldNames(chart, plotType);
JPanel selectedPane = paneList.get(index);
if (chart != null && chartPlot != null && selectedPane instanceof VanChartConditionAttrPane) {
((VanChartConditionAttrPane) selectedPane).populateBean(chartPlot);
if (chart != null) {
ColSelectedWithSummaryMethodEditor.update(index, chart.getPlot());
}
}
}

20
designer-form/src/main/java/com/fr/design/fit/common/NewUIModeAutoChangeLine.java

@ -1,20 +0,0 @@
package com.fr.design.fit.common;
import com.fr.base.DefaultAutoChangeLine;
import com.fr.base.Style;
import com.fr.stable.unit.UNIT;
import java.awt.Font;
import java.util.List;
public class NewUIModeAutoChangeLine extends DefaultAutoChangeLine {
@Override
public List<String> textAutoChangeLine(String text, Font font, Style style, UNIT unitWidth, int resolution) {
return autoChangeLine(text, font, style, unitWidth, resolution);
}
protected double calculateShowWidth(double paintWidth, Style style, int resolution) {
return paintWidth - style.getPaddingLeft() - style.getPaddingRight() - style.getBorderLeftWidth();
}
}

69
designer-form/src/main/java/com/fr/design/fit/common/NewUIModeRotationDraw.java

@ -1,69 +0,0 @@
package com.fr.design.fit.common;
import com.fr.base.BaseUtils;
import com.fr.base.DefaultRotationTextDrawProvider;
import com.fr.base.GraphHelper;
import com.fr.base.Style;
import com.fr.design.mainframe.PX;
import com.fr.stable.Constants;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.util.List;
public class NewUIModeRotationDraw extends DefaultRotationTextDrawProvider {
@Override
public void drawRotationText(Graphics2D g2d, String text, Style style, Font rfont, int width, int height, int horizontalAlignment, int resolution) {
FontMetrics cellFM = GraphHelper.getFontMetrics(rfont);
List lineTextList = BaseUtils.getLineTextList(text, style, rfont, height, width, resolution, new NewUIModeAutoChangeLine());
drawRotationText(g2d, lineTextList, style, cellFM, width, height, horizontalAlignment, resolution);
}
protected int calculateTextWidth(int width, Style style) {
return width - style.getPaddingRight();
}
protected double calculateTextX(Style style, int width, int textWidth, int horizontalAlignment, int resolution) {
double textX = padding2PixExcludeRight(style.getPaddingLeft(), resolution);
if (horizontalAlignment == Constants.CENTER) {
textX += (width - textWidth - textX) / 2f;
} else if (horizontalAlignment == Constants.RIGHT) {
textX = width - style.getPaddingRight() - textWidth;
}
return textX;
}
protected int toPXWithResolution(double pt, int resolution) {
return (int) PX.toPixWithResolution(pt, resolution);
}
protected double padding2PixExcludeRight(int padding, int resolution) {
return PX.toPixWithResolution(padding, resolution);
}
protected int calculateTextY(Style style, int height, int textHeight, int textAscent, List lineTextList, int resolution) {
// 计算Y的高度.
int textY = 0;
int textAllHeight = textHeight * lineTextList.size();
double spacingBefore = toPXWithResolution(style.getSpacingBefore(), resolution);
double spacingAfter = toPXWithResolution(style.getSpacingAfter(), resolution);
double lineSpacing = toPXWithResolution(style.getLineSpacing(), resolution);
textAllHeight += spacingBefore + spacingAfter + lineSpacing * lineTextList.size();
if (style.getVerticalAlignment() == Constants.TOP) {
} else if (style.getVerticalAlignment() == Constants.CENTER) {
if (height > textAllHeight) {// 如果所有文本的高度小于当前可以绘区域的高度,就从0开始画字符.
textY = (height - textAllHeight) / 2;
}
} else if (style.getVerticalAlignment() == Constants.BOTTOM) {
if (height > textAllHeight) {
textY = height - textAllHeight;
}
}
textY += textAscent;// 在绘画的时候,必须添加Ascent的高度.
textY += spacingBefore + lineSpacing;//james:加上"段前间距"+“行间距”
return textY;
}
}

29
designer-form/src/main/java/com/fr/design/mainframe/JForm.java

@ -41,6 +41,7 @@ import com.fr.design.event.TargetModifiedEvent;
import com.fr.design.event.TargetModifiedListener;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.fit.FormFitAttrAction;
import com.fr.design.fit.common.FormDesignerUtil;
import com.fr.design.fun.PreviewProvider;
import com.fr.design.fun.PropertyItemPaneProvider;
import com.fr.design.gui.frpane.HyperlinkGroupPane;
@ -109,12 +110,7 @@ import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.tree.TreePath;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
@ -1307,4 +1303,25 @@ public class JForm extends JTemplate<Form, FormUndoState> implements BaseJForm<F
public XLayoutContainer getRootComponent() {
return this.formDesign.getRootComponent();
}
@Override
public Rectangle getElementCaseRectangle(FormElementCase elementCase) {
final Rectangle rectangle = new Rectangle();
FormDesigner designer = this.getFormDesign();
if (designer == null) {
return rectangle;
}
XElementCase xElementCase = FormDesignerUtil.getXelementCase(designer.getRootComponent(), elementCase);
if (xElementCase != null) {
rectangle.setBounds(xElementCase.getBounds());
//减去内边距的宽和高
Insets insets = xElementCase.getInsets();
rectangle.width -= insets.left + insets.right;
rectangle.height -= insets.top + insets.bottom;
}
return rectangle;
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save