Browse Source

Merge pull request #9517 in DESIGN/design from feature/x to bugfix/11.0

* commit '5515d671ea4032679bc129f814e5f2cf9c299cea': (23 commits)
  REPORT-72828 启动页配置项屏蔽
  REPORT-76291 【迭代】【数据连接为空】次管查看无权限的数据集,没有提示 【问题原因】获取数据连接名称的方式错了,误写成了获取数据集名称,因此判断成了有权限 【改动思路】改用正确方式获取数据连接的名称 【review建议】无
  REPORT-75919 【迭代】更新日志-交互问题 1、修改交互
  REPORT-76174 【迭代】【数据连接面板为空】数据表搜索框-交互问题 【问题原因】1. 开发的时候没做这个TextField鼠标悬浮变色的功能;2. 部分代码质量问题 【改动思路】1. 加上悬浮变色边框的逻辑;2. 代码质量问题修改 【review建议】无
  REPORT-76076 插件管理-插件管理机制优化-内置插件多时,消息提示显示异常 【问题原因】设计器通知中心的消息弹窗,弹窗的宽度是由消息内容长度决定的,所以插件过多时,会把弹窗拉得很长 【改动思路】跟产品沟通后,添加分行逻辑 【review建议】无
  REPORT-75919 【迭代】更新日志-交互问题 1、修改交互
  REPORT-72635 - 数据连接面板为空的问题(含控制权限) 【问题原因】迭代任务,问题与改动思路详见https://kms.fineres.com/pages/viewpage.action?pageId=443822299 【改动思路】同上 【review建议】无
  REPORT-75786 11.0feature版本设计器无法启动
  REPORT-75786 11.0feature版本设计器无法启动 DesignUtils.initLookAndFeel 需要先解密。 会用到 GeneralUtils 的逻辑
  REPORT-72828 设计器启动优化之起始页设计 1、修复远程目录的展示问题 2、UI效果,距离右边 6 px 3、参数设置放到 UI 线程中
  REPORT-70746 更新日志的显示逻辑优化
  REPORT-70746 更新日志的显示逻辑优化
  REPORT-70746 更新日志的显示逻辑优化
  REPORT-70537:数据连接优化埋点
  补充注释
  REPORT-72828 设计器启动优化之起始页设计 1-添加 loading 页面 2-手动调用部分功能 3-预热功能和在预热中对部分功能的忽视 4-启动页相关的UI 5-预加载服务
  REPORT-72354 导出图片优化二期
  REPORT-72384 && REPORT-72443 1、下拉树优化V2 2、控件性能优化内置V2
  KERNEL-11406  FRM和FVS的新表格支持后台调整行高列宽
  REPORT-74411 插件-插件管理机制优化-当本地不存在内置插件的时候,平台还是会收到内置通知 【问题原因】没有对消息做判空 【改动思路】1.添加判空,当不存在内置插件时,不推送消息通知;2.调一下提示语的间隔 【review建议】无
  ...
bugfix/11.0
superman 2 years ago
parent
commit
26e452fafd
  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. 46
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  10. 57
      designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java
  11. 38
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java
  12. 4
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java
  13. 113
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java
  14. 16
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java
  15. 54
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java
  16. 23
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/SwitchableTableDataPane.java
  17. 54
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TableDataLoadingPane.java
  18. 45
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TipsPane.java
  19. 2
      designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java
  20. 2
      designer-base/src/main/java/com/fr/design/gui/ibutton/UITabGroup.java
  21. 19
      designer-base/src/main/java/com/fr/design/gui/ilable/ActionLabel.java
  22. 3
      designer-base/src/main/java/com/fr/design/gui/itooltip/UIToolTip.java
  23. 7
      designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/TreeAttrChangeListener.java
  24. 50
      designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/TreeRootPane.java
  25. 47
      designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java
  26. 33
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java
  27. 23
      designer-base/src/main/java/com/fr/design/mainframe/DesignerUIModeConfig.java
  28. 108
      designer-base/src/main/java/com/fr/design/mainframe/TransparentPane.java
  29. 11
      designer-base/src/main/java/com/fr/design/notification/NotificationCenter.java
  30. 143
      designer-base/src/main/java/com/fr/design/plugin/remind/PluginErrorDesignReminder.java
  31. 211
      designer-base/src/main/java/com/fr/design/plugin/remind/PluginInvalidateRemindDialog.java
  32. 6
      designer-base/src/main/java/com/fr/design/plugin/remind/PluginStartFailedRemindDialog.java
  33. 34
      designer-base/src/main/java/com/fr/design/update/actions/NewFeatureAction.java
  34. 171
      designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java
  35. 6
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTable.java
  36. 6
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableCellRender.java
  37. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTextAreaCellRender.java
  38. 29
      designer-base/src/main/java/com/fr/design/utils/DesignUtils.java
  39. 87
      designer-base/src/main/java/com/fr/design/widget/component/ReturnTypePane.java
  40. 79
      designer-base/src/main/java/com/fr/start/BaseDesigner.java
  41. 77
      designer-base/src/main/java/com/fr/start/common/DesignerOpenEmptyPanel.java
  42. 55
      designer-base/src/main/java/com/fr/start/common/DesignerStartupConfig.java
  43. 176
      designer-base/src/main/java/com/fr/start/common/DesignerStartupContext.java
  44. 32
      designer-base/src/main/java/com/fr/start/common/DesignerStartupExecutor.java
  45. 20
      designer-base/src/main/java/com/fr/start/common/DesignerStartupPool.java
  46. 51
      designer-base/src/main/java/com/fr/start/common/DesignerStartupUtil.java
  47. 0
      designer-base/src/main/java/com/fr/start/module/StartupArgs.java
  48. 17
      designer-base/src/main/java/com/fr/startup/ui/StartupPageConstants.java
  49. 111
      designer-base/src/main/java/com/fr/startup/ui/StartupPageModel.java
  50. 40
      designer-base/src/main/java/com/fr/startup/ui/StartupPageUtil.java
  51. 339
      designer-base/src/main/java/com/fr/startup/ui/StartupPageWindow.java
  52. 501
      designer-base/src/main/java/com/fr/startup/ui/StartupPageWorkspacePanel.java
  53. 49
      designer-base/src/main/java/com/fr/startup/ui/StartupWorkspaceBean.java
  54. 2
      designer-base/src/main/resources/com/fr/design/i18n/dimension_en.properties
  55. 2
      designer-base/src/main/resources/com/fr/design/i18n/dimension_ja_JP.properties
  56. 2
      designer-base/src/main/resources/com/fr/design/i18n/dimension_ko_KR.properties
  57. 3
      designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties
  58. 2
      designer-base/src/main/resources/com/fr/design/i18n/dimension_zh_TW.properties
  59. 3
      designer-base/src/main/resources/com/fr/design/standard/system/add.svg
  60. 3
      designer-base/src/main/resources/com/fr/design/standard/system/add_hover.svg
  61. 32
      designer-base/src/main/resources/com/fr/design/standard/system/cpt.svg
  62. 4
      designer-base/src/main/resources/com/fr/design/standard/system/home_folder.svg
  63. 6
      designer-base/src/main/resources/com/fr/design/standard/system/remote_connect.svg
  64. 18
      designer-base/src/main/resources/com/fr/design/startup/create_new_template.svg
  65. 11
      designer-base/src/main/resources/com/fr/design/startup/local_server_background_28.svg
  66. 11
      designer-base/src/main/resources/com/fr/design/startup/local_server_background_36.svg
  67. 3
      designer-base/src/main/resources/com/fr/design/startup/more.svg
  68. 3
      designer-base/src/main/resources/com/fr/design/startup/more_hover.svg
  69. 12
      designer-base/src/main/resources/com/fr/design/startup/remote_server_background_28.svg
  70. 18
      designer-base/src/main/resources/com/fr/design/startup/remote_server_background_36.svg
  71. 3
      designer-base/src/main/resources/com/fr/design/startup/show_less.svg
  72. 3
      designer-base/src/main/resources/com/fr/design/startup/show_more.svg
  73. 33
      designer-base/src/test/java/com/fr/design/EnvChangeEntranceTest.java
  74. 72
      designer-base/src/test/java/com/fr/design/plugin/remind/PluginErrorDesignReminderTest.java
  75. 2
      designer-base/src/test/java/com/fr/design/utils/DevDebugUtils.java
  76. 6
      designer-base/src/test/java/com/fr/design/utils/DevUtils.java
  77. 32
      designer-base/src/test/java/com/fr/startup/ui/StartupPageWindowTest.java
  78. 20
      designer-form/src/main/java/com/fr/design/fit/common/NewUIModeAutoChangeLine.java
  79. 69
      designer-form/src/main/java/com/fr/design/fit/common/NewUIModeRotationDraw.java
  80. 20
      designer-form/src/main/java/com/fr/design/widget/ui/designer/CheckBoxGroupDefinePane.java
  81. 18
      designer-form/src/main/java/com/fr/design/widget/ui/designer/ComboCheckBoxDefinePane.java
  82. 68
      designer-form/src/main/java/com/fr/design/widget/ui/designer/TreeEditorDefinePane.java
  83. 2
      designer-realize/src/main/java/com/fr/design/fit/NewUIModeCellElementPainter.java
  84. 119
      designer-realize/src/main/java/com/fr/design/report/ImageExportPane.java
  85. 20
      designer-realize/src/main/java/com/fr/design/widget/ui/CheckBoxGroupDefinePane.java
  86. 18
      designer-realize/src/main/java/com/fr/design/widget/ui/ComboCheckBoxDefinePane.java
  87. 104
      designer-realize/src/main/java/com/fr/design/widget/ui/TreeComboBoxEditorDefinePane.java
  88. 17
      designer-realize/src/main/java/com/fr/design/widget/ui/TreeEditorDefinePane.java
  89. 3
      designer-realize/src/main/java/com/fr/grid/GridUtils.java
  90. 40
      designer-realize/src/main/java/com/fr/start/DesignerInitial.java
  91. 2
      designer-realize/src/main/java/com/fr/start/DesignerJavaRuntime.java
  92. 7
      designer-realize/src/main/java/com/fr/start/LifecycleFatalErrorHandler.java
  93. 54
      designer-realize/src/main/java/com/fr/start/MainDesigner.java
  94. 1
      designer-realize/src/main/java/com/fr/start/SplashContext.java
  95. 11
      designer-realize/src/main/java/com/fr/start/common/SplashPane.java
  96. 77
      designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java
  97. 30
      designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java
  98. 6
      designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java
  99. 24
      designer-realize/src/main/java/com/fr/start/module/optimized/DesignerPluginActivator.java
  100. 119
      designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.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,
