Browse Source

Merge pull request #817 in DESIGN/design from ~PLOUGH/10-design:feature/10.0 to feature/10.0

* commit 'c8e3f2eebbbf2532db84cd3737820b0f8a291e6e':
  REPORT-14865 更新日志推送=>跳过推送版本&修复单元测试错误
  REPORT-14865 更新日志推送=>调整代码
  REPORT-14865 更新日志推送=>调整代码
  REPORT-14865 更新日志推送=>改用 withComponent 方法
  REPORT-14865 更新日志推送=>修改包名
  REPORT-14865 更新日志推送=>跳转更新
  REPORT-14865 更新日志推送=>调整代码
  REPORT-14865 更新日志推送=>国际化
  REPORT-14865 更新日志推送=>调整代码
  REPORT-14865 更新日志推送(部分)
  REPORT-14865 更新日志推送=>ModernUIPane 传一份到 feature
  REPORT-14865 更新日志推送=>实现弹窗逻辑的核心类
  REPORT-14865 更新日志推送=>持久化,重构
  REPORT-14865 更新日志推送=>“自动推送更新”开关
research/10.0
plough 6 years ago
parent
commit
e245126bbe
  1. 47
      designer-base/src/main/java/com/fr/design/DesignerEnvManager.java
  2. 40
      designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java
  3. 28
      designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java
  4. 2
      designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java
  5. 53
      designer-base/src/main/java/com/fr/design/ui/Assistant.java
  6. 83
      designer-base/src/main/java/com/fr/design/ui/EmbProtocolHandler.java
  7. 22
      designer-base/src/main/java/com/fr/design/ui/ModernRequestClient.java
  8. 15
      designer-base/src/main/java/com/fr/design/ui/ModernUIConstants.java
  9. 180
      designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java
  10. 6
      designer-base/src/main/java/com/fr/design/update/actions/FileDownloader.java
  11. 5
      designer-base/src/main/java/com/fr/design/update/actions/SoftwareUpdateAction.java
  12. 2
      designer-base/src/main/java/com/fr/design/update/domain/DownloadItem.java
  13. 2
      designer-base/src/main/java/com/fr/design/update/domain/UpdateConstants.java
  14. 2
      designer-base/src/main/java/com/fr/design/update/domain/UpdateInfoCachePropertyManager.java
  15. 2
      designer-base/src/main/java/com/fr/design/update/factory/DirectoryOperationFactory.java
  16. 61
      designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java
  17. 152
      designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateDialog.java
  18. 174
      designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateManager.java
  19. 91
      designer-base/src/main/java/com/fr/design/update/push/DesignerUpdateInfo.java
  20. 2
      designer-base/src/main/java/com/fr/design/update/ui/dialog/EncodingDetect.java
  21. 9
      designer-base/src/main/java/com/fr/design/update/ui/dialog/RestoreDialog.java
  22. 5
      designer-base/src/main/java/com/fr/design/update/ui/dialog/RestoreResultDialog.java
  23. 49
      designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java
  24. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/ColorfulCellRender.java
  25. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/LoadingLabel.java
  26. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateActionLabel.java
  27. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTable.java
  28. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableCellRender.java
  29. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableModel.java
  30. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTextAreaCellRender.java
  31. 12
      designer-base/src/main/resources/com/fr/design/ui/InitNameSpace.js
  32. 8
      designer-base/src/main/resources/com/fr/design/ui/InsertScript.js
  33. 9
      designer-base/src/main/resources/com/fr/design/ui/InsertStyle.js
  34. 220
      designer-base/src/main/resources/com/fr/design/ui/help/demo.js
  35. 12
      designer-base/src/main/resources/com/fr/design/ui/tpl.html
  36. 22
      designer-base/src/main/resources/com/fr/design/ui/update/push/pushUpdate.css
  37. 95
      designer-base/src/main/resources/com/fr/design/ui/update/push/pushUpdate.js
  38. 30
      designer-base/src/test/java/com/fr/design/ui/FineUIDemo.java
  39. 80
      designer-base/src/test/java/com/fr/design/ui/ModernUIPaneTest.java
  40. 32
      designer-base/src/test/java/com/fr/design/ui/StartComponent.java
  41. 72
      designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateConfigManagerTest.java
  42. 23
      designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateDialogTest.java
  43. 76
      designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateManagerTest.java
  44. 97
      designer-base/src/test/java/com/fr/design/update/push/DesignerUpdateInfoTest.java
  45. 20
      designer-base/src/test/resources/com/fr/design/ui/demo.html
  46. 11
      designer-base/src/test/resources/com/fr/design/ui/fineui.html
  47. 57
      designer-base/src/test/resources/com/fr/design/ui/script/start.js

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

