Browse Source

Merge branch 'feature/x' of https://code.fineres.com/scm/~fly.li/design into feature/x

feature/x
Fly.Li 2 years ago
parent
commit
2beadd4b06
  1. 24
      designer-base/src/main/java/com/fr/base/function/UITerminator.java
  2. 53
      designer-base/src/main/java/com/fr/design/DesignerEnvManager.java
  3. 4
      designer-base/src/main/java/com/fr/design/actions/file/PreferenceAction.java
  4. 44
      designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java
  5. 148
      designer-base/src/main/java/com/fr/design/components/loading/LoadingPane.java
  6. 107
      designer-base/src/main/java/com/fr/design/components/tooltip/ModernToolTip.java
  7. 7
      designer-base/src/main/java/com/fr/design/constants/DesignerLaunchStatus.java
  8. 3
      designer-base/src/main/java/com/fr/design/gui/itooltip/UIToolTip.java
  9. 47
      designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java
  10. 35
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java
  11. 108
      designer-base/src/main/java/com/fr/design/mainframe/TransparentPane.java
  12. 34
      designer-base/src/main/java/com/fr/design/update/actions/NewFeatureAction.java
  13. 111
      designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java
  14. 29
      designer-base/src/main/java/com/fr/design/utils/DesignUtils.java
  15. 81
      designer-base/src/main/java/com/fr/start/BaseDesigner.java
  16. 77
      designer-base/src/main/java/com/fr/start/common/DesignerOpenEmptyPanel.java
  17. 55
      designer-base/src/main/java/com/fr/start/common/DesignerStartupConfig.java
  18. 176
      designer-base/src/main/java/com/fr/start/common/DesignerStartupContext.java
  19. 32
      designer-base/src/main/java/com/fr/start/common/DesignerStartupExecutor.java
  20. 20
      designer-base/src/main/java/com/fr/start/common/DesignerStartupPool.java
  21. 51
      designer-base/src/main/java/com/fr/start/common/DesignerStartupUtil.java
  22. 0
      designer-base/src/main/java/com/fr/start/module/StartupArgs.java
  23. 17
      designer-base/src/main/java/com/fr/startup/ui/StartupPageConstants.java
  24. 111
      designer-base/src/main/java/com/fr/startup/ui/StartupPageModel.java
  25. 40
      designer-base/src/main/java/com/fr/startup/ui/StartupPageUtil.java
  26. 339
      designer-base/src/main/java/com/fr/startup/ui/StartupPageWindow.java
  27. 501
      designer-base/src/main/java/com/fr/startup/ui/StartupPageWorkspacePanel.java
  28. 49
      designer-base/src/main/java/com/fr/startup/ui/StartupWorkspaceBean.java
  29. 1
      designer-base/src/main/resources/com/fr/design/i18n/dimension_zh.properties
  30. 3
      designer-base/src/main/resources/com/fr/design/standard/system/add.svg
  31. 3
      designer-base/src/main/resources/com/fr/design/standard/system/add_hover.svg
  32. 32
      designer-base/src/main/resources/com/fr/design/standard/system/cpt.svg
  33. 4
      designer-base/src/main/resources/com/fr/design/standard/system/home_folder.svg
  34. 6
      designer-base/src/main/resources/com/fr/design/standard/system/remote_connect.svg
  35. 18
      designer-base/src/main/resources/com/fr/design/startup/create_new_template.svg
  36. 11
      designer-base/src/main/resources/com/fr/design/startup/local_server_background_28.svg
  37. 11
      designer-base/src/main/resources/com/fr/design/startup/local_server_background_36.svg
  38. 3
      designer-base/src/main/resources/com/fr/design/startup/more.svg
  39. 3
      designer-base/src/main/resources/com/fr/design/startup/more_hover.svg
  40. 12
      designer-base/src/main/resources/com/fr/design/startup/remote_server_background_28.svg
  41. 18
      designer-base/src/main/resources/com/fr/design/startup/remote_server_background_36.svg
  42. 3
      designer-base/src/main/resources/com/fr/design/startup/show_less.svg
  43. 3
      designer-base/src/main/resources/com/fr/design/startup/show_more.svg
  44. 2
      designer-base/src/test/java/com/fr/design/utils/DevDebugUtils.java
  45. 6
      designer-base/src/test/java/com/fr/design/utils/DevUtils.java
  46. 32
      designer-base/src/test/java/com/fr/startup/ui/StartupPageWindowTest.java
  47. 40
      designer-realize/src/main/java/com/fr/start/DesignerInitial.java
  48. 2
      designer-realize/src/main/java/com/fr/start/DesignerJavaRuntime.java
  49. 7
      designer-realize/src/main/java/com/fr/start/LifecycleFatalErrorHandler.java
  50. 61
      designer-realize/src/main/java/com/fr/start/MainDesigner.java
  51. 1
      designer-realize/src/main/java/com/fr/start/SplashContext.java
  52. 11
      designer-realize/src/main/java/com/fr/start/common/SplashPane.java
  53. 72
      designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java
  54. 36
      designer-realize/src/main/java/com/fr/start/module/DesignerStartup.java
  55. 24
      designer-realize/src/main/java/com/fr/start/module/optimized/DesignerPluginActivator.java
  56. 119
      designer-realize/src/main/java/com/fr/start/module/optimized/DesignerStartupPageActivator.java
  57. 36
      designer-realize/src/main/java/com/fr/start/preload/PreLoadService.java
  58. 31
      designer-realize/src/main/java/com/fr/start/util/DesignerStartupPageUtil.java
  59. 47
      designer-realize/src/main/java/com/fr/start/warmup/DesignerPreWarmTask.java

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