/**
* 设计器模块启动完成
*/

46
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;
@ -1017,8 +1019,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());
}
}

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

@ -7,6 +7,7 @@ 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.design.ExtraDesignClassManager;
import com.fr.design.data.MapCompareUtils;
import com.fr.design.dialog.BasicDialog;
@ -186,6 +187,9 @@ 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;
}

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

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

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

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

171
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;
@ -86,6 +88,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 +96,6 @@ public class UpdateMainDialog extends UIDialog {
private LoadingLabel loadingLabel;
//更新按钮
private UIButton updateButton;
//有新版本提示标签
private UILabel updateLabel;
//jar包版本信息面板,包括当前版本和最新版本
private JPanel jarVersionInfoPane;
@ -157,13 +158,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 +179,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 +191,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 +217,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 +228,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 +297,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 +320,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,14 +414,21 @@ 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) {
@ -483,7 +487,7 @@ public class UpdateMainDialog extends UIDialog {
continue;
}
}
if (isValidLogInfo(updateInfo[1])) {
if (isValidLogInfo(updateInfo[1]) && curJarDate != null) {
updateInfoList.add(new Object[]{UPDATE_INFO_TABLE_FORMAT.format(updateTime), updateInfo[1], updateTime.after(curJarDate)});
}
}
@ -531,9 +535,10 @@ 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));
@ -546,7 +551,7 @@ public class UpdateMainDialog extends UIDialog {
}
}
if (isValidLogInfo(updateTitle)) {
updateInfoList.add(new Object[]{UPDATE_INFO_TABLE_FORMAT.format(updateTime), updateTitle, updateTime.after(curJarDate)});
updateInfoList.add(new Object[]{UPDATE_INFO_TABLE_FORMAT.format(updateTime), updateVersionStr, updateTitle, updateTime.after(curJarDate)});
}
}
return new ArrayList<>(updateInfoList);
@ -579,14 +584,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 +611,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 +657,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 +681,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;

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

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

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

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

20
designer-form/src/main/java/com/fr/design/widget/ui/designer/CheckBoxGroupDefinePane.java