@ -14,6 +14,7 @@ import com.fr.design.env.DesignerWorkspaceType;
import com.fr.design.env.LocalDesignerWorkspaceInfo;
import com.fr.design.env.RemoteDesignerWorkspaceInfo;
import com.fr.design.file.HistoryTemplateListPane;
import com.fr.design.update.push.DesignerPushUpdateConfigManager;
import com.fr.design.style.color.ColorSelectConfigManager;
import com.fr.design.utils.DesignUtils;
import com.fr.file.FILEFactory;
@ -146,6 +147,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
*/
private AlphaFineConfigManager alphaFineConfigManager = new AlphaFineConfigManager();
private DesignerPushUpdateConfigManager designerPushUpdateConfigManager = DesignerPushUpdateConfigManager.getInstance();
public static final String CAS_CERTIFICATE_PATH = "certificatePath";
@ -164,6 +166,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private static List<SwingWorker> mapWorkerList = new ArrayList<SwingWorker>();
private boolean imageCompress = false;//图片压缩
// 开启内嵌web页面的调试窗口
private boolean openDebug = false;
/**
* DesignerEnvManager.
@ -689,6 +693,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.joinProductImprove = joinProductImprove;
}
public boolean isAutoPushUpdateEnabled() {
return designerPushUpdateConfigManager.isAutoPushUpdateEnabled();
}
public void setAutoPushUpdateEnabled(boolean autoPushUpdateEnabled) {
designerPushUpdateConfigManager.setAutoPushUpdateEnabled(autoPushUpdateEnabled);
}
/**
* 是否磁盘空间参数
*
@ -1383,6 +1395,13 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
reader.readXMLObject(this.configManager);
}
private void readOpenDebug(XMLableReader reader) {
String tmpVal;
if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) {
this.openDebug = Boolean.parseBoolean(tmpVal);
}
}
public String getUUID() {
return StringUtils.isEmpty(uuid) ? UUID.randomUUID().toString() : uuid;
}
@ -1411,6 +1430,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.imageCompress = imageCompress;
}
public boolean isOpenDebug() {
return openDebug;
}
public void setOpenDebug(boolean openDebug) {
this.openDebug = openDebug;
}
/**
* Read XML.<br>
* The method will be invoked when read data from XML file.<br>
@ -1464,6 +1491,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
readAlphaFineAttr(reader);
} else if (name.equals("RecentColors")) {
readRecentColor(reader);
} else if ("OpenDebug".equals(name)) {
readOpenDebug(reader);
} else if (name.equals(DesignerPushUpdateConfigManager.XML_TAG)) {
readDesignerPushUpdateAttr(reader);
} else {
readLayout(reader, name);
}
@ -1646,6 +1677,10 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
checkRecentOpenedFileNum();
}
private void readDesignerPushUpdateAttr(XMLableReader reader) {
reader.readXMLObject(designerPushUpdateConfigManager);
}
/**
* Write XML.<br>
* The method will be invoked when save data to XML file.<br>
@ -1668,6 +1703,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
writeHttpsParas(writer);
writeAlphaFineAttr(writer);
writeRecentColor(writer);
writeOpenDebug(writer);
writeDesignerPushUpdateAttr(writer);
writer.end();
}
@ -1683,6 +1720,13 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
}
}
private void writeOpenDebug(XMLPrintWriter writer) {
if (this.openDebug) {
writer.startTAG("OpenDebug");
writer.textNode(String.valueOf(openDebug));
writer.end();
}
}
//写入uuid
private void writeUUID(XMLPrintWriter writer) {
@ -1899,4 +1943,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
.end();
}
private void writeDesignerPushUpdateAttr(XMLPrintWriter writer) {
this.designerPushUpdateConfigManager.writeXML(writer);
}
}

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

@ -18,12 +18,13 @@ import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ispinner.UISpinner;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.update.push.DesignerPushUpdateManager;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.design.utils.gui.UIComponentUtils;
import com.fr.design.widget.FRWidgetFactory;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRFont;
@ -117,7 +118,6 @@ public class PreferencePane extends BasicPane {
private KeyStroke shortCutKeyStore = null;
private UIColorButton gridLineColorTBButton;
private UIColorButton paginationLineColorTBButton;
private UICheckBox supportCellEditorDefCheckBox;
@ -131,7 +131,9 @@ public class PreferencePane extends BasicPane {
private UITextField jdkHomeTextField;
private UICheckBox oracleSpace;
private UISpinner cachingTemplateSpinner;
private UICheckBox joinProductImprove;
private UICheckBox openDebugComboBox;
private UICheckBox joinProductImproveCheckBox;
private UICheckBox autoPushUpdateCheckBox;
public PreferencePane() {
this.initComponents();
@ -149,7 +151,6 @@ public class PreferencePane extends BasicPane {
jtabPane.addTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Advanced"), advancePane);
contentPane.add(jtabPane, BorderLayout.NORTH);
createFunctionPane(generalPane);
createEditPane(generalPane);
createGuiOfGridPane(generalPane);
@ -171,9 +172,19 @@ public class PreferencePane extends BasicPane {
oracleSpace = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Show_All_Oracle_Tables"));
oraclePane.add(oracleSpace);
JPanel improvePane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Product_Improve"));
joinProductImprove = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Join_Product_Improve"));
improvePane.add(joinProductImprove);
JPanel debuggerPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_Develop_Tools"));
openDebugComboBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Open_Debug_Window"));
debuggerPane.add(openDebugComboBox, BorderLayout.CENTER);
advancePane.add(debuggerPane);
JPanel improvePane = FRGUIPaneFactory.createVerticalTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Product_Improve"));
joinProductImproveCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Join_Product_Improve"));
improvePane.add(joinProductImproveCheckBox);
if (DesignerPushUpdateManager.getInstance().isAutoPushUpdateSupported()) {
autoPushUpdateCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Automatic_Push_Update"));
improvePane.add(autoPushUpdateCheckBox);
}
JPanel spaceUpPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
spaceUpPane.add(oraclePane, BorderLayout.NORTH);
@ -550,9 +561,15 @@ public class PreferencePane extends BasicPane {
this.portEditor.setValue(new Integer(designerEnvManager.getEmbedServerPort()));
openDebugComboBox.setSelected(designerEnvManager.isOpenDebug());
this.oracleSpace.setSelected(designerEnvManager.isOracleSystemSpace());
this.cachingTemplateSpinner.setValue(designerEnvManager.getCachingTemplateLimit());
this.joinProductImprove.setSelected(designerEnvManager.isJoinProductImprove());
this.joinProductImproveCheckBox.setSelected(designerEnvManager.isJoinProductImprove());
if (this.autoPushUpdateCheckBox != null) {
this.autoPushUpdateCheckBox.setSelected(designerEnvManager.isAutoPushUpdateEnabled());
}
}
private int chooseCase(int sign) {
@ -609,9 +626,14 @@ public class PreferencePane extends BasicPane {
designerEnvManager.setJettyServerPort(portEditor.getValue().intValue());
designerEnvManager.setOpenDebug(openDebugComboBox.isSelected());
designerEnvManager.setOracleSystemSpace(this.oracleSpace.isSelected());
designerEnvManager.setCachingTemplateLimit((int) this.cachingTemplateSpinner.getValue());
designerEnvManager.setJoinProductImprove(this.joinProductImprove.isSelected());
designerEnvManager.setJoinProductImprove(this.joinProductImproveCheckBox.isSelected());
if (this.autoPushUpdateCheckBox != null) {
designerEnvManager.setAutoPushUpdateEnabled(this.autoPushUpdateCheckBox.isSelected());
}
designerEnvManager.setUndoLimit(maxUndoLimit.getSelectedIndex() * SELECTED_INDEX_5);
if (maxUndoLimit.getSelectedIndex() == SELECTED_INDEX_5) {

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

@ -3,8 +3,16 @@ package com.fr.design.layout;
import com.fr.design.border.UITitledBorder;
import com.fr.design.gui.ilable.UILabel;
import javax.swing.*;
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.LayoutManager;
public class FRGUIPaneFactory {
@ -143,6 +151,22 @@ public class FRGUIPaneFactory {
return jp;
}
/**
* 创建一个带标题边框面板垂直居左布局
*
* @param string 边框标题
* @return JPanel对象
*/
public static JPanel createVerticalTitledBorderPane(String string) {
JPanel jp = new JPanel();
UITitledBorder explainBorder = UITitledBorder.createBorderWithTitle(string);
jp.setBorder(explainBorder);
VerticalFlowLayout layout = new VerticalFlowLayout();
layout.setAlignLeft(true);
jp.setLayout(layout);
return jp;
}
/**
* 创建一个带标题边框面板并且居中显示
*

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

@ -49,7 +49,7 @@ import com.fr.design.menu.MenuDef;
import com.fr.design.menu.SeparatorDef;
import com.fr.design.menu.ShortCut;
import com.fr.design.menu.ToolBarDef;
import com.fr.design.onlineupdate.actions.SoftwareUpdateAction;
import com.fr.design.update.actions.SoftwareUpdateAction;
import com.fr.design.remote.action.RemoteDesignAuthManagerAction;
import com.fr.design.utils.ThemeUtils;
import com.fr.general.ComparatorUtils;

53
designer-base/src/main/java/com/fr/design/ui/Assistant.java

@ -0,0 +1,53 @@
package com.fr.design.ui;
import com.fr.stable.StringUtils;
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.BrowserContext;
import com.teamdev.jxbrowser.chromium.ProtocolService;
import com.teamdev.jxbrowser.chromium.URLResponse;
import java.io.DataInputStream;
import java.io.InputStream;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-03-07
*/
public class Assistant {
public static URLResponse inputStream2Response(InputStream inputStream, String filePath) throws Exception {
URLResponse response = new URLResponse();
DataInputStream stream = new DataInputStream(inputStream);
byte[] data = new byte[stream.available()];
stream.readFully(data);
response.setData(data);
String mimeType = getMimeType(filePath);
response.getHeaders().setHeader("Content-Type", mimeType);
return response;
}
private static String getMimeType(String path) {
if (StringUtils.isBlank(path)) {
return "text/html";
}
if (path.endsWith(".html")) {
return "text/html";
}
if (path.endsWith(".css")) {
return "text/css";
}
if (path.endsWith(".js")) {
return "text/javascript";
}
return "text/html";
}
public static void setEmbProtocolHandler(Browser browser, EmbProtocolHandler handler) {
BrowserContext browserContext = browser.getContext();
ProtocolService protocolService = browserContext.getProtocolService();
// 支持读取jar包中文件的自定义协议————emb:/com/fr/design/images/bbs.png
protocolService.setProtocolHandler("emb", handler);
}
}

83
designer-base/src/main/java/com/fr/design/ui/EmbProtocolHandler.java

@ -0,0 +1,83 @@
package com.fr.design.ui;
import com.fr.general.IOUtils;
import com.fr.stable.StringUtils;
import com.fr.web.struct.AssembleComponent;
import com.fr.web.struct.AtomBuilder;
import com.fr.web.struct.PathGroup;
import com.fr.web.struct.category.ScriptPath;
import com.fr.web.struct.category.StylePath;
import com.teamdev.jxbrowser.chromium.ProtocolHandler;
import com.teamdev.jxbrowser.chromium.URLRequest;
import com.teamdev.jxbrowser.chromium.URLResponse;
import java.io.InputStream;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-03-07
*/
public class EmbProtocolHandler implements ProtocolHandler {
private AssembleComponent component;
public EmbProtocolHandler() {
}
public EmbProtocolHandler(AssembleComponent component) {
this.component = component;
}
@Override
public URLResponse onRequest(URLRequest req) {
try {
String path = req.getURL();
if (path.startsWith("emb:dynamic")) {
URLResponse response = new URLResponse();
response.setData(htmlText().getBytes());
response.getHeaders().setHeader("Content-Type", "text/html");
return response;
} else {
int index = path.indexOf("=");
if (index > 0) {
path = path.substring(index + 1);
} else {
path = path.substring(4);
}
InputStream inputStream = IOUtils.readResource(path);
return Assistant.inputStream2Response(inputStream, path);
}
} catch (Exception ignore) {
}
return null;
}
private String htmlText() {
PathGroup pathGroup = AtomBuilder.create().buildAssembleFilePath(ModernRequestClient.KEY, component);
StylePath[] stylePaths = pathGroup.toStylePathGroup();
StringBuilder styleText = new StringBuilder();
for (StylePath path : stylePaths) {
if (StringUtils.isNotBlank(path.toFilePath())) {
styleText.append("<link rel=\"stylesheet\" href=\"emb:");
styleText.append(path.toFilePath());
styleText.append("\"/>");
}
}
String result = ModernUIConstants.HTML_TPL.replaceAll("##style##", styleText.toString());
ScriptPath[] scriptPaths = pathGroup.toScriptPathGroup();
StringBuilder scriptText = new StringBuilder();
for (ScriptPath path : scriptPaths) {
if (StringUtils.isNotBlank(path.toFilePath())) {
scriptText.append("<script src=\"emb:");
scriptText.append(path.toFilePath());
scriptText.append("\"></script>");
}
}
result = result.replaceAll("##script##", scriptText.toString());
return result;
}
}

