diff --git a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java index dba3141b7..1fb6a94a8 100644 --- a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java +++ b/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 mapWorkerList = new ArrayList(); 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.
* The method will be invoked when read data from XML file.
@@ -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.
* The method will be invoked when save data to XML file.
@@ -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); + } } diff --git a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java index 9e4b7c2c0..aa679de9b 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java +++ b/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) { diff --git a/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java b/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java index db48cf995..d906cc39e 100644 --- a/designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java +++ b/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; + } + /** * 创建一个带标题边框面板并且居中显示 * diff --git a/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java b/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java index 3885ff71d..cc5148256 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/ui/Assistant.java b/designer-base/src/main/java/com/fr/design/ui/Assistant.java new file mode 100644 index 000000000..601f0ac36 --- /dev/null +++ b/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); + } +} diff --git a/designer-base/src/main/java/com/fr/design/ui/EmbProtocolHandler.java b/designer-base/src/main/java/com/fr/design/ui/EmbProtocolHandler.java new file mode 100644 index 000000000..6636e2874 --- /dev/null +++ b/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(""); + } + } + 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(""); + } + } + result = result.replaceAll("##script##", scriptText.toString()); + return result; + } +} diff --git a/designer-base/src/main/java/com/fr/design/ui/ModernRequestClient.java b/designer-base/src/main/java/com/fr/design/ui/ModernRequestClient.java new file mode 100644 index 000000000..8a19c84c8 --- /dev/null +++ b/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; + }} diff --git a/designer-base/src/main/java/com/fr/design/ui/ModernUIConstants.java b/designer-base/src/main/java/com/fr/design/ui/ModernUIConstants.java new file mode 100644 index 000000000..ed6fb542e --- /dev/null +++ b/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"); +} diff --git a/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java b/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java new file mode 100644 index 000000000..81f9e051b --- /dev/null +++ b/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 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 { + + private ModernUIPane pane = new ModernUIPane<>(); + + public Builder prepare(ScriptContextListener contextListener) { + pane.browser.addScriptContextListener(contextListener); + return this; + } + + public Builder prepare(LoadListener loadListener) { + pane.browser.addLoadListener(loadListener); + return this; + } + + /** + * 加载jar包中的资源 + * @param path 资源路径 + */ + public Builder withEMB(final String path) { + Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler()); + pane.browser.loadURL("emb:" + path); + return this; + } + + /** + * 加载url指向的资源 + * @param url 文件的地址 + */ + public Builder withURL(final String url) { + Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler()); + pane.browser.loadURL(url); + return this; + } + + /** + * 加载Atom组件 + * @param component Atom组件 + */ + public Builder withComponent(AssembleComponent component) { + Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler(component)); + pane.browser.loadURL("emb:dynamic"); + return this; + } + + /** + * 加载html文本内容 + * @param html 要加载html文本内容 + */ + public Builder withHTML(String html) { + Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler()); + pane.browser.loadHTML(html); + return this; + } + + /** + * 设置该前端页面做数据交换所使用的对象 + * @param namespace 对象名 + */ + public Builder namespace(String namespace) { + pane.namespace = namespace; + return this; + } + + /** + * java端往js端传数据时使用的变量名字 + * @param name 变量的名字 + */ + public Builder variable(String name) { + pane.variable = name; + return this; + } + + /** + * js端往java端传数据时执行的函数表达式 + * @param expression 函数表达式 + */ + public Builder expression(String expression) { + pane.expression = expression; + return this; + } + + public ModernUIPane build() { + return pane; + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/actions/FileDownloader.java b/designer-base/src/main/java/com/fr/design/update/actions/FileDownloader.java similarity index 95% rename from designer-base/src/main/java/com/fr/design/onlineupdate/actions/FileDownloader.java rename to designer-base/src/main/java/com/fr/design/update/actions/FileDownloader.java index d076cc01e..556fa5113 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/actions/FileDownloader.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/actions/SoftwareUpdateAction.java b/designer-base/src/main/java/com/fr/design/update/actions/SoftwareUpdateAction.java similarity index 83% rename from designer-base/src/main/java/com/fr/design/onlineupdate/actions/SoftwareUpdateAction.java rename to designer-base/src/main/java/com/fr/design/update/actions/SoftwareUpdateAction.java index 1b14f5f0b..cb412dcb1 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/actions/SoftwareUpdateAction.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/domain/DownloadItem.java b/designer-base/src/main/java/com/fr/design/update/domain/DownloadItem.java similarity index 98% rename from designer-base/src/main/java/com/fr/design/onlineupdate/domain/DownloadItem.java rename to designer-base/src/main/java/com/fr/design/update/domain/DownloadItem.java index 6871190aa..220f2602d 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/domain/DownloadItem.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/domain/UpdateConstants.java b/designer-base/src/main/java/com/fr/design/update/domain/UpdateConstants.java similarity index 97% rename from designer-base/src/main/java/com/fr/design/onlineupdate/domain/UpdateConstants.java rename to designer-base/src/main/java/com/fr/design/update/domain/UpdateConstants.java index 293c5d1f0..737deafe6 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/domain/UpdateConstants.java +++ b/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. diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/domain/UpdateInfoCachePropertyManager.java b/designer-base/src/main/java/com/fr/design/update/domain/UpdateInfoCachePropertyManager.java similarity index 95% rename from designer-base/src/main/java/com/fr/design/onlineupdate/domain/UpdateInfoCachePropertyManager.java rename to designer-base/src/main/java/com/fr/design/update/domain/UpdateInfoCachePropertyManager.java index 7895c6913..32537fcf4 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/domain/UpdateInfoCachePropertyManager.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/factory/DirectoryOperationFactory.java b/designer-base/src/main/java/com/fr/design/update/factory/DirectoryOperationFactory.java similarity index 98% rename from designer-base/src/main/java/com/fr/design/onlineupdate/factory/DirectoryOperationFactory.java rename to designer-base/src/main/java/com/fr/design/update/factory/DirectoryOperationFactory.java index 9d929c095..906b71412 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/factory/DirectoryOperationFactory.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java new file mode 100644 index 000000000..9ea734e73 --- /dev/null +++ b/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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateDialog.java b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateDialog.java new file mode 100644 index 000000000..92f02e39d --- /dev/null +++ b/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 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() + .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(); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateManager.java b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateManager.java new file mode 100644 index 000000000..3620b2962 --- /dev/null +++ b/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()); + } +} diff --git a/designer-base/src/main/java/com/fr/design/update/push/DesignerUpdateInfo.java b/designer-base/src/main/java/com/fr/design/update/push/DesignerUpdateInfo.java new file mode 100644 index 000000000..5d5e02a47 --- /dev/null +++ b/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; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/EncodingDetect.java b/designer-base/src/main/java/com/fr/design/update/ui/dialog/EncodingDetect.java similarity index 99% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/EncodingDetect.java rename to designer-base/src/main/java/com/fr/design/update/ui/dialog/EncodingDetect.java index ecd63fa16..41bba0f4f 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/EncodingDetect.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/RestoreDialog.java b/designer-base/src/main/java/com/fr/design/update/ui/dialog/RestoreDialog.java similarity index 93% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/RestoreDialog.java rename to designer-base/src/main/java/com/fr/design/update/ui/dialog/RestoreDialog.java index c316311ab..402df06b8 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/RestoreDialog.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/RestoreResultDialog.java b/designer-base/src/main/java/com/fr/design/update/ui/dialog/RestoreResultDialog.java similarity index 98% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/RestoreResultDialog.java rename to designer-base/src/main/java/com/fr/design/update/ui/dialog/RestoreResultDialog.java index 680d3190d..cc2290216 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/RestoreResultDialog.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/UpdateMainDialog.java b/designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java similarity index 96% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/UpdateMainDialog.java rename to designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java index 570042d4e..5e5943051 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/dialog/UpdateMainDialog.java +++ b/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(); diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/ColorfulCellRender.java b/designer-base/src/main/java/com/fr/design/update/ui/widget/ColorfulCellRender.java similarity index 97% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/ColorfulCellRender.java rename to designer-base/src/main/java/com/fr/design/update/ui/widget/ColorfulCellRender.java index 461489839..e5d644b20 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/ColorfulCellRender.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/LoadingLabel.java b/designer-base/src/main/java/com/fr/design/update/ui/widget/LoadingLabel.java similarity index 96% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/LoadingLabel.java rename to designer-base/src/main/java/com/fr/design/update/ui/widget/LoadingLabel.java index a21d67e46..f45f6d67f 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/LoadingLabel.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateActionLabel.java b/designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateActionLabel.java similarity index 98% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateActionLabel.java rename to designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateActionLabel.java index 74c2b6ae5..efd10fb8b 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateActionLabel.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTable.java b/designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTable.java similarity index 96% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTable.java rename to designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTable.java index f94a514ad..c7690f3d5 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTable.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTableCellRender.java b/designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableCellRender.java similarity index 96% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTableCellRender.java rename to designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableCellRender.java index 22c603c86..9a853762e 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTableCellRender.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTableModel.java b/designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableModel.java similarity index 96% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTableModel.java rename to designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableModel.java index 147f88a29..0fa128e36 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTableModel.java +++ b/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; diff --git a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTextAreaCellRender.java b/designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTextAreaCellRender.java similarity index 96% rename from designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTextAreaCellRender.java rename to designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTextAreaCellRender.java index 1e3cebdf8..4f9836d4c 100644 --- a/designer-base/src/main/java/com/fr/design/onlineupdate/ui/widget/UpdateInfoTextAreaCellRender.java +++ b/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; diff --git a/designer-base/src/main/resources/com/fr/design/ui/InitNameSpace.js b/designer-base/src/main/resources/com/fr/design/ui/InitNameSpace.js new file mode 100644 index 000000000..0274d5fa5 --- /dev/null +++ b/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); \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/ui/InsertScript.js b/designer-base/src/main/resources/com/fr/design/ui/InsertScript.js new file mode 100644 index 000000000..8ad60313e --- /dev/null +++ b/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); +}); \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/ui/InsertStyle.js b/designer-base/src/main/resources/com/fr/design/ui/InsertStyle.js new file mode 100644 index 000000000..18ccb7e41 --- /dev/null +++ b/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); +}); \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/ui/help/demo.js b/designer-base/src/main/resources/com/fr/design/ui/help/demo.js new file mode 100644 index 000000000..fd4694d1a --- /dev/null +++ b/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 + }] + }); +}); \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/ui/tpl.html b/designer-base/src/main/resources/com/fr/design/ui/tpl.html new file mode 100644 index 000000000..92df75539 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/ui/tpl.html @@ -0,0 +1,12 @@ + + + + + Title + ##style## + ##script## + + + + + \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/ui/update/push/pushUpdate.css b/designer-base/src/main/resources/com/fr/design/ui/update/push/pushUpdate.css new file mode 100644 index 000000000..e583a96aa --- /dev/null +++ b/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; +} \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/ui/update/push/pushUpdate.js b/designer-base/src/main/resources/com/fr/design/ui/update/push/pushUpdate.js new file mode 100644 index 000000000..722b3d3cd --- /dev/null +++ b/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() + ")"); +}); \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/ui/FineUIDemo.java b/designer-base/src/test/java/com/fr/design/ui/FineUIDemo.java new file mode 100644 index 000000000..c875716a5 --- /dev/null +++ b/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 pane = new ModernUIPane.Builder() + .withComponent(StartComponent.KEY).build(); + contentPane.add(pane, BorderLayout.CENTER); + frame.setVisible(true); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + } +} diff --git a/designer-base/src/test/java/com/fr/design/ui/ModernUIPaneTest.java b/designer-base/src/test/java/com/fr/design/ui/ModernUIPaneTest.java new file mode 100644 index 000000000..f5c8aaaa9 --- /dev/null +++ b/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 pane = new ModernUIPane.Builder() + .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); + } + + } + +} \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/ui/StartComponent.java b/designer-base/src/test/java/com/fr/design/ui/StartComponent.java new file mode 100644 index 000000000..7811142f0 --- /dev/null +++ b/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}; + } + +} diff --git a/designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateConfigManagerTest.java b/designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateConfigManagerTest.java new file mode 100644 index 000000000..17831b0b7 --- /dev/null +++ b/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("")); + 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()); + } +} diff --git a/designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateDialogTest.java b/designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateDialogTest.java new file mode 100644 index 000000000..ae3edf150 --- /dev/null +++ b/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); + } +} diff --git a/designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateManagerTest.java b/designer-base/src/test/java/com/fr/design/update/push/DesignerPushUpdateManagerTest.java new file mode 100644 index 000000000..333580f1a --- /dev/null +++ b/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()); + } + +} diff --git a/designer-base/src/test/java/com/fr/design/update/push/DesignerUpdateInfoTest.java b/designer-base/src/test/java/com/fr/design/update/push/DesignerUpdateInfoTest.java new file mode 100644 index 000000000..14f986e8e --- /dev/null +++ b/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 + } + } +} diff --git a/designer-base/src/test/resources/com/fr/design/ui/demo.html b/designer-base/src/test/resources/com/fr/design/ui/demo.html new file mode 100644 index 000000000..2beae25a7 --- /dev/null +++ b/designer-base/src/test/resources/com/fr/design/ui/demo.html @@ -0,0 +1,20 @@ + + + + + Title + + + +
测试页面,请点击最下面的按钮
+ + + + + \ No newline at end of file diff --git a/designer-base/src/test/resources/com/fr/design/ui/fineui.html b/designer-base/src/test/resources/com/fr/design/ui/fineui.html new file mode 100644 index 000000000..a02004a35 --- /dev/null +++ b/designer-base/src/test/resources/com/fr/design/ui/fineui.html @@ -0,0 +1,11 @@ + + + + + Title + +