53
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;
@ -188,7 +189,9 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private DesignerPushUpdateConfigManager designerPushUpdateConfigManager = DesignerPushUpdateConfigManager.getInstance();
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";
@ -1000,6 +1003,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
public void setLanguage(Locale locale) {
this.language = locale;
}
public boolean isStartupPageEnabled() {
return this.designerStartupConfig.isEnabled();
}
public void setStartupPageEnabled(boolean enabled) {
this.designerStartupConfig.setEnabled(enabled);
}
/**
* 返回环境名称迭代器
@ -1119,23 +1130,26 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
public void setCurrentDirectoryPrefix(String prefix) {
this.CurrentDirectoryPrefix = prefix;
}
/**
* 返回最近打开的文件路径列表
*/
public List<String> getRecentOpenedFilePathList() {
if (StringUtils.isEmpty(getCurEnvName())) {
public List<String> getRecentOpenedFilePathList4Env(String envName) {
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")) {
@ -1869,6 +1885,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private void readEnvDetectorConfig(XMLableReader reader) {
reader.readXMLObject(this.envDetectorConfig);
}
private void readStartupConfig(XMLableReader reader) {
reader.readXMLObject(this.designerStartupConfig);
}
private void readHttpsParas(XMLableReader reader) {
String tempVal;
@ -2084,6 +2104,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
writeHttpsParas(writer);
writeAlphaFineAttr(writer);
writeEnvDetectorConfig(writer);
writeStartupConfig(writer);
writeRecentColor(writer);
writeOpenDebug(writer);
writeDesignerPushUpdateAttr(writer);
@ -2133,6 +2154,12 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.envDetectorConfig.writeXML(writer);
}
}
private void writeStartupConfig(XMLPrintWriter writer) {
if (this.designerStartupConfig != null) {
this.designerStartupConfig.writeXML(writer);
}
}
//写入uuid
private void writeUUID(XMLPrintWriter writer) {

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

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

@ -18,6 +18,7 @@ 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;
@ -56,6 +57,7 @@ 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;
@ -67,10 +69,12 @@ 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;
@ -183,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;
@ -195,7 +200,7 @@ public class PreferencePane extends BasicPane {
private JProgressBar gcProgressBar;
private Timer gcProgressTimer;
private UIButton gcOkButton = new UIButton(i18nText("Fine-Design_Report_OK"));
private UIRadioButton previewResolutionBtnS;
private UIRadioButton previewResolutionBtnM;
@ -215,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);
@ -232,6 +241,8 @@ public class PreferencePane extends BasicPane {
createLogPane(advancePane);
createLanPane(generalPane);
createStartupPagePane(generalPane);
createLengthPane(advancePane);
@ -296,7 +307,7 @@ public class PreferencePane extends BasicPane {
designerStartupOption.add(cloudAnalyticsDelayCheckBox);
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"));
@ -325,6 +336,14 @@ public class PreferencePane extends BasicPane {
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);
@ -631,6 +650,21 @@ public class PreferencePane extends BasicPane {
languageComboBox.setFont(FRFont.getInstance("Dialog", Font.PLAIN, 12));//为了在中文系统中显示韩文
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)
@ -820,6 +854,7 @@ public class PreferencePane extends BasicPane {
previewResolutionBtnM.setEnabled(enabled);
this.cloudAnalyticsDelayCheckBox.setSelected(designerEnvManager.isCloudAnalyticsDelay());
this.startupPageEnabledCheckBox.setSelected(designerEnvManager.isStartupPageEnabled());
}
private int chooseCase(int sign) {
@ -886,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() {

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

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

@ -15,7 +15,12 @@ public enum DesignerLaunchStatus implements Event<Null> {
* 初始化环境完成
*/
WORKSPACE_INIT_COMPLETE,
/**
* 设计器模块初始化开始
*/
DESIGNER_INIT_STARTED,
/**
* 设计器模块启动完成
*/

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;

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;
@ -148,6 +151,50 @@ public class FRGUIPaneFactory {
public static LayoutManager createNColumnGridLayout(int nColumn) {
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) {
}
};
}
/**
* 创建一个带标题边框面板

35
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()) {
@ -302,10 +305,15 @@ 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
@ -798,6 +806,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();
}
/**
* 添加新建模板, 并激活.

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

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

111
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;
@ -185,7 +188,7 @@ public class UpdateMainDialog extends UIDialog {
double[] rowUpdateContentPaneSize = {TableLayout.PREFERRED};
double[] columnUpdateContentPaneSize = {TableLayout.PREFERRED, TableLayout.FILL, TableLayout.PREFERRED};
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();
@ -196,7 +199,8 @@ public class UpdateMainDialog extends UIDialog {
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_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);
@ -417,14 +421,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 +494,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 +542,9 @@ 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 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));
@ -608,41 +619,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 +665,12 @@ public class UpdateMainDialog extends UIDialog {
return false;
}
private ActionLabel getNewFeatureActionLabel(final String text){
ActionLabel actionLabel = new ActionLabel(text);
actionLabel.addActionListener(new NewFeatureAction());
return actionLabel;
}
/**
* 显示窗口
*/
@ -705,4 +688,42 @@ 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);
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();
}
}
}
}

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

81
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,19 +157,52 @@ 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) {
String className = "com.apple.eawt.FullScreenUtilities";
String methodName = "setWindowCanFullScreen";

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

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

@ -15,6 +15,7 @@ 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

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

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

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.
@ -18,6 +19,26 @@ import com.fr.stable.bridge.StableFactory;
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() {
@ -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()));

61
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;
@ -110,13 +120,19 @@ public class MainDesigner extends BaseDesigner {
*/
public static void main(String[] args) {
showSplash();
DesignerStartupContext.getRecorder().start();
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 +141,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 +159,47 @@ 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);
CompletableFuture<Void> splashFuture = CompletableFuture.runAsync(() -> {
DesignerEnvManager.getEnvManager(false);
})
.thenRun(MainDesigner::showSplash);
PreLoadService.getInstance().addFuture(splashFuture);
}
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;
/**

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

@ -137,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.
@ -165,41 +168,60 @@ public class DesignerActivator extends Activator implements Prepare {
DesignerMessageHelper.getInstance().prepareShowMessage();
}
});
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());
@ -500,9 +522,9 @@ public class DesignerActivator extends Activator implements Prepare {
@Override
public void prepare() {
OptimizeUtil.close(() -> {
if (!OptimizeUtil.isOpen()) {
LoginAuthServer.getInstance().compatibleStart();
});
}
ContentReplacerCenter.getInstance().register();
EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener<Null>() {
@Override
@ -530,7 +552,7 @@ public class DesignerActivator extends Activator implements Prepare {
addMutable(PluginEmbedInfo.KEY, DefaultPluginEmbedInfo.create(PLUGIN_EXPORT_IMAGE_SETTING));
}
private void startLoginAuthServer() {
private void startBBSLoginAuthServer() {
OptimizeUtil.open(() -> {
// 设计器启动后启动

36
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,17 +78,17 @@ 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();
DesignUtils.clientSend(new String[]{"end"});
RestartHelper.restart();
}
@Override
protected void cancelEvent() {
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

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

36
designer-realize/src/main/java/com/fr/start/preload/PreLoadService.java

@ -0,0 +1,36 @@
package com.fr.start.preload;
import com.fr.start.common.DesignerStartupPool;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* created by Harrison on 2022/06/01
**/
public class PreLoadService {
private List<CompletableFuture<?>> futures = new ArrayList<>();
public static PreLoadService getInstance() {
return PreLoadServiceHolder.INSTANCE;
}
private static class PreLoadServiceHolder {
private static final PreLoadService INSTANCE = new PreLoadService();
}
public void addFuture(CompletableFuture<?> future) {
futures.add(future);
}
public void addRunnable(Runnable runnable) {
futures.add(CompletableFuture.runAsync(runnable, DesignerStartupPool.common()));
}
public void waitForAll() {
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
}
}

31
designer-realize/src/main/java/com/fr/start/util/DesignerStartupPageUtil.java

@ -0,0 +1,31 @@
package com.fr.start.util;
import com.fr.module.ModuleContext;
import com.fr.start.module.DesignerWorkspaceActivator;
/**
* created by Harrison on 2022/07/11
**/
public class DesignerStartupPageUtil {
/**
* 进入工作目录
*/
public static void enterWorkspace() {
ModuleContext
.getModule(DesignerWorkspaceActivator.class)
.start();
}
/**
* 退出工作目录
*/
public static void exitWorkspace() {
ModuleContext
.getModule(DesignerWorkspaceActivator.class)
.stop();
}
}

47
designer-realize/src/main/java/com/fr/start/warmup/DesignerPreWarmTask.java

@ -0,0 +1,47 @@
package com.fr.start.warmup;
import com.fr.log.FineLoggerFactory;
import com.fr.start.common.DesignerStartupContext;
import com.fr.start.util.DesignerStartupPageUtil;
import java.util.concurrent.CompletableFuture;
/**
* 预热服务
*
* created by Harrison on 2022/07/03
**/
public class DesignerPreWarmTask {
private CompletableFuture<Void> warmupTask = null;
public void start() {
if (DesignerStartupContext.getInstance().canWarmup()) {
warmupTask = CompletableFuture.runAsync(() -> {
try {
DesignerStartupContext.getInstance().setOnWarmup(true);
// 尝试预热,启动关闭
// 这里测试直接启动/关闭,比等待插件启动更快
// ps: 这里还有优化空间
// 方向一:改成单纯的预热,不启动工程
// 方向二:模块启动可以终止
DesignerStartupPageUtil.enterWorkspace();
DesignerStartupPageUtil.exitWorkspace();
} catch (Exception e) {
FineLoggerFactory.getLogger().debug("designer warm up failed", e);
} finally {
DesignerStartupContext.getInstance().setOnWarmup(false);
}
});
}
}
public void join() {
if (warmupTask != null) {
warmupTask.join();
}
}
}
Loading…
Cancel
Save