22
designer-base/src/main/java/com/fr/design/ui/ModernRequestClient.java

@ -0,0 +1,22 @@
package com.fr.design.ui;
import com.fr.web.struct.browser.RequestClient;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-03-07
*/
public enum ModernRequestClient implements RequestClient {
KEY;
@Override
public boolean isIE() {
return false;
}
@Override
public boolean isLowIEVersion() {
return false;
}}

15
designer-base/src/main/java/com/fr/design/ui/ModernUIConstants.java

@ -0,0 +1,15 @@
package com.fr.design.ui;
import com.fr.general.IOUtils;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-03-05
*/
class ModernUIConstants {
static final String SCRIPT_INIT_NAME_SPACE = IOUtils.readResourceAsString("/com/fr/design/ui/InitNameSpace.js");
static final String HTML_TPL = IOUtils.readResourceAsString("/com/fr/design/ui/tpl.html");
}

180
designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java

@ -0,0 +1,180 @@
package com.fr.design.ui;
import com.fr.design.DesignerEnvManager;
import com.fr.design.dialog.BasicPane;
import com.fr.web.struct.AssembleComponent;
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.BrowserPreferences;
import com.teamdev.jxbrowser.chromium.JSValue;
import com.teamdev.jxbrowser.chromium.events.FinishLoadingEvent;
import com.teamdev.jxbrowser.chromium.events.LoadAdapter;
import com.teamdev.jxbrowser.chromium.events.LoadListener;
import com.teamdev.jxbrowser.chromium.events.ScriptContextAdapter;
import com.teamdev.jxbrowser.chromium.events.ScriptContextEvent;
import com.teamdev.jxbrowser.chromium.events.ScriptContextListener;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;
import javax.swing.JSplitPane;
import java.awt.BorderLayout;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-03-04
* 用于加载html5的Swing容器可以在设计选项设置中打开调试窗口示例可查看com.fr.design.ui.ModernUIPaneTest
*/
public class ModernUIPane<T> extends BasicPane {
private Browser browser;
private String namespace = "Pool";
private String variable = "data";
private String expression = "update()";
private ModernUIPane() {
initialize();
}
private void initialize() {
if (browser == null) {
setLayout(new BorderLayout());
BrowserPreferences.setChromiumSwitches("--disable-google-traffic");
if (DesignerEnvManager.getEnvManager().isOpenDebug()) {
JSplitPane splitPane = new JSplitPane();
add(splitPane, BorderLayout.CENTER);
splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
splitPane.setDividerLocation(500);
BrowserPreferences.setChromiumSwitches("--remote-debugging-port=9222");
initializeBrowser();
splitPane.setLeftComponent(new BrowserView(browser));
Browser debugger = new Browser();
debugger.loadURL(browser.getRemoteDebuggingURL());
BrowserView debuggerView = new BrowserView(debugger);
splitPane.setRightComponent(debuggerView);
} else {
initializeBrowser();
add(new BrowserView(browser), BorderLayout.CENTER);
}
}
}
private void initializeBrowser() {
browser = new Browser();
// 初始化的时候,就把命名空间对象初始化好,确保window.a.b.c("a.b.c"为命名空间)对象都是初始化过的
browser.addScriptContextListener(new ScriptContextAdapter() {
@Override
public void onScriptContextCreated(ScriptContextEvent event) {
event.getBrowser().executeJavaScript(String.format(ModernUIConstants.SCRIPT_INIT_NAME_SPACE, namespace));
}
});
}
@Override
protected String title4PopupWindow() {
return "Modern";
}
public void populate(final T t) {
browser.addScriptContextListener(new ScriptContextAdapter() {
@Override
public void onScriptContextCreated(ScriptContextEvent event) {
JSValue ns = event.getBrowser().executeJavaScriptAndReturnValue("window." + namespace);
ns.asObject().setProperty(variable, t);
}
});
}
public T update() {
JSValue jsValue = browser.executeJavaScriptAndReturnValue("window." + namespace + "." + expression);
if (jsValue.isObject()) {
return (T)jsValue.asJavaObject();
}
return null;
}
public static class Builder<T> {
private ModernUIPane<T> pane = new ModernUIPane<>();
public Builder<T> prepare(ScriptContextListener contextListener) {
pane.browser.addScriptContextListener(contextListener);
return this;
}
public Builder<T> prepare(LoadListener loadListener) {
pane.browser.addLoadListener(loadListener);
return this;
}
/**
* 加载jar包中的资源
* @param path 资源路径
*/
public Builder<T> withEMB(final String path) {
Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler());
pane.browser.loadURL("emb:" + path);
return this;
}
/**
* 加载url指向的资源
* @param url 文件的地址
*/
public Builder<T> withURL(final String url) {
Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler());
pane.browser.loadURL(url);
return this;
}
/**
* 加载Atom组件
* @param component Atom组件
*/
public Builder<T> withComponent(AssembleComponent component) {
Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler(component));
pane.browser.loadURL("emb:dynamic");
return this;
}
/**
* 加载html文本内容
* @param html 要加载html文本内容
*/
public Builder<T> withHTML(String html) {
Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler());
pane.browser.loadHTML(html);
return this;
}
/**
* 设置该前端页面做数据交换所使用的对象
* @param namespace 对象名
*/
public Builder<T> namespace(String namespace) {
pane.namespace = namespace;
return this;
}
/**
* java端往js端传数据时使用的变量名字
* @param name 变量的名字
*/
public Builder<T> variable(String name) {
pane.variable = name;
return this;
}
/**
* js端往java端传数据时执行的函数表达式
* @param expression 函数表达式
*/
public Builder<T> expression(String expression) {
pane.expression = expression;
return this;
}
public ModernUIPane<T> build() {
return pane;
}
}
}

6
designer-base/src/main/java/com/fr/design/onlineupdate/actions/FileDownloader.java → designer-base/src/main/java/com/fr/design/update/actions/FileDownloader.java

@ -1,9 +1,9 @@
package com.fr.design.onlineupdate.actions;
package com.fr.design.update.actions;
import com.fr.design.onlineupdate.domain.UpdateConstants;
import com.fr.design.update.domain.UpdateConstants;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.design.onlineupdate.domain.DownloadItem;
import com.fr.design.update.domain.DownloadItem;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StableUtils;

5
designer-base/src/main/java/com/fr/design/onlineupdate/actions/SoftwareUpdateAction.java → designer-base/src/main/java/com/fr/design/update/actions/SoftwareUpdateAction.java

@ -1,10 +1,9 @@
package com.fr.design.onlineupdate.actions;
package com.fr.design.update.actions;
import com.fr.base.BaseUtils;
import com.fr.design.actions.UpdateAction;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.onlineupdate.ui.dialog.UpdateMainDialog;
import com.fr.locale.InterProviderFactory;
import com.fr.design.update.ui.dialog.UpdateMainDialog;
import java.awt.event.ActionEvent;

2
designer-base/src/main/java/com/fr/design/onlineupdate/domain/DownloadItem.java → designer-base/src/main/java/com/fr/design/update/domain/DownloadItem.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.domain;
package com.fr.design.update.domain;
import com.fr.general.ComparatorUtils;
import com.fr.json.JSONObject;