@ -7,7 +7,7 @@ import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.present.dict.DictionaryPane;
import com.fr.design.widget.component.CheckBoxDictPane;
import com.fr.design.widget.component.ReturnTypePane;
import com.fr.design.widget.ui.designer.btn.ButtonGroupDefinePane;
import com.fr.form.ui.CheckBoxGroup;
@ -17,7 +17,7 @@ import java.awt.*;
public class CheckBoxGroupDefinePane extends ButtonGroupDefinePane<CheckBoxGroup> {
private DictionaryPane dictPane;
private CheckBoxDictPane checkBoxDictPane;
private ReturnTypePane returnTypePane;
private UICheckBox checkbox;
public CheckBoxGroupDefinePane(XCreator xCreator) {
@ -40,12 +40,12 @@ public class CheckBoxGroupDefinePane extends ButtonGroupDefinePane<CheckBoxGroup
public JPanel createOtherPane(){
checkbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Choose_Type_All"));
checkbox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
checkBoxDictPane = new CheckBoxDictPane();
returnTypePane = new ReturnTypePane();
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
Component[][] components = new Component[][]{
new Component[]{checkbox, null },
new Component[]{checkBoxDictPane, null},
new Component[]{returnTypePane, null},
};
double[] rowSize = {p, p};
double[] columnSize = {p, f};
@ -56,7 +56,7 @@ public class CheckBoxGroupDefinePane extends ButtonGroupDefinePane<CheckBoxGroup
@Override
protected void populateSubButtonGroupBean(CheckBoxGroup ob) {
this.checkBoxDictPane.populate(ob);
this.returnTypePane.populate(ob);
this.dictPane.populateBean(ob.getDictionary());
checkbox.setSelected(ob.isChooseAll());
}
@ -66,14 +66,14 @@ public class CheckBoxGroupDefinePane extends ButtonGroupDefinePane<CheckBoxGroup
@Override
protected CheckBoxGroup updateSubButtonGroupBean() {
CheckBoxGroup ob = (CheckBoxGroup) creator.toData();
checkBoxDictPane.update(ob);
returnTypePane.update(ob);
ob.setDictionary(this.dictPane.updateBean());
ob.setChooseAll(checkbox.isSelected());
return ob;
}
@Override
public DataCreatorUI dataUI() {
return dictPane;
}
@Override
public DataCreatorUI dataUI() {
return dictPane;
}
}

18
designer-form/src/main/java/com/fr/design/widget/ui/designer/ComboCheckBoxDefinePane.java

@ -8,7 +8,7 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.widget.component.CheckBoxDictPane;
import com.fr.design.widget.component.ReturnTypePane;
import com.fr.form.ui.ComboCheckBox;
@ -16,10 +16,10 @@ import javax.swing.*;
import java.awt.*;
public class ComboCheckBoxDefinePane extends DictEditorDefinePane<ComboCheckBox> {
private UICheckBox supportTagCheckBox;
private CheckBoxDictPane checkBoxDictPane;
private UITextField waterMarkDictPane;
private UICheckBox removeRepeatCheckBox;
private UICheckBox supportTagCheckBox;
private ReturnTypePane returnTypePane;
private UITextField waterMarkDictPane;
private UICheckBox removeRepeatCheckBox;
public ComboCheckBoxDefinePane(XCreator xCreator) {
super(xCreator);
@ -40,13 +40,13 @@ public class ComboCheckBoxDefinePane extends DictEditorDefinePane<ComboCheckBox>
public JPanel createOtherPane(){
supportTagCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Support_Tag"), true);
supportTagCheckBox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
checkBoxDictPane = new CheckBoxDictPane();
returnTypePane = new ReturnTypePane();
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
Component[][] components = new Component[][]{
new Component[]{supportTagCheckBox, null },
new Component[]{checkBoxDictPane, null},
new Component[]{returnTypePane, null},
};
double[] rowSize = {p, p};
double[] columnSize = {p, f};
@ -56,7 +56,7 @@ public class ComboCheckBoxDefinePane extends DictEditorDefinePane<ComboCheckBox>
}
protected void populateSubDictionaryEditorBean(ComboCheckBox ob){
this.checkBoxDictPane.populate(ob);
this.returnTypePane.populate(ob);
waterMarkDictPane.setText(ob.getWaterMark());
formWidgetValuePane.populate(ob);
this.supportTagCheckBox.setSelected(ob.isSupportTag());
@ -65,7 +65,7 @@ public class ComboCheckBoxDefinePane extends DictEditorDefinePane<ComboCheckBox>
protected ComboCheckBox updateSubDictionaryEditorBean(){
ComboCheckBox combo = (ComboCheckBox) creator.toData();
checkBoxDictPane.update(combo);
returnTypePane.update(combo);
formWidgetValuePane.update(combo);
combo.setWaterMark(waterMarkDictPane.getText());
combo.setSupportTag(this.supportTagCheckBox.isSelected());

68
designer-form/src/main/java/com/fr/design/widget/ui/designer/TreeEditorDefinePane.java

@ -1,78 +1,50 @@
package com.fr.design.widget.ui.designer;
import com.fr.design.data.DataCreatorUI;
import com.fr.design.designer.IntervalConstants;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itree.refreshabletree.TreeRootPane;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.widget.accessibles.AccessibleTreeModelEditor;
import com.fr.design.widget.component.ReturnTypePane;
import com.fr.form.ui.TreeEditor;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
/*
* richer:tree editor
*/
public class TreeEditorDefinePane extends CustomWritableRepeatEditorPane<TreeEditor> {
private ReturnTypePane returnTypePane;
protected TreeRootPane treeRootPane;
private UICheckBox mutiSelect;
private UICheckBox loadAsync;
private UICheckBox returnLeaf;
private UICheckBox returnPath;
private AccessibleTreeModelEditor accessibleTreeModelEditor;
public TreeEditorDefinePane(XCreator xCreator) {
super(xCreator);
treeRootPane = new TreeRootPane();
}
public JPanel createOtherPane() {
mutiSelect = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tree_Mutiple_Selection_Or_Not"));
mutiSelect.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
loadAsync = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Widget_Load_By_Async"));
loadAsync.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
loadAsync.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
UICheckBox checkBox = (UICheckBox) e.getSource();
doLoadTypeChange(checkBox.isSelected());
treeRootPane = new TreeRootPane();
returnTypePane = new ReturnTypePane();
JPanel panel = FRGUIPaneFactory.createBorderLayout_L_Pane();
panel.add(treeRootPane, BorderLayout.NORTH);
returnTypePane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
panel.add(returnTypePane, BorderLayout.CENTER);
treeRootPane.addTreeAttrChangeListener(treeAttr -> {
boolean showReturnTypePane = treeAttr.isMultipleSelection() && !treeAttr.isReturnFullPath();
returnTypePane.setVisible(showReturnTypePane);
if (!showReturnTypePane) {
returnTypePane.setReturnType(ReturnTypePane.ReturnType.ARRAY);
}
});
returnLeaf = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Return_Leaf"));
returnLeaf.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
returnPath = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Return_Path"));
returnPath.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
Component[][] components = new Component[][]{
new Component[]{mutiSelect},
new Component[]{loadAsync},
new Component[]{returnLeaf},
new Component[]{returnPath}
};
double[] rowSize = {p, p, p, p};
double[] columnSize = {p};
JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, IntervalConstants.INTERVAL_L2, IntervalConstants.INTERVAL_L1);
return panel;
}
private void doLoadTypeChange(Boolean selected) {
//给埋点插件提供一个方法,埋埋点用
}
@Override
public String title4PopupWindow() {
return "tree";
@ -89,10 +61,7 @@ public class TreeEditorDefinePane extends CustomWritableRepeatEditorPane<TreeEdi
accessibleTreeModelEditor.setValue(e.getBuildModelConfig());
formWidgetValuePane.populate(e);
treeRootPane.populate(e.getTreeAttr());
mutiSelect.setSelected(e.isMultipleSelection());
loadAsync.setSelected(e.isAjax());
returnLeaf.setSelected(e.isSelectLeafOnly());
returnPath.setSelected(e.isReturnFullPath());
returnTypePane.populate(e);
}
@ -101,11 +70,8 @@ public class TreeEditorDefinePane extends CustomWritableRepeatEditorPane<TreeEdi
TreeEditor editor = (TreeEditor) creator.toData();
formWidgetValuePane.update(editor);
editor.setTreeAttr(treeRootPane.update());
editor.setMultipleSelection(mutiSelect.isSelected());
editor.setAjax(loadAsync.isSelected());
editor.setSelectLeafOnly(returnLeaf.isSelected());
editor.setReturnFullPath(returnPath.isSelected());
editor.setBuildModelConfig(accessibleTreeModelEditor.getValue());
returnTypePane.update(editor);
return editor;
}

2
designer-realize/src/main/java/com/fr/design/fit/NewUIModeCellElementPainter.java

@ -1,6 +1,6 @@
package com.fr.design.fit;
import com.fr.design.fit.common.NewUIModeRotationDraw;
import com.fr.form.fit.NewUIModeRotationDraw;
import com.fr.grid.CellElementPainter;
import com.fr.report.cell.TemplateCellElement;
import com.fr.report.core.PaintUtils;

119
designer-realize/src/main/java/com/fr/design/report/ImageExportPane.java

@ -9,8 +9,9 @@ import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.io.attr.ImageExportAttr;
import com.fr.io.attr.ReportExportAttr;
import com.fr.report.ReportConfigManager;
import java.awt.Color;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JComponent;
@ -35,33 +36,26 @@ public class ImageExportPane extends AbstractExportPane {
private UIRadioButton globalFormatJpg;
private UIRadioButton globalFormatPng;
private UIRadioButton previewResolutionBtnS;
private UIRadioButton previewResolutionBtnM;
private UIRadioButton previewRenderSpeed;
private UIRadioButton previewRenderQuality;
private UIRadioButton templateThumbnail;
private UIRadioButton templatePaging;
private static final int RESOLUTION_S = 96;
private static final int RESOLUTION_M = 192;
private static final int RESOLUTION_L = 300;
private static final int DPI_SCALE_S = 1;
private static final int DPI_SCALE_M = 2;
private static final int GAP = 20;
public static final String GLOBAL_CONF = Toolkit.i18nText("Fine-Design_Image_Export_Global_Configuration");
private ReportExportAttr reportExportAttr;
public static final String GLOBAL_CONF = Toolkit.i18nText("Fine-Design_Image_Export_Setting");
public ImageExportPane() {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JPanel globalTitlePane = FRGUIPaneFactory.createTitledBorderPane(GLOBAL_CONF);
JPanel previewSetting = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_Preview"));
JPanel tipsTitlePane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Report_Advice"));
UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Image_Export_Tips"));
tipLabel.setForeground(Color.RED);
tipsTitlePane.add(tipLabel);
this.add(globalTitlePane, BorderLayout.NORTH);
this.add(previewSetting, BorderLayout.CENTER);
initGlobalSettings();
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
@ -69,6 +63,7 @@ public class ImageExportPane extends AbstractExportPane {
{new UILabel(Toolkit.i18nText("Fine-Design_Image_Export_Resolution") + ":"), this.globalResolutionBtnS, this.globalResolutionBtnM, this.globalResolutionBtnL},
{new UILabel(Toolkit.i18nText("Fine-Design_Report_Format") + ":"), this.globalFormatJpg, null, this.globalFormatPng},
{new UILabel(Toolkit.i18nText("Fine-Design_Image_Export_Rendering_Quality") + ":"), this.globalRenderQuality, null, this.globalRenderSpeed},
{new UILabel(Toolkit.i18nText("Fine-Design_Image_Export_Typesetting") + ":"), this.templateThumbnail, null, this.templatePaging}
};
centerPane.add(
TableLayoutHelper.createCommonTableLayoutPane(
@ -77,23 +72,8 @@ public class ImageExportPane extends AbstractExportPane {
new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL, TableLayout.FILL},
GAP),
BorderLayout.CENTER);
centerPane.add(tipsTitlePane,BorderLayout.SOUTH);
globalTitlePane.add(centerPane, BorderLayout.CENTER);
JPanel templateCenterPane = 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},
};
templateCenterPane.add(
TableLayoutHelper.createCommonTableLayoutPane(
templateComps,
new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL},
new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL},
GAP),
BorderLayout.CENTER);
previewSetting.add(templateCenterPane, BorderLayout.CENTER);
}
@ -101,36 +81,29 @@ public class ImageExportPane extends AbstractExportPane {
globalResolutionBtnS = new UIRadioButton("96dpi", true);
globalResolutionBtnM = new UIRadioButton("192dpi");
globalResolutionBtnL = new UIRadioButton("300dpi");
ButtonGroup globalResolutionBtnGroup = new ButtonGroup();
globalResolutionBtnGroup.add(globalResolutionBtnS);
globalResolutionBtnGroup.add(globalResolutionBtnM);
globalResolutionBtnGroup.add(globalResolutionBtnL);
wrapButtonsInButtonGroup(globalResolutionBtnS, globalResolutionBtnM, globalResolutionBtnL);
globalFormatJpg = new UIRadioButton("jpg", true);
globalFormatPng = new UIRadioButton("png");
ButtonGroup globalFormatGroup = new ButtonGroup();
globalFormatGroup.add(globalFormatJpg);
globalFormatGroup.add(globalFormatPng);
wrapButtonsInButtonGroup(globalFormatJpg, globalFormatPng);
globalRenderQuality = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Quality_First"), true);
globalRenderSpeed = new UIRadioButton(Toolkit.i18nText(("Fine-Design_Image_Export_Speed_Priority")));
ButtonGroup globalRenderGroup = new ButtonGroup();
globalRenderGroup.add(globalRenderQuality);
globalRenderGroup.add(globalRenderSpeed);
previewResolutionBtnS = new UIRadioButton("100%", true);
previewResolutionBtnM = new UIRadioButton("200%");
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);
wrapButtonsInButtonGroup(globalRenderQuality, globalRenderSpeed);
templateThumbnail = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Thumbnail"));
templatePaging = new UIRadioButton(Toolkit.i18nText("Fine-Design_Image_Export_Paging"));
wrapButtonsInButtonGroup(templateThumbnail, templatePaging);
}
private void wrapButtonsInButtonGroup(AbstractButton... buttons) {
if (buttons != null) {
ButtonGroup buttonGroup = new ButtonGroup();
for (AbstractButton button : buttons) {
buttonGroup.add(button);
}
}
}
/**
* 展示界面
@ -150,10 +123,6 @@ public class ImageExportPane extends AbstractExportPane {
updateBean();
}
private ImageExportAttr getGlobalImageExportAttr() {
return ReportConfigManager.getProviderInstance().getImageExportAttr();
}
/**
* 标题
*
@ -166,7 +135,11 @@ public class ImageExportPane extends AbstractExportPane {
@Override
public void populateBean(Object exportAttr) {
ImageExportAttr attr = getGlobalImageExportAttr();
ReportExportAttr reportExportAttr = (ReportExportAttr) exportAttr;
ImageExportAttr attr = reportExportAttr.getImageExportAttr();
if (attr == null) {
attr = new ImageExportAttr();
}
switch (attr.getResolution()) {
case 192:
globalResolutionBtnM.setSelected(true);
@ -187,24 +160,17 @@ public class ImageExportPane extends AbstractExportPane {
} else {
globalRenderQuality.setSelected(true);
}
if (attr.getPreviewRenderQuality() == ImageExportAttr.RENDER_SPEED) {
previewRenderSpeed.setSelected(true);
} else {
previewRenderQuality.setSelected(true);
}
if (attr.getPreviewResolutionScale() == DPI_SCALE_S) {
previewResolutionBtnS.setSelected(true);
if (attr.isPaging()) {
templatePaging.setSelected(true);
} else {
previewResolutionBtnM.setSelected(true);
templateThumbnail.setSelected(true);
}
}
@Override
public void updateBean(Object exportAttr) {
ImageExportAttr attr = getGlobalImageExportAttr();
ReportExportAttr reportExportAttr = (ReportExportAttr) exportAttr;
ImageExportAttr attr = new ImageExportAttr();
if (globalResolutionBtnS.isSelected()) {
attr.setResolution(RESOLUTION_S);
} else if (globalResolutionBtnM.isSelected()) {
@ -222,17 +188,8 @@ public class ImageExportPane extends AbstractExportPane {
} else {
attr.setRenderQuality(ImageExportAttr.RENDER_QUALITY);
}
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);
}
attr.setPaging(templatePaging.isSelected());
reportExportAttr.setImageExportAttr(attr);
}
@Override

20
designer-realize/src/main/java/com/fr/design/widget/ui/CheckBoxGroupDefinePane.java

@ -9,12 +9,12 @@ import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.widget.component.CheckBoxDictPane;
import com.fr.design.widget.component.ReturnTypePane;
import com.fr.form.ui.CheckBoxGroup;
public class CheckBoxGroupDefinePane extends FieldEditorDefinePane<CheckBoxGroup> {
CheckBoxDictPane checkBoxDictPane;
private ReturnTypePane returnTypePane;
private UICheckBox checkbox;
private ButtonGroupDictPane buttonGroupDictPane;
@ -40,13 +40,13 @@ public class CheckBoxGroupDefinePane extends FieldEditorDefinePane<CheckBoxGroup
checkbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Provide_Choose_All"));
checkbox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
buttonGroupDictPane = new ButtonGroupDictPane();
checkBoxDictPane = new CheckBoxDictPane();
returnTypePane = new ReturnTypePane();
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
Component[][] components = new Component[][]{
new Component[]{buttonGroupDictPane, null },
new Component[]{checkbox, null },
new Component[]{checkBoxDictPane, null },
new Component[]{returnTypePane, null },
};
double[] rowSize = {p, p, p, p};
@ -60,7 +60,7 @@ public class CheckBoxGroupDefinePane extends FieldEditorDefinePane<CheckBoxGroup
@Override
protected void populateSubFieldEditorBean(CheckBoxGroup ob) {
checkBoxDictPane.populate(ob);
returnTypePane.populate(ob);
checkbox.setSelected(ob.isChooseAll());
this.buttonGroupDictPane.populate(ob);
}
@ -68,14 +68,14 @@ public class CheckBoxGroupDefinePane extends FieldEditorDefinePane<CheckBoxGroup
@Override
protected CheckBoxGroup updateSubFieldEditorBean() {
CheckBoxGroup ob = new CheckBoxGroup();
checkBoxDictPane.update(ob);
returnTypePane.update(ob);
ob.setChooseAll(checkbox.isSelected());
this.buttonGroupDictPane.update(ob);
return ob;
}
@Override
public DataCreatorUI dataUI() {
return null;
}
@Override
public DataCreatorUI dataUI() {
return null;
}
}

18
designer-realize/src/main/java/com/fr/design/widget/ui/ComboCheckBoxDefinePane.java

@ -9,7 +9,7 @@ import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.widget.accessibles.AccessibleDictionaryEditor;
import com.fr.design.widget.component.CheckBoxDictPane;
import com.fr.design.widget.component.ReturnTypePane;
import com.fr.form.ui.ComboCheckBox;
@ -17,9 +17,9 @@ import javax.swing.*;
import java.awt.*;
public class ComboCheckBoxDefinePane extends CustomWritableRepeatEditorPane<ComboCheckBox> {
private CheckBoxDictPane checkBoxDictPane;
private ReturnTypePane returnTypePane;
private AccessibleDictionaryEditor dictPane;
private UICheckBox supportTagCheckBox;
private UICheckBox supportTagCheckBox;
public ComboCheckBoxDefinePane() {
super.initComponents();
@ -28,7 +28,7 @@ public class ComboCheckBoxDefinePane extends CustomWritableRepeatEditorPane<Comb
@Override
protected JPanel setForthContentPane() {
dictPane = new AccessibleDictionaryEditor();
checkBoxDictPane = new CheckBoxDictPane();
returnTypePane = new ReturnTypePane();
supportTagCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Support_Tag"), true);
supportTagCheckBox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
JPanel advancePane = FRGUIPaneFactory.createBorderLayout_S_Pane();
@ -37,7 +37,7 @@ public class ComboCheckBoxDefinePane extends CustomWritableRepeatEditorPane<Comb
Component[][] components = new Component[][]{
new Component[]{supportTagCheckBox, null },
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_DS_Dictionary")), dictPane },
new Component[]{checkBoxDictPane, null },
new Component[]{returnTypePane, null },
};
double[] rowSize = {p, p, p, p};
@ -52,16 +52,16 @@ public class ComboCheckBoxDefinePane extends CustomWritableRepeatEditorPane<Comb
@Override
protected void populateSubCustomWritableRepeatEditorBean(ComboCheckBox e) {
this.dictPane.setValue(e.getDictionary());
this.checkBoxDictPane.populate(e);
this.supportTagCheckBox.setSelected(e.isSupportTag());
this.returnTypePane.populate(e);
this.supportTagCheckBox.setSelected(e.isSupportTag());
}
@Override
protected ComboCheckBox updateSubCustomWritableRepeatEditorBean() {
ComboCheckBox combo = new ComboCheckBox();
combo.setSupportTag(this.supportTagCheckBox.isSelected());
combo.setSupportTag(this.supportTagCheckBox.isSelected());
combo.setDictionary((Dictionary) this.dictPane.getValue());
checkBoxDictPane.update(combo);
returnTypePane.update(combo);
return combo;
}

104
designer-realize/src/main/java/com/fr/design/widget/ui/TreeComboBoxEditorDefinePane.java

@ -12,64 +12,78 @@ import com.fr.design.gui.itree.refreshabletree.TreeRootPane;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.widget.accessibles.AccessibleTreeModelEditor;
import com.fr.design.widget.component.ReturnTypePane;
import com.fr.form.ui.TreeComboBoxEditor;
import com.fr.form.ui.TreeEditor;
public class TreeComboBoxEditorDefinePane extends CustomWritableRepeatEditorPane<TreeEditor> {
protected AccessibleTreeModelEditor treeSettingPane;
protected TreeRootPane treeRootPane;
protected AccessibleTreeModelEditor treeSettingPane;
public TreeComboBoxEditorDefinePane() {
this.initComponents();
}
private ReturnTypePane returnTypePane;
protected TreeRootPane treeRootPane;
public TreeComboBoxEditorDefinePane() {
this.initComponents();
}
@Override
protected JPanel setForthContentPane() {
JPanel content = FRGUIPaneFactory.createBorderLayout_L_Pane();
content.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
treeRootPane = new TreeRootPane();
content.add(treeRootPane, BorderLayout.NORTH);
return content;
}
@Override
protected JPanel setFirstContentPane() {
treeSettingPane = new AccessibleTreeModelEditor();
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
JPanel north = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Create_Tree")), treeSettingPane}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W2, IntervalConstants.INTERVAL_L1);
north.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
JPanel center = super.setFirstContentPane();
jPanel.add(north, BorderLayout.NORTH);
jPanel.add(center, BorderLayout.CENTER);
return jPanel;
}
@Override
protected JPanel setForthContentPane() {
JPanel content = FRGUIPaneFactory.createBorderLayout_L_Pane();
treeRootPane = new TreeRootPane();
returnTypePane = new ReturnTypePane();
content.add(treeRootPane, BorderLayout.NORTH);
returnTypePane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
content.add(returnTypePane, BorderLayout.CENTER);
treeRootPane.addTreeAttrChangeListener(treeAttr -> {
boolean showReturnTypePane = treeAttr.isMultipleSelection() && !treeAttr.isReturnFullPath();
returnTypePane.setVisible(showReturnTypePane);
if (!showReturnTypePane) {
returnTypePane.setReturnType(ReturnTypePane.ReturnType.ARRAY);
}
});
content.add(treeRootPane, BorderLayout.NORTH);
return content;
}
@Override
protected JPanel setFirstContentPane() {
treeSettingPane = new AccessibleTreeModelEditor();
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
JPanel north = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Create_Tree")), treeSettingPane}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W2, IntervalConstants.INTERVAL_L1);
north.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
JPanel center = super.setFirstContentPane();
jPanel.add(north, BorderLayout.NORTH);
jPanel.add(center, BorderLayout.CENTER);
return jPanel;
}
@Override
protected String title4PopupWindow() {
return "treecombobox";
}
@Override
protected String title4PopupWindow() {
return "treecombobox";
}
@Override
protected void populateSubCustomWritableRepeatEditorBean(TreeEditor e) {
treeSettingPane.setValue(e.getBuildModelConfig());
treeRootPane.populate(e.getTreeAttr());
}
@Override
protected void populateSubCustomWritableRepeatEditorBean(TreeEditor e) {
treeSettingPane.setValue(e.getBuildModelConfig());
treeRootPane.populate(e.getTreeAttr());
returnTypePane.populate(e);
}
@Override
protected TreeComboBoxEditor updateSubCustomWritableRepeatEditorBean() {
TreeComboBoxEditor editor = new TreeComboBoxEditor();
editor.setBuildModelConfig(treeSettingPane.getValue());
editor.setTreeAttr(treeRootPane.update());
return editor;
}
@Override
protected TreeComboBoxEditor updateSubCustomWritableRepeatEditorBean() {
TreeComboBoxEditor editor = new TreeComboBoxEditor();
editor.setBuildModelConfig(treeSettingPane.getValue());
editor.setTreeAttr(treeRootPane.update());
returnTypePane.update(editor);
return editor;
}
@Override
public DataCreatorUI dataUI() {
return null;
}
@Override
public DataCreatorUI dataUI() {
return null;
}
}

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

@ -8,6 +8,7 @@ import com.fr.design.gui.itree.refreshabletree.TreeRootPane;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.widget.accessibles.AccessibleTreeModelEditor;
import com.fr.design.widget.component.ReturnTypePane;
import com.fr.form.ui.TreeEditor;
@ -19,6 +20,8 @@ import java.awt.*;
* richer:tree editor
*/
public class TreeEditorDefinePane extends FieldEditorDefinePane<TreeEditor> {
private ReturnTypePane returnTypePane;
protected TreeRootPane treeRootPane;
private AccessibleTreeModelEditor accessibleTreeModelEditor;
@ -32,6 +35,7 @@ public class TreeEditorDefinePane extends FieldEditorDefinePane<TreeEditor> {
protected void populateSubFieldEditorBean(TreeEditor e) {
this.accessibleTreeModelEditor.setValue(e.getBuildModelConfig());
treeRootPane.populate(e.getTreeAttr());
returnTypePane.populate(e);
if (this.removeRepeatCheckBox != null) {
this.removeRepeatCheckBox.setSelected(e.isRemoveRepeat());
}
@ -42,6 +46,7 @@ public class TreeEditorDefinePane extends FieldEditorDefinePane<TreeEditor> {
TreeEditor editor = new TreeEditor();
editor.setBuildModelConfig(accessibleTreeModelEditor.getValue());
editor.setTreeAttr(treeRootPane.update());
returnTypePane.update(editor);
if (this.removeRepeatCheckBox != null) {
editor.setRemoveRepeat(this.removeRepeatCheckBox.isSelected());
}
@ -75,9 +80,19 @@ public class TreeEditorDefinePane extends FieldEditorDefinePane<TreeEditor> {
protected JPanel setThirdContentPane() {
JPanel content = FRGUIPaneFactory.createBorderLayout_L_Pane();
content.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
treeRootPane = new TreeRootPane();
returnTypePane = new ReturnTypePane();
content.add(treeRootPane, BorderLayout.NORTH);
returnTypePane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
content.add(returnTypePane, BorderLayout.CENTER);
treeRootPane.addTreeAttrChangeListener(treeAttr -> {
boolean showReturnTypePane = treeAttr.isMultipleSelection() && !treeAttr.isReturnFullPath();
returnTypePane.setVisible(showReturnTypePane);
if (!showReturnTypePane) {
returnTypePane.setReturnType(ReturnTypePane.ReturnType.ARRAY);
}
});
//content.add(treeRootPane, BorderLayout.NORTH);
return content;
}

3
designer-realize/src/main/java/com/fr/grid/GridUtils.java

@ -448,7 +448,8 @@ public class GridUtils {
int editElementcolumn = editCellElement.getColumn();
UNIT preferredHeight = PaintUtils.analyzeCellElementPreferredHeight(
editCellElement,
columnWidthList.getRangeValue(editElementcolumn, editElementcolumn + editCellElement.getColumnSpan()));
columnWidthList.getRangeValue(editElementcolumn, editElementcolumn + editCellElement.getColumnSpan()),
DesignerUIModeConfig.getInstance().getAutoChangeLineStrategy());
if (editCellElement.getRowSpan() == 1) {
rowHeightList.set(editCellElement.getRow(),
UNIT.max(preferredHeight, rowHeightList.get(editCellElement.getRow())));

40
designer-realize/src/main/java/com/fr/start/DesignerInitial.java

@ -10,6 +10,7 @@ import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.invoke.Reflect;
import com.fr.stable.bridge.StableFactory;
import com.fr.task.Once;
/**
* Created by juhaoyu on 2019-06-14.
@ -19,6 +20,26 @@ public class DesignerInitial {
private static volatile BaseDesigner designer;
private static final Once OPEN_LAST_FILE_INIT = new Once(() -> {
EventDispatcher.listen(DesignerLaunchStatus.OPEN_LAST_FILE_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
EventDispatcher.stopListen(this);
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
DesignerContext.getDesignerFrame().setVisible(true);
DesignerContext.getDesignerFrame().resizeFrame();
//启动画面结束
SplashContext.getInstance().hide();
}
});
DesignerLaunchStatus.setStatus(DesignerLaunchStatus.STARTUP_COMPLETE);
}
});
});
public static void init(final String... args) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
@ -34,6 +55,8 @@ public class DesignerInitial {
}
public static void prepare() {
DesignerLaunchStatus.setStatus(DesignerLaunchStatus.DESIGNER_INIT_STARTED);
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
@ -42,21 +65,6 @@ public class DesignerInitial {
}
}
});
EventDispatcher.listen(DesignerLaunchStatus.OPEN_LAST_FILE_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
EventDispatcher.stopListen(this);
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
DesignerContext.getDesignerFrame().setVisible(true);
DesignerContext.getDesignerFrame().resizeFrame();
//启动画面结束
SplashContext.getInstance().hide();
}
});
DesignerLaunchStatus.setStatus(DesignerLaunchStatus.STARTUP_COMPLETE);
}
});
OPEN_LAST_FILE_INIT.run();
}
}

2
designer-realize/src/main/java/com/fr/start/DesignerJavaRuntime.java

@ -2,7 +2,6 @@ package com.fr.start;
import com.fr.design.os.impl.SupportOSImpl;
import com.fr.general.ComparatorUtils;
import com.fr.general.GeneralContext;
import com.fr.general.GeneralUtils;
import com.fr.general.IOUtils;
import com.fr.locale.InterProviderFactory;
@ -15,7 +14,6 @@ import com.fr.stable.os.OperatingSystem;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

7
designer-realize/src/main/java/com/fr/start/LifecycleFatalErrorHandler.java

@ -26,6 +26,7 @@ import com.fr.stable.lifecycle.ErrorType;
import com.fr.stable.lifecycle.ErrorTypeHelper;
import com.fr.stable.lifecycle.FineLifecycleFatalError;
import com.fr.stable.project.ProjectConstants;
import com.fr.start.common.DesignerStartupContext;
import javax.swing.JOptionPane;
import java.util.Collection;
@ -54,6 +55,12 @@ public class LifecycleFatalErrorHandler {
}
public void handle(FineLifecycleFatalError fatal) {
if (DesignerStartupContext.getInstance().onWarmup()) {
// 如果是预热过程中的错误,不理
return;
}
SplashContext.getInstance().hide();
FineProcessContext.getParentPipe().fire(new CarryMessageEvent(ReportState.STOP.getValue()));

54
designer-realize/src/main/java/com/fr/start/MainDesigner.java

@ -1,6 +1,7 @@
package com.fr.start;
import com.fr.base.function.UITerminator;
import com.fr.base.vcs.DesignerMode;
import com.fr.design.DesignerEnvManager;
import com.fr.design.actions.file.WebPreviewUtils;
@ -32,6 +33,8 @@ import com.fr.design.mainframe.alphafine.component.AlphaFinePane;
import com.fr.design.mainframe.bbs.UserInfoLabel;
import com.fr.design.mainframe.bbs.UserInfoPane;
import com.fr.design.mainframe.guide.entry.GuideEntryPane;
import com.fr.design.mainframe.messagecollect.StartErrorMessageCollector;
import com.fr.design.mainframe.messagecollect.entity.DesignerErrorMessage;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
import com.fr.design.menu.KeySetUtils;
import com.fr.design.menu.MenuDef;
@ -44,6 +47,8 @@ import com.fr.design.monitor.DesignerLifecycleMonitorContext;
import com.fr.design.notification.ui.NotificationCenterPane;
import com.fr.design.share.SharableManager;
import com.fr.design.ui.util.UIUtil;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.DesignerPort;
import com.fr.design.utils.concurrent.ThreadFactoryBuilder;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.env.utils.DesignerInteractionHistory;
@ -61,8 +66,10 @@ import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.lifecycle.FineLifecycleFatalError;
import com.fr.stable.xml.XMLTools;
import com.fr.start.common.DesignerStartupContext;
import com.fr.start.common.SplashCommon;
import com.fr.start.module.StartupArgs;
import com.fr.start.preload.PreLoadService;
import com.fr.start.server.ServerTray;
import com.fr.third.org.apache.commons.lang3.time.StopWatch;
import com.fr.van.chart.map.server.ChartMapEditorAction;
@ -74,11 +81,14 @@ import javax.swing.border.MatteBorder;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
@ -109,14 +119,19 @@ public class MainDesigner extends BaseDesigner {
* @param args 参数
*/
public static void main(String[] args) {
DesignerStartupContext.getRecorder().start();
showSplash();
startPreload0();
DeepLinkManager.getInstance().start(args);
StopWatch watch = new StopWatch();
watch.start();
DesignerLifecycleMonitorContext.getMonitor().beforeStart();
//启动运行时
FineRuntime.start();
startPreload1();
DesignerSubListener.getInstance().start();
EventDispatcher.listen(LifecycleErrorEvent.SELF, new Listener<FineLifecycleFatalError>() {
@Override
@ -125,6 +140,8 @@ public class MainDesigner extends BaseDesigner {
}
});
Module designerRoot = ModuleContext.parseRoot("designer-startup.xml");
FineLoggerFactory.getLogger().debug("designer-startup prepared cost {} ms", DesignerStartupContext.getRecorder().getTime(TimeUnit.MILLISECONDS));
//传递启动参数
designerRoot.setSingleton(StartupArgs.class, new StartupArgs(args));
try {
@ -141,6 +158,41 @@ public class MainDesigner extends BaseDesigner {
watch.stop();
}
/**
* {@link FineRuntime#start()} 运行后
*/
private static void startPreload1() {
CompletableFuture<Void> initLookAndFeel = CompletableFuture.runAsync(DesignUtils::initLookAndFeel);
PreLoadService.getInstance().addFuture(initLookAndFeel);
}
/**
* {@link FineRuntime#start()} 运行前
*/
private static void startPreload0() {
PreLoadService.getInstance().addRunnable(() -> {
if (DesignUtils.isPortOccupied()) {
UITerminator action = new UITerminator() {
@Override
protected void doRun() {
StartErrorMessageCollector.getInstance().record(DesignerErrorMessage.PORT_OCCUPIED.getId(),
DesignerErrorMessage.PORT_OCCUPIED.getMessage());
DesignerPort.getInstance().resetPort();
}
};
action.run();
}
});
Runnable fontLoad = () -> {
Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
};
PreLoadService.getInstance().addRunnable(fontLoad);
}
private static void showSplash() {
// 快快显示启动画面
UIUtil.invokeAndWaitIfNeeded(new Runnable() {

1
designer-realize/src/main/java/com/fr/start/SplashContext.java

@ -83,7 +83,6 @@ public class SplashContext {
//取消监听
EventDispatcher.stopListen(listener);
splashStrategy.hide();
// 一次性
splashStrategy = null;
}
}

11
designer-realize/src/main/java/com/fr/start/common/SplashPane.java

@ -4,17 +4,22 @@ import com.bulenkov.iconloader.IconLoader;
import com.bulenkov.iconloader.util.JBUI;
import com.fr.base.GraphHelper;
import com.fr.design.locale.impl.SplashMark;
import com.fr.stable.GraphicsConfig;
import com.fr.general.locale.LocaleCenter;
import com.fr.general.locale.LocaleMark;
import com.fr.stable.GraphDrawHelper;
import com.fr.stable.GraphicsConfig;
import com.fr.stable.StringUtils;
import com.fr.stable.os.OperatingSystem;
import com.fr.value.NotNullLazyValue;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import javax.swing.Icon;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Locale;
/**

77
designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java

@ -102,6 +102,8 @@ import com.fr.log.FineLoggerFactory;
import com.fr.log.LogHandler;
import com.fr.module.Activator;
import com.fr.module.extension.Prepare;
import com.fr.plugin.beforeload.embed.DefaultPluginEmbedInfo;
import com.fr.plugin.beforeload.embed.PluginEmbedInfo;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.injectable.PluginModule;
import com.fr.plugin.manage.PluginFilter;
@ -135,16 +137,19 @@ import com.fr.stable.script.ValueConverter;
import com.fr.stable.xml.ObjectTokenizer;
import com.fr.stable.xml.ObjectXMLWriterFinder;
import com.fr.start.BBSGuestPaneProvider;
import com.fr.start.common.DesignerStartupExecutor;
import com.fr.start.common.DesignerStartupPool;
import com.fr.task.Once;
import com.fr.workspace.WorkContext;
import com.fr.xml.ReportXMLUtils;
import javax.swing.SwingWorker;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.swing.SwingWorker;
import java.util.concurrent.CompletableFuture;
/**
* Created by juhaoyu on 2018/1/31.
@ -154,7 +159,7 @@ import javax.swing.SwingWorker;
public class DesignerActivator extends Activator implements Prepare {
private LogHandler<DesignerLogAppender> logHandler = null;
private static final String PLUGIN_EXPORT_IMAGE_SETTING = "com.fr.plugin.exportimagesettings.v11";
private final Once pushUpdateTask = new Once(new Runnable() {
@Override
public void run() {
@ -164,40 +169,59 @@ public class DesignerActivator extends Activator implements Prepare {
}
});
private boolean hasUpdated = false;
@Override
public void start() {
startLoginAuthServer();
migrateBBSInfoFromFineDB();
FormThemeConfigMigrator.getInstance().upgrade();
ReportThemeConfigMigrator.getInstance().upgrade();
List<LocaleMarker> markers = findMutable(InterMutableKey.Path);
for (LocaleMarker marker : markers) {
if (marker.match(LocaleScope.DESIGN)) {
DesignI18nImpl.getInstance().addResource(marker.getPath());
}
}
designerModuleStart();
loadLogAppender();
DesignerSocketIO.update();
DesignerWorkspaceLoader.init();
OSSupportCenter.buildAction(new OSBasedAction() {
@Override
public void execute(Object... objects) {
UserInfoPane.getInstance().updateBBSUserInfo();
}
}, SupportOSImpl.BBS_USER_LOGIN_PANE);
storePassport();
AlphaFineHelper.switchConfig4Locale();
RecoverManager.register(new RecoverForDesigner());
pushUpdateTask.run();
PluginResourceLoader.INSTANCE.checkOldShopFile();
UpmResourceLoader.INSTANCE.checkOldShopFile();
CompletableFuture<Void> themeConfigPrepare = CompletableFuture.runAsync(() -> {
FormThemeConfigMigrator.getInstance().upgrade();
ReportThemeConfigMigrator.getInstance().upgrade();
}, DesignerStartupPool.common());
CompletableFuture<Void> mainDesignerPrepare = CompletableFuture.runAsync(this::designerModuleStart, DesignerStartupPool.common());
CompletableFuture<Void> otherFeaturesPrepare = CompletableFuture.runAsync(() -> {
startBBSLoginAuthServer();
migrateBBSInfoFromFineDB();
OSSupportCenter.buildAction(new OSBasedAction() {
@Override
public void execute(Object... objects) {
UserInfoPane.getInstance().updateBBSUserInfo();
}
}, SupportOSImpl.BBS_USER_LOGIN_PANE);
loadLogAppender();
DesignerSocketIO.update();
DesignerWorkspaceLoader.init();
storePassport();
AlphaFineHelper.switchConfig4Locale();
RecoverManager.register(new RecoverForDesigner());
});
CompletableFuture<Void> resourcePrepare = CompletableFuture.runAsync(() -> {
pushUpdateTask.run();
PluginResourceLoader.INSTANCE.checkOldShopFile();
UpmResourceLoader.INSTANCE.checkOldShopFile();
}, DesignerStartupPool.common());
CompletableFuture
.allOf(mainDesignerPrepare, themeConfigPrepare, otherFeaturesPrepare, resourcePrepare)
.join();
}
@Override
public void afterAllStart() {
DesignerLaunchStatus.setStatus(DesignerLaunchStatus.DESIGNER_INIT_COMPLETE);
DesignerStartupExecutor.getInstance().execute(() -> DesignerLaunchStatus.setStatus(DesignerLaunchStatus.DESIGNER_INIT_COMPLETE));
//生成BasicChartQuickEditor对象,需要用到ChartDesignerActivator的注册信息(DesignModuleFactory.registerChartPropertyPaneClass(ChartPropertyPane.class);)
//所以不能在registerCellEditor函数中进行注册
ActionFactory.registerCellEditor(ChartCollection.class, new BasicChartQuickEditor());
@ -520,9 +544,14 @@ public class DesignerActivator extends Activator implements Prepare {
}.execute();
}
});
prepareDefaultEmbedPluginInfo();
}
private void prepareDefaultEmbedPluginInfo() {
addMutable(PluginEmbedInfo.KEY, DefaultPluginEmbedInfo.create(PLUGIN_EXPORT_IMAGE_SETTING));
}
private void startLoginAuthServer() {
private void startBBSLoginAuthServer() {
OptimizeUtil.open(() -> {
// 设计器启动后启动

30
designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java

@ -17,7 +17,6 @@ import com.fr.design.mainframe.messagecollect.StartErrorMessageCollector;
import com.fr.design.mainframe.messagecollect.StartupMessageCollector;
import com.fr.design.mainframe.messagecollect.entity.DesignerErrorMessage;
import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.DesignerPort;
import com.fr.env.utils.WorkspaceUtils;
import com.fr.event.Event;
import com.fr.event.Listener;
@ -35,12 +34,15 @@ import com.fr.stable.project.ProjectConstants;
import com.fr.start.DesignerProcessType;
import com.fr.start.ServerStarter;
import com.fr.start.event.LazyStartupEvent;
import com.fr.start.preload.PreLoadService;
import com.fr.start.server.FineEmbedServer;
import com.fr.third.guava.base.Stopwatch;
import com.fr.value.NotNullLazyValue;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Created by juhaoyu on 2018/1/8.
@ -58,17 +60,15 @@ public class DesignerStartup extends Activator {
@Override
public void beforeAllStart() {
BuildContext.setBuildFilePath("/com/fr/stable/build.properties");
registerDaoSelector();
// 初始化look and feel
DesignUtils.initLookAndFeel();
if (DesignUtils.isPortOccupied()) {
StartErrorMessageCollector.getInstance().record(DesignerErrorMessage.PORT_OCCUPIED.getId(),
DesignerErrorMessage.PORT_OCCUPIED.getMessage());
DesignerPort.getInstance().resetPort();
}
Stopwatch beforeWatch = Stopwatch.createStarted();
PreLoadService.getInstance().waitForAll();
FineLoggerFactory.getLogger().debug( "DesignerStartup cost {} ms to wait load", beforeWatch.elapsed(TimeUnit.MILLISECONDS));
if (DesignUtils.isStarted()) {
// 如果端口被占用了 说明程序已经运行了一次,也就是说,已经建立一个监听服务器,现在只要给服务器发送命令就好了
final String[] args = startupArgsValue.getValue().get();
@ -78,10 +78,10 @@ public class DesignerStartup extends Activator {
FineLoggerFactory.getLogger().info("The Designer Has Been Started");
if (args.length == 0) {
TipDialog dialog = new TipDialog(null,
DesignerProcessType.INSTANCE.obtain(),
Toolkit.i18nText("Fine-Design_Last_Designer_Process_Not_Exist"),
Toolkit.i18nText("Fine-Design_End_Occupied_Process"),
Toolkit.i18nText("Fine-Design_Basic_Cancel")) {
DesignerProcessType.INSTANCE.obtain(),
Toolkit.i18nText("Fine-Design_Last_Designer_Process_Not_Exist"),
Toolkit.i18nText("Fine-Design_End_Occupied_Process"),
Toolkit.i18nText("Fine-Design_Basic_Cancel")) {
@Override
protected void endEvent() {
dispose();
@ -96,13 +96,13 @@ public class DesignerStartup extends Activator {
};
dialog.setVisible(true);
StartErrorMessageCollector.getInstance().record(DesignerErrorMessage.DESIGNER_PROCESS_OCCUPIED.getId(),
DesignerErrorMessage.DESIGNER_PROCESS_OCCUPIED.getMessage(),
StringUtils.EMPTY);
DesignerErrorMessage.DESIGNER_PROCESS_OCCUPIED.getMessage(),
StringUtils.EMPTY);
FineLoggerFactory.getLogger().error(DesignerErrorMessage.DESIGNER_PROCESS_OCCUPIED.getId() + ": " + DesignerErrorMessage.DESIGNER_PROCESS_OCCUPIED.getMessage());
}
DesignerExiter.getInstance().execute();
return;
}
}
@Override

6
designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java

@ -7,7 +7,7 @@ import com.fr.design.editlock.ConnectionLockChangeChecker;
import com.fr.design.editlock.ServerTableDataLockChangeChecker;
import com.fr.design.env.DesignerWorkspaceGenerator;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.env.LocalDesignerWorkspaceInfo;
import com.fr.design.plugin.remind.PluginErrorDesignReminder;
import com.fr.design.versioncheck.VersionCheckUtils;
import com.fr.env.utils.WorkspaceUtils;
import com.fr.event.Event;
@ -16,7 +16,6 @@ import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.log.FineLoggerFactory;
import com.fr.module.Activator;
import com.fr.stable.StringUtils;
import com.fr.value.NotNullLazyValue;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
@ -74,7 +73,8 @@ public class DesignerWorkspaceProvider extends Activator {
EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null aNull) {
EnvChangeEntrance.getInstance().pluginErrorRemind();
PluginErrorDesignReminder.getInstance().remindStartFailedPlugins();
PluginErrorDesignReminder.getInstance().remindInvalidatePlugins();
}
});
}

24
designer-realize/src/main/java/com/fr/start/module/optimized/DesignerPluginActivator.java

@ -0,0 +1,24 @@
package com.fr.start.module.optimized;
import com.fr.module.Activator;
import com.fr.module.ModuleContext;
import com.fr.plugin.PluginActivator;
import com.fr.start.common.DesignerStartupExecutor;
/**
* created by Harrison on 2022/06/22
**/
public class DesignerPluginActivator extends Activator {
@Override
public void start() {
DesignerStartupExecutor.getInstance().execute(() -> ModuleContext.getModule(PluginActivator.class).start());
}
@Override
public void stop() {
ModuleContext.getModule(PluginActivator.class).stop();
}
}

119
designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.java

@ -0,0 +1,119 @@
package com.fr.start.module.optimized;
import com.fr.design.ui.util.UIUtil;
import com.fr.log.FineLoggerFactory;
import com.fr.module.Activator;
import com.fr.start.SplashContext;
import com.fr.start.common.DesignerStartupContext;
import com.fr.start.module.StartupArgs;
import com.fr.start.util.DesignerStartupPageUtil;
import com.fr.start.warmup.DesignerPreWarmTask;
import com.fr.startup.ui.StartupPageModel;
import com.fr.startup.ui.StartupPageWindow;
import com.fr.third.org.apache.commons.lang3.time.StopWatch;
import com.fr.value.NotNullLazyValue;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.TimeUnit;
/**
* 设计器起始页启动器
* <a href="https://kms.fineres.com/pages/viewpage.action?pageId=416850313">设计文档</a>
*
* created by Harrison on 2022/07/03
**/
public class DesignerStartupPageActivator extends Activator {
private final NotNullLazyValue<StartupArgs> startupArgsValue = new NotNullLazyValue<StartupArgs>() {
@NotNull
@Override
protected StartupArgs compute() {
return findSingleton(StartupArgs.class);
}
};
@Override
public void start() {
DesignerStartupContext context = DesignerStartupContext.getInstance();
context.setStartupArgs(startupArgsValue.getValue());
if (context.isShowStartupPage()) {
showDesignerStartupPage(context);
} else {
DesignerStartupPageUtil.enterWorkspace();
}
}
private void showDesignerStartupPage(DesignerStartupContext context) {
// 启动页关闭
SplashContext.getInstance().hide();
// 预热任务启动
DesignerPreWarmTask warmTask = new DesignerPreWarmTask();
warmTask.start();
// 即时暂停
DesignerStartupContext.getRecorder().suspend();
UIUtil.invokeLaterIfNeeded(() -> {
StartupPageModel model = StartupPageModel.create();
context.setStartupPageModel(model);
// selectAndOpenLast
model.setOpenLastTemplateRunnable(() -> {
context.setOpenLastFile(true);
launchAfterWarmup(warmTask);
});
// selectAndOpenEmpty
model.setOpenEmptyTemplateRunnable(() -> {
context.setOpenEmpty(true);
launchAfterWarmup(warmTask);
});
// selectAndCreateNew
model.setCreateNewTemplateRunnable(() -> {
context.setCreateNew(true);
launchAfterWarmup(warmTask);
});
StartupPageWindow window = new StartupPageWindow(model);
window.setVisible(true);
context.setOnWaiting(true);
});
}
private void launchAfterWarmup(DesignerPreWarmTask warmTask) {
StopWatch stopWatch = StopWatch.createStarted();
try {
DesignerStartupContext.getRecorder().resume();
// 等待中切换
DesignerStartupContext.getInstance().setOnWaiting(false);
warmTask.join();
FineLoggerFactory.getLogger().debug("designer-startup-page warm up cost {} ms", stopWatch.getTime(TimeUnit.MILLISECONDS));
DesignerStartupContext.getInstance().setOnStartup(true);
DesignerStartupPageUtil.enterWorkspace();
} finally {
UIUtil.invokeLaterIfNeeded(() -> {
// 换到 awt 线程中关闭,不然异步会出现问题。
DesignerStartupContext.getInstance().setOnStartup(false);
});
}
FineLoggerFactory.getLogger().debug("designer-startup-page started cost {} ms", DesignerStartupContext.getRecorder().getTime(TimeUnit.MILLISECONDS));
}
@Override
public void stop() {
}
}

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

Loading…
Cancel
Save