2
designer-base/src/main/java/com/fr/design/onlineupdate/domain/UpdateConstants.java → designer-base/src/main/java/com/fr/design/update/domain/UpdateConstants.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.domain;
package com.fr.design.update.domain;
/**
* Created by XINZAI on 2018/8/21.

2
designer-base/src/main/java/com/fr/design/onlineupdate/domain/UpdateInfoCachePropertyManager.java → designer-base/src/main/java/com/fr/design/update/domain/UpdateInfoCachePropertyManager.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.domain;
package com.fr.design.update.domain;
import com.fr.log.FineLoggerFactory;

2
designer-base/src/main/java/com/fr/design/onlineupdate/factory/DirectoryOperationFactory.java → designer-base/src/main/java/com/fr/design/update/factory/DirectoryOperationFactory.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.factory;
package com.fr.design.update.factory;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;

61
designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java

@ -0,0 +1,61 @@
package com.fr.design.update.push;
import com.fr.stable.StringUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLWriter;
import com.fr.stable.xml.XMLableReader;
/**
* 持久化与设计器自动推送更新相关的配置
* Created by plough on 2019/4/8.
*/
public class DesignerPushUpdateConfigManager implements XMLReadable, XMLWriter {
public static final String XML_TAG = "DesignerPushUpdateConfigManager";
private static DesignerPushUpdateConfigManager singleton;
private boolean autoPushUpdateEnabled = true; // 是否开启自动推送更新
private String lastIgnoredVersion = StringUtils.EMPTY; // 最近一次跳过的更新版本
private DesignerPushUpdateConfigManager() {
}
public static DesignerPushUpdateConfigManager getInstance() {
if (singleton == null) {
singleton = new DesignerPushUpdateConfigManager();
}
return singleton;
}
@Override
public void readXML(XMLableReader reader) {
if (reader.isAttr()) {
this.setAutoPushUpdateEnabled(reader.getAttrAsBoolean("autoPushUpdateEnabled", true));
this.setLastIgnoredVersion(reader.getAttrAsString("lastIgnoredVersion", StringUtils.EMPTY));
}
}
@Override
public void writeXML(XMLPrintWriter writer) {
writer.startTAG(XML_TAG);
writer.attr("autoPushUpdateEnabled", autoPushUpdateEnabled);
writer.attr("lastIgnoredVersion", lastIgnoredVersion);
writer.end();
}
public boolean isAutoPushUpdateEnabled() {
return autoPushUpdateEnabled;
}
public void setAutoPushUpdateEnabled(boolean autoPushUpdateEnabled) {
this.autoPushUpdateEnabled = autoPushUpdateEnabled;
}
public String getLastIgnoredVersion() {
return lastIgnoredVersion;
}
public void setLastIgnoredVersion(String lastIgnoredVersion) {
this.lastIgnoredVersion = lastIgnoredVersion;
}
}

152
designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateDialog.java

@ -0,0 +1,152 @@
package com.fr.design.update.push;
import com.fr.design.dialog.UIDialog;
import com.fr.design.ui.ModernUIPane;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.web.struct.AssembleComponent;
import com.fr.web.struct.Atom;
import com.fr.web.struct.browser.RequestClient;
import com.fr.web.struct.category.ScriptPath;
import com.fr.web.struct.category.StylePath;
import com.fr.web.struct.impl.FineUI;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
/**
* Created by plough on 2019/4/10.
*/
class DesignerPushUpdateDialog extends UIDialog {
public static final Dimension DEFAULT = new Dimension(640, 320);
private ModernUIPane<Model> jsPane;
private DesignerPushUpdateDialog(Frame parent) {
super(parent);
setModal(true);
initComponents();
}
static void createAndShow(Frame parent, DesignerUpdateInfo updateInfo) {
DesignerPushUpdateDialog dialog = new DesignerPushUpdateDialog(parent);
dialog.populate(updateInfo);
dialog.showDialog();
}
private void initComponents() {
JPanel contentPane = (JPanel) getContentPane();
contentPane.setLayout(new BorderLayout());
jsPane = new ModernUIPane.Builder<Model>()
.withComponent(new AssembleComponent() {
@Override
public ScriptPath script(RequestClient req) {
return ScriptPath.build("/com/fr/design/ui/update/push/pushUpdate.js");
}
@Override
public StylePath style(RequestClient req) {
return StylePath.build("/com/fr/design/ui/update/push/pushUpdate.css");
}
@Override
public Atom[] refer() {
return new Atom[]{FineUI.KEY};
}
}).namespace("Pool").build();
contentPane.add(jsPane);
}
private void populate(DesignerUpdateInfo updateInfo) {
Model model = createModel(updateInfo);
jsPane.populate(model);
}
private Model createModel(DesignerUpdateInfo updateInfo) {
Model model = new Model();
model.setVersion(updateInfo.getPushVersion());
model.setContent(updateInfo.getPushContent());
model.setMoreInfoUrl(updateInfo.getMoreInfoUrl());
model.setBackgroundUrl(updateInfo.getBackgroundUrl());
return model;
}
@Override
public void checkValid() throws Exception {
// do nothing
}
/**
* 显示窗口
*/
private void showDialog() {
setSize(DEFAULT);
setUndecorated(true);
GUICoreUtils.centerWindow(this);
setVisible(true);
}
public class Model {
private String version;
private String content;
private String moreInfoUrl;
private String backgroundUrl;
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getMoreInfoUrl() {
return moreInfoUrl;
}
public void setMoreInfoUrl(String moreInfoUrl) {
this.moreInfoUrl = moreInfoUrl;
}
public String getBackgroundUrl() {
return backgroundUrl;
}
public void setBackgroundUrl(String backgroundUrl) {
this.backgroundUrl = backgroundUrl;
}
public void updateNow() {
DesignerPushUpdateManager.getInstance().doUpdate();
exit();
}
public void remindNextTime() {
exit();
}
public void skipThisVersion() {
DesignerPushUpdateManager.getInstance().skipCurrentPushVersion();
exit();
}
public String i18nText(String key) {
return com.fr.design.i18n.Toolkit.i18nText(key);
}
private void exit() {
DesignerPushUpdateDialog.this.dialogExit();
}
}
}

174
designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateManager.java

@ -0,0 +1,174 @@
package com.fr.design.update.push;
import com.fr.design.event.DesignerOpenedListener;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.design.update.ui.dialog.UpdateMainDialog;
import com.fr.general.CloudCenter;
import com.fr.general.GeneralContext;
import com.fr.general.GeneralUtils;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import java.io.IOException;
/**
* Created by plough on 2019/4/8.
*/
public class DesignerPushUpdateManager {
private static final String SPLIT_CHAR = "-";
private static DesignerPushUpdateManager singleton;
private DesignerUpdateInfo updateInfo;
private DesignerPushUpdateConfigManager config;
static {
DesignerContext.getDesignerFrame().addDesignerOpenedListener(new DesignerOpenedListener() {
@Override
public void designerOpened() {
getInstance().checkAndPop();
}
});
}
private DesignerPushUpdateManager() {
config = DesignerPushUpdateConfigManager.getInstance();
}
public static DesignerPushUpdateManager getInstance() {
if (singleton == null) {
singleton = new DesignerPushUpdateManager();
}
return singleton;
}
private void initUpdateInfo(String currentVersion, String latestVersion) {
String lastIgnoredVersion = config.getLastIgnoredVersion();
String updatePushInfo = CloudCenter.getInstance().acquireUrlByKind("update.push");
JSONObject pushData = new JSONObject(updatePushInfo);
updateInfo = new DesignerUpdateInfo(currentVersion, latestVersion, lastIgnoredVersion, pushData);
}
private String getFullLatestVersion() {
try {
String res = HttpToolbox.get(CloudCenter.getInstance().acquireUrlByKind("jar10.update"));
return new JSONObject(res).optString("buildNO");
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return StringUtils.EMPTY;
}
private String getVersionByFullNO(String fullNO) {
if (fullNO.contains(SPLIT_CHAR)) {
fullNO = fullNO.substring(fullNO.lastIndexOf(SPLIT_CHAR) + 1);
}
return fullNO;
}
private String getPrefixByFullNO(String fullNO) {
if (fullNO.contains(SPLIT_CHAR)) {
return fullNO.substring(0, fullNO.lastIndexOf(SPLIT_CHAR));
}
return StringUtils.EMPTY;
}
/**
* "自动更新推送"选项是否生效
*/
public boolean isAutoPushUpdateSupported() {
boolean isLocalEnv = WorkContext.getCurrent().isLocal();
boolean isChineseEnv = GeneralContext.isChineseEnv();
return isAutoPushUpdateSupported(isLocalEnv, isChineseEnv);
}
private boolean isAutoPushUpdateSupported(boolean isLocalEnv, boolean isChineseEnv) {
// 远程设计和非中文环境,都不生效
return isLocalEnv && isChineseEnv;
}
/**
* 检查更新如果有合适的更新版本则弹窗
*/
public void checkAndPop() {
new Thread() {
@Override
public void run() {
if (!shouldPopUp()) {
FineLoggerFactory.getLogger().debug("skip push update");
return;
}
final DesignerFrame designerFrame = DesignerContext.getDesignerFrame();
DesignerPushUpdateDialog.createAndShow(designerFrame, updateInfo);
}
}.start();
}
private boolean shouldPopUp() {
if (updateInfo == null) {
String fullCurrentVersion = GeneralUtils.readFullBuildNO();
// todo: 开发测试用
if (!fullCurrentVersion.contains(SPLIT_CHAR)) {
fullCurrentVersion = "stable-2019.01.03.17.01.05.257";
}
String fullLatestVersion = getFullLatestVersion();
boolean isValidJarVersion = isValidJarVersion(fullCurrentVersion, fullLatestVersion);
if (!isValidJarVersion) {
FineLoggerFactory.getLogger().info("Jar version is not valid for push update.");
return false;
} else {
String currentVersion = getVersionByFullNO(fullCurrentVersion);
String latestVersion = getVersionByFullNO(fullLatestVersion);
initUpdateInfo(currentVersion, latestVersion);
}
}
return isAutoPushUpdateSupported() && updateInfo.hasNewPushVersion();
}
private boolean isValidJarVersion(String fullCurrentVersion, String fullLatestVersion) {
// todo: 目前设定的逻辑是 feature/release/stable 都弹,且不区分版本号。后期肯定要变的,注释代码先留着
// // 无效的情况:
// // 1. 版本号格式有误
// // 2. 当前用的是 release 或 feature 的 jar 包
// // 3. 代码启动的
// String prefix = getPrefixByFullNO(fullLatestVersion);
// return StringUtils.isNotEmpty(prefix) && fullCurrentVersion.startsWith(prefix);
// 无效的情况:
// 1. 版本号格式有误(正常情况下都有前缀,只有异常的时候才可能出现)
// 2. 代码启动的(fullCurrentVersion 为"不是安装版本")
String prefix = getPrefixByFullNO(fullLatestVersion);
return StringUtils.isNotEmpty(prefix) && fullCurrentVersion.contains(SPLIT_CHAR);
}
/**
* 跳转到更新升级窗口并自动开始更新
*/
void doUpdate() {
new Thread() {
@Override
public void run() {
UpdateMainDialog dialog = new UpdateMainDialog(DesignerContext.getDesignerFrame());
dialog.setAutoUpdateAfterInit();
dialog.showDialog();
}
}.start();
}
/**
* 跳过当前的推送版本
*/
void skipCurrentPushVersion() {
if (updateInfo == null) {
return;
}
config.setLastIgnoredVersion(updateInfo.getPushVersion());
}
}

91
designer-base/src/main/java/com/fr/design/update/push/DesignerUpdateInfo.java

@ -0,0 +1,91 @@
package com.fr.design.update.push;
import com.fr.general.ComparatorUtils;
import com.fr.json.JSONObject;
import com.fr.stable.StringUtils;
import java.security.InvalidParameterException;
/**
* Created by plough on 2019/4/8.
*/
class DesignerUpdateInfo {
private static final String KEY_VERSION = "version";
private static final String KEY_CONTENT = "content";
private static final String KEY_BACKGROUND_URL = "background";
private static final String KEY_MORE_INFO_URL = "more";
private final String currentVersion; // 当前版本
private final String latestVersion; // 最新版本
private final String lastIgnoredVersion; // 最近一次跳过的版本
private final String pushVersion; // 推送版本
private final String pushContent; // 推送更新内容
private final String backgroundUrl; // 推送背景图片 url
private final String moreInfoUrl; // 更多新特性
DesignerUpdateInfo(String currentVersion, String latestVersion, String lastIgnoredVersion, JSONObject pushData) {
this.currentVersion = currentVersion;
this.latestVersion = latestVersion;
this.lastIgnoredVersion = lastIgnoredVersion;
this.pushVersion = pushData.optString(KEY_VERSION);
this.pushContent = pushData.optString(KEY_CONTENT);
this.backgroundUrl = pushData.optString(KEY_BACKGROUND_URL);
this.moreInfoUrl = pushData.optString(KEY_MORE_INFO_URL);
// 简单做下参数校验
if (hasEmptyField()) {
throw new InvalidParameterException();
}
}
private boolean hasEmptyField() {
// lastIgnoredVersion 可以为空
return StringUtils.isEmpty(currentVersion)
|| StringUtils.isEmpty(latestVersion)
|| StringUtils.isEmpty(pushVersion)
|| StringUtils.isEmpty(pushContent)
|| StringUtils.isEmpty(backgroundUrl)
|| StringUtils.isEmpty(moreInfoUrl);
}
String getCurrentVersion() {
return currentVersion;
}
String getLatestVersion() {
return latestVersion;
}
String getLastIgnoredVersion() {
return lastIgnoredVersion;
}
String getPushVersion() {
return pushVersion;
}
String getPushContent() {
return pushContent;
}
String getBackgroundUrl() {
return backgroundUrl;
}
String getMoreInfoUrl() {
return moreInfoUrl;
}
boolean hasNewPushVersion() {
boolean result = ComparatorUtils.compare(pushVersion, currentVersion) > 0
&& ComparatorUtils.compare(pushVersion, latestVersion) <= 0;
if (StringUtils.isNotEmpty(lastIgnoredVersion)) {
result = result && ComparatorUtils.compare(pushVersion, lastIgnoredVersion) > 0;
}
return result;
}
}

2
designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/EncodingDetect.java → designer-base/src/main/java/com/fr/design/update/ui/dialog/EncodingDetect.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.ui.dialog;
package com.fr.design.update.ui.dialog;
import java.io.File;

9
designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/RestoreDialog.java → designer-base/src/main/java/com/fr/design/update/ui/dialog/RestoreDialog.java

@ -1,13 +1,12 @@
package com.fr.design.onlineupdate.ui.dialog;
package com.fr.design.update.ui.dialog;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.onlineupdate.domain.UpdateConstants;
import com.fr.design.onlineupdate.factory.DirectoryOperationFactory;
import com.fr.design.onlineupdate.ui.widget.ColorfulCellRender;
import com.fr.design.update.domain.UpdateConstants;
import com.fr.design.update.factory.DirectoryOperationFactory;
import com.fr.design.update.ui.widget.ColorfulCellRender;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StableUtils;

5
designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/RestoreResultDialog.java → designer-base/src/main/java/com/fr/design/update/ui/dialog/RestoreResultDialog.java

@ -1,14 +1,13 @@
package com.fr.design.onlineupdate.ui.dialog;
package com.fr.design.update.ui.dialog;
import com.fr.base.FRContext;
import com.fr.design.RestartHelper;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.onlineupdate.domain.UpdateConstants;
import com.fr.design.update.domain.UpdateConstants;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.ComparatorUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;

49
designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/UpdateMainDialog.java → designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.ui.dialog;
package com.fr.design.update.ui.dialog;
import com.fr.base.FRContext;
import com.fr.design.RestartHelper;
@ -11,17 +11,17 @@ import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.onlineupdate.actions.FileDownloader;
import com.fr.design.onlineupdate.domain.DownloadItem;
import com.fr.design.onlineupdate.domain.UpdateConstants;
import com.fr.design.onlineupdate.domain.UpdateInfoCachePropertyManager;
import com.fr.design.onlineupdate.factory.DirectoryOperationFactory;
import com.fr.design.onlineupdate.ui.widget.LoadingLabel;
import com.fr.design.onlineupdate.ui.widget.UpdateActionLabel;
import com.fr.design.onlineupdate.ui.widget.UpdateInfoTable;
import com.fr.design.onlineupdate.ui.widget.UpdateInfoTableCellRender;
import com.fr.design.onlineupdate.ui.widget.UpdateInfoTableModel;
import com.fr.design.onlineupdate.ui.widget.UpdateInfoTextAreaCellRender;
import com.fr.design.update.actions.FileDownloader;
import com.fr.design.update.domain.DownloadItem;
import com.fr.design.update.domain.UpdateConstants;
import com.fr.design.update.domain.UpdateInfoCachePropertyManager;
import com.fr.design.update.factory.DirectoryOperationFactory;
import com.fr.design.update.ui.widget.LoadingLabel;
import com.fr.design.update.ui.widget.UpdateActionLabel;
import com.fr.design.update.ui.widget.UpdateInfoTable;
import com.fr.design.update.ui.widget.UpdateInfoTableCellRender;
import com.fr.design.update.ui.widget.UpdateInfoTableModel;
import com.fr.design.update.ui.widget.UpdateInfoTextAreaCellRender;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.ComparatorUtils;
import com.fr.general.DateUtils;
@ -59,7 +59,14 @@ import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -137,6 +144,8 @@ public class UpdateMainDialog extends UIDialog {
private String lastUpdateCacheTime;
private String lastUpdateCacheState = UPDATE_CACHE_STATE_FAIL;
private boolean autoUpdateAfterInit = false; // 是否在加载结束后,自动开始更新
public UpdateMainDialog(Dialog parent) {
super(parent);
initComponents();
@ -148,6 +157,13 @@ public class UpdateMainDialog extends UIDialog {
initComponents();
}
/**
* 等待面板初始化结束后点击"更新"按钮
*/
public void setAutoUpdateAfterInit() {
autoUpdateAfterInit = true;
}
private void initUpdateActionPane() {
double[] rowUpdateSubContentPaneSize = {UPDATE_CONTENT_PANE_ROW_SIZE, TableLayout.PREFERRED, UPDATE_CONTENT_PANE_ROW_SIZE};
double[] rowUpdateContentPaneSize = {TableLayout.PREFERRED};
@ -428,6 +444,7 @@ public class UpdateMainDialog extends UIDialog {
getUpdateInfoSuccess = true;
//step4:update cache file,start from cacheRecordTime,end latest server jartime
updateCachedInfoFile(jsonArray);
afterInit();
} catch (Exception e) {
getUpdateInfoSuccess = true;
FineLoggerFactory.getLogger().error(e.getMessage());
@ -436,6 +453,12 @@ public class UpdateMainDialog extends UIDialog {
};
}
private void afterInit() {
if (autoUpdateAfterInit) {
updateButton.doClick();
}
}
//从文件中读取缓存的更新信息
private void getCachedUpdateInfo(String keyword) throws Exception {
String cacheInfoPath = getUpdateCacheInfo();

2
designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/ColorfulCellRender.java → designer-base/src/main/java/com/fr/design/update/ui/widget/ColorfulCellRender.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.ui.widget;
package com.fr.design.update.ui.widget;
import javax.swing.JList;
import javax.swing.JPanel;

2
designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/LoadingLabel.java → designer-base/src/main/java/com/fr/design/update/ui/widget/LoadingLabel.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.ui.widget;
package com.fr.design.update.ui.widget;
import com.fr.design.gui.ilable.UILabel;
import com.fr.general.IOUtils;

2
designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateActionLabel.java → designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateActionLabel.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.ui.widget;
package com.fr.design.update.ui.widget;
import com.fr.design.gui.ilable.UILabel;

2
designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTable.java → designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTable.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.ui.widget;
package com.fr.design.update.ui.widget;
import javax.swing.JTable;
import javax.swing.table.TableModel;

2
designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTableCellRender.java → designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableCellRender.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.ui.widget;
package com.fr.design.update.ui.widget;
import com.fr.general.ComparatorUtils;
import com.fr.stable.StringUtils;

2
designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTableModel.java → designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableModel.java

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.ui.widget;
package com.fr.design.update.ui.widget;
import javax.swing.table.AbstractTableModel;
import java.util.List;

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

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.ui.widget;
package com.fr.design.update.ui.widget;
import javax.swing.BorderFactory;
import javax.swing.JTable;

12
designer-base/src/main/resources/com/fr/design/ui/InitNameSpace.js

@ -0,0 +1,12 @@
var arr ="%s".split(".").reverse();
var create = function (obj, names) {
var name = names.pop();
if (!name) {
return;
}
if (!obj[name]) {
obj[name] = {};
}
create(obj[name], names);
};
create(window, arr);

8
designer-base/src/main/resources/com/fr/design/ui/InsertScript.js

@ -0,0 +1,8 @@
var arr = "%s".split(",");
var header = document.getElementsByTagName("head")[0];
arr.forEach(function(el) {
var script = document.createElement("script")
script.type = "text/javascript";
script.src = "emb:" + el;
header.appendChild(script);
});

9
designer-base/src/main/resources/com/fr/design/ui/InsertStyle.js

@ -0,0 +1,9 @@
var arr = "%s".split(",");
var header = document.getElementsByTagName("head")[0];
arr.forEach(function(el) {
var css = document.createElement("link");
css.type = "text/css";
css.rel = "stylesheet";
css.href = "emb:" + el;
header.appendChild(css);
});

220
designer-base/src/main/resources/com/fr/design/ui/help/demo.js

@ -0,0 +1,220 @@
window.addEventListener("load", function (ev) {
window.BI.i18nText = function(key) {return window.Pool.i18n.i18nText(key);}
var combo1 = BI.createWidget({
type: "bi.vertical",
items: [
{
type: "bi.text_value_combo",
text: "选项1",
width: 300,
items: [
{
el: {
type: "bi.single_select_radio_item",
width: 290,
text: "选项1",
value: 1
},
text: "选项1",
value: 1,
lgap: 10
},
{
el: {
type: "bi.single_select_radio_item",
width: 290,
text: "选项2",
value: 2
},
lgap: 10,
text: "选项2",
value: 2
},
{
el: {
type: "bi.single_select_radio_item",
width: 290,
text: "选项3",
value: 3
},
lgap: 10,
text: "选项3",
value: 3
}
]
}
]
});
var date = BI.createWidget({
type: "bi.left",
items: [{
el: {
type: "bi.date_time_combo",
value: {
year: 2018,
month: 9,
day: 28,
hour: 13,
minute: 31,
second: 1
}
}
}]
});
var comboTree = BI.createWidget({
type: "bi.vertical",
items: [
{
type: "bi.tree_value_chooser_combo",
width: 300,
itemsCreator: function(op, callback) {
callback([
{
id: 1,
text: "第1项",
value: "1"
},
{
id: 2,
text: "第2项",
value: "2"
},
{
id: 3,
text: "第3项",
value: "3",
open: true
},
{
id: 11,
pId: 1,
text: "子项1",
value: "11"
},
{
id: 12,
pId: 1,
text: "子项2",
value: "12"
},
{
id: 13,
pId: 1,
text: "子项3",
value: "13"
},
{
id: 31,
pId: 3,
text: "子项1",
value: "31"
},
{
id: 32,
pId: 3,
text: "子项2",
value: "32"
},
{
id: 33,
pId: 3,
text: "子项3",
value: "33"
}
]);
}
}
]
});
var color = BI.createWidget({
type: "bi.left",
items: [{
type: "bi.simple_color_chooser",
width: 24,
height: 24
}, {
el: {
type: "bi.color_chooser",
width: 230,
height: 24
},
lgap: 10
}]
});
var Slider = BI.inherit(BI.Widget, {
props: {
width: 300,
height: 50,
min: 0,
max: 100
},
mounted: function() {
var o = this.options;
this.singleSliderInterval.setMinAndMax({
min: o.min,
max: o.max
});
this.singleSliderInterval.setValue({
min: 10,
max: 80
});
this.singleSliderInterval.populate();
},
render: function() {
var self = this,
o = this.options;
return {
type: "bi.vertical",
element: this,
items: [
{
type: "bi.interval_slider",
digit: 0,
width: o.width,
height: o.height,
ref: function(_ref) {
self.singleSliderInterval = _ref;
}
}
]
};
}
});
BI.shortcut("demo.slider_interval", Slider);
var slider = BI.createWidget({
type: "demo.slider_interval"
});
BI.createWidget({
type:"bi.absolute",
element: "body",
items: [{
el: combo1,
left: 100,
top: 100
}, {
el : date,
left: 100,
top : 150
}, {
el : comboTree,
left : 100,
top : 200
}, {
el : color,
left : 100,
top : 250
}, {
el : slider,
left : 400,
top : 100
}]
});
});

12
designer-base/src/main/resources/com/fr/design/ui/tpl.html

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
##style##
##script##
</head>
<body>
</body>
</html>

22
designer-base/src/main/resources/com/fr/design/ui/update/push/pushUpdate.css

@ -0,0 +1,22 @@
body {
padding-left: 30px;
padding-top: 30px;
color: white;
}
.title {
font-size: 30px;
}
.desc {
margin-top: 35px;
}
.moreInfo {
margin-top: 15px;
}
.buttonGroup {
margin-top: 35px;
}
.button-ignore {
background-color: white !important;
border: 1px solid white !important;
}

95
designer-base/src/main/resources/com/fr/design/ui/update/push/pushUpdate.js

@ -0,0 +1,95 @@
function i18nText(key) {
return Pool.data.i18nText(key);
}
window.addEventListener("load", function (ev) {
var title = BI.createWidget({
type: "bi.vertical",
items: [
{
type: "bi.label",
text: i18nText("Fine-Design_Find_New_Version"),
cls: "title",
textAlign: "left"
},
{
type: "bi.label",
text: Pool.data.getVersion(),
textAlign: "left"
}
]
});
var desc = BI.createWidget({
type: "bi.vertical",
cls: "desc",
items: [
{
type: "bi.label",
text: Pool.data.getContent(),
textAlign: "left"
}
]
});
var moreInfo = BI.createWidget({
type: "bi.text_button",
text: i18nText("Fine-Design_Basic_More_Information"),
cls: "moreInfo",
textAlign: "left"
});
var buttonGroup = BI.createWidget({
type: 'bi.left',
cls: "buttonGroup",
items: [
{
type: 'bi.button',
text: i18nText("Fine-Design_Update_Now"),
level: 'common',
height: 30,
handler: function() {
Pool.data.updateNow();
}
},
{
el: {
type: 'bi.button',
text: i18nText("Fine-Design_Remind_Me_Next_Time"),
level: 'ignore',
height: 30,
handler: function() {
Pool.data.remindNextTime();
}
},
lgap: 10
},
{
el: {
type: 'bi.button',
text: i18nText("Fine-Design_Skip_This_Version"),
level: 'ignore',
height: 30,
handler: function() {
Pool.data.skipThisVersion();
}
},
lgap: 10
}
]
});
var container = BI.createWidget({
type:"bi.vertical",
element: "body",
cls: "container",
items: [
title,
desc,
moreInfo,
buttonGroup
]
});
container.element.css("background", "url(" + Pool.data.getBackgroundUrl() + ")");
});

30
designer-base/src/test/java/com/fr/design/ui/FineUIDemo.java

@ -0,0 +1,30 @@
package com.fr.design.ui;
import com.fr.design.DesignerEnvManager;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-03-07
*/
public class FineUIDemo {
public static void main(String... args) {
final JFrame frame = new JFrame();
frame.setSize(1200, 800);
JPanel contentPane = (JPanel) frame.getContentPane();
// 是否需要开启调试窗口
DesignerEnvManager.getEnvManager().setOpenDebug(true);
final ModernUIPane<ModernUIPaneTest.Model> pane = new ModernUIPane.Builder<ModernUIPaneTest.Model>()
.withComponent(StartComponent.KEY).build();
contentPane.add(pane, BorderLayout.CENTER);
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}

80
designer-base/src/test/java/com/fr/design/ui/ModernUIPaneTest.java

@ -0,0 +1,80 @@
package com.fr.design.ui;
import com.fr.design.DesignerEnvManager;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-03-05
*/
public class ModernUIPaneTest {
public static void main(String... args) {
final JFrame frame = new JFrame();
frame.setSize(1200, 800);
JPanel contentPane = (JPanel) frame.getContentPane();
// 是否需要开启调试窗口
DesignerEnvManager.getEnvManager().setOpenDebug(true);
final ModernUIPane<Model> pane = new ModernUIPane.Builder<Model>()
.withEMB("/com/fr/design/ui/demo.html").namespace("Pool").build();
contentPane.add(pane, BorderLayout.CENTER);
Model model = new Model();
model.setAge(20);
model.setName("Pick");
pane.populate(model);
JPanel panel = new JPanel(new FlowLayout());
contentPane.add(panel, BorderLayout.SOUTH);
JButton button = new JButton("点击我可以看到Swing的弹框,输出填写的信息");
panel.add(button);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Model returnValue = pane.update();
if (returnValue != null) {
JOptionPane.showMessageDialog(frame, String.format("姓名为:%s,年龄为:%d", returnValue.getName(), returnValue.getAge()));
}
}
});
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static class Model {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void print(String message) {
System.out.println(message);
}
}
}

32
designer-base/src/test/java/com/fr/design/ui/StartComponent.java

@ -0,0 +1,32 @@
package com.fr.design.ui;
import com.fr.web.struct.AssembleComponent;
import com.fr.web.struct.Atom;
import com.fr.web.struct.browser.RequestClient;
import com.fr.web.struct.category.ScriptPath;
import com.fr.web.struct.impl.FineUI;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-03-08
*/
public class StartComponent extends AssembleComponent {
public static final StartComponent KEY = new StartComponent();
private StartComponent() {
}
@Override
public ScriptPath script(RequestClient req) {
return ScriptPath.build("/com/fr/design/ui/script/start.js");
}
@Override
public Atom[] refer() {
return new Atom[] {FineUI.KEY};
}
}

72
designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateConfigManagerTest.java

@ -0,0 +1,72 @@
package com.fr.design.update.push;
import com.fr.stable.StringUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.javax.xml.stream.XMLStreamException;
import org.junit.Test;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
* Created by plough on 2019/4/8.
*/
public class DesignerPushUpdateConfigManagerTest {
@Test
public void testSingleton() {
DesignerPushUpdateConfigManager m1 = DesignerPushUpdateConfigManager.getInstance();
DesignerPushUpdateConfigManager m2 = DesignerPushUpdateConfigManager.getInstance();
assertSame(m1, m2);
}
@Test
public void testDefaultValue() throws XMLStreamException {
DesignerPushUpdateConfigManager configManager = DesignerPushUpdateConfigManager.getInstance();
XMLableReader xmlReader = XMLableReader.createXMLableReader(new StringReader("<xml></xml>"));
xmlReader.readXMLObject(configManager);
assertEquals(StringUtils.EMPTY, configManager.getLastIgnoredVersion());
assertTrue(configManager.isAutoPushUpdateEnabled());
}
@Test
public void testReadAndWrite() throws XMLStreamException {
final String initLastIngnoredVersion = "1.1.2";
final boolean initAutoPushEnabled = false;
DesignerPushUpdateConfigManager configManager = DesignerPushUpdateConfigManager.getInstance();
configManager.setLastIgnoredVersion(initLastIngnoredVersion);
configManager.setAutoPushUpdateEnabled(initAutoPushEnabled);
// 写入 xml
StringWriter sw = new StringWriter();
XMLPrintWriter writer = XMLPrintWriter.create(new PrintWriter(sw));
configManager.writeXML(writer);
writer.flush();
writer.close();
String xml_str = sw.getBuffer().toString();
// 临时修改配置
configManager.setAutoPushUpdateEnabled(true);
configManager.setLastIgnoredVersion("0.20.1");
// 从 xml 中读取
StringReader sr = new StringReader(xml_str);
XMLableReader xmlReader = XMLableReader.createXMLableReader(sr);
xmlReader.readXMLObject(configManager);
// 验证:与写入时的配置一致
assertEquals(initLastIngnoredVersion, configManager.getLastIgnoredVersion());
assertEquals(initAutoPushEnabled, configManager.isAutoPushUpdateEnabled());
}
}

23
designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateDialogTest.java

@ -0,0 +1,23 @@
package com.fr.design.update.push;
import com.fr.design.DesignerEnvManager;
import com.fr.json.JSONObject;
/**
* Created by plough on 2019/4/10.
*/
public class DesignerPushUpdateDialogTest {
public static void main(String[] args) {
DesignerEnvManager.getEnvManager().setOpenDebug(true);
JSONObject jo = JSONObject.create();
jo.put("version", "2019.03.06.04.02.43.6");
jo.put("content", "test content");
jo.put("more", "http://baidu.com");
jo.put("background", "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1555043827901&di=fc266992abef5a7e13b4e0cb98975a75&imgtype=0&src=http%3A%2F%2Fi5.3conline.com%2Fimages%2Fpiclib%2F201203%2F20%2Fbatch%2F1%2F130280%2F1332249463721rez0li5fg0_medium.jpg");
DesignerUpdateInfo mockUpdateInfo = new DesignerUpdateInfo("111.22.11", "2211.231.1", "11.23.1", jo);
DesignerPushUpdateDialog.createAndShow(null, mockUpdateInfo);
}
}

76
designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateManagerTest.java

@ -0,0 +1,76 @@
package com.fr.design.update.push;
import com.fr.design.event.DesignerOpenedListener;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.invoke.Reflect;
import com.fr.stable.StringUtils;
import org.easymock.EasyMock;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
/**
* Created by plough on 2019/4/8.
*/
@RunWith(value = PowerMockRunner.class)
@PrepareForTest(DesignerContext.class)
public class DesignerPushUpdateManagerTest {
@BeforeClass
public static void setUp() {
DesignerFrame mockFrame = EasyMock.mock(DesignerFrame.class);
mockFrame.addDesignerOpenedListener(EasyMock.anyObject(DesignerOpenedListener.class));
EasyMock.replay(mockFrame);
PowerMock.mockStatic(DesignerContext.class);
EasyMock.expect(DesignerContext.getDesignerFrame()).andReturn(mockFrame).anyTimes();
PowerMock.replayAll();
}
@Test
public void testSingleton() {
DesignerPushUpdateManager m1 = DesignerPushUpdateManager.getInstance();
DesignerPushUpdateManager m2 = DesignerPushUpdateManager.getInstance();
assertSame(m1, m2);
}
@Test
public void testIsAutoPushUpdateSupported() {
// 中文环境 + 本地设计 -> true
DesignerPushUpdateManager pushUpdateManager = DesignerPushUpdateManager.getInstance();
assertEquals(true, Reflect.on(pushUpdateManager).call("isAutoPushUpdateSupported", true, true).get());
// 非中文环境 || 远程设计 -> false
assertEquals(false, Reflect.on(pushUpdateManager).call("isAutoPushUpdateSupported", false, true).get());
assertEquals(false, Reflect.on(pushUpdateManager).call("isAutoPushUpdateSupported", true, false).get());
assertEquals(false, Reflect.on(pushUpdateManager).call("isAutoPushUpdateSupported", false, false).get());
}
@Test
public void testSkipCurrentPushVersion() {
DesignerPushUpdateManager pushUpdateManager = DesignerPushUpdateManager.getInstance();
// 1. updateInfo 为 null 的情况
pushUpdateManager.skipCurrentPushVersion();
assertEquals(StringUtils.EMPTY, DesignerPushUpdateConfigManager.getInstance().getLastIgnoredVersion());
// 2. updateInfo 有值的情况
final String PUSH_VERSION = "stable-2019.02.03.12.44.22";
DesignerUpdateInfo mockInfo = EasyMock.mock(DesignerUpdateInfo.class);
EasyMock.expect(mockInfo.getPushVersion()).andReturn(PUSH_VERSION).anyTimes();
Reflect.on(pushUpdateManager).set("updateInfo", mockInfo);
EasyMock.replay(mockInfo);
pushUpdateManager.skipCurrentPushVersion();
assertEquals(PUSH_VERSION, DesignerPushUpdateConfigManager.getInstance().getLastIgnoredVersion());
}
}

97
designer-base/src/test/java/com/fr/design/update/push/DesignerUpdateInfoTest.java

@ -0,0 +1,97 @@
package com.fr.design.update.push;
import com.fr.json.JSONObject;
import com.fr.stable.StringUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.security.InvalidParameterException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Created by plough on 2019/4/9.
*/
public class DesignerUpdateInfoTest {
private static final String CURRENT_VERSION = "2018.09.03.xx";
private static final String LATEST_VERSION = "2019.04.03.yy";
private static final String LAST_IGNORED_VERSION = "2019.02.03.yy";
private static final String PUSH_VERSION = "2019.01.03.21.11";
private static final String PUSH_CONTENT = "the update desc content";
private static final String PUSH_BACKGROUND = "http://image.fr.com/123.jpg";
private static final String PUSH_MORE = "http://help.finereport.com/xxx";
private DesignerUpdateInfo updateInfo;
@Before
public void setUp() {
JSONObject pushData = JSONObject.create();
pushData.put("version", PUSH_VERSION);
pushData.put("content", PUSH_CONTENT);
pushData.put("background", PUSH_BACKGROUND);
pushData.put("more", PUSH_MORE);
updateInfo = new DesignerUpdateInfo(CURRENT_VERSION, LATEST_VERSION, LAST_IGNORED_VERSION, pushData);
}
@Test
public void testGetters() {
assertEquals(CURRENT_VERSION, updateInfo.getCurrentVersion());
assertEquals(LATEST_VERSION, updateInfo.getLatestVersion());
assertEquals(LAST_IGNORED_VERSION, updateInfo.getLastIgnoredVersion());
assertEquals(PUSH_VERSION, updateInfo.getPushVersion());
assertEquals(PUSH_CONTENT, updateInfo.getPushContent());
assertEquals(PUSH_BACKGROUND, updateInfo.getBackgroundUrl());
assertEquals(PUSH_MORE, updateInfo.getMoreInfoUrl());
}
@Test
public void testHasNewPushVersion() {
// (1)最近被跳过的维护版本号 X0;
// (2)本地版本号 Y;
// (3)最新的推送版本号 X;
// (4)最新的版本号 Z
// 必须满足:Y < X <= Z && X > X0,才返回 true
// 1 true
assertTrue(hasNewVersion("2019.01.03.xx", "2018.05.03.xx", "2019.04.03.yy", "2018.05.03.xx"));
assertTrue(hasNewVersion("2019.01.03.xx", "2018.05.03.xx", "2019.04.03.yy", null));
assertTrue(hasNewVersion("2019.01.03.xx", "2018.05.03.xx", "2019.04.03.yy", StringUtils.EMPTY));
// 2 false
// 2.1 X <= Y && X > X0
assertFalse(hasNewVersion("2019.01.03.xx", "2019.03.03.xx", "2019.04.03.yy", "2018.05.03.xx"));
assertFalse(hasNewVersion("2019.03.03.xx", "2019.03.03.xx", "2019.04.03.yy", "2018.05.03.xx"));
// 2.2 X > Z && X > X0
assertFalse(hasNewVersion("2020.01.03.xx", "2019.03.03.xx", "2019.04.03.yy", "2018.05.03.xx"));
// 2.3 Y < X <= Z && X <= X0
assertFalse(hasNewVersion("2019.01.03.xx", "2018.05.03.xx", "2019.04.03.yy", "2019.02.03.xx"));
assertFalse(hasNewVersion("2019.01.03.xx", "2018.05.03.xx", "2019.04.03.yy", "2019.01.03.xx"));
}
private boolean hasNewVersion(String X, String Y, String Z, String X0) {
JSONObject pushData = JSONObject.create();
pushData.put("version", X);
pushData.put("content", PUSH_CONTENT);
pushData.put("background", PUSH_BACKGROUND);
pushData.put("more", PUSH_MORE);
DesignerUpdateInfo updateInfo = new DesignerUpdateInfo(Y, Z, X0, pushData);
return updateInfo.hasNewPushVersion();
}
@Test
public void testParameterValidation() {
try {
DesignerUpdateInfo updateInfo = new DesignerUpdateInfo(null, null, null, new JSONObject());
Assert.fail("should not reach here!");
} catch (InvalidParameterException e) {
// do nothing
}
}
}

20
designer-base/src/test/resources/com/fr/design/ui/demo.html

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
Pool.update = function () {
Pool.data.setAge(parseInt(document.getElementById("age").value));
Pool.data.setName(document.getElementById("name").value);
return Pool.data;
};
</script>
</head>
<body>
<div>测试页面,请点击最下面的按钮</div>
<input id="name" type="text" placeholder="请输入名字"/>
<input id="age" type="number" placeholder="请输入年龄"/>
<img src="emb:/com/fr/design/images/splash_10.gif">
</body>
</html>

11
designer-base/src/test/resources/com/fr/design/ui/fineui.html

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="emb:/com/fr/web/ui/fineui.min.css"/>
<script src="emb:/com/fr/web/ui/fineui.min.js"/>
</head>
<body>
</body>
</html>

57
designer-base/src/test/resources/com/fr/design/ui/script/start.js

@ -0,0 +1,57 @@
window.addEventListener("load", function (ev) {
var combo1 = BI.createWidget({
type: "bi.vertical",
items: [
{
type: "bi.text_value_combo",
text: "选项1",
width: 300,
items: [
{
el: {
type: "bi.single_select_radio_item",
width: 290,
text: "选项1",
value: 1
},
text: "选项1",
value: 1,
lgap: 10
},
{
el: {
type: "bi.single_select_radio_item",
width: 290,
text: "选项2",
value: 2
},
lgap: 10,
text: "选项2",
value: 2
},
{
el: {
type: "bi.single_select_radio_item",
width: 290,
text: "选项3",
value: 3
},
lgap: 10,
text: "选项3",
value: 3
}
]
}
]
});
BI.createWidget({
type:"bi.absolute",
element: "body",
items: [{
el: combo1,
left: 100,
top: 100
}]
});
});
Loading…
Cancel
Save