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 66a516554..dcc588fa3 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,8 @@ 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.mainframe.vcs.VcsConfigManager; +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 +148,9 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { */ private AlphaFineConfigManager alphaFineConfigManager = new AlphaFineConfigManager(); + private DesignerPushUpdateConfigManager designerPushUpdateConfigManager = DesignerPushUpdateConfigManager.getInstance(); + + private VcsConfigManager vcsConfigManager = VcsConfigManager.getInstance(); public static final String CAS_CERTIFICATE_PATH = "certificatePath"; @@ -693,6 +698,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.joinProductImprove = joinProductImprove; } + public boolean isAutoPushUpdateEnabled() { + return designerPushUpdateConfigManager.isAutoPushUpdateEnabled(); + } + + public void setAutoPushUpdateEnabled(boolean autoPushUpdateEnabled) { + designerPushUpdateConfigManager.setAutoPushUpdateEnabled(autoPushUpdateEnabled); + } + /** * 是否磁盘空间参数 * @@ -1333,6 +1346,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { } } + private void readJettyPort(XMLableReader reader) { String tmpVal; if ((tmpVal = reader.getElementValue()) != null) { @@ -1477,14 +1491,18 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { readUUID(reader); } else if ("status".equals(name)) { readActiveStatus(reader); - } else if (CAS_PARAS.equals(name)) { + } else if (ComparatorUtils.equals(CAS_PARAS, name)) { readHttpsParas(reader); - } else if ("AlphaFineConfigManager".equals(name)) { + } else if (name.equals("AlphaFineConfigManager")) { readAlphaFineAttr(reader); - } else if ("RecentColors".equals(name)) { + } else if (name.equals("RecentColors")) { readRecentColor(reader); } else if ("OpenDebug".equals(name)) { readOpenDebug(reader); + } else if (name.equals(DesignerPushUpdateConfigManager.XML_TAG)) { + readDesignerPushUpdateAttr(reader); + } else if (name.equals(vcsConfigManager.XML_TAG)) { + readVcsAttr(reader); } else { readLayout(reader, name); } @@ -1667,6 +1685,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { checkRecentOpenedFileNum(); } + private void readDesignerPushUpdateAttr(XMLableReader reader) { + reader.readXMLObject(designerPushUpdateConfigManager); + } + + private void readVcsAttr(XMLableReader reader) { + reader.readXMLObject(vcsConfigManager); + } + /** * Write XML.
* The method will be invoked when save data to XML file.
@@ -1690,6 +1716,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { writeAlphaFineAttr(writer); writeRecentColor(writer); writeOpenDebug(writer); + writeDesignerPushUpdateAttr(writer); + writeVcsAttr(writer); writer.end(); } @@ -1713,7 +1741,6 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { } } - //写入uuid private void writeUUID(XMLPrintWriter writer) { writer.startTAG("uuid"); @@ -1929,4 +1956,20 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { .end(); } + private void writeDesignerPushUpdateAttr(XMLPrintWriter writer) { + this.designerPushUpdateConfigManager.writeXML(writer); + } + + private void writeVcsAttr(XMLPrintWriter writer) { + this.vcsConfigManager.writeXML(writer); + } + + + public VcsConfigManager getVcsConfigManager() { + return vcsConfigManager; + } + + public void setVcsConfigManager(VcsConfigManager vcsConfigManager) { + this.vcsConfigManager = vcsConfigManager; + } } diff --git a/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java b/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java index 110b97563..93f282454 100644 --- a/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java +++ b/designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java @@ -22,9 +22,9 @@ import com.fr.start.server.ServerTray; import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContextCallback; import com.fr.workspace.Workspace; -import com.fr.workspace.connect.AuthException; import com.fr.workspace.connect.WorkspaceConnectionInfo; import com.fr.workspace.engine.channel.http.FunctionalHttpRequest; +import com.fr.workspace.engine.exception.WorkspaceAuthException; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; @@ -120,7 +120,7 @@ public class EnvChangeEntrance { } }); - } catch (AuthException | RegistEditionException e) { + } catch (WorkspaceAuthException | RegistEditionException e) { // String title = Toolkit.i18nText("Fine-Design_Basic_Remote_Connect_Auth_Failed"); // String title = Toolkit.i18nText("Fine-Design_Basic_Lic_Does_Not_Support_Remote"); strategy.showTip(new PopTip() { diff --git a/designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java b/designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java new file mode 100644 index 000000000..9ab799bcc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java @@ -0,0 +1,41 @@ +package com.fr.design.actions.community; + +import com.fr.design.menu.MenuKeySet; +import com.fr.design.utils.BrowseUtils; +import com.fr.general.CloudCenter; +import com.fr.general.IOUtils; + +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; + +public class FacebookFansAction extends UpAction { + + public FacebookFansAction() { + this.setMenuKeySet(FACEBOOKFANS); + this.setName(getMenuKeySet().getMenuName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(IOUtils.readIcon("/com/fr/design/images/bbs/facebook.png")); + } + + @Override + public void actionPerformed(ActionEvent arg0) { + BrowseUtils.browser(CloudCenter.getInstance().acquireUrlByKind("facebook.fans.tw")); + } + + public static final MenuKeySet FACEBOOKFANS = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'F'; + } + + @Override + public String getMenuName() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Community_FaceBook_Fans"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} diff --git a/designer-base/src/main/java/com/fr/design/actions/file/PreferenceAction.java b/designer-base/src/main/java/com/fr/design/actions/file/PreferenceAction.java index eb652abb8..08273202d 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/PreferenceAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/PreferenceAction.java @@ -4,9 +4,10 @@ import com.fr.design.DesignerEnvManager; import com.fr.design.actions.UpdateAction; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.DialogActionAdapter; -import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerFrame; +import com.fr.design.mainframe.DesignerFrameFileDealerPane; import com.fr.design.mainframe.JTemplate; import com.fr.design.menu.KeySetUtils; @@ -38,9 +39,10 @@ public class PreferenceAction extends UpdateAction { preferencePane.update(DesignerEnvManager.getEnvManager()); DesignerEnvManager.loadLogSetting(); DesignerEnvManager.getEnvManager().saveXMLFile(); - JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); jt.refreshToolArea(); preferencePane.showRestartDialog(); + DesignerFrameFileDealerPane.getInstance().refreshDockingView(); } }); 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 4edf71c3b..7afc21d31 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 @@ -2,6 +2,7 @@ package com.fr.design.actions.file; import com.fr.base.BaseUtils; import com.fr.config.Configuration; +import com.fr.config.ServerPreferenceConfig; import com.fr.design.DesignerEnvManager; import com.fr.design.RestartHelper; import com.fr.design.dialog.BasicDialog; @@ -23,8 +24,10 @@ 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.mainframe.vcs.VcsConfigManager; +import com.fr.design.mainframe.vcs.common.VcsHelper; +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; @@ -41,6 +44,8 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; @@ -118,7 +123,6 @@ public class PreferencePane extends BasicPane { private KeyStroke shortCutKeyStore = null; private UIColorButton gridLineColorTBButton; - private UIColorButton paginationLineColorTBButton; private UICheckBox supportCellEditorDefCheckBox; @@ -133,7 +137,17 @@ public class PreferencePane extends BasicPane { private UICheckBox oracleSpace; private UISpinner cachingTemplateSpinner; private UICheckBox openDebugComboBox; - private UICheckBox joinProductImprove; + private UICheckBox useOptimizedUPMCheckbox; + private UICheckBox joinProductImproveCheckBox; + private UICheckBox autoPushUpdateCheckBox; + + private UICheckBox vcsEnableCheckBox; + private UICheckBox saveCommitCheckBox; + private UICheckBox useIntervalCheckBox; + private IntegerEditor saveIntervalEditor; + private UILabel remindVcsLabel; + + public PreferencePane() { this.initComponents(); @@ -151,11 +165,11 @@ 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); createColorSettingPane(generalPane); + createVcsSettingPane(generalPane); // ConfPane JPanel confLocationPane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane(); @@ -172,16 +186,25 @@ public class PreferencePane extends BasicPane { JPanel oraclePane = FRGUIPaneFactory.createTitledBorderPane("Oracle" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Oracle_All_Tables")); oracleSpace = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Show_All_Oracle_Tables")); oraclePane.add(oracleSpace); - - 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.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 upmSelectorPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager")); + useOptimizedUPMCheckbox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Use_New_Update_Plugin_Manager")); + upmSelectorPane.add(useOptimizedUPMCheckbox); + advancePane.add(upmSelectorPane); + + 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); @@ -190,6 +213,45 @@ public class PreferencePane extends BasicPane { advancePane.add(spaceUpPane); } + private void createVcsSettingPane(JPanel generalPane) { + JPanel vcsPane = FRGUIPaneFactory.createVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Vcs_Title")); + generalPane.add(vcsPane); + remindVcsLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Remind")); + remindVcsLabel.setVisible(!VcsHelper.getInstance().needInit()); + vcsEnableCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Vcs_SaveAuto")); + saveCommitCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Vcs_No_Delete")); + saveIntervalEditor = new IntegerEditor(60); + useIntervalCheckBox = new UICheckBox(); + JPanel enableVcsPanel = new JPanel(FRGUIPaneFactory.createLeftZeroLayout()); + enableVcsPanel.add(vcsEnableCheckBox); + enableVcsPanel.add(remindVcsLabel); + JPanel intervalPanel = new JPanel(FRGUIPaneFactory.createLeftZeroLayout()); + UILabel everyLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Every")); + UILabel delayLabel = new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Delay")); + intervalPanel.add(useIntervalCheckBox); + intervalPanel.add(everyLabel); + intervalPanel.add(saveIntervalEditor); + intervalPanel.add(delayLabel); + vcsEnableCheckBox.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + boolean selected = vcsEnableCheckBox.isSelected(); + if (selected) { + saveCommitCheckBox.setEnabled(true); + saveIntervalEditor.setEnabled(true); + useIntervalCheckBox.setEnabled(true); + } else { + saveCommitCheckBox.setEnabled(false); + saveIntervalEditor.setEnabled(false); + useIntervalCheckBox.setEnabled(false); + } + } + }); + vcsPane.add(enableVcsPanel); + vcsPane.add(intervalPanel); + vcsPane.add(saveCommitCheckBox); + } + private void createFunctionPane(JPanel generalPane) { JPanel functionPane = FRGUIPaneFactory.createTitledBorderPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preference_Function")); generalPane.add(functionPane); @@ -539,6 +601,22 @@ public class PreferencePane extends BasicPane { defaultStringToFormulaBox.setEnabled(false); defaultStringToFormulaBox.setSelected(false); } + VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager(); + if (VcsHelper.getInstance().needInit()) { + vcsEnableCheckBox.setSelected(vcsConfigManager.isVcsEnable()); + } else { + vcsEnableCheckBox.setEnabled(false); + vcsEnableCheckBox.setSelected(false); + } + if (!vcsEnableCheckBox.isSelected()) { + saveCommitCheckBox.setEnabled(false); + saveIntervalEditor.setEnabled(false); + useIntervalCheckBox.setEnabled(false); + } + + saveIntervalEditor.setValue(vcsConfigManager.getSaveInterval()); + saveCommitCheckBox.setSelected(vcsConfigManager.isSaveCommit()); + useIntervalCheckBox.setSelected(vcsConfigManager.isUseInterval()); supportCellEditorDefCheckBox.setSelected(designerEnvManager.isSupportCellEditorDef()); @@ -558,11 +636,16 @@ public class PreferencePane extends BasicPane { this.portEditor.setValue(new Integer(designerEnvManager.getEmbedServerPort())); - openDebugComboBox.setSelected(designerEnvManager.isOpenDebug()); +// openDebugComboBox.setSelected(designerEnvManager.isOpenDebug()); + useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM()); 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) { @@ -619,11 +702,19 @@ public class PreferencePane extends BasicPane { designerEnvManager.setJettyServerPort(portEditor.getValue().intValue()); - designerEnvManager.setOpenDebug(openDebugComboBox.isSelected()); +// 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()); + VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager(); + vcsConfigManager.setSaveInterval(this.saveIntervalEditor.getValue()); + vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected()); + vcsConfigManager.setSaveCommit(this.saveCommitCheckBox.isSelected()); + vcsConfigManager.setUseInterval(this.useIntervalCheckBox.isSelected()); + if (this.autoPushUpdateCheckBox != null) { + designerEnvManager.setAutoPushUpdateEnabled(this.autoPushUpdateCheckBox.isSelected()); + } designerEnvManager.setUndoLimit(maxUndoLimit.getSelectedIndex() * SELECTED_INDEX_5); if (maxUndoLimit.getSelectedIndex() == SELECTED_INDEX_5) { @@ -642,6 +733,18 @@ public class PreferencePane extends BasicPane { } }); + Configurations.update(new Worker() { + @Override + public void run() { + ServerPreferenceConfig.getInstance().setUseOptimizedUPM(useOptimizedUPMCheckbox.isSelected()); + } + + @Override + public Class[] targets() { + return new Class[] {ServerPreferenceConfig.class}; + } + }); + } diff --git a/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java b/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java index 58221a03a..f5dc26f10 100644 --- a/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java @@ -1,7 +1,6 @@ package com.fr.design.actions.help; import com.fr.base.BaseUtils; -import com.fr.base.Utils; import com.fr.design.actions.UpdateAction; import com.fr.design.menu.MenuKeySet; import com.fr.general.CloudCenter; @@ -10,9 +9,7 @@ import com.fr.general.http.HttpToolbox; import com.fr.log.FineLoggerFactory; import com.fr.stable.CommonUtils; import com.fr.stable.ProductConstants; -import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; -import com.fr.stable.os.OperatingSystem; import com.fr.third.org.apache.http.HttpStatus; import com.fr.third.org.apache.http.StatusLine; import com.fr.third.org.apache.http.client.methods.HttpGet; @@ -21,12 +18,10 @@ import javax.swing.KeyStroke; import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; -import java.io.File; -import java.io.IOException; import java.net.URI; public class TutorialAction extends UpdateAction { - + public TutorialAction() { this.setMenuKeySet(HELP_TUTORIAL); this.setName(getMenuKeySet().getMenuName()); @@ -35,27 +30,6 @@ public class TutorialAction extends UpdateAction { this.setAccelerator(getMenuKeySet().getKeyStroke()); } - private void nativeExcuteMacInstallHomePrograms(String appName) { - String installHome = StableUtils.getInstallHome(); - if(installHome == null) { - FineLoggerFactory.getLogger().error("Can not find the install home, please check it."); - } else { - String appPath = StableUtils.pathJoin(new String[]{installHome, "bin", appName}); - if(!(new File(appPath)).exists()) { - FineLoggerFactory.getLogger().error(appPath + " can not be found."); - } - - String cmd = "open " + appPath; - Runtime runtime = Runtime.getRuntime(); - - try { - runtime.exec(cmd); - } catch (IOException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - - } - } /** * 动作 * @param evt 事件 @@ -67,14 +41,10 @@ public class TutorialAction extends UpdateAction { Desktop.getDesktop().browse(new URI(helpURL)); return; } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); } } - - if (OperatingSystem.isUnix()) { - nativeExcuteMacInstallHomePrograms("helptutorial.app"); - } else { - Utils.nativeExcuteInstallHomePrograms("helptutorial.exe"); - } + FineLoggerFactory.getLogger().warn(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Offline_Helptutorial_Msg")); } // 生成帮助文档 sitecenter key, help.zh_CN.10 @@ -116,4 +86,4 @@ public class TutorialAction extends UpdateAction { } }; -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/actions/server/PluginManagerAction.java b/designer-base/src/main/java/com/fr/design/actions/server/PluginManagerAction.java index ecd0d961a..1b7d7bbc4 100644 --- a/designer-base/src/main/java/com/fr/design/actions/server/PluginManagerAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/server/PluginManagerAction.java @@ -1,10 +1,11 @@ package com.fr.design.actions.server; -import com.fr.base.BaseUtils; +import com.fr.config.ServerPreferenceConfig; import com.fr.design.actions.UpdateAction; import com.fr.design.extra.WebViewDlgHelper; import com.fr.design.menu.MenuKeySet; - +import com.fr.design.upm.UpmFinder; +import com.fr.general.IOUtils; import javax.swing.*; import java.awt.event.ActionEvent; @@ -20,12 +21,17 @@ public class PluginManagerAction extends UpdateAction { this.setMenuKeySet(PLUGIN_MANAGER); this.setName(getMenuKeySet().getMenuKeySetName()); this.setMnemonic(getMenuKeySet().getMnemonic()); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/server/plugin.png")); + this.setSmallIcon(IOUtils.readIcon("/com/fr/design/images/server/plugin.png")); } @Override public void actionPerformed(ActionEvent e) { - WebViewDlgHelper.createPluginDialog(); + // 可以启用新版本的插件商店(使用JxBrowser作为容器) + if (ServerPreferenceConfig.getInstance().isUseOptimizedUPM()) { + UpmFinder.showUPMDialog(); + } else { + WebViewDlgHelper.createPluginDialog(); + } } public static final MenuKeySet PLUGIN_MANAGER = new MenuKeySet() { diff --git a/designer-base/src/main/java/com/fr/design/bridge/exec/JSBridge.java b/designer-base/src/main/java/com/fr/design/bridge/exec/JSBridge.java new file mode 100644 index 000000000..4c7995243 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/bridge/exec/JSBridge.java @@ -0,0 +1,17 @@ +package com.fr.design.bridge.exec; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-18 + * 用于标记一个方法是用于和JS做桥接的,避免被误删除 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.SOURCE) +public @interface JSBridge { +} diff --git a/designer-base/src/main/java/com/fr/design/bridge/exec/JSCallback.java b/designer-base/src/main/java/com/fr/design/bridge/exec/JSCallback.java new file mode 100644 index 000000000..0a0451b54 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/bridge/exec/JSCallback.java @@ -0,0 +1,18 @@ +package com.fr.design.bridge.exec; + +/** + * Created by ibm on 2017/5/27. + */ +public class JSCallback { + + private JSExecutor executeScript; + + public JSCallback(JSExecutor jsExecutor) { + this.executeScript = jsExecutor; + } + + public void execute(String newValue) { + executeScript.executor(newValue); + } +} + diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/JSExecutor.java b/designer-base/src/main/java/com/fr/design/bridge/exec/JSExecutor.java similarity index 72% rename from designer-base/src/main/java/com/fr/design/extra/exe/callback/JSExecutor.java rename to designer-base/src/main/java/com/fr/design/bridge/exec/JSExecutor.java index 2adbadc87..9ded472eb 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/JSExecutor.java +++ b/designer-base/src/main/java/com/fr/design/bridge/exec/JSExecutor.java @@ -1,4 +1,4 @@ -package com.fr.design.extra.exe.callback; +package com.fr.design.bridge.exec; /** * Created by ibm on 2017/6/21. diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/JSCallback.java b/designer-base/src/main/java/com/fr/design/bridge/exec/JSUtils.java similarity index 59% rename from designer-base/src/main/java/com/fr/design/extra/exe/callback/JSCallback.java rename to designer-base/src/main/java/com/fr/design/bridge/exec/JSUtils.java index d01446ee0..730a283e1 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/JSCallback.java +++ b/designer-base/src/main/java/com/fr/design/bridge/exec/JSUtils.java @@ -1,46 +1,20 @@ -package com.fr.design.extra.exe.callback; +package com.fr.design.bridge.exec; +import com.fr.stable.ArrayUtils; import com.fr.stable.StringUtils; -import javafx.application.Platform; -import javafx.scene.web.WebEngine; import netscape.javascript.JSObject; +import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** - * Created by ibm on 2017/5/27. + * @author richie + * @version 10.0 + * Created by richie on 2019-04-18 */ -public class JSCallback { - - private JSExecutor executeScript; - - public JSCallback(final WebEngine webEngine, final JSObject callback) { - init(webEngine, callback); - } - - public void init(final WebEngine webEngine, final JSObject callback){ - executeScript = new JSExecutor() { - @Override - public void executor(final String newValue) { - Platform.runLater(new Runnable() { - @Override - public void run() { - String fun = "(" + callback + ")(\"" + trimText(newValue) + "\")"; - try { - webEngine.executeScript(fun); - } catch (Exception e) { - webEngine.executeScript("alert(\"" + e.getMessage() + "\")"); - } - } - }); - } - }; - } - - public void execute(String newValue) { - executeScript.executor(newValue); - } +public class JSUtils { /** @@ -60,7 +34,7 @@ public class JSCallback { * @param old 原始字符串 * @return 处理之后的字符串 */ - private String trimText(String old) { + public static String trimText(String old) { if (StringUtils.isNotBlank(old)) { String b = filterHtmlTag(old); return b.replaceAll("\\\\n", StringUtils.EMPTY).replaceAll("\\\\t", StringUtils.EMPTY).replaceAll("\"", "\\\\\"").replaceAll("\'", "\\\\\'").replaceAll("\\\\\\\\", "\\\\\\\\\\\\"); @@ -73,7 +47,7 @@ public class JSCallback { * @param origin 原始字符串 * @return 处理之后的字符串 */ - private String filterHtmlTag(String origin) { + public static String filterHtmlTag(String origin) { String regHtml = "<[^>]+>"; Pattern patternHtml = Pattern.compile(regHtml, Pattern.CASE_INSENSITIVE); Matcher matchHtml = patternHtml.matcher(origin); @@ -81,5 +55,15 @@ public class JSCallback { return origin; } + public String[] jsObjectToStringArray(JSObject obj) { + if (obj == null) { + return ArrayUtils.EMPTY_STRING_ARRAY; + } + int len = (int) obj.getMember("length"); + List list = new ArrayList<>(); + for (int i = 0; i < len; i++) { + list.add(obj.getSlot(i).toString()); + } + return list.toArray(new String[len]); + } } - diff --git a/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java b/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java index bed0dc96b..a18ae856e 100644 --- a/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java +++ b/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java @@ -147,6 +147,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp private boolean isIncludeUnderline(String name) { return ComparatorUtils.equals(name.indexOf(StoreProcedureAssist.GROUP_MARKER), -1) ? false : true; } + public abstract void addDataPane(final AbstractTableDataPane uPanel, String paneName); public abstract TableDataTree getDataTree(); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java index 37aa4ef12..56f81e9a5 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java @@ -324,4 +324,31 @@ public class TableDataTreePane extends BasicTableDataTreePane { dataTree.refresh(); return Collections.unmodifiableMap(tdNameMap); } + public void addDataPane(final AbstractTableDataPane uPanel, String paneName) { + final NamePane nPanel = uPanel.asNamePane(); + nPanel.setObjectName(paneName); + final String oldName = paneName; + + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); + tc.renameTableData(oldName, nPanel.getObjectName(), false); + TableDataSource tds = tc.getBook(); + TableData td = uPanel.updateBean(); + if (td instanceof TableDataSourceDependent) { + ((TableDataSourceDependent) td).setTableDataSource(tds); + } + String tdName = nPanel.getObjectName(); + tds.putTableData(tdName, td); + Map map = new HashMap(); + if (!ComparatorUtils.equals(oldName, tdName)) { + map.put(oldName, tdName); + } + fireDSChanged(map); + tc.fireTargetModified(); + tc.parameterChanged(); + int[] rows = dataTree.getSelectionRows(); + dataTree.refreshChildByName(tdName); + dataTree.setSelectionRows(rows); + } } diff --git a/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java b/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java index 8c7053650..c01daff70 100644 --- a/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java +++ b/designer-base/src/main/java/com/fr/design/dialog/BasicPane.java @@ -2,13 +2,18 @@ package com.fr.design.dialog; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.UITextField; - -import com.fr.stable.core.PropertyChangeAdapter; +import com.fr.design.i18n.Toolkit; import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.stable.core.PropertyChangeAdapter; -import javax.swing.*; +import javax.swing.JPanel; import javax.swing.event.DocumentEvent; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Window; /* * _denny: 这里的BasicPane通常会有populate & update方法 @@ -298,18 +303,20 @@ public abstract class BasicPane extends JPanel { public void checkValid() throws Exception { } - public static final class NamePane extends BasicPane { + public static class NamePane extends BasicPane { private UITextField nameTextField; + private UILabel Name; private BasicPane centerPane; private UILabel showfield; private PropertyChangeAdapter changeListener; - private NamePane(BasicPane bPane) { + public NamePane(BasicPane bPane) { this.setLayout(new BorderLayout(4, 4)); nameTextField = new UITextField(30); + Name = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Name") + ":"); JPanel northPane = new JPanel(new BorderLayout(4, 4)); - northPane.add(new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Hyperlink_Name") + ":"), BorderLayout.WEST); + northPane.add(Name, BorderLayout.WEST); northPane.add(nameTextField, BorderLayout.CENTER); northPane.add(showfield = new UILabel(" "), BorderLayout.EAST); showfield.setForeground(new Color(204, 0, 1)); @@ -343,6 +350,11 @@ public abstract class BasicPane extends JPanel { } } + public void setVisible(boolean isVisible) { + this.nameTextField.setVisible(isVisible); + this.Name.setVisible(isVisible); + } + public String getObjectName() { return this.nameTextField.getText().trim(); } diff --git a/designer-base/src/main/java/com/fr/design/editor/editor/DateEditor.java b/designer-base/src/main/java/com/fr/design/editor/editor/DateEditor.java index 3b1abe6f0..c40161ba6 100644 --- a/designer-base/src/main/java/com/fr/design/editor/editor/DateEditor.java +++ b/designer-base/src/main/java/com/fr/design/editor/editor/DateEditor.java @@ -153,6 +153,10 @@ public class DateEditor extends Editor { this.uiDatePicker.setSelectedItem(new Date()); } + public UIDatePicker getUiDatePicker() { + return uiDatePicker; + } + /** * Request focus */ diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginJavaFxExecutor.java b/designer-base/src/main/java/com/fr/design/extra/PluginJavaFxExecutor.java new file mode 100644 index 000000000..c3863a46d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/extra/PluginJavaFxExecutor.java @@ -0,0 +1,42 @@ +package com.fr.design.extra; + +import com.fr.design.bridge.exec.JSExecutor; +import com.fr.design.bridge.exec.JSUtils; +import javafx.application.Platform; +import javafx.scene.web.WebEngine; +import netscape.javascript.JSObject; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-18 + */ +public class PluginJavaFxExecutor implements JSExecutor { + + public static PluginJavaFxExecutor create(WebEngine webEngine, JSObject callback) { + return new PluginJavaFxExecutor(webEngine, callback); + } + + private WebEngine webEngine; + private JSObject callback; + + private PluginJavaFxExecutor(WebEngine webEngine, JSObject callback) { + this.webEngine = webEngine; + this.callback = callback; + } + + @Override + public void executor(final String newValue) { + Platform.runLater(new Runnable() { + @Override + public void run() { + String fun = "(" + callback + ")(\"" + JSUtils.trimText(newValue) + "\")"; + try { + webEngine.executeScript(fun); + } catch (Exception e) { + webEngine.executeScript("alert(\"" + e.getMessage() + "\")"); + } + } + }); + } +} diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java b/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java index 99e02bdc1..774578630 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java @@ -3,7 +3,7 @@ package com.fr.design.extra; import com.fr.config.MarketConfig; import com.fr.design.extra.exe.callback.InstallFromDiskCallback; import com.fr.design.extra.exe.callback.InstallOnlineCallback; -import com.fr.design.extra.exe.callback.JSCallback; +import com.fr.design.bridge.exec.JSCallback; import com.fr.design.extra.exe.callback.ModifyStatusCallback; import com.fr.design.extra.exe.callback.UninstallPluginCallback; import com.fr.design.extra.exe.callback.UpdateFromDiskCallback; diff --git a/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java b/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java index 02a51ad3f..492bbfd97 100644 --- a/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java +++ b/designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java @@ -3,6 +3,7 @@ package com.fr.design.extra; import com.fr.base.passport.FinePassportManager; import com.fr.config.MarketConfig; import com.fr.design.RestartHelper; +import com.fr.design.bridge.exec.JSCallback; import com.fr.design.dialog.UIDialog; import com.fr.design.extra.exe.GetInstalledPluginsExecutor; import com.fr.design.extra.exe.GetPluginCategoriesExecutor; @@ -11,12 +12,9 @@ import com.fr.design.extra.exe.GetPluginPrefixExecutor; import com.fr.design.extra.exe.PluginLoginExecutor; import com.fr.design.extra.exe.ReadUpdateOnlineExecutor; import com.fr.design.extra.exe.SearchOnlineExecutor; -import com.fr.design.extra.exe.callback.JSCallback; import com.fr.design.gui.ilable.UILabel; import com.fr.design.utils.concurrent.ThreadFactoryBuilder; - import com.fr.general.CloudCenter; -import com.fr.json.JSONException; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; import com.fr.plugin.context.PluginMarker; @@ -172,7 +170,7 @@ public class PluginWebBridge { * @param callback 回调函数 */ public void installPluginOnline(final String pluginInfo, final JSObject callback) { - JSCallback jsCallback = new JSCallback(webEngine, callback); + JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); PluginMarker pluginMarker = PluginUtils.createPluginMarker(pluginInfo); PluginOperateUtils.installPluginOnline(pluginMarker, jsCallback); } @@ -183,7 +181,7 @@ public class PluginWebBridge { * @param filePath 插件包的路径 */ public void installPluginFromDisk(final String filePath, final JSObject callback) { - JSCallback jsCallback = new JSCallback(webEngine, callback); + JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); File file = new File(filePath); PluginOperateUtils.installPluginFromDisk(file, jsCallback); } @@ -194,7 +192,7 @@ public class PluginWebBridge { * @param pluginInfo 插件信息 */ public void uninstallPlugin(final String pluginInfo, final boolean isForce, final JSObject callback) { - JSCallback jsCallback = new JSCallback(webEngine, callback); + JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); PluginOperateUtils.uninstallPlugin(pluginInfo, isForce, jsCallback); } @@ -204,7 +202,7 @@ public class PluginWebBridge { * @param pluginIDs 插件集合 */ public void updatePluginOnline(JSObject pluginIDs, final JSObject callback) { - JSCallback jsCallback = new JSCallback(webEngine, callback); + JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); String[] pluginInfos = jsObjectToStringArray(pluginIDs); List pluginMarkerList = new ArrayList(); for (int i = 0; i < pluginInfos.length; i++) { @@ -219,7 +217,7 @@ public class PluginWebBridge { * @param filePath 插件包的路径 */ public void updatePluginFromDisk(String filePath, final JSObject callback) { - JSCallback jsCallback = new JSCallback(webEngine, callback); + JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); File file = new File(filePath); PluginOperateUtils.updatePluginFromDisk(file, jsCallback); } @@ -230,7 +228,7 @@ public class PluginWebBridge { * @param pluginID 插件ID */ public void setPluginActive(String pluginID, final JSObject callback) { - JSCallback jsCallback = new JSCallback(webEngine, callback); + JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); PluginOperateUtils.setPluginActive(pluginID, jsCallback); } @@ -427,7 +425,7 @@ public class PluginWebBridge { * @param callback */ public void registerLoginInfo(final JSObject callback) { - JSCallback jsCallback = new JSCallback(webEngine, callback); + JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); PluginOperateUtils.getLoginInfo(jsCallback, uiLabel); } @@ -559,7 +557,7 @@ public class PluginWebBridge { } public void getPackInfo(final JSObject callback){ - JSCallback jsCallback = new JSCallback(webEngine, callback); + JSCallback jsCallback = new JSCallback(PluginJavaFxExecutor.create(webEngine, callback)); jsCallback.execute(StringUtils.EMPTY); } diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java index 1e170c844..e8096efbf 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java @@ -1,5 +1,6 @@ package com.fr.design.extra.exe.callback; +import com.fr.design.bridge.exec.JSCallback; import com.fr.design.extra.PluginOperateUtils; import com.fr.design.extra.PluginUtils; diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java index 9b86641e6..23b6679b6 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java @@ -1,5 +1,6 @@ package com.fr.design.extra.exe.callback; +import com.fr.design.bridge.exec.JSCallback; import com.fr.design.extra.PluginOperateUtils; import com.fr.log.FineLoggerFactory; diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/ModifyStatusCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/ModifyStatusCallback.java index 681180053..b7b817ef4 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/ModifyStatusCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/ModifyStatusCallback.java @@ -1,5 +1,6 @@ package com.fr.design.extra.exe.callback; +import com.fr.design.bridge.exec.JSCallback; import com.fr.design.extra.PluginUtils; import com.fr.plugin.manage.control.PluginTaskCallback; diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UninstallPluginCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UninstallPluginCallback.java index a6f781b94..db8a69188 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UninstallPluginCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UninstallPluginCallback.java @@ -1,5 +1,6 @@ package com.fr.design.extra.exe.callback; +import com.fr.design.bridge.exec.JSCallback; import com.fr.design.extra.PluginUtils; import com.fr.log.FineLoggerFactory; diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java index cd0ccab84..26315fd03 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java @@ -1,5 +1,6 @@ package com.fr.design.extra.exe.callback; +import com.fr.design.bridge.exec.JSCallback; import com.fr.design.extra.PluginOperateUtils; import com.fr.design.extra.PluginUtils; diff --git a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java index c857960c7..28f4f6a31 100644 --- a/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java +++ b/designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java @@ -1,5 +1,6 @@ package com.fr.design.extra.exe.callback; +import com.fr.design.bridge.exec.JSCallback; import com.fr.design.extra.PluginOperateUtils; import com.fr.log.FineLoggerFactory; diff --git a/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java b/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java index f790eca94..528f6a56c 100644 --- a/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java +++ b/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java @@ -41,17 +41,17 @@ public class HistoryTemplateListCache implements CallbackEvent { private List> historyList; private JTemplate editingTemplate; - private static volatile HistoryTemplateListCache THIS; + private static volatile HistoryTemplateListCache instacne; public static HistoryTemplateListCache getInstance() { - if (THIS == null) { + if (instacne == null) { synchronized (HistoryTemplateListCache.class) { - if (THIS == null) { - THIS = new HistoryTemplateListCache(); + if (instacne == null) { + instacne = new HistoryTemplateListCache(); } } } - return THIS; + return instacne; } private HistoryTemplateListCache() { @@ -66,8 +66,8 @@ public class HistoryTemplateListCache implements CallbackEvent { public void closeSelectedReport(JTemplate selected) { DesignModuleFactory.clearChartPropertyPane(); DesignTableDataManager.closeTemplate(selected); - //直接关闭模板的时候退出权限编辑 - if (DesignModeContext.isAuthorityEditing()) { + //直接关闭模板的时候(当且仅当设计器tab上只剩一个模板)退出权限编辑 + if (DesignModeContext.isAuthorityEditing() && historyList.size() <= 1) { DesignerContext.getDesignerFrame().closeAuthorityEditing(); } if (contains(selected) == -1) { diff --git a/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java b/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java index 65989dfcc..968f72a59 100644 --- a/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java +++ b/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java @@ -751,8 +751,11 @@ public class MutilTempalteTabPane extends JComponent { JTemplate template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); selectedIndex = HistoryTemplateListCache.getInstance().contains(template); } - //如果是已后台关闭的模板,则重新打开文件 - openedTemplate.get(selectedIndex).activeOldJTemplate(); + if (selectedIndex < openedTemplate.size()) { + //如果是已后台关闭的模板,则重新打开文件 + openedTemplate.get(selectedIndex).activeOldJTemplate(); + } + } } diff --git a/designer-base/src/main/java/com/fr/design/fun/OemProcessor.java b/designer-base/src/main/java/com/fr/design/fun/OemProcessor.java new file mode 100644 index 000000000..44acc1190 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/OemProcessor.java @@ -0,0 +1,38 @@ +package com.fr.design.fun; + +import com.fr.design.menu.MenuDef; +import com.fr.start.SplashStrategy; + +import java.awt.image.BufferedImage; +import java.util.List; + +/** + * 设计器Oem接口 + */ +public interface OemProcessor { + public static final String MARK_STRING = "OemProcessor"; + + /** + * 启动动画,如果不替换则返回null + * + * @return + */ + SplashStrategy createSplashStrategy(); + + /** + * 替换标题图标--DesignerFrame.initTitleIcon + * 如果不替换则返回null + * + * @return + */ + List createTitleIcon(); + + /** + * 处理设计器菜单(增删改) + * + * @param menuDefs 已加载的菜单 + * @return 新的菜单数组 + */ + MenuDef[] dealWithMenuDef(MenuDef[] menuDefs); + +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractOemProcessor.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractOemProcessor.java new file mode 100644 index 000000000..d49bfdf24 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractOemProcessor.java @@ -0,0 +1,25 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.OemProcessor; +import com.fr.design.menu.MenuDef; +import com.fr.start.SplashStrategy; + +import java.awt.image.BufferedImage; +import java.util.List; + +public abstract class AbstractOemProcessor implements OemProcessor{ + @Override + public MenuDef[] dealWithMenuDef(MenuDef[] menuDefs) { + return menuDefs; + } + + @Override + public List createTitleIcon() { + return null; + } + + @Override + public SplashStrategy createSplashStrategy() { + return null; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/date/SingleObjectComboBoxModel.java b/designer-base/src/main/java/com/fr/design/gui/date/SingleObjectComboBoxModel.java index 788d1104e..62cf79347 100644 --- a/designer-base/src/main/java/com/fr/design/gui/date/SingleObjectComboBoxModel.java +++ b/designer-base/src/main/java/com/fr/design/gui/date/SingleObjectComboBoxModel.java @@ -1,6 +1,7 @@ package com.fr.design.gui.date; import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; import javax.swing.AbstractListModel; import javax.swing.ComboBoxModel; @@ -9,7 +10,7 @@ import java.util.Date; public class SingleObjectComboBoxModel extends AbstractListModel implements ComboBoxModel { private SimpleDateFormat dateFormat; - private String selectedDate = ""; + private String selectedDate = StringUtils.EMPTY; public SingleObjectComboBoxModel() { } @@ -28,6 +29,7 @@ public class SingleObjectComboBoxModel extends AbstractListModel implements Comb public void setSelectedItem(Object anItem) { if (anItem == null) { + selectedDate = StringUtils.EMPTY; return; } if (anItem instanceof Date) { diff --git a/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java b/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java index aa9cabd49..fb44f618f 100644 --- a/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java +++ b/designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java @@ -6,6 +6,7 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; import javax.swing.BorderFactory; import javax.swing.JComboBox; @@ -157,7 +158,11 @@ public class UIDatePicker extends UIComboBox implements Serializable { * 设置当前选择的日期 */ public void setSelectedDate(Date date) throws ParseException { - this.setSelectedItem(dateFormat.format(date)); + if (date == null) { + this.setSelectedItem(null); + } else { + this.setSelectedItem(dateFormat.format(date)); + } } public void setSelectedItem(Object anObject) { @@ -215,8 +220,11 @@ public class UIDatePicker extends UIComboBox implements Serializable { try { String strDate = comboBox.getSelectedItem().toString(); synchronized (this) { - Date selectionDate = dateFormat.parse(strDate); - calendarPanel.setSelectedDate(selectionDate); + Date selectionDate = new Date(); + if (StringUtils.isNotBlank(strDate)) { + selectionDate = dateFormat.parse(strDate); + } + calendarPanel.setSelectedDate(selectionDate); calendarPanel.updateHMS(); } } catch (Exception e) { diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIToggleButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIToggleButton.java index 4b8975235..45c878419 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ibutton/UIToggleButton.java +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UIToggleButton.java @@ -25,10 +25,13 @@ import com.fr.stable.StringUtils; * @since 2012-5-11下午4:28:24 */ public class UIToggleButton extends UIButton implements GlobalNameObserver{ + + private static final int ICON_COUNT = 2; private boolean isSelected; private boolean isEventBannded = false; private String toggleButtonName = ""; private GlobalNameListener globalNameListener = null; + private Icon[] icons; public UIToggleButton() { this(StringUtils.EMPTY); @@ -53,9 +56,9 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ * @param icons */ public UIToggleButton(Icon[] icons) { - super(icons[0], null, icons[1]); - setSelectedIcon(icons[1]); + super(icons[0], null, null); setExtraPainted(true); + this.icons = icons; addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { @@ -73,10 +76,10 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ * @param icons */ public UIToggleButton(Icon[] icons, boolean needRelease) { - super(icons[0], null, icons[1]); + super(icons[0], null, null); setBorderPainted(true); - setSelectedIcon(icons[1]); setExtraPainted(true); + this.icons = icons; if (!needRelease) { addActionListener(new AbstractAction() { @Override @@ -92,6 +95,7 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ addMouseListener(getMouseListener()); } + @Override public void setGlobalName(String name){ toggleButtonName = name ; } @@ -100,6 +104,7 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ * * @return */ + @Override public boolean isSelected() { return isSelected; } @@ -115,12 +120,15 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ super.setSelected(isSelected); if (this.isSelected != isSelected) { this.isSelected = isSelected; - repaint(); + refresh(isSelected); } } + + @Override protected void initListener(){ if(shouldResponseChangeListener()){ this.addChangeListener(new ChangeListener() { + @Override public void stateChanged(ChangeEvent e) { if (uiObserverListener == null) { return; @@ -138,10 +146,30 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ if (this.isSelected != isSelected) { this.isSelected = isSelected; fireSelectedChanged(); - repaint(); + refresh(isSelected); } } + + + private void refresh(final boolean isSelected) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + Icon[] icons = UIToggleButton.this.icons; + if (icons != null && icons.length == ICON_COUNT) { + if (isSelected) { + UIToggleButton.this.setIcon(icons[1]); + } else { + UIToggleButton.this.setIcon(icons[0]); + } + } + UIToggleButton.this.repaint(); + } + }); + } + + protected MouseListener getMouseListener() { return new MouseAdapter() { @Override @@ -157,6 +185,7 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ this.isEventBannded = ban; } + @Override protected void fireStateChanged() { } @@ -187,6 +216,7 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ } } + @Override protected void paintOtherBorder(Graphics g) { Graphics2D g2d = (Graphics2D) g; g2d.setStroke(UIConstants.BS); @@ -200,6 +230,7 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ * * @return 如果需要响应观察者事件则返回true,否则返回false */ + @Override public boolean shouldResponseChangeListener() { return true; } @@ -208,6 +239,7 @@ public class UIToggleButton extends UIButton implements GlobalNameObserver{ * * @param listener 观察者监听事件 */ + @Override public void registerNameListener(GlobalNameListener listener) { globalNameListener = listener; } diff --git a/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java b/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java index c9c398829..ba6913a38 100644 --- a/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java +++ b/designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java @@ -92,6 +92,18 @@ public class UISpinner extends JPanel implements UIObserver, GlobalNameObserver } public void setValue(double value) { + setValue(value, true); + } + + /** + * 赋值但不触发保存,只是展现,一般是populate的时候用 + * @param value + */ + public void setValueWithoutEvent(double value) { + setValue(value, false); + } + + public void setValue(double value, boolean fireStateChange) { if (globalNameListener != null && shouldResponseNameListener()) { globalNameListener.setGlobalName(spinnerName); } @@ -102,8 +114,9 @@ public class UISpinner extends JPanel implements UIObserver, GlobalNameObserver } this.value = value; setTextField(value); - - fireStateChanged(); + if (fireStateChange) { + fireStateChanged(); + } } protected void setTextField(double value){ diff --git a/designer-base/src/main/java/com/fr/design/gui/style/AlignmentPane.java b/designer-base/src/main/java/com/fr/design/gui/style/AlignmentPane.java index 11fbaf8c8..9bbca6d2b 100644 --- a/designer-base/src/main/java/com/fr/design/gui/style/AlignmentPane.java +++ b/designer-base/src/main/java/com/fr/design/gui/style/AlignmentPane.java @@ -20,8 +20,10 @@ import com.fr.design.gui.ispinner.UISpinner; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.utils.gui.UIComponentUtils; import com.fr.event.EventDispatcher; import com.fr.general.ComparatorUtils; +import com.fr.general.IOUtils; import com.fr.plugin.ExtraClassManager; import com.fr.plugin.context.PluginContext; import com.fr.plugin.manage.PluginFilter; @@ -94,11 +96,11 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO imageLayoutComboBox = new UIComboBox(LAYOUT); initTextRotationCombox(); - Icon[][] hAlignmentIconArray = {{BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal_white.png")}, - {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal_white.png")}, - {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal_white.png")}, - {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_s_normal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_s_normal_white.png")}, - {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/defaultAlignment.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/defaultAlignment_white.png")}}; + Icon[][] hAlignmentIconArray = {{IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal_white.png")}, + {IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal_white.png")}, + {IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal_white.png")}, + {IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_s_normal.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_s_normal_white.png")}, + {IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/defaultAlignment.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/defaultAlignment_white.png")}}; Integer[] hAlignment = new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT, Integer.valueOf(Constants.DISTRIBUTED), Constants.NULL}; hAlignmentPane = new UIButtonGroup(hAlignmentIconArray, hAlignment); hAlignmentPane.setAllToolTips(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Left"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Center"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Right"), @@ -106,9 +108,9 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO hPaneContainer = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); vPaneContainer = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); - Icon[][] vAlignmentIconArray = {{BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_top_normal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_top_normal_white.png")}, - {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_center_normal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_center_normal_white.png")}, - {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_down_normal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_down_normal_white.png")}}; + Icon[][] vAlignmentIconArray = {{IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_top_normal.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_top_normal_white.png")}, + {IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_center_normal.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_center_normal_white.png")}, + {IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_down_normal.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/v_down_normal_white.png")}}; Integer[] vAlignment = new Integer[]{Constants.TOP, Constants.CENTER, Constants.BOTTOM}; vAlignmentPane = new UIButtonGroup(vAlignmentIconArray, vAlignment); vAlignmentPane.setAllToolTips(new String[]{com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Top"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Center"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Tooltips_Bottom")}); @@ -210,9 +212,11 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO private JPanel basicPane() { double f = TableLayout.FILL; double p = TableLayout.PREFERRED; + UILabel horizontalLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Horizontal") + " ", SwingConstants.LEFT); + UIComponentUtils.setLineWrap(horizontalLabel); Component[][] components = new Component[][]{ new Component[]{null, null}, - new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Horizontal") + " ", SwingConstants.LEFT), hPaneContainer}, + new Component[]{horizontalLabel, hPaneContainer}, new Component[]{null, null}, new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Style_Alignment_Pane_Vertical") + " ", SwingConstants.RIGHT), vPaneContainer}, new Component[]{null, null} @@ -304,6 +308,7 @@ public class AlignmentPane extends AbstractBasicStylePane implements GlobalNameO * * @param style the new style. */ + @Override public void populateBean(Style style) { hAlignmentPane.setSelectedItem(BaseUtils.getAlignment4Horizontal(style)); vAlignmentPane.setSelectedItem(style.getVerticalAlignment()); diff --git a/designer-base/src/main/java/com/fr/design/icon/BorderIcon.java b/designer-base/src/main/java/com/fr/design/icon/BorderIcon.java index 3a52f4c50..9d5e71305 100644 --- a/designer-base/src/main/java/com/fr/design/icon/BorderIcon.java +++ b/designer-base/src/main/java/com/fr/design/icon/BorderIcon.java @@ -22,16 +22,18 @@ public class BorderIcon implements Icon { this.cellBorderStyle = cellBorderStyle; } + @Override public int getIconHeight() { return height; } + @Override public int getIconWidth() { return width; } - public static void drawLine(Graphics g, double x1, double y1, double x2, + private void drawLine(Graphics g, double x1, double y1, double x2, double y2, int lineStyle, Color color) { g.setColor(color); x1--; @@ -63,6 +65,7 @@ public class BorderIcon implements Icon { } } + @Override public void paintIcon(Component c, Graphics g, int x, int y) { int defaultWidth = c.getWidth(); int defaultHeight = c.getHeight(); @@ -81,9 +84,9 @@ public class BorderIcon implements Icon { cellBorderStyle.getBottomColor()); drawLine(gr, x1, y1, x1, y2, cellBorderStyle.getLeftStyle(), cellBorderStyle.getLeftColor()); - drawLine(gr, defaultWidth / 2, x1, defaultWidth / 2, x2, + drawLine(gr, defaultWidth / 2, y1, defaultWidth / 2, y2, cellBorderStyle.getVerticalStyle(), cellBorderStyle.getVerticalColor()); - drawLine(gr, y1, defaultHeight / 2, y2, defaultHeight / 2, + drawLine(gr, x1, defaultHeight / 2, x2, defaultHeight / 2, cellBorderStyle.getHorizontalStyle(), cellBorderStyle.getHorizontalColor()); } diff --git a/designer-base/src/main/java/com/fr/design/javascript/beautify/JavaScriptFormatHelper.java b/designer-base/src/main/java/com/fr/design/javascript/beautify/JavaScriptFormatHelper.java index 7f1468a45..8e794f192 100644 --- a/designer-base/src/main/java/com/fr/design/javascript/beautify/JavaScriptFormatHelper.java +++ b/designer-base/src/main/java/com/fr/design/javascript/beautify/JavaScriptFormatHelper.java @@ -1,16 +1,16 @@ package com.fr.design.javascript.beautify; -import com.fr.log.FineLoggerFactory; +import com.eclipsesource.v8.V8; +import com.eclipsesource.v8.V8Array; +import com.eclipsesource.v8.V8Object; +import com.eclipsesource.v8.utils.V8ObjectUtils; import com.fr.general.IOUtils; -import com.fr.script.ScriptFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.EncodeConstants; -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptException; import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; +import java.io.UnsupportedEncodingException; public class JavaScriptFormatHelper { @@ -34,15 +34,21 @@ public class JavaScriptFormatHelper { */ public static String beautify(String jsCode, BeautifyOption option) { InputStream resourceAsStream = IOUtils.readResource("com/fr/design/javascript/beautify/beautify.js"); - ScriptEngine scriptEngine = ScriptFactory.newScriptEngine(); String result = jsCode; + V8 v8 = V8.createV8Runtime(); try { - Reader reader = new InputStreamReader(resourceAsStream); - scriptEngine.eval(reader); - Invocable invocable = (Invocable) scriptEngine; - result = (String) invocable.invokeFunction("js_beautify_global", jsCode, option.toFormatArgument()); - } catch (ScriptException | NoSuchMethodException e) { + v8.executeVoidScript(IOUtils.inputStream2String(resourceAsStream, EncodeConstants.ENCODING_UTF_8)); + V8Array parameters = new V8Array(v8); + parameters.push(jsCode); + V8Object arg = V8ObjectUtils.toV8Object(v8, option.toFormatArgument()); + parameters.push(arg); + result = v8.executeStringFunction("js_beautify_global", parameters); + parameters.release(); + arg.release(); + } catch (UnsupportedEncodingException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); + } finally { + v8.release(true); } return result; } 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/DesignerFrame.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java index 55e07cc1c..e10de8ab4 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java @@ -24,6 +24,7 @@ import com.fr.design.file.MutilTempalteTabPane; import com.fr.design.file.NewTemplatePane; import com.fr.design.file.SaveSomeTemplatePane; import com.fr.design.file.TemplateTreePane; +import com.fr.design.fun.OemProcessor; import com.fr.design.fun.TitlePlaceProcessor; import com.fr.design.fun.impl.AbstractTemplateTreeShortCutProvider; import com.fr.design.gui.ibutton.UIButton; @@ -36,6 +37,7 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.loghandler.LogMessageBar; import com.fr.design.mainframe.toolbar.ToolBarMenuDock; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; +import com.fr.design.mainframe.vcs.common.VcsHelper; import com.fr.design.menu.MenuManager; import com.fr.design.menu.ShortCut; import com.fr.design.utils.gui.GUICoreUtils; @@ -57,6 +59,7 @@ import com.fr.stable.ProductConstants; import com.fr.stable.StringUtils; import com.fr.stable.image4j.codec.ico.ICODecoder; import com.fr.stable.project.ProjectConstants; +import com.fr.start.OemHandler; import com.fr.workspace.WorkContext; import com.fr.workspace.Workspace; import com.fr.workspace.connect.WorkspaceConnectionInfo; @@ -458,8 +461,19 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta try { @SuppressWarnings("unchecked") - List image = ICODecoder.read(DesignerFrame.class - .getResourceAsStream("/com/fr/base/images/oem/logo.ico")); + OemProcessor oemProcessor = OemHandler.findOem(); + List image = null; + if (oemProcessor != null) { + try { + image = oemProcessor.createTitleIcon(); + } catch (Throwable e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + if (image == null) { + image = ICODecoder.read(DesignerFrame.class + .getResourceAsStream("/com/fr/base/images/oem/logo.ico")); + } this.setIconImages(image); } catch (IOException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); @@ -911,6 +925,7 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta } jt.addJTemplateActionListener(this); jt.addTargetModifiedListener(this); + jt.addJTemplateActionListener(VcsHelper.getInstance()); centerTemplateCardPane.showJTemplate(jt); setTitle(); layeredPane.repaint(); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java index 7b9db81ed..b48433c5c 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java @@ -2,6 +2,7 @@ package com.fr.design.mainframe; import com.fr.base.BaseUtils; import com.fr.base.vcs.DesignerMode; +import com.fr.cluster.engine.base.FineClusterConfig; import com.fr.design.DesignModelAdapter; import com.fr.design.DesignerEnvManager; import com.fr.design.ExtraDesignClassManager; @@ -26,6 +27,8 @@ 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.vcs.common.VcsHelper; +import com.fr.design.mainframe.vcs.ui.FileVersionsPanel; import com.fr.design.menu.KeySetUtils; import com.fr.design.menu.ShortCut; import com.fr.design.menu.ToolBarDef; @@ -43,7 +46,9 @@ import com.fr.plugin.manage.PluginFilter; import com.fr.plugin.observer.PluginEvent; import com.fr.plugin.observer.PluginEventListener; import com.fr.stable.CoreConstants; +import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; +import com.fr.stable.project.ProjectConstants; import com.fr.third.org.apache.commons.io.FilenameUtils; import com.fr.workspace.WorkContext; @@ -75,6 +80,9 @@ import static javax.swing.JOptionPane.WARNING_MESSAGE; public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarStateChangeListener, ResponseDataSourceChange { + private static final String FILE = "file"; + private static volatile DesignerFrameFileDealerPane THIS; + static { GeneralContext.listenPluginRunningChanged(new PluginEventListener() { @@ -91,10 +99,6 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt }); } - private static final String FILE = "file"; - - private static volatile DesignerFrameFileDealerPane THIS; - private List otherToolbarStateChangeListeners = new ArrayList<>(); private FileOperations selectedOperation; @@ -111,25 +115,8 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt private DelFileAction delFileAction = new DelFileAction(); + private VcsAction vcsAction = new VcsAction(); - /** - * 刷新 - */ - public void refresh() { - selectedOperation.refresh(); - } - - public static DesignerFrameFileDealerPane getInstance() { - - if (THIS == null) { - synchronized (DesignerFrameFileDealerPane.class) { - if (THIS == null) { - THIS = new DesignerFrameFileDealerPane(); - } - } - } - return THIS; - } private DesignerFrameFileDealerPane() { @@ -158,6 +145,24 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt stateChange(); } + public static DesignerFrameFileDealerPane getInstance() { + + if (THIS == null) { + synchronized (DesignerFrameFileDealerPane.class) { + if (THIS == null) { + THIS = new DesignerFrameFileDealerPane(); + } + } + } + return THIS; + } + + /** + * 刷新 + */ + public void refresh() { + selectedOperation.refresh(); + } public final void setCurrentEditingTemplate(JTemplate jt) { @@ -196,12 +201,31 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt for (ShortCut shortCut : extraShortCuts) { toolbarDef.addShortCut(shortCut); } + addVcsAction(toolbarDef); toolbarDef.updateToolBar(toolBar); resetActionStatus(); refresh(); } + /** + * 添加VcsAction + * @param toolbarDef + */ + private void addVcsAction(ToolBarDef toolbarDef) { + if (VcsHelper.getInstance().needInit()) { + vcsAction = new VcsAction(); + if (FineClusterConfig.getInstance().isCluster()) { + vcsAction.setName(Toolkit.i18nText("Fine-Design_Vcs_NotSupportRemote")); + } else { + vcsAction.setName(Toolkit.i18nText("Fine-Design_Vcs_Title")); + } + toolbarDef.addShortCut(vcsAction); + + } + } + + private void resetActionStatus() { newFolderAction.setEnabled(false); @@ -209,6 +233,7 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt showInExplorerAction.setEnabled(false); renameAction.setEnabled(false); delFileAction.setEnabled(false); + vcsAction.setEnabled(false); this.repaint(); } @@ -245,6 +270,41 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt } } + private boolean isCurrentEditing(String path) { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + String editing = jt.getEditingFILE().getPath(); + return ComparatorUtils.equals(editing, path); + } + + /** + * 按钮状态改变 + */ + @Override + public void stateChange() { + + int selectedPathNum = TemplateTreePane.getInstance().countSelectedPath(); + + // 新建文件夹,重命名操作,在explorer中打开三个操作在选中单个文件夹或者文件时可用,其他情况不可用 + boolean singleSelected = selectedPathNum == 1; + newFolderAction.setEnabled(singleSelected); + renameAction.setEnabled(singleSelected); + showInExplorerAction.setEnabled(singleSelected); + // 删除操作在至少选中一个时可用 + boolean selected = selectedPathNum > 0; + delFileAction.setEnabled(selected); + // 刷新操作始终可用 + refreshTreeAction.setEnabled(true); + //触发vcsAction变化 + vcsAction.fireVcsActionChange(); + + // 其他状态 + otherStateChange(); + } + + public FileOperations getSelectedOperation() { + return selectedOperation; + } + /* * 新建文件夹 */ @@ -273,6 +333,78 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt } + /** + * 版本管理 + */ + private class VcsAction extends UpdateAction { + + public VcsAction() { + this.setSmallIcon(VcsHelper.VCS_LIST_PNG); + } + + @Override + public void actionPerformed(ActionEvent e) { + String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath(); + path = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, path); + + boolean isCurrentEditing = isCurrentEditing(path); + + // 如果模板已经打开了,关掉,避免出现2个同名tab(1个是模板,1个是版本) + closeOpenedTemplate(path, isCurrentEditing); + FileVersionsPanel fileVersionTablePanel = FileVersionsPanel.getInstance(); + fileVersionTablePanel.showFileVersionsPane(); + stateChange(); + + } + + /** + * 版本管理可用状态的监控 + */ + private void fireVcsActionChange() { + if (!DesignerEnvManager.getEnvManager().getVcsConfigManager().isVcsEnable() || VcsHelper.getInstance().isUnSelectedTemplate() || FineClusterConfig.getInstance().isCluster()) { + setEnabled(false); + return; + } + + + + + if (WorkContext.getCurrent() != null) { + if (!WorkContext.getCurrent().isLocal()) { + //当前环境为远程环境时 + FileNode node = TemplateTreePane.getInstance().getTemplateFileTree().getSelectedFileNode(); + if (selectedOperation.getFilePath() != null) { + if (node.getLock() != null && !ComparatorUtils.equals(node.getUserID(), node.getLock())) { + setEnabled(false); + } else { + setEnabled(true); + } + } else { + setEnabled(false); + } + } else { + //当前环境为本地环境时 + setEnabled(selectedOperation.getFilePath() != null); + } + } + } + + private void closeOpenedTemplate(String path, boolean isCurrentEditing) { + for (JTemplate jTemplate : HistoryTemplateListCache.getInstance().getHistoryList()) { + if (ComparatorUtils.equals(jTemplate.getEditingFILE().getPath(), path)) { + if (isCurrentEditing) { + MutilTempalteTabPane.getInstance().setIsCloseCurrent(true); + } + MutilTempalteTabPane.getInstance().closeFormat(jTemplate); + MutilTempalteTabPane.getInstance().closeSpecifiedTemplate(jTemplate); + return; + } + } + } + + + } + /** * 在系统资源管理器中打开 */ @@ -374,35 +506,6 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt } } - /** - * 按钮状态改变 - */ - @Override - public void stateChange() { - - int selectedPathNum = TemplateTreePane.getInstance().countSelectedPath(); - - // 新建文件夹,重命名操作,在explorer中打开三个操作在选中单个文件夹或者文件时可用,其他情况不可用 - boolean singleSelected = selectedPathNum == 1; - newFolderAction.setEnabled(singleSelected); - renameAction.setEnabled(singleSelected); - showInExplorerAction.setEnabled(singleSelected); - - // 删除操作在至少选中一个时可用 - boolean selected = selectedPathNum > 0; - delFileAction.setEnabled(selected); - - // 刷新操作始终可用 - refreshTreeAction.setEnabled(true); - - // 其他状态 - otherStateChange(); - } - - public FileOperations getSelectedOperation() { - return selectedOperation; - } - /** * 重命名对话框 * 支持快捷键Enter,ESC diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java b/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java index a5f4a72ac..8b32d1427 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java @@ -30,18 +30,21 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener // 判断是否切换设计器状态到禁止拷贝剪切 if (jt.getTarget().getAttrMark(DesignBanCopyAttrMark.XML_TAG) != null) { DesignModeContext.switchTo(DesignerMode.BAN_COPY_AND_CUT); - } else { + } else if (!DesignModeContext.isVcsMode() && !DesignModeContext.isAuthorityEditing()){ DesignModeContext.switchTo(DesignerMode.NORMAL); } DesignerFrameFileDealerPane.getInstance().setCurrentEditingTemplate(jt); if (component != null) { + component.onLostFocus(); remove(component); } - add(component = jt, BorderLayout.CENTER); + component = jt; + add(component, BorderLayout.CENTER); validate(); repaint(); revalidate(); component.requestGridFocus(); + component.onGetFocus(); } protected JTemplate getSelectedJTemplate() { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java index 35f7d3391..852130c1e 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java @@ -12,6 +12,7 @@ import com.fr.design.DesignModelAdapter; import com.fr.design.DesignState; import com.fr.design.DesignerEnvManager; import com.fr.design.ExtraDesignClassManager; +import com.fr.design.actions.AllowAuthorityEditAction; import com.fr.design.actions.TableDataSourceAction; import com.fr.design.actions.edit.RedoAction; import com.fr.design.actions.edit.UndoAction; @@ -34,8 +35,9 @@ import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.gui.itree.filetree.TemplateFileTree; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.templateinfo.TemplateInfoCollector; -import com.fr.design.mainframe.templateinfo.TemplateProcessInfo; +import com.fr.design.mainframe.template.info.TemplateInfoCollector; +import com.fr.design.mainframe.template.info.TemplateProcessInfo; +import com.fr.design.mainframe.template.info.TimeConsumeTimer; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.mainframe.toolbar.VcsScene; import com.fr.design.menu.MenuDef; @@ -91,9 +93,7 @@ public abstract class JTemplate> private static short currentIndex = 0;// 此变量用于多次新建模板时,让名字不重复 private DesignModelAdapter designModel; private PreviewProvider previewType; - private long openTime = 0L; // 打开模板的时间点(包括新建模板) - private TemplateInfoCollector tic = TemplateInfoCollector.getInstance(); - private StringBuilder process = new StringBuilder(""); // 制作模板的过程 + private TimeConsumeTimer consumeTimer = new TimeConsumeTimer(); public int resolution = ScreenResolution.getScreenResolution(); public JTemplate() { @@ -101,7 +101,6 @@ public abstract class JTemplate> public JTemplate(T t, String defaultFileName) { this(t, new MemFILE(newTemplateNameByIndex(defaultFileName)), true); - openTime = System.currentTimeMillis(); } public JTemplate(T t, FILE file) { @@ -113,7 +112,7 @@ public abstract class JTemplate> // 判断是否切换设计器状态到禁止拷贝剪切 if (t.getAttrMark(DesignBanCopyAttrMark.XML_TAG) != null) { DesignModeContext.switchTo(com.fr.design.base.mode.DesignerMode.BAN_COPY_AND_CUT); - } else { + } else if (!DesignModeContext.isVcsMode() && !DesignModeContext.isAuthorityEditing()) { DesignModeContext.switchTo(com.fr.design.base.mode.DesignerMode.NORMAL); } this.template = t; @@ -124,12 +123,24 @@ public abstract class JTemplate> this.add(createCenterPane(), BorderLayout.CENTER); this.undoState = createUndoState(); designModel = createDesignModel(); - // 如果不是新建模板,并且在收集列表中 - if (!isNewFile && tic.inList(t)) { - openTime = System.currentTimeMillis(); - process.append(tic.loadProcess(t)); - } + consumeTimer.setEnabled(shouldInitForCollectInfo(isNewFile)); + } + + void onGetFocus() { + consumeTimer.start(); + } + + void onLostFocus() { + consumeTimer.stop(); + } + + private boolean shouldInitForCollectInfo(boolean isNewFile) { + if (isNewFile) { + return true; + } + // 不是新建模板,但是已经在收集列表中 + return TemplateInfoCollector.getInstance().contains(template.getTemplateID()); } // 刷新右侧属性面板 @@ -142,35 +153,28 @@ public abstract class JTemplate> // 为收集模版信息作准备 private void initForCollect() { generateTemplateId(); - if (openTime == 0) { - openTime = System.currentTimeMillis(); - } + consumeTimer.setEnabled(true); + consumeTimer.start(); } private void collectInfo() { // 执行收集操作 - if (openTime == 0) { // 旧模板,不收集数据 + collectInfo(StringUtils.EMPTY); + } + + private void collectInfo(String originID) { // 执行收集操作 + if (!consumeTimer.isEnabled()) { return; } - long saveTime = System.currentTimeMillis(); // 保存模板的时间点 try { - tic.collectInfo(template, this, openTime, saveTime); + int timeConsume = consumeTimer.popTime(); + TemplateInfoCollector.getInstance().collectInfo(template.getTemplateID(), originID, getProcessInfo(), timeConsume); } catch (Throwable th) { // 不管收集过程中出现任何异常,都不应该影响模版保存 } - openTime = saveTime; // 更新 openTime,准备下一次计算 + consumeTimer.start(); // 准备下一次计算 } public abstract TemplateProcessInfo getProcessInfo(); - // 追加过程记录 - public void appendProcess(String s) { - process.append(s); - } - - // 获取过程记录 - public String getProcess() { - return process.toString(); - } - public U getUndoState() { return undoState; } @@ -621,15 +625,20 @@ public abstract class JTemplate> } } + // 保存新模板时会进入此方法(新建模板直接保存,或者另存为) protected boolean saveNewFile(FILE editingFILE, String oldName) { + String originID = StringUtils.EMPTY; + if (StringUtils.isNotEmpty(this.template.getTemplateID())) { + originID = this.template.getTemplateID(); + } // 在保存之前,初始化 templateID - initForCollect(); // 如果保存新模板(新建模板直接保存,或者另存为),则添加 templateID + initForCollect(); this.editingFILE = editingFILE; boolean result = this.saveFile(); if (result) { DesignerFrameFileDealerPane.getInstance().refresh(); - collectInfo(); + collectInfo(originID); } //更换最近打开 DesignerEnvManager.getEnvManager().replaceRecentOpenedFilePath(oldName, this.getPath()); @@ -678,7 +687,6 @@ public abstract class JTemplate> this.saved = true; this.authoritySaved = true; DesignerContext.getDesignerFrame().setTitle(); - this.fireJTemplateSaved(); return true; } @@ -819,7 +827,7 @@ public abstract class JTemplate> // Process the listeners last to first, notifying // those that are interested in this event - for (int i = listeners.length - 2; i >= 0; i -= 2) { + for (int i = listeners.length - 1; i >= 0; i -= 1) { if (listeners[i] == JTemplateActionListener.class) { ((JTemplateActionListener) listeners[i + 1]).templateSaved(this); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java index cea108892..2c1818614 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java @@ -7,7 +7,7 @@ import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.gui.frpane.HyperlinkGroupPane; import com.fr.design.gui.frpane.HyperlinkGroupPaneActionProvider; import com.fr.design.gui.imenu.UIMenuItem; -import com.fr.design.mainframe.templateinfo.TemplateProcessInfo; +import com.fr.design.mainframe.template.info.TemplateProcessInfo; import com.fr.design.menu.ShortCut; import com.fr.design.menu.ToolBarDef; import com.fr.file.FILE; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/DownMenuStyleDefinePane.java b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/DownMenuStyleDefinePane.java index ff76e5fed..c5e19e881 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/DownMenuStyleDefinePane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/DownMenuStyleDefinePane.java @@ -2,7 +2,6 @@ package com.fr.design.mainframe.mobile.ui; import com.fr.base.GraphHelper; import com.fr.base.Icon; -import com.fr.base.IconManager; import com.fr.design.constants.LayoutConstants; import com.fr.design.designer.IntervalConstants; import com.fr.design.gui.ilable.UILabel; @@ -11,6 +10,7 @@ import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.widget.UITitleSplitLine; import com.fr.design.mainframe.widget.preview.MobileTemplatePreviewPane; import com.fr.form.ui.CardSwitchButton; +import com.fr.form.ui.WidgetInfoConfig; import com.fr.form.ui.container.cardlayout.WCardTagLayout; import com.fr.general.FRFont; import com.fr.general.cardtag.mobile.DownMenuStyle; @@ -40,6 +40,7 @@ public class DownMenuStyleDefinePane extends StyleDefinePaneWithSelectConf { super(tagLayout); } + @Override protected void createExtraConfPane(JPanel centerPane) { JPanel panel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 0); panel.setBorder(BorderFactory.createEmptyBorder(0, 20, 5, 20)); @@ -134,12 +135,13 @@ public class DownMenuStyleDefinePane extends StyleDefinePaneWithSelectConf { private static final int GAP = 6; private static final String PAINT_ICON = "fund_white"; private static final String ICON_PATH = "/com/fr/web/images/fund_white.png"; - private LineDescription splitLine; + private transient LineDescription splitLine; public DownMenuStylePreviewPane() { this.setBackground(Color.decode("#3888EE")); } + @Override public void repaint() { super.repaint(); } @@ -172,7 +174,7 @@ public class DownMenuStyleDefinePane extends StyleDefinePaneWithSelectConf { g2d.setColor(oldColor); } Icon icon = new Icon(PAINT_ICON, ICON_PATH); - g2d.drawImage(IconManager.getIconManager().getDefaultIconImage(icon), (eachWidth - ICON_OFFSET) / 2, (panelHeight - ICON_OFFSET - GAP - fontHeight) / 2, null); + g2d.drawImage(WidgetInfoConfig.getInstance().getIconManager().getDefaultIconImage(icon), (eachWidth - ICON_OFFSET) / 2, (panelHeight - ICON_OFFSET - GAP - fontHeight) / 2, null); g2d.drawString(displayName, (eachWidth - width) / 2, (panelHeight + ICON_OFFSET + GAP - fontHeight) / 2 + ascent); Stroke oldStroke = g2d.getStroke(); if (splitLine.getLineStyle() != 0) { @@ -187,6 +189,7 @@ public class DownMenuStyleDefinePane extends StyleDefinePaneWithSelectConf { } + @Override public void populateConfig(MobileTemplateStyle templateStyle) { super.populateConfig(templateStyle); this.splitLine = ((DownMenuStyle) templateStyle).getSplitLine(); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/template/info/DesignerOpenHistory.java b/designer-base/src/main/java/com/fr/design/mainframe/template/info/DesignerOpenHistory.java new file mode 100644 index 000000000..560431f1b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/template/info/DesignerOpenHistory.java @@ -0,0 +1,129 @@ +package com.fr.design.mainframe.template.info; + +import com.fr.general.ComparatorUtils; +import com.fr.log.FineLoggerFactory; +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; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +/** + * 管理打开设计器的日期记录 + * Created by plough on 2019/4/19. + */ +class DesignerOpenHistory implements XMLReadable, XMLWriter { + static final String XML_TAG = "DesignerOpenHistory"; + private static DesignerOpenHistory singleton; + private static final String SPLITTER = ","; + private static final int LENGTH = 3; // 保留最近 3 次的记录 + // 最近的日期是 history[0],最早的日期是 history[LENGTH-1] + private String[] history = new String[LENGTH]; + + private DesignerOpenHistory() { + for (int i = 0; i < LENGTH; i++) { + history[i] = StringUtils.EMPTY; + } + } + + static DesignerOpenHistory getInstance() { + if (singleton == null) { + singleton = new DesignerOpenHistory(); + } + return singleton; + } + + void update() { + String today = getToday(); + if (ComparatorUtils.equals(history[0], today)) { + return; + } + shiftByOne(); + history[0] = today; + } + + /** + * 设计器在 dayCount 时间内启动超过 X 次(目前定的 X = 3) + */ + boolean isOpenEnoughTimesInPeriod(int dayCount) { + boolean enoughTimes = StringUtils.isNotEmpty(history[LENGTH - 1]); + if (!enoughTimes) { + return false; + } + return getHistorySpanDayCount() < dayCount; + } + + + /** + * 获取历史记录中囊括的日子数。即最早的历史记录 history[LENGTH - 1],到最晚的记录 history[0] 之间的时间跨度 + */ + int getHistorySpanDayCount() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + try { + Date earliestDate = sdf.parse(getEarliestDate()); + Date latestDate = sdf.parse(history[0]); + long diffInMillies = latestDate.getTime() - earliestDate.getTime(); + return (int)TimeUnit.DAYS.convert(diffInMillies,TimeUnit.MILLISECONDS) + 1; + } catch (ParseException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return 1; + } + + /** + * 今天是否已经打开过设计器 + */ + boolean hasOpenedToday() { + String today = getToday(); + return ComparatorUtils.equals(today, history[0]); + } + + private String getEarliestDate() { + for (int i = LENGTH - 1; i >= 0; i--) { + if (StringUtils.isNotEmpty(history[i])) { + return history[i]; + } + } + throw new AssertionError("Designer open history is empty!"); + } + + private void shiftByOne() { + for (int i = LENGTH - 1; i > 0; i--) { + history[i] = history[i-1]; + } + } + + private String getToday() { + return new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); + } + + @Override + public String toString() { + return StringUtils.join(SPLITTER, history); + } + + private void parseString(String s) { + String[] arr = s.split(SPLITTER); + System.arraycopy(arr, 0, history, 0, arr.length); + } + + @Override + public void readXML(XMLableReader reader) { + if (XML_TAG.equals(reader.getTagName())) { + parseString(reader.getElementValue()); + } + } + + @Override + public void writeXML(XMLPrintWriter writer) { + writer.startTAG(XML_TAG); + writer.textNode(toString()); + writer.end(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/template/info/SendHelper.java b/designer-base/src/main/java/com/fr/design/mainframe/template/info/SendHelper.java new file mode 100644 index 000000000..db489fb3c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/template/info/SendHelper.java @@ -0,0 +1,47 @@ +package com.fr.design.mainframe.template.info; + +import com.fr.design.mainframe.SiteCenterToken; +import com.fr.general.CloudCenter; +import com.fr.general.ComparatorUtils; +import com.fr.general.http.HttpToolbox; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * 负责向服务器发送信息 + * Created by plough on 2019/4/18. + */ +class SendHelper { + private static final String CONSUMING_URL = CloudCenter.getInstance().acquireUrlByKind("tempinfo.consuming") + "/single"; + private static final String PROCESS_URL = CloudCenter.getInstance().acquireUrlByKind("tempinfo.process") + "/single"; + + private static boolean sendConsumingInfo(String content) { + return sendSingleTemplateInfo(CONSUMING_URL, content); + } + + private static boolean sendProcessInfo(String content) { + return sendSingleTemplateInfo(PROCESS_URL, content); + } + + static boolean sendTemplateInfo(TemplateInfo templateInfo) { + return SendHelper.sendConsumingInfo(templateInfo.getConsumingMapJsonString()) && SendHelper.sendProcessInfo(templateInfo.getProcessMapJsonString()); + } + + private static boolean sendSingleTemplateInfo(String url, String content) { + Map para = new HashMap<>(); + para.put("token", SiteCenterToken.generateToken()); + para.put("content", content); + + try { + String res = HttpToolbox.post(url, para); + return ComparatorUtils.equals(new JSONObject(res).get("status"), "success"); + } catch (Throwable e) { + // 客户不需要关心,错误等级为 debug 就行了 + FineLoggerFactory.getLogger().debug(e.getMessage(), e); + } + return false; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfo.java b/designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfo.java new file mode 100644 index 000000000..900210bd0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfo.java @@ -0,0 +1,260 @@ +package com.fr.design.mainframe.template.info; + +import com.fr.config.MarketConfig; +import com.fr.design.DesignerEnvManager; +import com.fr.general.GeneralUtils; +import com.fr.json.JSONObject; +import com.fr.stable.ProductConstants; +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; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; + +/** + * 对应一张模版的记录 + * Created by plough on 2019/4/18. + */ +class TemplateInfo implements XMLReadable, XMLWriter { + static final String XML_TAG = "TemplateInfo"; + + private static final String XML_PROCESS_MAP = "processMap"; + private static final String XML_CONSUMING_MAP = "consumingMap"; + private static final String ATTR_DAY_COUNT = "day_count"; + private static final String ATTR_TEMPLATE_ID = "templateID"; + private static final String ATTR_ORIGIN_ID = "originID"; + private static final String ATTR_PROCESS = "process"; + private static final String ATTR_FLOAT_COUNT = "float_count"; + private static final String ATTR_WIDGET_COUNT = "widget_count"; + private static final String ATTR_CELL_COUNT = "cell_count"; + private static final String ATTR_BLOCK_COUNT = "block_count"; + private static final String ATTR_REPORT_TYPE = "report_type"; + private static final String ATTR_ACTIVITYKEY = "activitykey"; + private static final String ATTR_JAR_TIME = "jar_time"; + private static final String ATTR_CREATE_TIME = "create_time"; + private static final String ATTR_UUID = "uuid"; + private static final String ATTR_TIME_CONSUME = "time_consume"; + private static final String ATTR_ORIGIN_TIME = "originTime"; + private static final String ATTR_VERSION = "version"; + private static final String ATTR_USERNAME = "username"; + + private static final int VALID_CELL_COUNT = 5; // 有效报表模板的格子数 + private static final int VALID_WIDGET_COUNT = 5; // 有效报表模板的控件数 + private static final int COMPLETE_DAY_COUNT = 15; // 判断模板是否完成的天数 + + private int idleDayCount; // 到现在为止,模版闲置(上次保存后没有再编辑过)的天数 + private String templateID = StringUtils.EMPTY; + private String originID = StringUtils.EMPTY; + // todo: processMap 和 consumingMap 还可以再拆解为小类,以后继续重构 + private Map processMap = new HashMap<>(); + private Map consumingMap = new HashMap<>(); + + private TemplateInfo() { + } + + private TemplateInfo(String templateID, String originID) { + this.templateID = templateID; + this.originID = originID; + } + + static TemplateInfo newInstanceByRead(XMLableReader reader) { + TemplateInfo templateInfo = new TemplateInfo(); + reader.readXMLObject(templateInfo); + return templateInfo; + } + + static TemplateInfo newInstance(String templateID) { + return newInstance(templateID, StringUtils.EMPTY, 0); + } + + static TemplateInfo newInstance(String templateID, String originID, int originTime) { + HashMap consumingMap = new HashMap<>(); + + String username = MarketConfig.getInstance().getBbsUsername(); + String uuid = DesignerEnvManager.getEnvManager().getUUID(); + String activitykey = DesignerEnvManager.getEnvManager().getActivationKey(); + String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(Calendar.getInstance().getTime()); + String jarTime = GeneralUtils.readBuildNO(); + String version = ProductConstants.VERSION; + consumingMap.put(ATTR_USERNAME, username); + consumingMap.put(ATTR_UUID, uuid); + consumingMap.put(ATTR_ACTIVITYKEY, activitykey); + consumingMap.put(ATTR_TEMPLATE_ID, templateID); + consumingMap.put(ATTR_ORIGIN_ID, originID); + consumingMap.put(ATTR_CREATE_TIME, createTime); + consumingMap.put(ATTR_TIME_CONSUME, originTime); // timeConsume 在原来模版的基础上累加 + consumingMap.put(ATTR_ORIGIN_TIME, originTime); + consumingMap.put(ATTR_JAR_TIME, jarTime); + consumingMap.put(ATTR_VERSION, version); + + TemplateInfo templateInfo = new TemplateInfo(templateID, originID); + templateInfo.consumingMap = consumingMap; + + return templateInfo; + } + + String getTemplateID() { + return templateID; + } + + String getOriginID() { + return originID; + } + + int getTimeConsume() { + return (int)consumingMap.get(ATTR_TIME_CONSUME); + } + + public void writeXML(XMLPrintWriter writer) { + writer.startTAG(XML_TAG); + if (StringUtils.isNotEmpty(templateID)) { + writer.attr(ATTR_TEMPLATE_ID, this.templateID); + } + if (StringUtils.isNotEmpty(originID)) { + writer.attr(ATTR_ORIGIN_ID, this.originID); + } + if (idleDayCount >= 0) { + writer.attr(ATTR_DAY_COUNT, this.idleDayCount); + } + writeProcessMap(writer); + writeConsumingMap(writer); + + writer.end(); + } + + private void writeProcessMap(XMLPrintWriter writer) { + writer.startTAG(XML_PROCESS_MAP); + writer.attr(ATTR_PROCESS, (String) processMap.get(ATTR_PROCESS)); + writer.attr(ATTR_FLOAT_COUNT, (int) processMap.get(ATTR_FLOAT_COUNT)); + writer.attr(ATTR_WIDGET_COUNT, (int) processMap.get(ATTR_WIDGET_COUNT)); + writer.attr(ATTR_CELL_COUNT, (int) processMap.get(ATTR_CELL_COUNT)); + writer.attr(ATTR_BLOCK_COUNT, (int) processMap.get(ATTR_BLOCK_COUNT)); + writer.attr(ATTR_REPORT_TYPE, (int) processMap.get(ATTR_REPORT_TYPE)); + writer.end(); + } + + private void writeConsumingMap(XMLPrintWriter writer) { + writer.startTAG(XML_CONSUMING_MAP); + writer.attr(ATTR_ACTIVITYKEY, (String) consumingMap.get(ATTR_ACTIVITYKEY)); + writer.attr(ATTR_JAR_TIME, (String) consumingMap.get(ATTR_JAR_TIME)); + writer.attr(ATTR_CREATE_TIME, (String) consumingMap.get(ATTR_CREATE_TIME)); + writer.attr(ATTR_UUID, (String) consumingMap.get(ATTR_UUID)); + writer.attr(ATTR_TIME_CONSUME, (int)consumingMap.get(ATTR_TIME_CONSUME)); + writer.attr(ATTR_ORIGIN_TIME, (int)consumingMap.get(ATTR_ORIGIN_TIME)); + writer.attr(ATTR_VERSION, (String) consumingMap.get(ATTR_VERSION)); + writer.attr(ATTR_USERNAME, (String) consumingMap.get(ATTR_USERNAME)); + writer.end(); + } + + public void readXML(XMLableReader reader) { + if (!reader.isChildNode()) { + idleDayCount = reader.getAttrAsInt(ATTR_DAY_COUNT, 0); + templateID = reader.getAttrAsString(ATTR_TEMPLATE_ID, StringUtils.EMPTY); + originID = reader.getAttrAsString(ATTR_ORIGIN_ID, StringUtils.EMPTY); + } else { + try { + String name = reader.getTagName(); + if (XML_PROCESS_MAP.equals(name)) { + processMap.put(ATTR_PROCESS, reader.getAttrAsString(ATTR_PROCESS, StringUtils.EMPTY)); + processMap.put(ATTR_FLOAT_COUNT, reader.getAttrAsInt(ATTR_FLOAT_COUNT, 0)); + processMap.put(ATTR_WIDGET_COUNT, reader.getAttrAsInt(ATTR_WIDGET_COUNT, 0)); + processMap.put(ATTR_CELL_COUNT, reader.getAttrAsInt(ATTR_CELL_COUNT, 0)); + processMap.put(ATTR_BLOCK_COUNT, reader.getAttrAsInt(ATTR_BLOCK_COUNT, 0)); + processMap.put(ATTR_REPORT_TYPE, reader.getAttrAsInt(ATTR_REPORT_TYPE, 0)); + processMap.put(ATTR_TEMPLATE_ID, templateID); + } else if (XML_CONSUMING_MAP.equals(name)) { + consumingMap.put(ATTR_ACTIVITYKEY, reader.getAttrAsString(ATTR_ACTIVITYKEY, StringUtils.EMPTY)); + consumingMap.put(ATTR_JAR_TIME, reader.getAttrAsString(ATTR_JAR_TIME, StringUtils.EMPTY)); + consumingMap.put(ATTR_CREATE_TIME, reader.getAttrAsString(ATTR_CREATE_TIME, StringUtils.EMPTY)); + consumingMap.put(ATTR_TEMPLATE_ID, templateID); + consumingMap.put(ATTR_ORIGIN_ID, originID); + consumingMap.put(ATTR_UUID, reader.getAttrAsString(ATTR_UUID, StringUtils.EMPTY)); + consumingMap.put(ATTR_TIME_CONSUME, reader.getAttrAsInt(ATTR_TIME_CONSUME, 0)); + consumingMap.put(ATTR_ORIGIN_TIME, reader.getAttrAsInt(ATTR_ORIGIN_TIME, 0)); + consumingMap.put(ATTR_VERSION, reader.getAttrAsString(ATTR_VERSION, "8.0")); + consumingMap.put(ATTR_USERNAME, reader.getAttrAsString(ATTR_USERNAME, StringUtils.EMPTY)); + } + } catch (Exception ex) { + // 什么也不做,使用默认值 + } + } + } + + boolean isTestTemplate() { + if (!isComplete()) { + return false; + } + + int reportType = (int) processMap.get(ATTR_REPORT_TYPE); + int cellCount = (int) processMap.get(ATTR_CELL_COUNT); + int floatCount = (int) processMap.get(ATTR_FLOAT_COUNT); + int blockCount = (int) processMap.get(ATTR_BLOCK_COUNT); + int widgetCount = (int) processMap.get(ATTR_WIDGET_COUNT); + boolean isTestTemplate; + if (reportType == 0) { // 普通报表 + isTestTemplate = cellCount <= VALID_CELL_COUNT && floatCount <= 1 && widgetCount <= VALID_WIDGET_COUNT; + } else if (reportType == 1) { // 聚合报表 + isTestTemplate = blockCount <= 1 && widgetCount <= VALID_WIDGET_COUNT; + } else { // 表单(reportType == 2) + isTestTemplate = widgetCount <= 1; + } + return isTestTemplate; + } + + boolean isComplete() { + // 条件 1. 超过15天未编辑 + // 条件 2. 设计器在这段未编辑的时间内启动超过 X 次(目前定的 X = 3)。即"设计器最近 X 次启动的时间跨度" < "未编辑时间"; + + return idleDayCount > COMPLETE_DAY_COUNT + && DesignerOpenHistory.getInstance().isOpenEnoughTimesInPeriod(idleDayCount); + } + + String getConsumingMapJsonString() { + return new JSONObject(consumingMap).toString(); + } + + String getProcessMapJsonString() { + return new JSONObject(processMap).toString(); + } + + boolean isReadyForSend() { + return isComplete() && !isTestTemplate(); + } + + void addTimeConsume(int timeConsume) { + timeConsume += (int)consumingMap.get(ATTR_TIME_CONSUME); // 加上之前的累计编辑时间 + consumingMap.put(ATTR_TIME_CONSUME, timeConsume); + } + + void updateProcessMap(TemplateProcessInfo processInfo) { + HashMap processMap = new HashMap<>(); + + // 暂不支持模版制作过程的收集 + processMap.put(ATTR_PROCESS, StringUtils.EMPTY); + + processMap.put(ATTR_REPORT_TYPE, processInfo.getReportType()); + processMap.put(ATTR_CELL_COUNT, processInfo.getCellCount()); + processMap.put(ATTR_FLOAT_COUNT, processInfo.getFloatCount()); + processMap.put(ATTR_BLOCK_COUNT, processInfo.getBlockCount()); + processMap.put(ATTR_WIDGET_COUNT, processInfo.getWidgetCount()); + + this.processMap = processMap; + } + + void resetIdleDayCount() { + this.idleDayCount = 0; + } + + void addIdleDayCountByOne() { + this.idleDayCount += 1; + } + + int getIdleDayCount() { + return this.idleDayCount; + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfoCollector.java b/designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfoCollector.java new file mode 100644 index 000000000..330b9304a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfoCollector.java @@ -0,0 +1,252 @@ +package com.fr.design.mainframe.template.info; + +import com.fr.base.FRContext; +import com.fr.base.io.XMLReadHelper; +import com.fr.design.DesignerEnvManager; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ProductConstants; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.xml.XMLPrintWriter; +import com.fr.stable.xml.XMLReadable; +import com.fr.stable.xml.XMLTools; +import com.fr.stable.xml.XMLWriter; +import com.fr.stable.xml.XMLableReader; +import com.fr.third.javax.xml.stream.XMLStreamException; +import com.fr.third.org.apache.commons.io.FileUtils; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 做模板的过程和耗时收集,辅助类 + * Created by plough on 2017/2/21. + */ +public class TemplateInfoCollector implements XMLReadable, XMLWriter { + private static final String XML_TAG = "TplInfo"; + private static final String XML_TEMPLATE_INFO_LIST = "TemplateInfoList"; + private static final String XML_FILE_NAME = "tpl.info"; + private static TemplateInfoCollector instance; + private Map templateInfoMap; + private DesignerOpenHistory designerOpenHistory; + + private TemplateInfoCollector() { + init(); + } + + private void init() { + templateInfoMap = new HashMap<>(); + designerOpenHistory = DesignerOpenHistory.getInstance(); + + loadFromFile(); + } + + public static TemplateInfoCollector getInstance() { + if (instance == null) { + instance = new TemplateInfoCollector(); + } + return instance; + } + + /** + * 根据模板ID是否在收集列表中,判断是否需要收集当前模板的信息 + */ + public boolean contains(String templateID) { + return StringUtils.isNotEmpty(templateID) && templateInfoMap.containsKey(templateID); + } + + /** + * 收集模板信息。如果之前没有记录,则新增;如果已有记录,则更新。 + * 同时将最新数据保存到文件中。 + * @param templateID 模版id + * @param originID 模版的原始id,仅对另存为的模版有效,对于非另存为的模版,值总是为空 + * @param processInfo 包含模版的一些基本信息(如模版类型、包含控件数量等) + * @param timeConsume 本次制作耗时,单位为 s + */ + public void collectInfo(String templateID, String originID, TemplateProcessInfo processInfo, int timeConsume) { + if (!shouldCollectInfo()) { + return; + } + + TemplateInfo templateInfo; + if (this.contains(templateID)) { + templateInfo = templateInfoMap.get(templateID); + } else { + int originTime = this.contains(originID) ? templateInfoMap.get(originID).getTimeConsume() : 0; + templateInfo = TemplateInfo.newInstance(templateID, originID, originTime); + templateInfoMap.put(templateID, templateInfo); + } + + // 收集制作耗时 + templateInfo.addTimeConsume(timeConsume); + // 收集模版基本信息 + templateInfo.updateProcessMap(processInfo); + // 刷新闲置日计数器 + templateInfo.resetIdleDayCount(); + + // 每次更新之后,都同步到暂存文件中 + saveInfo(); + } + + /** + * 发送本地模板信息到服务器,并清空已发送模版的本地记录 + */ + public void sendTemplateInfo() { + // 每次启动设计器后,都会执行这个函数(被 InformationCollector 的 collectStartTime 调用) + addIdleDayCount(); + + removeTestTemplates(); + + List removeLaterList = new ArrayList<>(); + + for (String key : templateInfoMap.keySet()) { + TemplateInfo templateInfo = templateInfoMap.get(key); + if (templateInfo.isReadyForSend()) { + if (SendHelper.sendTemplateInfo(templateInfo)) { + removeLaterList.add(key); + } + } + } + + // 清空记录 + for (String key : removeLaterList) { + removeFromTemplateInfoList(key); + } + + saveInfo(); + } + + /** + * 获取缓存文件存放路径 + */ + private static File getInfoFile() { + return new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), XML_FILE_NAME)); + } + + void loadFromFile() { + if (!getInfoFile().exists()) { + return; + } + + XMLableReader reader = null; + try (InputStream in = new FileInputStream(getInfoFile())) { + // XMLableReader 还是应该考虑实现 Closable 接口的,这样就能使用 try-with 语句了 + reader = XMLReadHelper.createXMLableReader(in, XMLPrintWriter.XML_ENCODER); + reader.readXMLObject(this); + } catch (FileNotFoundException e) { + // do nothing + } catch (XMLStreamException | IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (XMLStreamException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + } + + TemplateInfo getOrCreateTemplateInfoByID(String templateID) { + if (templateInfoMap.containsKey(templateID)) { + return templateInfoMap.get(templateID); + } + TemplateInfo templateInfo = TemplateInfo.newInstance(templateID); + templateInfoMap.put(templateID, templateInfo); + return templateInfo; + } + + private boolean shouldCollectInfo() { + return DesignerEnvManager.getEnvManager().isJoinProductImprove() && FRContext.isChineseEnv(); + } + + /** + * 将包含所有信息的对象保存到文件 + */ + private void saveInfo() { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + XMLTools.writeOutputStreamXML(this, out); + out.flush(); + out.close(); + String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8); + FileUtils.writeStringToFile(getInfoFile(), fileContent, StandardCharsets.UTF_8); + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage()); + } + } + + /** + * 更新 day_count:打开设计器却未编辑模板的连续日子 + */ + private void addIdleDayCount() { + // 判断今天是否第一次打开设计器,为了防止同一天内,多次 addIdleDayCount + if (designerOpenHistory.hasOpenedToday()) { + return; + } + for (TemplateInfo templateInfo : templateInfoMap.values()) { + templateInfo.addIdleDayCountByOne(); + } + designerOpenHistory.update(); + } + + // 删除所有已完成的测试模版 + private void removeTestTemplates() { + ArrayList testTemplateKeys = new ArrayList<>(); // 保存测试模板的key + for (String key : templateInfoMap.keySet()) { + if (templateInfoMap.get(key).isTestTemplate()) { + testTemplateKeys.add(key); + } + } + // 删除测试模板 + for (String key : testTemplateKeys) { + removeFromTemplateInfoList(key); + } + } + + private void removeFromTemplateInfoList(String key) { + templateInfoMap.remove(key); + } + + @Override + public void readXML(XMLableReader reader) { + if (reader.isChildNode()) { + try { + String name = reader.getTagName(); + if (DesignerOpenHistory.XML_TAG.equals(name)) { + reader.readXMLObject(designerOpenHistory); + } else if (TemplateInfo.XML_TAG.equals(name)) { + TemplateInfo templateInfo = TemplateInfo.newInstanceByRead(reader); + templateInfoMap.put(templateInfo.getTemplateID(), templateInfo); + } + } catch (Exception ex) { + // 什么也不做,使用默认值 + } + } + } + + @Override + public void writeXML(XMLPrintWriter writer) { + writer.startTAG(XML_TAG); + + designerOpenHistory.writeXML(writer); + + writer.startTAG(XML_TEMPLATE_INFO_LIST); + for (TemplateInfo templateInfo : templateInfoMap.values()) { + templateInfo.writeXML(writer); + } + writer.end(); + + writer.end(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/templateinfo/TemplateProcessInfo.java b/designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateProcessInfo.java similarity index 74% rename from designer-base/src/main/java/com/fr/design/mainframe/templateinfo/TemplateProcessInfo.java rename to designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateProcessInfo.java index 0307e4fd6..427d48c73 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/templateinfo/TemplateProcessInfo.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateProcessInfo.java @@ -1,10 +1,14 @@ -package com.fr.design.mainframe.templateinfo; +package com.fr.design.mainframe.template.info; import com.fr.base.io.BaseBook; /** * Created by plough on 2017/3/17. */ +// todo: 重构 +// 1. 命名不好,表意不清晰。 +// 2. 逻辑混乱,到底是一个 Info 类,还是一个 InfoCollector 类? +// 3. 耦合太强,用组合替代继承 public abstract class TemplateProcessInfo { protected T template; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/template/info/TimeConsumeTimer.java b/designer-base/src/main/java/com/fr/design/mainframe/template/info/TimeConsumeTimer.java new file mode 100644 index 000000000..527341411 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/template/info/TimeConsumeTimer.java @@ -0,0 +1,69 @@ +package com.fr.design.mainframe.template.info; + +/** + * Created by plough on 2019/4/19. + */ +public class TimeConsumeTimer { + private static final int ONE_THOUSAND = 1000; + private enum State { + RUNNING, STOPPED + } + private int timeConsume; // 单位 s + private long startMS; // 单位 ms + private long stopMS; + private State state; + private boolean enabled; + + public TimeConsumeTimer() { + reset(); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void start() { + if (!isEnabled() || isRunning()) { + return; + } + startMS = System.currentTimeMillis(); + state = State.RUNNING; + } + + public void stop() { + if (!isEnabled() || !isRunning()) { + return; + } + stopMS = System.currentTimeMillis(); + + timeConsume += ((stopMS - startMS) / ONE_THOUSAND); + startMS = 0; + stopMS = 0; + state = State.STOPPED; + } + + public int popTime() { + if (!isEnabled()) { + return 0; + } + stop(); + int result = timeConsume; + reset(); + return result; + } + + private boolean isRunning() { + return state == State.RUNNING; + } + + private void reset() { + timeConsume = 0; + startMS = 0; + stopMS = 0; + state = State.STOPPED; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/templateinfo/TemplateInfoCollector.java b/designer-base/src/main/java/com/fr/design/mainframe/templateinfo/TemplateInfoCollector.java deleted file mode 100644 index 57ff2ce8a..000000000 --- a/designer-base/src/main/java/com/fr/design/mainframe/templateinfo/TemplateInfoCollector.java +++ /dev/null @@ -1,550 +0,0 @@ -package com.fr.design.mainframe.templateinfo; - -import com.fr.base.FRContext; -import com.fr.base.io.BaseBook; -import com.fr.config.MarketConfig; -import com.fr.design.DesignerEnvManager; -import com.fr.design.mainframe.DesignerContext; -import com.fr.design.mainframe.JTemplate; -import com.fr.design.mainframe.SiteCenterToken; -import com.fr.general.CloudCenter; -import com.fr.general.ComparatorUtils; -import com.fr.general.GeneralUtils; -import com.fr.general.IOUtils; -import com.fr.general.http.HttpClient; -import com.fr.json.JSONObject; -import com.fr.log.FineLoggerFactory; -import com.fr.stable.EncodeConstants; -import com.fr.stable.ProductConstants; -import com.fr.stable.StableUtils; -import com.fr.stable.StringUtils; -import com.fr.stable.xml.XMLPrintWriter; -import com.fr.stable.xml.XMLReadable; -import com.fr.stable.xml.XMLTools; -import com.fr.stable.xml.XMLWriter; -import com.fr.stable.xml.XMLableReader; -import com.fr.third.javax.xml.stream.XMLStreamException; -import com.fr.workspace.WorkContext; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.ObjectInputStream; -import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -/** - * 做模板的过程和耗时收集,辅助类 - * Created by plough on 2017/2/21. - */ -public class TemplateInfoCollector implements Serializable, XMLReadable, XMLWriter { - static final long serialVersionUID = 2007L; - private static final String FILE_NAME = "tpl.info"; - private static final String OBJECT_FILE_NAME = "tplInfo.ser"; - private static final int VALID_CELL_COUNT = 5; // 有效报表模板的格子数 - private static final int VALID_WIDGET_COUNT = 5; // 有效报表模板的控件数 - private static final int COMPLETE_DAY_COUNT = 15; // 判断模板是否完成的天数 - private static final int ONE_THOUSAND = 1000; - private static final String XML_DESIGNER_OPEN_DATE = "DesignerOpenDate"; - private static final String XML_TEMPLATE_INFO_LIST = "TemplateInfoList"; - private static final String XML_TEMPLATE_INFO = "TemplateInfo"; - private static final String XML_PROCESS_MAP = "processMap"; - private static final String XML_CONSUMING_MAP = "consumingMap"; - private static final String ATTR_DAY_COUNT = "day_count"; - private static final String ATTR_TEMPLATE_ID = "templateID"; - private static final String ATTR_PROCESS = "process"; - private static final String ATTR_FLOAT_COUNT = "float_count"; - private static final String ATTR_WIDGET_COUNT = "widget_count"; - private static final String ATTR_CELL_COUNT = "cell_count"; - private static final String ATTR_BLOCK_COUNT = "block_count"; - private static final String ATTR_REPORT_TYPE = "report_type"; - private static final String ATTR_ACTIVITYKEY = "activitykey"; - private static final String ATTR_JAR_TIME = "jar_time"; - private static final String ATTR_CREATE_TIME = "create_time"; - private static final String ATTR_UUID = "uuid"; - private static final String ATTR_TIME_CONSUME = "time_consume"; - private static final String ATTR_VERSION = "version"; - private static final String ATTR_USERNAME = "username"; - private static final String JSON_CONSUMING_MAP = "jsonConsumingMap"; - private static final String JSON_PROCESS_MAP = "jsonProcessMap"; - private static TemplateInfoCollector instance; - private Map> templateInfoList; - private String designerOpenDate; //设计器最近一次打开日期 - - - @SuppressWarnings("unchecked") - private TemplateInfoCollector() { - templateInfoList = new HashMap<>(); - setDesignerOpenDate(); - } - - /** - * 获取缓存文件存放路径 - */ - private static File getInfoFile() { - return new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), FILE_NAME)); - } - - private static File getObjectInfoFile() { - return new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), OBJECT_FILE_NAME)); - } - - public static TemplateInfoCollector getInstance() { - if (instance == null) { - instance = new TemplateInfoCollector(); - readXMLFile(instance, getInfoFile()); - // 兼容过渡。如果没有新文件,则从老文件读取数据。以后都是读写新的 xml 文件 - if (!getInfoFile().exists() && getObjectInfoFile().exists()) { - try { - ObjectInputStream is = new ObjectInputStream(new FileInputStream(getObjectInfoFile())); - instance = (TemplateInfoCollector) is.readObject(); - } catch (Exception ex) { - // 什么也不做,instance 使用新值 - } - } - } - return instance; - } - - private static void readXMLFile(XMLReadable xmlReadable, File xmlFile) { - if (xmlFile == null || !xmlFile.exists()) { - return; - } - String charset = EncodeConstants.ENCODING_UTF_8; - try { - String fileContent = getFileContent(xmlFile); - InputStream xmlInputStream = new ByteArrayInputStream(fileContent.getBytes(charset)); - InputStreamReader inputStreamReader = new InputStreamReader(xmlInputStream, charset); - XMLableReader xmlReader = XMLableReader.createXMLableReader(inputStreamReader); - - if (xmlReader != null) { - xmlReader.readXMLObject(xmlReadable); - } - xmlInputStream.close(); - } catch (FileNotFoundException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } catch (IOException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } catch (XMLStreamException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - - } - - private static String getFileContent(File xmlFile) throws FileNotFoundException, UnsupportedEncodingException { - InputStream is = new FileInputStream(xmlFile); - return IOUtils.inputStream2String(is); - } - - public static void main(String[] args) { - TemplateInfoCollector tic = TemplateInfoCollector.getInstance(); - tic.sendTemplateInfo(); - } - - /** - * 把设计器最近打开日期设定为当前日期 - */ - private void setDesignerOpenDate() { - designerOpenDate = new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); - } - - /** - * 判断今天是否第一次打开设计器 - */ - private boolean designerOpenFirstTime() { - String today = new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); - return !ComparatorUtils.equals(today, designerOpenDate); - } - - private boolean shouldCollectInfo() { - //只收集本地环境的 - if (!WorkContext.getCurrent().isLocal()) { - return false; - } - return DesignerEnvManager.getEnvManager().isJoinProductImprove() && FRContext.isChineseEnv(); - } - - public void appendProcess(String log) { - if (!shouldCollectInfo()) { - return; - } - // 获取当前编辑的模板 - JTemplate jt = DesignerContext.getDesignerFrame().getSelectedJTemplate(); - // 追加过程记录 - jt.appendProcess(log); - } - - /** - * 加载已经存储的模板过程 - */ - @SuppressWarnings("unchecked") - public String loadProcess(T t) { - HashMap processMap = (HashMap) templateInfoList.get(t.getTemplateID()).get(XML_PROCESS_MAP); - return (String) processMap.get(ATTR_PROCESS); - } - - /** - * 根据模板ID是否在收集列表中,判断是否需要收集当前模板的信息 - */ - public boolean inList(T t) { - return templateInfoList.containsKey(t.getTemplateID()); - } - - /** - * 将包含所有信息的对象保存到文件 - */ - private void saveInfo() { - try { - FileOutputStream out = new FileOutputStream(getInfoFile()); - XMLTools.writeOutputStreamXML(this, out); - } catch (Exception ex) { - FineLoggerFactory.getLogger().error(ex.getMessage()); - } - } - - /** - * 更新 day_count:打开设计器却未编辑模板的连续日子 - */ - private void addDayCount() { - if (designerOpenFirstTime()) { - for (String key : templateInfoList.keySet()) { - HashMap templateInfo = templateInfoList.get(key); - int dayCount = (int) templateInfo.get(ATTR_DAY_COUNT) + 1; - templateInfo.put(ATTR_DAY_COUNT, dayCount); - } - setDesignerOpenDate(); - } - } - - /** - * 收集模板信息。如果之前没有记录,则新增;如果已有记录,则更新。 - * 同时将最新数据保存到文件中。 - */ - @SuppressWarnings("unchecked") - public void collectInfo(T t, JTemplate jt, long openTime, long saveTime) { - if (!shouldCollectInfo()) { - return; - } - - HashMap templateInfo; - - long timeConsume = ((saveTime - openTime) / ONE_THOUSAND); // 制作模板耗时(单位:s) - String templateID = t.getTemplateID(); - - if (inList(t)) { // 已有记录 - templateInfo = templateInfoList.get(templateID); - // 更新 conusmingMap - HashMap consumingMap = (HashMap) templateInfo.get(XML_CONSUMING_MAP); - timeConsume += (long) consumingMap.get(ATTR_TIME_CONSUME); // 加上之前的累计编辑时间 - consumingMap.put(ATTR_TIME_CONSUME, timeConsume); - } else { // 新增 - templateInfo = new HashMap<>(); - templateInfo.put(XML_CONSUMING_MAP, getNewConsumingMap(templateID, openTime, timeConsume)); - } - - // 直接覆盖 processMap - templateInfo.put(XML_PROCESS_MAP, getProcessMap(templateID, jt)); - - // 保存模板时,让 day_count 归零 - templateInfo.put(ATTR_DAY_COUNT, 0); - - templateInfoList.put(templateID, templateInfo); - - saveInfo(); // 每次更新之后,都同步到暂存文件中 - } - - private HashMap getNewConsumingMap(String templateID, long openTime, long timeConsume) { - HashMap consumingMap = new HashMap<>(); - - String username = MarketConfig.getInstance().getBbsUsername(); - String uuid = DesignerEnvManager.getEnvManager().getUUID(); - String activitykey = DesignerEnvManager.getEnvManager().getActivationKey(); - String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(Calendar.getInstance().getTime()); - String jarTime = GeneralUtils.readBuildNO(); - String version = ProductConstants.VERSION; - consumingMap.put(ATTR_USERNAME, username); - consumingMap.put(ATTR_UUID, uuid); - consumingMap.put(ATTR_ACTIVITYKEY, activitykey); - consumingMap.put(ATTR_TEMPLATE_ID, templateID); - consumingMap.put(ATTR_CREATE_TIME, createTime); - consumingMap.put(ATTR_TIME_CONSUME, timeConsume); - consumingMap.put(ATTR_JAR_TIME, jarTime); - consumingMap.put(ATTR_VERSION, version); - - return consumingMap; - } - - private HashMap getProcessMap(String templateID, JTemplate jt) { - HashMap processMap = new HashMap<>(); - - processMap.put(ATTR_TEMPLATE_ID, templateID); - processMap.put(ATTR_PROCESS, jt.getProcess()); - - TemplateProcessInfo info = jt.getProcessInfo(); - processMap.put(ATTR_REPORT_TYPE, info.getReportType()); - processMap.put(ATTR_CELL_COUNT, info.getCellCount()); - processMap.put(ATTR_FLOAT_COUNT, info.getFloatCount()); - processMap.put(ATTR_BLOCK_COUNT, info.getBlockCount()); - processMap.put(ATTR_WIDGET_COUNT, info.getWidgetCount()); - - return processMap; - } - - /** - * 发送本地模板信息到服务器 - */ - public void sendTemplateInfo() { - addDayCount(); - String consumingUrl = CloudCenter.getInstance().acquireUrlByKind("tempinfo.consuming") + "/single"; - String processUrl = CloudCenter.getInstance().acquireUrlByKind("tempinfo.process") + "/single"; - ArrayList> completeTemplatesInfo = getCompleteTemplatesInfo(); - for (HashMap templateInfo : completeTemplatesInfo) { - String jsonConsumingMap = templateInfo.get(JSON_CONSUMING_MAP); - String jsonProcessMap = templateInfo.get(JSON_PROCESS_MAP); - if (sendSingleTemplateInfo(consumingUrl, jsonConsumingMap) && sendSingleTemplateInfo(processUrl, jsonProcessMap)) { - // 清空记录 - removeFromTemplateInfoList(templateInfo.get(ATTR_TEMPLATE_ID)); - } - } - saveInfo(); - } - - private boolean sendSingleTemplateInfo(String url, String content) { - HashMap para = new HashMap<>(); - para.put("token", SiteCenterToken.generateToken()); - para.put("content", content); - HttpClient httpClient = new HttpClient(url, para, true); - httpClient.setTimeout(5000); - httpClient.asGet(); - - if (!httpClient.isServerAlive()) { - return false; - } - - String res = httpClient.getResponseText(); - boolean success; - try { - success = ComparatorUtils.equals(new JSONObject(res).get("status"), "success"); - } catch (Exception ex) { - success = false; - } - return success; - } - - /** - * 返回已完成的模板信息 - */ - @SuppressWarnings("unchecked") - private ArrayList> getCompleteTemplatesInfo() { - ArrayList> completeTemplatesInfo = new ArrayList<>(); - ArrayList testTemplateKeys = new ArrayList<>(); // 保存测试模板的key - for (String key : templateInfoList.keySet()) { - HashMap templateInfo = templateInfoList.get(key); - if ((int) templateInfo.get(ATTR_DAY_COUNT) <= COMPLETE_DAY_COUNT) { // 未完成模板 - continue; - } - if (isTestTemplate(templateInfo)) { - testTemplateKeys.add(key); - continue; - } - HashMap consumingMap = (HashMap) templateInfo.get(XML_CONSUMING_MAP); - HashMap processMap = (HashMap) templateInfo.get(XML_PROCESS_MAP); - String jsonConsumingMap = new JSONObject(consumingMap).toString(); - String jsonProcessMap = new JSONObject(processMap).toString(); - HashMap jsonTemplateInfo = new HashMap<>(); - jsonTemplateInfo.put(JSON_CONSUMING_MAP, jsonConsumingMap); - jsonTemplateInfo.put(JSON_PROCESS_MAP, jsonProcessMap); - jsonTemplateInfo.put(ATTR_TEMPLATE_ID, key); - completeTemplatesInfo.add(jsonTemplateInfo); - } - // 删除测试模板 - for (String key : testTemplateKeys) { - removeFromTemplateInfoList(key); - } - return completeTemplatesInfo; - } - - private void removeFromTemplateInfoList(String key) { - templateInfoList.remove(key); - } - - @SuppressWarnings("unchecked") - private boolean isTestTemplate(HashMap templateInfo) { - HashMap processMap = (HashMap) templateInfo.get(XML_PROCESS_MAP); - int reportType = (int) processMap.get(ATTR_REPORT_TYPE); - int cellCount = (int) processMap.get(ATTR_CELL_COUNT); - int floatCount = (int) processMap.get(ATTR_FLOAT_COUNT); - int blockCount = (int) processMap.get(ATTR_BLOCK_COUNT); - int widgetCount = (int) processMap.get(ATTR_WIDGET_COUNT); - boolean isTestTemplate = false; - if (reportType == 0) { // 普通报表 - isTestTemplate = cellCount <= VALID_CELL_COUNT && floatCount <= 1 && widgetCount <= VALID_WIDGET_COUNT; - } else if (reportType == 1) { // 聚合报表 - isTestTemplate = blockCount <= 1 && widgetCount <= VALID_WIDGET_COUNT; - } else { // 表单(reportType == 2) - isTestTemplate = widgetCount <= 1; - } - return isTestTemplate; - } - - @SuppressWarnings("unchecked") - @Override - public void readXML(XMLableReader reader) { - if (reader.isChildNode()) { - try { - String name = reader.getTagName(); - if (XML_DESIGNER_OPEN_DATE.equals(name)) { - this.designerOpenDate = reader.getElementValue(); - } else if (XML_TEMPLATE_INFO_LIST.equals(name)) { - readTemplateInfoList(reader); - } - } catch (Exception ex) { - // 什么也不做,使用默认值 - } - } - } - - private void readTemplateInfoList(XMLableReader reader) { - reader.readXMLObject(new XMLReadable() { - public void readXML(XMLableReader reader) { - if (XML_TEMPLATE_INFO.equals(reader.getTagName())) { - TemplateInfo templateInfo = new TemplateInfo(); - reader.readXMLObject(templateInfo); - templateInfoList.put(templateInfo.getTemplateID(), templateInfo.getTemplateInfo()); - } - } - }); - } - - @Override - public void writeXML(XMLPrintWriter writer) { - writer.startTAG("TplInfo"); - - writer.startTAG(XML_DESIGNER_OPEN_DATE); - writer.textNode(designerOpenDate); - writer.end(); - - writeTemplateInfoList(writer); - - writer.end(); - } - - private void writeTemplateInfoList(XMLPrintWriter writer) { - //启停 - writer.startTAG(XML_TEMPLATE_INFO_LIST); - for (String templateID : templateInfoList.keySet()) { - new TemplateInfo(templateInfoList.get(templateID)).writeXML(writer); - } - writer.end(); - } - - private class TemplateInfo implements XMLReadable, XMLWriter { - - private int dayCount; - private String templateID; - private HashMap processMap = new HashMap<>(); - private HashMap consumingMap = new HashMap<>(); - - @SuppressWarnings("unchecked") - public TemplateInfo(HashMap templateInfo) { - this.dayCount = (int) templateInfo.get(ATTR_DAY_COUNT); - this.processMap = (HashMap) templateInfo.get(XML_PROCESS_MAP); - this.consumingMap = (HashMap) templateInfo.get(XML_CONSUMING_MAP); - this.templateID = (String) processMap.get(ATTR_TEMPLATE_ID); - } - - public TemplateInfo() { - } - - public String getTemplateID() { - return templateID; - } - - public HashMap getTemplateInfo() { - HashMap templateInfo = new HashMap<>(); - templateInfo.put(XML_PROCESS_MAP, processMap); - templateInfo.put(XML_CONSUMING_MAP, consumingMap); - templateInfo.put(ATTR_DAY_COUNT, dayCount); - return templateInfo; - } - - public void writeXML(XMLPrintWriter writer) { - writer.startTAG(XML_TEMPLATE_INFO); - if (StringUtils.isNotEmpty(templateID)) { - writer.attr(ATTR_TEMPLATE_ID, this.templateID); - } - if (dayCount >= 0) { - writer.attr(ATTR_DAY_COUNT, this.dayCount); - } - writeProcessMap(writer); - writeConsumingMap(writer); - - writer.end(); - } - - private void writeProcessMap(XMLPrintWriter writer) { - writer.startTAG(XML_PROCESS_MAP); - writer.attr(ATTR_PROCESS, (String) processMap.get(ATTR_PROCESS)); - writer.attr(ATTR_FLOAT_COUNT, (int) processMap.get(ATTR_FLOAT_COUNT)); - writer.attr(ATTR_WIDGET_COUNT, (int) processMap.get(ATTR_WIDGET_COUNT)); - writer.attr(ATTR_CELL_COUNT, (int) processMap.get(ATTR_CELL_COUNT)); - writer.attr(ATTR_BLOCK_COUNT, (int) processMap.get(ATTR_BLOCK_COUNT)); - writer.attr(ATTR_REPORT_TYPE, (int) processMap.get(ATTR_REPORT_TYPE)); - writer.end(); - } - - private void writeConsumingMap(XMLPrintWriter writer) { - writer.startTAG(XML_CONSUMING_MAP); - writer.attr(ATTR_ACTIVITYKEY, (String) consumingMap.get(ATTR_ACTIVITYKEY)); - writer.attr(ATTR_JAR_TIME, (String) consumingMap.get(ATTR_JAR_TIME)); - writer.attr(ATTR_CREATE_TIME, (String) consumingMap.get(ATTR_CREATE_TIME)); - writer.attr(ATTR_UUID, (String) consumingMap.get(ATTR_UUID)); - writer.attr(ATTR_TIME_CONSUME, (long) consumingMap.get(ATTR_TIME_CONSUME)); - writer.attr(ATTR_VERSION, (String) consumingMap.get(ATTR_VERSION)); - writer.attr(ATTR_USERNAME, (String) consumingMap.get(ATTR_USERNAME)); - writer.end(); - } - - public void readXML(XMLableReader reader) { - if (!reader.isChildNode()) { - dayCount = reader.getAttrAsInt(ATTR_DAY_COUNT, 0); - templateID = reader.getAttrAsString(ATTR_TEMPLATE_ID, StringUtils.EMPTY); - } else { - try { - String name = reader.getTagName(); - if (XML_PROCESS_MAP.equals(name)) { - processMap.put(ATTR_PROCESS, reader.getAttrAsString(ATTR_PROCESS, StringUtils.EMPTY)); - processMap.put(ATTR_FLOAT_COUNT, reader.getAttrAsInt(ATTR_FLOAT_COUNT, 0)); - processMap.put(ATTR_WIDGET_COUNT, reader.getAttrAsInt(ATTR_WIDGET_COUNT, 0)); - processMap.put(ATTR_CELL_COUNT, reader.getAttrAsInt(ATTR_CELL_COUNT, 0)); - processMap.put(ATTR_BLOCK_COUNT, reader.getAttrAsInt(ATTR_BLOCK_COUNT, 0)); - processMap.put(ATTR_REPORT_TYPE, reader.getAttrAsInt(ATTR_REPORT_TYPE, 0)); - processMap.put(ATTR_TEMPLATE_ID, templateID); - } else if (XML_CONSUMING_MAP.equals(name)) { - consumingMap.put(ATTR_ACTIVITYKEY, reader.getAttrAsString(ATTR_ACTIVITYKEY, StringUtils.EMPTY)); - consumingMap.put(ATTR_JAR_TIME, reader.getAttrAsString(ATTR_JAR_TIME, StringUtils.EMPTY)); - consumingMap.put(ATTR_CREATE_TIME, reader.getAttrAsString(ATTR_CREATE_TIME, StringUtils.EMPTY)); - consumingMap.put(ATTR_TEMPLATE_ID, templateID); - consumingMap.put(ATTR_UUID, reader.getAttrAsString(ATTR_UUID, StringUtils.EMPTY)); - consumingMap.put(ATTR_TIME_CONSUME, reader.getAttrAsLong(ATTR_TIME_CONSUME, 0)); - consumingMap.put(ATTR_VERSION, reader.getAttrAsString(ATTR_VERSION, "8.0")); - consumingMap.put(ATTR_USERNAME, reader.getAttrAsString(ATTR_USERNAME, StringUtils.EMPTY)); - } - } catch (Exception ex) { - // 什么也不做,使用默认值 - } - } - } - - } -} 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 ff31f0156..7e0d6b359 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 @@ -13,6 +13,7 @@ import com.fr.design.actions.community.BBSAction; import com.fr.design.actions.community.BugAction; import com.fr.design.actions.community.CenterAction; import com.fr.design.actions.community.CusDemandAction; +import com.fr.design.actions.community.FacebookFansAction; import com.fr.design.actions.community.NeedAction; import com.fr.design.actions.community.QuestionAction; import com.fr.design.actions.community.SignAction; @@ -38,6 +39,7 @@ import com.fr.design.actions.server.PlatformManagerAction; import com.fr.design.actions.server.PluginManagerAction; import com.fr.design.file.NewTemplatePane; import com.fr.design.fun.MenuHandler; +import com.fr.design.fun.OemProcessor; import com.fr.design.fun.TableDataPaneProcessor; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ilable.UILabel; @@ -51,11 +53,12 @@ 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; import com.fr.general.GeneralContext; +import com.fr.log.FineLoggerFactory; import com.fr.plugin.context.PluginContext; import com.fr.plugin.context.PluginRuntime; import com.fr.plugin.manage.PluginFilter; @@ -64,6 +67,7 @@ import com.fr.plugin.observer.PluginEventListener; import com.fr.plugin.observer.PluginEventType; import com.fr.stable.ArrayUtils; import com.fr.stable.StringUtils; +import com.fr.start.OemHandler; import com.fr.workspace.WorkContext; import javax.swing.JComponent; @@ -148,7 +152,6 @@ public abstract class ToolBarMenuDock { } }; - private static final String FINEREPORT = "FineReport"; private static final int MENUBAR_HEIGHT = 22; private static final List PLUGIN_LISTENERS = new ArrayList<>(); @@ -200,6 +203,18 @@ public abstract class ToolBarMenuDock { }; this.menus = menus(plus); + try { + OemProcessor oemProcessor = OemHandler.findOem(); + if (oemProcessor != null) { + this.menus = oemProcessor.dealWithMenuDef(this.menus); + if (this.menus == null) { + this.menus = menus(plus); + } + } + } catch (Throwable e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + this.menus = menus(plus); + } for (int i = 0; i < menus.length; i++) { menus[i].setHasRecMenu(true); UIMenu subMenu = menus[i].createJMenu(); @@ -528,6 +543,9 @@ public abstract class ToolBarMenuDock { shortCuts.add(new CusDemandAction()); shortCuts.add(new CenterAction()); shortCuts.add(new SignAction()); + if (Locale.TAIWAN.equals(GeneralContext.getLocale())) { + shortCuts.add(new FacebookFansAction()); + } return shortCuts.toArray(new ShortCut[shortCuts.size()]); } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsConfigManager.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsConfigManager.java new file mode 100644 index 000000000..f61bba67a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsConfigManager.java @@ -0,0 +1,74 @@ +package com.fr.design.mainframe.vcs; + +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 XiaXiang on 2019/4/26. + */ +public class VcsConfigManager implements XMLReadable, XMLWriter { + public static final String XML_TAG = "VcsConfigManager"; + private static volatile VcsConfigManager instance = new VcsConfigManager(); + private boolean vcsEnable = true; + private boolean saveCommit = true; + private boolean useInterval = true; + private int saveInterval = 60; + + public static VcsConfigManager getInstance() { + return instance; + } + + public boolean isVcsEnable() { + return vcsEnable; + } + + public void setVcsEnable(boolean vcsEnable) { + this.vcsEnable = vcsEnable; + } + + public boolean isSaveCommit() { + return saveCommit; + } + + public void setSaveCommit(boolean saveCommit) { + this.saveCommit = saveCommit; + } + + public boolean isUseInterval() { + return useInterval; + } + + public void setUseInterval(boolean useInterval) { + this.useInterval = useInterval; + } + + public int getSaveInterval() { + return saveInterval; + } + + public void setSaveInterval(int saveInterval) { + this.saveInterval = saveInterval; + } + + @Override + public void readXML(XMLableReader reader) { + if (reader.isAttr()) { + this.setSaveCommit(reader.getAttrAsBoolean("saveCommit", true)); + this.setSaveInterval(reader.getAttrAsInt("saveInterval", 60)); + this.setUseInterval(reader.getAttrAsBoolean("useInterval", true)); + this.setVcsEnable(reader.getAttrAsBoolean("vcsEnable", true)); + } + } + + @Override + public void writeXML(XMLPrintWriter writer) { + writer.startTAG(XML_TAG); + writer.attr("saveCommit", this.isSaveCommit()); + writer.attr("saveInterval", this.getSaveInterval()); + writer.attr("useInterval", this.isUseInterval()); + writer.attr("vcsEnable", this.isVcsEnable()); + writer.end(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsCacheFileNodeFile.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsCacheFileNodeFile.java new file mode 100644 index 000000000..40edc01f0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsCacheFileNodeFile.java @@ -0,0 +1,75 @@ +package com.fr.design.mainframe.vcs.common; + +import com.fr.base.io.XMLEncryptUtils; +import com.fr.file.FileNodeFILE; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.stable.StableUtils; +import com.fr.workspace.WorkContext; +import com.fr.workspace.resource.WorkResourceOutputStream; +import com.fr.workspace.server.lock.TplOperator; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; + + +public class VcsCacheFileNodeFile extends FileNodeFILE { + + private final FileNode node; + + public VcsCacheFileNodeFile(FileNode node) { + super(node); + this.node = node; + } + + /** + * 和FileNodeFILE中一样,只是去掉了必须以reportlets开头的限制,改为vcs开头 + * + * @return + * @throws Exception + */ + @Override + public InputStream asInputStream() throws Exception { + if (node == null) { + return null; + } + + String envPath = node.getEnvPath(); + // envPath必须以vcs开头 + if (!envPath.startsWith(VcsHelper.VCS_CACHE_DIR)) { + return null; + } + + InputStream in = new ByteArrayInputStream( + WorkContext.getCurrent().get(TplOperator.class).readAndLockFile( + StableUtils.pathJoin(VcsHelper.VCS_CACHE_DIR, envPath.substring(VcsHelper.VCS_CACHE_DIR.length() + 1)) + ) + ); + + return envPath.endsWith(".cpt") || envPath.endsWith(".frm") + ? XMLEncryptUtils.decodeInputStream(in) : in; + } + + + /** + * 和FileNodeFILE中一样,只是去掉了必须以reportlets开头的限制,改为vcs开头 + * + * @return + * @throws Exception + */ + @Override + public OutputStream asOutputStream() { + if (ComparatorUtils.equals(node, null)) { + return null; + } + + String envPath = node.getEnvPath(); + // envPath必须以reportLets开头 + if (!envPath.startsWith(VcsHelper.VCS_CACHE_DIR)) { + return null; + } + + return new WorkResourceOutputStream(StableUtils.pathJoin(VcsHelper.VCS_CACHE_DIR, envPath.substring(VcsHelper.VCS_CACHE_DIR.length() + 1))); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java new file mode 100644 index 000000000..fa649b66a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java @@ -0,0 +1,177 @@ +package com.fr.design.mainframe.vcs.common; + +import com.fr.cluster.engine.base.FineClusterConfig; +import com.fr.design.DesignerEnvManager; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.TemplateTreePane; +import com.fr.design.gui.itree.filetree.TemplateFileTree; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerFrameFileDealerPane; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.JTemplateActionListener; +import com.fr.design.mainframe.vcs.VcsConfigManager; +import com.fr.design.mainframe.vcs.ui.FileVersionTable; +import com.fr.general.IOUtils; +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.manage.PluginManager; +import com.fr.report.entity.VcsEntity; +import com.fr.stable.StringUtils; +import com.fr.stable.project.ProjectConstants; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.vcs.VcsOperator; + +import javax.swing.Icon; +import javax.swing.border.EmptyBorder; +import java.awt.Color; +import java.util.Date; + +import static com.fr.stable.StableUtils.pathJoin; + +/** + * Created by XiaXiang on 2019/4/17. + */ +public class VcsHelper implements JTemplateActionListener { + + public final static Color TABLE_SELECT_BACKGROUND = new Color(0xD8F2FD); + public final static Color COPY_VERSION_BTN_COLOR = new Color(0x419BF9); + public final static EmptyBorder EMPTY_BORDER = new EmptyBorder(10, 10, 0, 10); + public final static EmptyBorder EMPTY_BORDER_MEDIUM = new EmptyBorder(5, 10, 0, 10); + public final static EmptyBorder EMPTY_BORDER_BOTTOM = new EmptyBorder(10, 10, 10, 10); + public final static Icon VCS_LIST_PNG = IOUtils.readIcon("/com/fr/design/images/vcs/vcs_list.png"); + public final static Icon VCS_BACK_PNG = IOUtils.readIcon("/com/fr/design/images/vcs/vcs_back.png"); + public final static Icon VCS_FILTER_PNG = IOUtils.readIcon("/com/fr/design/images/vcs/icon_filter@1x.png"); + public final static Icon VCS_EDIT_PNG = IOUtils.readIcon("/com/fr/design/images/vcs/icon_edit.png"); + public final static Icon VCS_DELETE_PNG = IOUtils.readIcon("/com/fr/design/images/vcs/icon_delete.png"); + public final static Icon VCS_USER_PNG = IOUtils.readIcon("/com/fr/design/images/vcs/icon_user@1x.png"); + public final static Icon VCS_REVERT = IOUtils.readIcon("/com/fr/design/images/vcs/icon_revert.png"); + public final static int OFFSET = 2; + private final static String VCS_DIR = "vcs"; + public final static String VCS_CACHE_DIR = pathJoin(VCS_DIR, "cache"); + private static final int MINUTE = 60 * 1000; + private final static String VCS_PLUGIN_ID = "com.fr.plugin.vcs.v10"; + private static final VcsHelper instance = new VcsHelper(); + + public static VcsHelper getInstance() { + return instance; + } + + private int containsFolderCounts() { + TemplateFileTree fileTree = TemplateTreePane.getInstance().getTemplateFileTree(); + if (fileTree.getSelectionPaths() == null) { + return 0; + } + + //选择的包含文件和文件夹的数目 + if (fileTree.getSelectionPaths().length == 0) { + return 0; + } + //所有的num减去模板的count,得到文件夹的count + return fileTree.getSelectionPaths().length - fileTree.getSelectedTemplatePaths().length; + } + + public String getCurrentUsername() { + return WorkContext.getCurrent().isLocal() + ? Toolkit.i18nText("Fine-Design_Vcs_Local_User") + : WorkContext.getCurrent().getConnection().getUserName(); + } + + private int selectedTemplateCounts() { + TemplateFileTree fileTree = TemplateTreePane.getInstance().getTemplateFileTree(); + if (fileTree.getSelectionPaths() == null) { + return 0; + } + + return fileTree.getSelectedTemplatePaths().length; + } + + public boolean isUnSelectedTemplate() { + return containsFolderCounts() + selectedTemplateCounts() != 1; + } + + private String getEditingFilename() { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + String editingFilePath = jt.getEditingFILE().getPath(); + if (editingFilePath.startsWith(ProjectConstants.REPORTLETS_NAME)) { + editingFilePath = editingFilePath.replaceFirst(ProjectConstants.REPORTLETS_NAME, StringUtils.EMPTY); + } else if (editingFilePath.startsWith(VcsHelper.VCS_CACHE_DIR)) { + editingFilePath = editingFilePath.replaceFirst(VcsHelper.VCS_CACHE_DIR, StringUtils.EMPTY); + } + if (editingFilePath.startsWith("/")) { + editingFilePath = editingFilePath.substring(1); + } + return editingFilePath; + } + + private boolean needDeleteVersion(VcsEntity entity) { + VcsConfigManager configManager = DesignerEnvManager.getEnvManager().getVcsConfigManager(); + if (entity == null || !configManager.isUseInterval()) { + return false; + } + if (configManager.isSaveCommit() && StringUtils.isNotBlank(entity.getCommitMsg())) { + return false; + } + return new Date().getTime() - entity.getTime().getTime() < DesignerEnvManager.getEnvManager().getVcsConfigManager().getSaveInterval() * MINUTE; + } + + public boolean needInit() { + PluginContext context = PluginManager.getContext(VCS_PLUGIN_ID); + return context == null || !context.isRunning(); + } + + /** + * 版本控制 + * + * @param jt + */ + public void fireVcs(final JTemplate jt) { + new Thread(new Runnable() { + @Override + public void run() { + + String fileName = getEditingFilename(); + VcsOperator operator = WorkContext.getCurrent().get(VcsOperator.class); + VcsEntity entity = operator.getFileVersionByIndex(fileName, 0); + int latestFileVersion = 0; + if (entity != null) { + latestFileVersion = entity.getVersion(); + } + if (jt.getEditingFILE() instanceof VcsCacheFileNodeFile) { + operator.saveVersionFromCache(getCurrentUsername(), fileName, StringUtils.EMPTY, latestFileVersion + 1); + String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath(); + FileVersionTable.getInstance().updateModel(1, WorkContext.getCurrent().get(VcsOperator.class).getVersions(path.replaceFirst("/", ""))); + } else { + operator.saveVersion(getCurrentUsername(), fileName, StringUtils.EMPTY, latestFileVersion + 1); + } + VcsEntity oldEntity = WorkContext.getCurrent().get(VcsOperator.class).getFileVersionByIndexAndUsername(fileName, getCurrentUsername(), 1); + if (needDeleteVersion(oldEntity)) { + operator.deleteVersion(oldEntity.getFilename(), oldEntity.getVersion()); + } + + } + }).start(); + + } + + + @Override + public void templateOpened(JTemplate jt) { + + } + + /** + * 模板保存时 处理. + * + * @param jt 模板 + */ + @Override + public void templateSaved(JTemplate jt) { + if (needInit() && DesignerEnvManager.getEnvManager().getVcsConfigManager().isVcsEnable() && !FineClusterConfig.getInstance().isCluster()) { + fireVcs(jt); + } + } + + @Override + public void templateClosed(JTemplate jt) { + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/EditFileVersionDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/EditFileVersionDialog.java new file mode 100644 index 000000000..105a9b872 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/EditFileVersionDialog.java @@ -0,0 +1,104 @@ +package com.fr.design.mainframe.vcs.ui; + +import com.fr.design.dialog.UIDialog; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrameFileDealerPane; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.report.entity.VcsEntity; +import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.vcs.VcsOperator; + +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * 编辑版本信息面板 + */ +public class EditFileVersionDialog extends UIDialog { + + private final UITextArea msgTestArea = new UITextArea(); + private final UILabel versionLabel = new UILabel(); + private VcsEntity entity; + + public EditFileVersionDialog(VcsEntity entity) { + this(DesignerContext.getDesignerFrame()); + this.entity = entity; + msgTestArea.setText(entity.getCommitMsg()); + versionLabel.setText(String.valueOf(entity.getVersion())); + } + + private EditFileVersionDialog(Frame parent) { + super(parent); + + initComponents(); + setModal(true); + setTitle(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Vcs_Save_Version")); + setSize(300, 220); + setResizable(false); + GUICoreUtils.centerWindow(this); + + } + + private void initComponents() { + + JPanel fontPane = new JPanel(new BorderLayout()); + fontPane.add(new UILabel(" " + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Vcs_Version_Message") + ":"), BorderLayout.NORTH); + + msgTestArea.setBorder(null); + UIScrollPane scrollPane = new UIScrollPane(msgTestArea); + + Component[][] components = new Component[][]{ + new Component[]{new UILabel(" " + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Vcs_Version_Number") + ":"), versionLabel}, + new Component[]{fontPane, scrollPane} + }; + double[] rowSizes = new double[]{25, 100}; + double[] columnSizes = new double[]{70, 200}; + + add(TableLayoutHelper.createTableLayoutPane(components, rowSizes, columnSizes), BorderLayout.CENTER); + + JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + add(buttonPane, BorderLayout.SOUTH); + + UIButton ok = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_OK")); + UIButton cancel = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Design_Action_Cancel")); + + buttonPane.add(ok); + buttonPane.add(cancel); + + ok.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + entity.setCommitMsg(msgTestArea.getText()); + WorkContext.getCurrent().get(VcsOperator.class).updateVersion(entity); + setVisible(false); + String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath(); + FileVersionTable table = FileVersionTable.getInstance(); + table.updateModel(table.getSelectedRow(), WorkContext.getCurrent().get(VcsOperator.class).getVersions(path.replaceFirst("/", StringUtils.EMPTY))); + } + }); + + cancel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + doCancel(); + } + }); + } + + @Override + public void checkValid() throws Exception { + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionCellEditor.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionCellEditor.java new file mode 100644 index 000000000..125d4bc4e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionCellEditor.java @@ -0,0 +1,80 @@ +package com.fr.design.mainframe.vcs.ui; + +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.MutilTempalteTabPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrameFileDealerPane; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.vcs.common.VcsHelper; +import com.fr.design.mainframe.vcs.common.VcsCacheFileNodeFile; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.report.entity.VcsEntity; +import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.vcs.VcsOperator; + +import javax.swing.AbstractCellEditor; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import java.awt.Component; + + +public class FileVersionCellEditor extends AbstractCellEditor implements TableCellEditor { + private static final long serialVersionUID = -7299526575184810693L; + //第一行 + private final JPanel firstRowPanel; + //其余行 + private final FileVersionRowPanel renderAndEditor; + + public FileVersionCellEditor() { + this.firstRowPanel = new FileVersionFirstRowPanel(); + this.renderAndEditor = new FileVersionRowPanel(); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + String fileOfVersion; + VcsOperator vcsOperator = WorkContext.getCurrent().get(VcsOperator.class); + Component editor = row == 0 ? firstRowPanel : renderAndEditor; + if (isSelected) { + return editor; + } else if (row == 0) { + String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath(); + fileOfVersion = vcsOperator.getFileOfCurrent(path.replaceFirst("/", "")); + } else { + renderAndEditor.update((VcsEntity) value); + fileOfVersion = vcsOperator.getFileOfFileVersion(((VcsEntity) value).getFilename(), ((VcsEntity) value).getVersion()); + + } + + editor.setBackground(VcsHelper.TABLE_SELECT_BACKGROUND); + if (StringUtils.isNotEmpty(fileOfVersion)) { + //先关闭当前打开的模板版本 + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + jt.stopEditing(); + //只有模板路径一致时关闭当前模板 + if (ComparatorUtils.equals(fileOfVersion, jt.getPath())) { + MutilTempalteTabPane.getInstance().setIsCloseCurrent(true); + MutilTempalteTabPane.getInstance().closeFormat(jt); + MutilTempalteTabPane.getInstance().closeSpecifiedTemplate(jt); + } + + //再打开cache中的模板 + DesignerContext.getDesignerFrame().openTemplate(new VcsCacheFileNodeFile(new FileNode(fileOfVersion, false))); + + } + + double height = editor.getPreferredSize().getHeight(); + if (table.getRowHeight(row) != height) { + table.setRowHeight(row, (int) height + VcsHelper.OFFSET); + } + return editor; + } + + @Override + public Object getCellEditorValue() { + return renderAndEditor.getVcsEntity(); + } +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionCellRender.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionCellRender.java new file mode 100644 index 000000000..40fa02c1f --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionCellRender.java @@ -0,0 +1,44 @@ +package com.fr.design.mainframe.vcs.ui; + +import com.fr.design.mainframe.vcs.common.VcsHelper; +import com.fr.report.entity.VcsEntity; + +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; + +import static com.fr.design.constants.UIConstants.TREE_BACKGROUND; +import static com.fr.design.mainframe.vcs.common.VcsHelper.TABLE_SELECT_BACKGROUND; + + +public class FileVersionCellRender implements TableCellRenderer { + + //第一行 + private final JPanel firstRowPanel; + //其余行 + private final FileVersionRowPanel render; + + public FileVersionCellRender() { + this.render = new FileVersionRowPanel(); + this.firstRowPanel = new FileVersionFirstRowPanel(); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + Component editor = row == 0 ? firstRowPanel : render; + // https://stackoverflow.com/questions/3054775/jtable-strange-behavior-from-getaccessiblechild-method-resulting-in-null-point + if (value != null) { + render.update((VcsEntity) value); + } + editor.setBackground(isSelected ? TABLE_SELECT_BACKGROUND : TREE_BACKGROUND); + + double height = editor.getPreferredSize().getHeight(); + if (table.getRowHeight(row) != height) { + table.setRowHeight(row, (int) height + VcsHelper.OFFSET); + } + return editor; + } + + +} \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionDialog.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionDialog.java new file mode 100644 index 000000000..15d8bae63 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionDialog.java @@ -0,0 +1,112 @@ +package com.fr.design.mainframe.vcs.ui; + +import com.fr.analysis.cloud.DateUtils; +import com.fr.design.dialog.UIDialog; +import com.fr.design.editor.editor.DateEditor; +import com.fr.design.gui.date.UIDatePicker; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.vcs.common.VcsHelper; +import com.fr.report.entity.VcsEntity; +import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.vcs.VcsOperator; + +import javax.swing.AbstractAction; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Date; +import java.util.List; + + + +public class FileVersionDialog extends UIDialog { + public static final long DELAY = 24 * 60 * 60 * 1000; + private UIButton okBtn; + private UIButton cancelBtn; + private DateEditor dateEditor; + private UITextField textField; + + + public FileVersionDialog(Frame frame, final String fileName) { + super(frame); + setUndecorated(true); + setModal(true); + JPanel panel = new JPanel(new BorderLayout()); + Box upBox = Box.createHorizontalBox(); + upBox.setBorder(VcsHelper.EMPTY_BORDER); + upBox.add(new UILabel(Toolkit.i18nText("Fine-Design_Vcs_buildTime") + " ")); + upBox.add(Box.createHorizontalGlue()); + dateEditor = new VcsDateEditor(new Date(), true, StringUtils.EMPTY, UIDatePicker.STYLE_CN_DATE1); + upBox.add(dateEditor); + Box downBox = Box.createHorizontalBox(); + downBox.setBorder(VcsHelper.EMPTY_BORDER); + downBox.add(new UILabel(Toolkit.i18nText("Fine-Design_Vcs_CommitMsg") + " ")); + textField = new UITextField(); + downBox.add(textField); + JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + okBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_OK")); + cancelBtn = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Design_Action_Cancel")); + buttonPane.setBorder(VcsHelper.EMPTY_BORDER); + buttonPane.add(okBtn); + buttonPane.add(cancelBtn); + okBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + FileVersionDialog.this.setVisible(false); + Date editorDate = dateEditor.getValue(); + Date start = editorDate == null ? new Date(0) : editorDate; + Date end = editorDate == null ? DateUtils.getLastHour() : new Date(start.getTime() + DELAY); + List vcsEntities = WorkContext.getCurrent().get(VcsOperator.class).getFilterVersions(fileName, start, end, textField.getText()); + FileVersionTable.getInstance().updateModel(1, vcsEntities); + + } + }); + cancelBtn.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + FileVersionDialog.this.setVisible(false); + } + }); + VcsLabel resetLabel = new VcsLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Vcs_resetValue"), VcsHelper.COPY_VERSION_BTN_COLOR); + resetLabel.setBorder(BorderFactory.createEmptyBorder(10, 160, 0, 10)); + resetLabel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dateEditor.setValue(null); + textField.setText(null); + FileVersionDialog.this.repaint(); + } + }); + panel.add(upBox, BorderLayout.NORTH); + panel.add(downBox, BorderLayout.CENTER); + panel.add(buttonPane, BorderLayout.SOUTH); + JPanel filterPane = new JPanel(new BorderLayout()); + filterPane.add(resetLabel, BorderLayout.NORTH); + filterPane.add(panel, BorderLayout.CENTER); + add(filterPane); + setSize(new Dimension(230, 125)); + centerWindow(frame); + } + + private void centerWindow(Window window) { + this.setLocation(window.getX(), 95); + + } + + @Override + public void checkValid() throws Exception { + + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionFirstRowPanel.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionFirstRowPanel.java new file mode 100644 index 000000000..ff0a93fa8 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionFirstRowPanel.java @@ -0,0 +1,21 @@ +package com.fr.design.mainframe.vcs.ui; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; + +import javax.swing.Box; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import java.awt.BorderLayout; + + +public class FileVersionFirstRowPanel extends JPanel { + + public FileVersionFirstRowPanel() { + super(new BorderLayout()); + Box upPane = Box.createVerticalBox(); + upPane.setBorder(new EmptyBorder(5, 10, 5, 10)); + upPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Vcs_Current"))); + add(upPane, BorderLayout.CENTER); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionRowPanel.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionRowPanel.java new file mode 100644 index 000000000..cd01d409c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionRowPanel.java @@ -0,0 +1,151 @@ +package com.fr.design.mainframe.vcs.ui; + +import com.fr.design.gui.frpane.UITextPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerFrameFileDealerPane; +import com.fr.design.mainframe.vcs.common.VcsHelper; +import com.fr.log.FineLoggerFactory; +import com.fr.report.entity.VcsEntity; +import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.vcs.VcsOperator; + +import javax.swing.Box; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.text.BadLocationException; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.SimpleDateFormat; +import java.util.Date; + + +public class FileVersionRowPanel extends JPanel { + + private VcsEntity vcsEntity; + private UILabel versionLabel = new UILabel(); + private UILabel usernameLabel = new UILabel(StringUtils.EMPTY, VcsHelper.VCS_USER_PNG, SwingConstants.LEFT); + private UITextPane msgLabel = new UITextPane(); + private UILabel timeLabel = new UILabel(); + private EditFileVersionDialog editDialog; + + + public FileVersionRowPanel() { + setLayout(new BorderLayout()); + + // version + username + Box upPane = Box.createHorizontalBox(); + upPane.setBorder(VcsHelper.EMPTY_BORDER_MEDIUM); + upPane.add(versionLabel); + upPane.add(Box.createHorizontalGlue()); + + + // msg + msgLabel.setBorder(VcsHelper.EMPTY_BORDER_MEDIUM); + msgLabel.setOpaque(false); + msgLabel.setBackground(new Color(0, 0, 0, 0)); + msgLabel.setEditable(false); + + // confirm + delete + edit + UIButton confirmBtn = new UIButton(VcsHelper.VCS_REVERT); + confirmBtn.set4ToolbarButton(); + confirmBtn.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_Revert")); + confirmBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + if (JOptionPane.showConfirmDialog(null, Toolkit.i18nText("Fine-Design_Vcs_Version_Revert_Confirm"), Toolkit.i18nText("Fine-Design_Vcs_Version_Revert_Title"), + JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + vcsEntity.setUsername(VcsHelper.getInstance().getCurrentUsername()); + WorkContext.getCurrent().get(VcsOperator.class).rollbackTo(vcsEntity); + FileVersionsPanel.getInstance().exitVcs(vcsEntity.getFilename()); + } + } + }); + UIButton deleteBtn = new UIButton(VcsHelper.VCS_DELETE_PNG); + deleteBtn.set4ToolbarButton(); + deleteBtn.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_Delete")); + deleteBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + if (JOptionPane.showConfirmDialog(null, Toolkit.i18nText("Fine-Design_Vcs_Delete-Confirm"), Toolkit.i18nText("Fine-Design_Vcs_Remove"), + JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + try { + WorkContext.getCurrent().get(VcsOperator.class).deleteVersion(vcsEntity.getFilename(), vcsEntity.getVersion()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage()); + } + FileVersionTable table = (FileVersionTable) (FileVersionRowPanel.this.getParent()); + String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath(); + try { + table.updateModel(table.getSelectedRow() - 1, WorkContext.getCurrent().get(VcsOperator.class).getVersions(path.replaceFirst("/", ""))); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage()); + } + } + } + }); + UIButton editBtn = new UIButton(VcsHelper.VCS_EDIT_PNG); + editBtn.set4ToolbarButton(); + editBtn.setToolTipText(Toolkit.i18nText("Fine-Design_Vcs_Edit")); + editBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showEditDialog(); + + } + }); + upPane.add(editBtn); + upPane.add(confirmBtn); + upPane.add(deleteBtn); + Box downPane = Box.createHorizontalBox(); + downPane.add(usernameLabel); + downPane.setBorder(VcsHelper.EMPTY_BORDER_BOTTOM); + downPane.add(Box.createHorizontalGlue()); + timeLabel.setForeground(VcsHelper.COPY_VERSION_BTN_COLOR); + downPane.add(timeLabel); + add(upPane, BorderLayout.NORTH); + add(msgLabel, BorderLayout.CENTER); + add(downPane, BorderLayout.SOUTH); + } + + private void showEditDialog() { + this.editDialog = new EditFileVersionDialog(vcsEntity); + + editDialog.setVisible(true); + update(vcsEntity); + } + + + public void update(final VcsEntity fileVersion) { + this.vcsEntity = fileVersion; + versionLabel.setText(String.format("V.%s", fileVersion.getVersion())); + usernameLabel.setText(fileVersion.getUsername()); + msgLabel.setText(StringUtils.EMPTY); + timeLabel.setText(timeStr(fileVersion.getTime())); + try { + StyledDocument doc = msgLabel.getStyledDocument(); + Style style = msgLabel.getLogicalStyle(); + StyleConstants.setForeground(style, Color.BLACK); + doc.insertString(doc.getLength(), " " + fileVersion.getCommitMsg(), style); + } catch (BadLocationException e) { + FineLoggerFactory.getLogger().error(e.getMessage()); + } + } + + private String timeStr(Date time) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return simpleDateFormat.format(time); + } + + public VcsEntity getVcsEntity() { + return vcsEntity; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionTable.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionTable.java new file mode 100644 index 000000000..aa9c87ca0 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionTable.java @@ -0,0 +1,79 @@ +package com.fr.design.mainframe.vcs.ui; + +import com.fr.report.entity.VcsEntity; + +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; +import java.util.List; + + +public class FileVersionTable extends JTable { + private static volatile FileVersionTable instance; + + private FileVersionTable() { + super(new CellModel(new ArrayList())); + + setDefaultRenderer(VcsEntity.class, new FileVersionCellRender()); + setDefaultEditor(VcsEntity.class, new FileVersionCellEditor()); + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + setTableHeader(null); + setRowHeight(30); + } + + public static FileVersionTable getInstance() { + if (instance == null) { + synchronized (FileVersionTable.class) { + if (instance == null) { + instance = new FileVersionTable(); + } + } + } + return instance; + } + + public void updateModel(int selectedRow, List entities) { + if (selectedRow > entities.size()) { + selectedRow = entities.size(); + } + setModel(new CellModel(entities)); + editCellAt(selectedRow, 0); + setRowSelectionInterval(selectedRow, selectedRow); + } + + private static class CellModel extends AbstractTableModel { + private static final long serialVersionUID = -6078568799037607690L; + private List vcsEntities; + + + CellModel(List vcsEntities) { + this.vcsEntities = vcsEntities; + } + + public Class getColumnClass(int columnIndex) { + return VcsEntity.class; + } + + public int getColumnCount() { + return 1; + } + + public int getRowCount() { + return (vcsEntities == null) ? 0 : vcsEntities.size() + 1; + } + + public Object getValueAt(int rowIndex, int columnIndex) { + if (rowIndex == 0) { + return null; + } + return (vcsEntities == null) ? null : vcsEntities.get(rowIndex - 1); + } + + public boolean isCellEditable(int columnIndex, int rowIndex) { + return true; + } + + + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionsPanel.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionsPanel.java new file mode 100644 index 000000000..4d9b6e35e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionsPanel.java @@ -0,0 +1,201 @@ +package com.fr.design.mainframe.vcs.ui; + +import com.fr.base.GraphHelper; +import com.fr.design.base.mode.DesignModeContext; +import com.fr.design.base.mode.DesignerMode; +import com.fr.design.dialog.BasicPane; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.file.MutilTempalteTabPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrameFileDealerPane; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.ToolBarNewTemplatePane; +import com.fr.design.mainframe.WestRegionContainerPane; +import com.fr.design.mainframe.vcs.common.VcsHelper; +import com.fr.design.menu.ToolBarDef; +import com.fr.file.FileNodeFILE; +import com.fr.file.filetree.FileNode; +import com.fr.stable.StableUtils; +import com.fr.stable.project.ProjectConstants; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.vcs.VcsOperator; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +public class FileVersionsPanel extends BasicPane { + private static final String ELLIPSIS = "..."; + private static volatile FileVersionsPanel instance; + + private UILabel titleLabel; + private String templatePath; + private UIButton filterBtn; + private FileVersionDialog versionDialog; + + + private FileVersionsPanel() { + initComponents(); + } + + public static FileVersionsPanel getInstance() { + if (instance == null) { + synchronized (FileVersionsPanel.class) { + if (instance == null) { + instance = new FileVersionsPanel(); + } + } + } + return instance; + } + + private void initComponents() { + setLayout(new BorderLayout()); + UIToolbar toolbar = ToolBarDef.createJToolBar(); + toolbar.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0)); + toolbar.setBorderPainted(true); + Box upPane = Box.createHorizontalBox(); + UIButton backBtn = new UIButton(VcsHelper.VCS_BACK_PNG); + backBtn.set4ToolbarButton(); + backBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + exitVcs(templatePath); + } + }); + toolbar.add(backBtn); + filterBtn = new UIButton(VcsHelper.VCS_FILTER_PNG); + filterBtn.set4ToolbarButton(); + filterBtn.setHorizontalAlignment(SwingConstants.RIGHT); + filterBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showFilterPane(); + } + }); + titleLabel = new UILabel() { + @Override + public Dimension getMaximumSize() { + return new Dimension(257, 21); + } + }; + upPane.add(titleLabel); + upPane.add(Box.createHorizontalGlue()); + upPane.add(filterBtn); + toolbar.add(Box.createHorizontalGlue()); + toolbar.add(upPane); + add(toolbar, BorderLayout.NORTH); + + UIScrollPane jScrollPane = new UIScrollPane(FileVersionTable.getInstance()); + add(jScrollPane, BorderLayout.CENTER); + } + + private void showFilterPane() { + String savePath = templatePath.startsWith("/") ? templatePath.substring(1) : templatePath; + versionDialog = new FileVersionDialog(DesignerContext.getDesignerFrame(), savePath); + versionDialog.setVisible(true); + } + + + /** + * 退出版本管理,并且打开模板 + * + * @param path 被管理的模板的名字 + */ + public void exitVcs(String path) { + + // 关闭当前打开的版本 + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + MutilTempalteTabPane.getInstance().setIsCloseCurrent(true); + MutilTempalteTabPane.getInstance().closeFormat(jt); + MutilTempalteTabPane.getInstance().closeSpecifiedTemplate(jt); + + updateDesignerFrame(true); + + final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, path); + DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(selectedFilePath, false))); + } + + private void refreshVersionTablePane() { + templatePath = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath(); + String[] paths = StableUtils.pathSplit(templatePath); + String filename = paths[paths.length - 1]; + int width = FileVersionTable.getInstance().getWidth() - 40; + if (getStringWidth(filename) > width) { + filename = getEllipsisName(filename, width); + } + titleLabel.setText(filename); + String path = DesignerFrameFileDealerPane.getInstance().getSelectedOperation().getFilePath(); + FileVersionTable.getInstance().updateModel(1, WorkContext.getCurrent().get(VcsOperator.class).getVersions(path.replaceFirst("/", ""))); + } + + public void showFileVersionsPane() { + updateDesignerFrame(false); + refreshVersionTablePane(); + } + + @Override + protected String title4PopupWindow() { + return null; + } + + + private void updateDesignerFrame(boolean isExit) { + // 左上侧面板 + WestRegionContainerPane.getInstance().replaceUpPane( + isExit ? DesignerFrameFileDealerPane.getInstance() : this); + + DesignModeContext.switchTo(isExit ? DesignerMode.NORMAL : DesignerMode.VCS); + // MutilTempalteTabPane & NewTemplatePane 是否可点 + ToolBarNewTemplatePane.getInstance().setButtonGray(!isExit); + + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (currentEditingTemplate.isJWorkBook()) { + DesignerContext.getDesignerFrame().resetToolkitByPlus(currentEditingTemplate); + } + } + + + private int getStringWidth(String str) { + return GraphHelper.getFontMetrics(this.getFont()).stringWidth(str); + } + + + private String getEllipsisName(String name, int maxStringlength) { + + //若是名字长度大于能显示的长度,那能显示的文字的最大长度还要减去省略号的最大长度 +// int maxellipsislength = maxStringlength - ELLIPSIS.length(); + int ellipsisWidth = getStringWidth(ELLIPSIS); + int leftkeyPoint = 0; + int rightKeyPoint = name.length() - 1; + int leftStrWidth = 0; + int rightStrWidth = 0; + while (leftStrWidth + rightStrWidth + ellipsisWidth < maxStringlength) { + if (leftStrWidth <= rightStrWidth) { + leftkeyPoint++; + } else { + rightKeyPoint--; + } + leftStrWidth = getStringWidth(name.substring(0, leftkeyPoint)); + rightStrWidth = getStringWidth(name.substring(rightKeyPoint)); + + if (leftStrWidth + rightStrWidth + ellipsisWidth > maxStringlength) { + if (leftStrWidth <= rightStrWidth) { + rightKeyPoint++; + } + break; + } + } + + return name.substring(0, leftkeyPoint) + ELLIPSIS + name.substring(rightKeyPoint); + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsDateEditor.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsDateEditor.java new file mode 100644 index 000000000..74b65ecfe --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsDateEditor.java @@ -0,0 +1,37 @@ +package com.fr.design.mainframe.vcs.ui; + +import com.fr.design.editor.editor.DateEditor; +import com.fr.log.FineLoggerFactory; + +import java.text.ParseException; +import java.util.Date; + +/** + * Created by XiaXiang on 2019/5/14. + */ +public class VcsDateEditor extends DateEditor { + private Date tempValue; + + public VcsDateEditor(Date value, boolean format, String name, int dateFormat) { + super(value, format, name, dateFormat); + this.tempValue = value; + } + + @Override + public Date getValue() { + if (tempValue == null) { + return null; + } + return super.getValue(); + } + + @Override + public void setValue(Date value) { + this.tempValue = value; + try { + getUiDatePicker().setSelectedDate(value); + } catch (ParseException parseException) { + FineLoggerFactory.getLogger().error(parseException.getMessage(), parseException); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsLabel.java b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsLabel.java new file mode 100755 index 000000000..a0180a137 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsLabel.java @@ -0,0 +1,32 @@ +package com.fr.design.mainframe.vcs.ui; + + +import com.fr.design.gui.ilable.ActionLabel; +import com.fr.design.gui.ilable.UILabel; + +import java.awt.Color; +import java.awt.Graphics; + +/** + * Created by XiaXiang on 2019/5/15. + */ +public class VcsLabel extends ActionLabel { + + + public VcsLabel(String text, Color color) { + super(text); + this.setForeground(color); + } + + public void paintComponent(Graphics g) { + if (ui != null) { + Graphics scratchGraphics = (g == null) ? null : g.create(); + try { + ui.update(scratchGraphics, this); + } + finally { + scratchGraphics.dispose(); + } + } + } +} \ No newline at end of file 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 index 601f0ac36..7a51c188c 100644 --- a/designer-base/src/main/java/com/fr/design/ui/Assistant.java +++ b/designer-base/src/main/java/com/fr/design/ui/Assistant.java @@ -49,5 +49,6 @@ public class Assistant { ProtocolService protocolService = browserContext.getProtocolService(); // 支持读取jar包中文件的自定义协议————emb:/com/fr/design/images/bbs.png protocolService.setProtocolHandler("emb", handler); + //protocolService.setProtocolHandler("file", 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 index 6636e2874..94456df97 100644 --- a/designer-base/src/main/java/com/fr/design/ui/EmbProtocolHandler.java +++ b/designer-base/src/main/java/com/fr/design/ui/EmbProtocolHandler.java @@ -1,7 +1,11 @@ package com.fr.design.ui; +import com.fr.base.TemplateUtils; import com.fr.general.IOUtils; import com.fr.stable.StringUtils; +import com.fr.third.org.apache.commons.codec.net.URLCodec; +import com.fr.third.org.apache.commons.io.FileUtils; +import com.fr.third.org.apache.commons.io.FilenameUtils; import com.fr.web.struct.AssembleComponent; import com.fr.web.struct.AtomBuilder; import com.fr.web.struct.PathGroup; @@ -11,7 +15,12 @@ import com.teamdev.jxbrowser.chromium.ProtocolHandler; import com.teamdev.jxbrowser.chromium.URLRequest; import com.teamdev.jxbrowser.chromium.URLResponse; +import java.io.File; +import java.io.FileInputStream; import java.io.InputStream; +import java.io.StringReader; +import java.net.URI; +import java.util.Map; /** * @author richie @@ -21,6 +30,7 @@ import java.io.InputStream; public class EmbProtocolHandler implements ProtocolHandler { private AssembleComponent component; + private Map map; public EmbProtocolHandler() { @@ -30,17 +40,35 @@ public class EmbProtocolHandler implements ProtocolHandler { this.component = component; } + public EmbProtocolHandler(AssembleComponent component, Map map) { + this.component = component; + this.map = map; + } + + public EmbProtocolHandler(Map map) { + this.map = map; + } @Override public URLResponse onRequest(URLRequest req) { try { String path = req.getURL(); - if (path.startsWith("emb:dynamic")) { + if (path.startsWith("file:")) { + String url = new URLCodec().decode(path); + String filePath = TemplateUtils.renderParameter4Tpl(url, map); + File file = new File(URI.create(filePath).getPath()); + InputStream inputStream = new FileInputStream(file); + if (path.endsWith(".svg")) { + System.out.println(path); + } + return Assistant.inputStream2Response(inputStream, "file:///" + file.getAbsolutePath()); + } + else if (path.startsWith("emb:dynamic")) { URLResponse response = new URLResponse(); response.setData(htmlText().getBytes()); response.getHeaders().setHeader("Content-Type", "text/html"); return response; - } else { + } else { int index = path.indexOf("="); if (index > 0) { path = path.substring(index + 1); @@ -51,7 +79,7 @@ public class EmbProtocolHandler implements ProtocolHandler { return Assistant.inputStream2Response(inputStream, path); } } catch (Exception ignore) { - + ignore.printStackTrace(); } return null; } 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 index 7d5566662..99a4fe97c 100644 --- a/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java +++ b/designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java @@ -22,6 +22,7 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Map; /** * @author richie @@ -98,6 +99,14 @@ public class ModernUIPane extends BasicPane { }); } + /** + * 转向一个新的地址,相当于重新加载 + * @param url 新的地址 + */ + public void redirect(String url) { + browser.loadURL(url); + } + @Override protected String title4PopupWindow() { return "Modern"; @@ -105,13 +114,11 @@ public class ModernUIPane extends BasicPane { public void populate(final T t) { - browser.addLoadListener(new LoadAdapter() { + browser.addScriptContextListener(new ScriptContextAdapter() { @Override - public void onFinishLoadingFrame(FinishLoadingEvent event) { - if (event.isMainFrame()) { - JSValue ns = event.getBrowser().executeJavaScriptAndReturnValue("window." + namespace); - ns.asObject().setProperty(variable, t); - } + public void onScriptContextCreated(ScriptContextEvent event) { + JSValue ns = event.getBrowser().executeJavaScriptAndReturnValue("window." + namespace); + ns.asObject().setProperty(variable, t); } }); } @@ -158,6 +165,16 @@ public class ModernUIPane extends BasicPane { return this; } + /** + * 加载url指向的资源 + * @param url 文件的地址 + */ + public Builder withURL(final String url, Map map) { + Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler(map)); + pane.browser.loadURL(url); + return this; + } + /** * 加载Atom组件 * @param component Atom组件 @@ -168,6 +185,17 @@ public class ModernUIPane extends BasicPane { return this; } + /** + * 加载Atom组件 + * @param component Atom组件 + */ + public Builder withComponent(AssembleComponent component, Map map) { + Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler(component, map)); + pane.browser.loadURL("emb:dynamic"); + return this; + } + + /** * 加载html文本内容 * @param html 要加载html文本内容 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..ab093605e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateDialog.java @@ -0,0 +1,196 @@ +package com.fr.design.update.push; + +import com.fr.design.dialog.UIDialog; +import com.fr.design.ui.ModernUIPane; +import com.fr.design.utils.BrowseUtils; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.intelli.record.FocusPoint; +import com.fr.intelli.record.MetricRegistry; +import com.fr.intelli.record.Original; +import com.fr.stable.StringUtils; +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 javax.swing.SwingUtilities; +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, 360); + + private ModernUIPane jsPane; + + private DesignerPushUpdateDialog(Frame parent) { + super(parent); + setModal(true); + initComponents(); + } + + static void createAndShow(final Frame parent, final DesignerUpdateInfo updateInfo) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + 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.getLatestVersion()); + 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 void browseMoreInfoUrl() { + if (StringUtils.isNotEmpty(moreInfoUrl)) { + BrowseUtils.browser(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(); + FocusPointManager.submit(FocusPointManager.OperateType.UPDATE); + exit(); + } + + public void remindNextTime() { + FocusPointManager.submit(FocusPointManager.OperateType.REMIND_NEXT_TIME); + exit(); + } + + public void skipThisVersion() { + DesignerPushUpdateManager.getInstance().skipCurrentPushVersion(); + FocusPointManager.submit(FocusPointManager.OperateType.SKIP); + exit(); + } + + public void closeWindow() { + FocusPointManager.submit(FocusPointManager.OperateType.CLOSE_WINDOW); + exit(); + } + + public String i18nText(String key) { + return com.fr.design.i18n.Toolkit.i18nText(key); + } + + private void exit() { + DesignerPushUpdateDialog.this.dialogExit(); + } + } + + private static class FocusPointManager { + + private static final String ID = "com.fr.update.push"; + private static final String TITLE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Push_Update_Focus_Point"); + + private enum OperateType { + CLOSE_WINDOW(0), UPDATE(1), REMIND_NEXT_TIME(2), SKIP(3); + private int index; + OperateType(int index) { + this.index = index; + } + private String toText() { + return String.valueOf(this.index); + } + } + + private static void submit(OperateType opType) { + FocusPoint focusPoint = FocusPoint.create(ID, opType.toText(), Original.EMBED); + focusPoint.setTitle(TITLE); + MetricRegistry.getMetric().submit(focusPoint); + } + } +} 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..dcb5d45fd --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateManager.java @@ -0,0 +1,168 @@ +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; + +/** + * Created by plough on 2019/4/8. + */ +public class DesignerPushUpdateManager { + private static final String SPLIT_CHAR = "-"; + private static DesignerPushUpdateManager singleton; + + private DesignerUpdateInfo updateInfo; + + static { + if (DesignerPushUpdateConfigManager.getInstance().isAutoPushUpdateEnabled()) { + DesignerContext.getDesignerFrame().addDesignerOpenedListener(new DesignerOpenedListener() { + @Override + public void designerOpened() { + getInstance().checkAndPop(); + } + }); + } + } + + private DesignerPushUpdateManager() { + } + + public static DesignerPushUpdateManager getInstance() { + if (singleton == null) { + singleton = new DesignerPushUpdateManager(); + } + return singleton; + } + + private void initUpdateInfo(String currentVersion, String latestVersion) { + String lastIgnoredVersion = DesignerPushUpdateConfigManager.getInstance().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 (Throwable 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; + } + + /** + * 检查更新,如果有合适的更新版本,则弹窗 + */ + private 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(); + + 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; + } + DesignerPushUpdateConfigManager.getInstance().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 b754fe2b4..0e83ff12f 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,10 +1,10 @@ -package com.fr.design.onlineupdate.ui.dialog; +package com.fr.design.update.ui.dialog; 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.stable.ProductConstants; 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 e0a8fa4de..ade5c6e27 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.design.RestartHelper; import com.fr.design.constants.LayoutConstants; @@ -10,17 +10,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; @@ -58,7 +58,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; @@ -136,6 +143,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(); @@ -147,6 +156,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}; @@ -427,6 +443,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()); @@ -435,6 +452,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/java/com/fr/design/upm/UpmBridge.java b/designer-base/src/main/java/com/fr/design/upm/UpmBridge.java new file mode 100644 index 000000000..3d0f28613 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/UpmBridge.java @@ -0,0 +1,406 @@ +package com.fr.design.upm; + +import com.fr.base.passport.FinePassportManager; +import com.fr.config.MarketConfig; +import com.fr.decision.webservice.v10.plugin.helper.category.impl.UpmResourceLoader; +import com.fr.design.bridge.exec.JSBridge; +import com.fr.design.bridge.exec.JSCallback; +import com.fr.design.extra.PluginOperateUtils; +import com.fr.design.extra.PluginUtils; +import com.fr.design.extra.exe.GetInstalledPluginsExecutor; +import com.fr.design.extra.exe.GetPluginCategoriesExecutor; +import com.fr.design.extra.exe.GetPluginFromStoreExecutor; +import com.fr.design.extra.exe.PluginLoginExecutor; +import com.fr.design.extra.exe.ReadUpdateOnlineExecutor; +import com.fr.design.extra.exe.SearchOnlineExecutor; +import com.fr.design.i18n.Toolkit; +import com.fr.design.upm.event.CertificateEvent; +import com.fr.design.upm.event.DownloadEvent; +import com.fr.design.upm.exec.UpmBrowserExecutor; +import com.fr.design.upm.task.UpmTaskWorker; +import com.fr.event.EventDispatcher; +import com.fr.general.CloudCenter; +import com.fr.general.GeneralUtils; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.context.PluginMarker; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; +import com.teamdev.jxbrowser.chromium.Browser; +import com.teamdev.jxbrowser.chromium.JSArray; +import com.teamdev.jxbrowser.chromium.JSFunction; +import com.teamdev.jxbrowser.chromium.JSObject; + +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.awt.*; +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; +import java.util.concurrent.RunnableFuture; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-12 + * 桥接Java和JavaScript的类 + */ +public class UpmBridge { + + public static UpmBridge getBridge(Browser browser) { + return new UpmBridge(browser); + } + + private JSObject window; + + private UpmBridge(Browser browser) { + this.window = browser.executeJavaScriptAndReturnValue("window").asObject(); + } + + public void startDownload(final JSFunction callback) { + + new SwingWorker(){ + @Override + protected Void doInBackground() throws Exception { + callback.invoke(window, Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Download_Start")); + UpmResourceLoader.INSTANCE.download(); + UpmResourceLoader.INSTANCE.install(); + return null; + } + + @Override + protected void done() { + try { + get(); + callback.invoke(window, Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Download_Success")); + EventDispatcher.fire(DownloadEvent.SUCCESS, "success"); + } catch (Exception e) { + callback.invoke(window, Toolkit.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Download_Error")); + FineLoggerFactory.getLogger().error(e.getMessage(), e); + EventDispatcher.fire(DownloadEvent.ERROR, "error"); + } + } + }.execute(); + } + + @JSBridge + public String i18nText(String key) { + return Toolkit.i18nText(key); + } + + @JSBridge + public void closeWindow() { + UpmFinder.closeWindow(); + } + + + @JSBridge + public boolean isDesigner() { + return true; + } + + @JSBridge + public void getPackInfo(final JSFunction callback) { + callback.invoke(window, StringUtils.EMPTY); + } + + /** + * 在线获取插件分类 + * + * @param callback 回调函数 + */ + @JSBridge + public void getPluginCategories(final JSFunction callback) { + UpmTaskWorker task = new UpmTaskWorker<>(new JSCallback(UpmBrowserExecutor.create(window, callback)), new GetPluginCategoriesExecutor()); + task.execute(); + } + + /** + * 根据条件获取在线插件 + * + * @param info 插件信息 + * @param callback 回调函数 + */ + @JSBridge + public void getPluginFromStoreNew(String info, final JSFunction callback) { + UpmTaskWorker task = new UpmTaskWorker<>(new JSCallback(UpmBrowserExecutor.create(window, callback)), new GetPluginFromStoreExecutor(new JSONObject(info))); + task.execute(); + } + + /** + * 已安装插件检查更新 + */ + @JSBridge + public void readUpdateOnline(final JSFunction callback) { + UpmTaskWorker task = new UpmTaskWorker<>(new JSCallback(UpmBrowserExecutor.create(window, callback)), new ReadUpdateOnlineExecutor()); + task.execute(); + } + + /** + * 获取已经安装的插件的数组 + */ + @JSBridge + public void getInstalledPlugins(final JSFunction callback) { + UpmTaskWorker task = new UpmTaskWorker<>(new JSCallback(UpmBrowserExecutor.create(window, callback)), new GetInstalledPluginsExecutor()); + task.execute(); + } + + /** + * 从插件服务器上更新选中的插件 + * + * @param pluginIDs 插件集合 + */ + @JSBridge + public void updatePluginOnline(Object pluginIDs, final JSFunction callback) { + JSCallback jsCallback = new JSCallback(UpmBrowserExecutor.create(window, callback)); + List pluginMarkerList = new ArrayList<>(); + if (pluginIDs instanceof String) { + pluginMarkerList.add(PluginUtils.createPluginMarker(pluginIDs.toString())); + } else if (pluginIDs instanceof JSArray) { + JSArray pluginInfos = (JSArray) pluginIDs; + for (int i = 0, len = pluginInfos.length(); i < len; i++) { + String value = pluginInfos.get(i).asString().getValue(); + pluginMarkerList.add(PluginUtils.createPluginMarker(value)); + } + } + PluginOperateUtils.updatePluginOnline(pluginMarkerList, jsCallback); + } + + /** + * 搜索在线插件 + * + * @param keyword 关键字 + */ + @JSBridge + public void searchPlugin(String keyword, final JSFunction callback) { + UpmTaskWorker worker = new UpmTaskWorker<>(new JSCallback(UpmBrowserExecutor.create(window, callback)), new SearchOnlineExecutor(keyword)); + worker.execute(); + } + + /** + * 从磁盘上选择插件安装包进行安装 + * + * @param filePath 插件包的路径 + */ + @JSBridge + public void installPluginFromDisk(final String filePath, final JSFunction callback) { + JSCallback jsCallback = new JSCallback(UpmBrowserExecutor.create(window, callback)); + File file = new File(filePath); + PluginOperateUtils.installPluginFromDisk(file, jsCallback); + } + + /** + * 卸载当前选中的插件 + * + * @param pluginInfo 插件信息 + */ + @JSBridge + public void uninstallPlugin(final String pluginInfo, final boolean isForce, final JSFunction callback) { + JSCallback jsCallback = new JSCallback(UpmBrowserExecutor.create(window, callback)); + PluginOperateUtils.uninstallPlugin(pluginInfo, isForce, jsCallback); + } + + /** + * 从插件服务器上安装插件 + * + * @param pluginInfo 插件的ID + * @param callback 回调函数 + */ + @JSBridge + public void installPluginOnline(final String pluginInfo, final JSFunction callback) { + JSCallback jsCallback = new JSCallback(UpmBrowserExecutor.create(window, callback)); + PluginMarker pluginMarker = PluginUtils.createPluginMarker(pluginInfo); + PluginOperateUtils.installPluginOnline(pluginMarker, jsCallback); + } + + /** + * 从磁盘上选择插件安装包进行插件升级 + * + * @param filePath 插件包的路径 + */ + public void updatePluginFromDisk(String filePath, final JSFunction callback) { + JSCallback jsCallback = new JSCallback(UpmBrowserExecutor.create(window, callback)); + File file = new File(filePath); + PluginOperateUtils.updatePluginFromDisk(file, jsCallback); + } + + /** + * 修改选中的插件的活跃状态 + * + * @param pluginID 插件ID + */ + @JSBridge + public void setPluginActive(String pluginID, final JSFunction callback) { + JSCallback jsCallback = new JSCallback(UpmBrowserExecutor.create(window, callback)); + PluginOperateUtils.setPluginActive(pluginID, jsCallback); + } + + /** + * 选择文件对话框 + * + * @return 选择的文件的路径 + */ + @JSBridge + public String showFileChooser() { + return showFileChooserWithFilter(StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 选择文件对话框 + * + * @param des 过滤文件描述 + * @param filter 文件的后缀 + * @return 选择的文件的路径 + * 这里换用JFileChooser会卡死,不知道为什么 + */ + @JSBridge + public String showFileChooserWithFilter(final String des, final String filter) { + RunnableFuture future = new FutureTask<>(new Callable() { + @Override + public String call() { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + + if (StringUtils.isNotEmpty(filter)) { + fileChooser.setFileFilter(new FileNameExtensionFilter(des, UpmUtils.findMatchedExtension(filter))); + } + + int result = fileChooser.showOpenDialog(UpmFinder.getDialog()); + if (result == JFileChooser.APPROVE_OPTION) { + return fileChooser.getSelectedFile().getAbsolutePath(); + } + return null; + } + }); + SwingUtilities.invokeLater(future); + try { + return future.get(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } + + /** + * 选择文件对话框 + * + * @param des 过滤文件描述 + * @param args 文件的后缀 + * @return 选择的文件的路径 + */ + @JSBridge + public String showFileChooserWithFilters(final String des, final Object args) { + RunnableFuture future = new FutureTask<>(new Callable() { + @Override + public String call() { + JFileChooser fileChooser = new JFileChooser(); + List filterList = new ArrayList<>(); + if (args instanceof String) { + filterList.add(GeneralUtils.objectToString(args)); + } else if (args instanceof JSArray) { + JSArray array = (JSArray)args; + for (int i = 0, len = array.length(); i < len; i ++) { + filterList.add(array.get(i).getStringValue()); + } + } + String[] filters = filterList.toArray(new String[0]); + if (ArrayUtils.isNotEmpty(filters)) { + FileNameExtensionFilter filter = new FileNameExtensionFilter(des, UpmUtils.findMatchedExtension(filters)); + fileChooser.setFileFilter(filter); + } + int result = fileChooser.showOpenDialog(UpmFinder.getDialog()); + if (result == JFileChooser.APPROVE_OPTION) { + return fileChooser.getSelectedFile().getAbsolutePath(); + } + return null; + } + }); + SwingUtilities.invokeLater(future); + try { + return future.get(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } + + ////////登录相关/////// + + /** + * 获取系统登录的用户名 + */ + @JSBridge + public String getLoginInfo(final JSFunction callback) { + registerLoginInfo(callback); + return MarketConfig.getInstance().getBbsUsername(); + } + + /** + * 系统登录注册 + * + * @param callback 回调函数 + */ + @JSBridge + public void registerLoginInfo(final JSFunction callback) { + JSCallback jsCallback = new JSCallback(UpmBrowserExecutor.create(window, callback)); + String username = MarketConfig.getInstance().getBbsUsername(); + if (StringUtils.isEmpty(username)) { + jsCallback.execute(StringUtils.EMPTY); + EventDispatcher.fire(CertificateEvent.LOGOUT, StringUtils.EMPTY); + } else { + jsCallback.execute(username); + EventDispatcher.fire(CertificateEvent.LOGIN, username); + } + } + + + /** + * 设计器端的用户登录 + * + * @param username 用户名 + * @param password 密码 + * @param callback 回调函数 + */ + @JSBridge + public void defaultLogin(String username, String password, final JSFunction callback) { + UpmTaskWorker worker = new UpmTaskWorker<>(new JSCallback(UpmBrowserExecutor.create(window, callback)), new PluginLoginExecutor(username, password)); + worker.execute(); + } + + /** + * 清除用户信息 + */ + public void clearUserInfo() { + MarketConfig.getInstance().setInShowBBsName(StringUtils.EMPTY); + FinePassportManager.getInstance().logout(); + EventDispatcher.fire(CertificateEvent.LOGOUT, StringUtils.EMPTY); + } + + /** + * 打开论坛消息界面 + */ + @JSBridge + public void getPriviteMessage() { + try { + String loginUrl = CloudCenter.getInstance().acquireUrlByKind("bbs.default"); + Desktop.getDesktop().browse(new URI(loginUrl)); + } catch (Exception exp) { + FineLoggerFactory.getLogger().info(exp.getMessage()); + } + } + + /** + * 忘记密码 + */ + @JSBridge + public void forgetHref() { + try { + Desktop.getDesktop().browse(new URI(CloudCenter.getInstance().acquireUrlByKind("bbs.reset"))); + } catch (Exception e) { + FineLoggerFactory.getLogger().info(e.getMessage()); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java b/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java new file mode 100644 index 000000000..5b90d4330 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/UpmFinder.java @@ -0,0 +1,68 @@ +package com.fr.design.upm; + +import com.fr.base.FRContext; +import com.fr.design.dialog.UIDialog; +import com.fr.design.mainframe.DesignerContext; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.fr.stable.StableUtils; +import com.fr.workspace.Workspace; +import com.fr.workspace.WorkspaceEvent; + +import javax.swing.*; +import java.io.File; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-12 + */ +public class UpmFinder { + + private static final String UPM_DIR = "/upm"; + private static final String MAIN_RESOURCE_PATH = UPM_DIR + "/plugin_design.html"; + + public static String installHome = FRContext.getCommonOperator().getWebRootPath(); + + private static UIDialog dialog = null; + + static { + EventDispatcher.listen(WorkspaceEvent.AfterSwitch, new Listener() { + @Override + public void on(Event event, Workspace param) { + installHome = FRContext.getCommonOperator().getWebRootPath(); + } + }); + } + + public static boolean checkUPMResourcesExist() { + String mainJsPath = StableUtils.pathJoin(installHome, MAIN_RESOURCE_PATH); + File file = new File(mainJsPath); + return file.exists(); + } + + public static String getMainResourcePath() { + return "file:///" + StableUtils.pathJoin(installHome, MAIN_RESOURCE_PATH); + } + + public static UIDialog getDialog() { + return dialog; + } + + public static void showUPMDialog() { + UpmShowPane upmPane = new UpmShowPane(); + if (dialog == null) { + dialog = new UpmShowDialog(DesignerContext.getDesignerFrame(), upmPane); + } + dialog.setVisible(true); + } + + public static void closeWindow() { + if (dialog != null) { + dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + dialog.setVisible(false); + dialog = null; + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/upm/UpmShowDialog.java b/designer-base/src/main/java/com/fr/design/upm/UpmShowDialog.java new file mode 100644 index 000000000..704e01121 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/UpmShowDialog.java @@ -0,0 +1,34 @@ +package com.fr.design.upm; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.UIDialog; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.stable.StableUtils; + +import javax.swing.*; +import java.awt.*; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-12 + */ +public class UpmShowDialog extends UIDialog { + + private static final Dimension DEFAULT_SHOP = new Dimension(900, 700); + + public UpmShowDialog(Frame frame, BasicPane pane) { + super(frame); + setUndecorated(true); + JPanel panel = (JPanel) getContentPane(); + panel.setLayout(new BorderLayout()); + add(pane, BorderLayout.CENTER); + setSize(DEFAULT_SHOP); + GUICoreUtils.centerWindow(this); + setResizable(false); + } + + @Override + public void checkValid() throws Exception { + } +} diff --git a/designer-base/src/main/java/com/fr/design/upm/UpmShowPane.java b/designer-base/src/main/java/com/fr/design/upm/UpmShowPane.java new file mode 100644 index 000000000..e64e5f02e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/UpmShowPane.java @@ -0,0 +1,63 @@ +package com.fr.design.upm; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.ui.ModernUIPane; +import com.fr.design.upm.event.DownloadEvent; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.teamdev.jxbrowser.chromium.JSValue; +import com.teamdev.jxbrowser.chromium.events.ScriptContextAdapter; +import com.teamdev.jxbrowser.chromium.events.ScriptContextEvent; + +import java.awt.*; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-12 + * Update Plugin Manager容器 + */ +public class UpmShowPane extends BasicPane { + + private ModernUIPane modernUIPane; + + @Override + protected String title4PopupWindow() { + return "UPM"; + } + + public UpmShowPane() { + setLayout(new BorderLayout()); + if (UpmFinder.checkUPMResourcesExist()) { + modernUIPane = new ModernUIPane.Builder<>() + .prepare(new ScriptContextAdapter() { + @Override + public void onScriptContextCreated(ScriptContextEvent event) { + JSValue window = event.getBrowser().executeJavaScriptAndReturnValue("window"); + window.asObject().setProperty("PluginHelper", UpmBridge.getBridge(event.getBrowser())); + } + }) + .withURL(UpmFinder.getMainResourcePath()) + .build(); + } else { + modernUIPane = new ModernUIPane.Builder<>() + .withComponent(WarnComponent.KEY) + .prepare(new ScriptContextAdapter() { + @Override + public void onScriptContextCreated(ScriptContextEvent event) { + JSValue window = event.getBrowser().executeJavaScriptAndReturnValue("window"); + window.asObject().setProperty("PluginHelper", UpmBridge.getBridge(event.getBrowser())); + } + }).build(); + EventDispatcher.listen(DownloadEvent.SUCCESS, new Listener() { + @Override + public void on(Event event, String param) { + modernUIPane.redirect(UpmFinder.getMainResourcePath()); + } + }); + } + add(modernUIPane, BorderLayout.CENTER); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/upm/UpmUtils.java b/designer-base/src/main/java/com/fr/design/upm/UpmUtils.java new file mode 100644 index 000000000..a74f0f616 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/UpmUtils.java @@ -0,0 +1,21 @@ +package com.fr.design.upm; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-18 + */ +public class UpmUtils { + + public static String[] findMatchedExtension(String... extensions) { + List list = new ArrayList<>(); + for (String ext : extensions) { + String[] arr = ext.split("\\."); + list.add(arr[arr.length - 1]); + } + return list.toArray(new String[0]); + } +} diff --git a/designer-base/src/main/java/com/fr/design/upm/WarnComponent.java b/designer-base/src/main/java/com/fr/design/upm/WarnComponent.java new file mode 100644 index 000000000..3ab134acf --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/WarnComponent.java @@ -0,0 +1,33 @@ +package com.fr.design.upm; + +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-04-12 + */ +public class WarnComponent extends AssembleComponent { + + public static final WarnComponent KEY = new WarnComponent(); + + private WarnComponent() { + + } + + @Override + public ScriptPath script(RequestClient req) { + return ScriptPath.build("com/fr/design/upm/warn.js"); + } + + @Override + public Atom[] refer() { + return new Atom[]{ + FineUI.KEY + }; + } +} diff --git a/designer-base/src/main/java/com/fr/design/upm/event/CertificateEvent.java b/designer-base/src/main/java/com/fr/design/upm/event/CertificateEvent.java new file mode 100644 index 000000000..571076844 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/event/CertificateEvent.java @@ -0,0 +1,12 @@ +package com.fr.design.upm.event; + +import com.fr.event.Event; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-18 + */ +public enum CertificateEvent implements Event { + LOGIN,LOGOUT +} diff --git a/designer-base/src/main/java/com/fr/design/upm/event/DownloadEvent.java b/designer-base/src/main/java/com/fr/design/upm/event/DownloadEvent.java new file mode 100644 index 000000000..e07156b83 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/event/DownloadEvent.java @@ -0,0 +1,13 @@ +package com.fr.design.upm.event; + +import com.fr.event.Event; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-12 + */ +public enum DownloadEvent implements Event { + + SUCCESS, ERROR +} diff --git a/designer-base/src/main/java/com/fr/design/upm/exec/UpmBrowserExecutor.java b/designer-base/src/main/java/com/fr/design/upm/exec/UpmBrowserExecutor.java new file mode 100644 index 000000000..572f7b5f2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/exec/UpmBrowserExecutor.java @@ -0,0 +1,30 @@ +package com.fr.design.upm.exec; + +import com.fr.design.bridge.exec.JSExecutor; +import com.teamdev.jxbrowser.chromium.JSFunction; +import com.teamdev.jxbrowser.chromium.JSObject; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-18 + */ +public class UpmBrowserExecutor implements JSExecutor { + + public static UpmBrowserExecutor create(JSObject window, JSFunction callback) { + return new UpmBrowserExecutor(window, callback); + } + + private JSObject window; + private JSFunction callback; + + private UpmBrowserExecutor(JSObject window, JSFunction callback) { + this.window = window; + this.callback = callback; + } + + @Override + public void executor(String newValue) { + callback.invoke(window, newValue); + } +} diff --git a/designer-base/src/main/java/com/fr/design/upm/loader/UpmDesignResourceLoader.java b/designer-base/src/main/java/com/fr/design/upm/loader/UpmDesignResourceLoader.java new file mode 100644 index 000000000..93857dc8b --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/loader/UpmDesignResourceLoader.java @@ -0,0 +1,27 @@ +package com.fr.design.upm.loader; + +import com.fr.decision.webservice.bean.plugin.store.ProjectInfoBean; +import com.fr.decision.webservice.v10.plugin.helper.category.impl.BaseResourceLoader; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-18 + */ +public class UpmDesignResourceLoader extends BaseResourceLoader { + + @Override + public String getPluginPath() { + return "upm/plugin_design.html"; + } + + @Override + public void checkResourceExist(ProjectInfoBean projectInfoBean) throws Exception { + + } + + @Override + public String getDownloadPath() throws Exception { + return "http://fanruan-market.oss-cn-shanghai.aliyuncs.com/upm/1.0/upm-10.0.zip"; + } +} diff --git a/designer-base/src/main/java/com/fr/design/upm/task/UpmTaskWorker.java b/designer-base/src/main/java/com/fr/design/upm/task/UpmTaskWorker.java new file mode 100644 index 000000000..4de519837 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/upm/task/UpmTaskWorker.java @@ -0,0 +1,52 @@ +package com.fr.design.upm.task; + +import com.fr.design.bridge.exec.JSCallback; +import com.fr.design.bridge.exec.JSUtils; +import com.fr.design.extra.Process; +import com.fr.design.extra.exe.Command; +import com.fr.design.extra.exe.Executor; +import com.fr.stable.StringUtils; + +import javax.swing.*; + +/** + * @author richie + * @version 10.0 + * Created by richie on 2019-04-17 + */ +public class UpmTaskWorker extends SwingWorker { + + private Executor executor; + private JSCallback callback; + + public UpmTaskWorker(final JSCallback callback, final Executor executor) { + this.executor = executor; + this.callback = callback; + } + + @Override + protected V doInBackground() throws Exception { + Command[] commands = executor.getCommands(); + for (Command command : commands) { + String message = command.getExecuteMessage(); + if (StringUtils.isNotBlank(message)) { + publish(message); + } + command.run(new Process() { + @Override + public void process(String s) { + if (StringUtils.isNotBlank(s)) { + publish(JSUtils.trimText(s)); + } + } + }); + } + return null; + } + + @Override + protected void done() { + String result = executor.getTaskFinishMessage(); + callback.execute(result); + } +} diff --git a/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java b/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java index 8687461a1..dab6e4f85 100644 --- a/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java +++ b/designer-base/src/main/java/com/fr/design/utils/DesignUtils.java @@ -1,6 +1,5 @@ package com.fr.design.utils; -import com.fr.base.BaseUtils; import com.fr.base.FeedBackInfo; import com.fr.base.ServerConfig; import com.fr.design.DesignerEnvManager; @@ -14,8 +13,7 @@ import com.fr.general.FRFont; import com.fr.general.GeneralContext; import com.fr.log.FineLoggerFactory; import com.fr.stable.ArrayUtils; -import com.fr.stable.CodeUtils; -import com.fr.stable.EncodeConstants; +import com.fr.stable.CommonCodeUtils; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; import com.fr.start.ServerStarter; @@ -33,32 +31,33 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; import java.net.ServerSocket; import java.net.Socket; import java.net.URI; -import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.Enumeration; import java.util.Locale; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * Some util method of Designer */ public class DesignUtils { - private static final int MESSAGEPORT = 51462; - private static final int TIME_OUT = 20 * 1000; + private static int port = DesignerPort.MESSAGE_PORT; - public synchronized static void setPort(int port) { - DesignUtils.port = port; + private DesignUtils() { } - private static int port = MESSAGEPORT; - - private DesignUtils() { + public synchronized static void setPort(int port) { + DesignUtils.port = port; } + public static int getPort() { + return port; + } /** * 通过端口是否被占用判断设计器有没有启动 @@ -70,8 +69,7 @@ public class DesignUtils { try { new Socket("localhost", port); return true; - } catch (Exception exp) { - + } catch (Exception ignored) { } return false; } @@ -82,7 +80,7 @@ public class DesignUtils { * @param lines 命令行 */ public static void clientSend(String[] lines) { - if (lines != null && lines.length <= 0) { + if (lines == null || lines.length == 0) { return; } Socket socket = null; @@ -90,18 +88,21 @@ public class DesignUtils { try { socket = new Socket("localhost", port); - writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), EncodeConstants.ENCODING_UTF_8))); + writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8))); for (int i = 0; i < lines.length; i++) { writer.println(lines[i]); } - writer.flush(); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } finally { try { - writer.close(); - socket.close(); + if (writer != null) { + writer.close(); + } + if (socket != null) { + socket.close(); + } } catch (IOException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } @@ -114,47 +115,52 @@ public class DesignUtils { * @param startPort 端口 * @param suffixs 文件后缀 */ - public static void creatListeningServer(final int startPort, final String[] suffixs) { - Thread serverSocketThread = new Thread() { + public static void createListeningServer(final int startPort, final String[] suffixs) { + ExecutorService service = Executors.newSingleThreadExecutor(); + service.execute(new Runnable() { + @Override public void run() { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(startPort); } catch (IOException e1) { - FineLoggerFactory.getLogger().error("Cannot create server socket on" + port); + FineLoggerFactory.getLogger().error("Cannot create server socket on " + port); } while (true) { try { - Socket socket = serverSocket.accept(); // 接收客户连接 - BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), EncodeConstants.ENCODING_UTF_8)); - String line = null; - while ((line = reader.readLine()) != null) { - if (line.startsWith("demo")) { - DesignerEnvManager.getEnvManager().setCurrentEnv2Default(); - ServerStarter.browserDemoURL(); - } else if (StringUtils.isNotEmpty(line)) { - File f = new File(line); - String path = f.getAbsolutePath(); - - boolean isMatch = false; - for (int i = 0; i < suffixs.length; i++) { - isMatch = isMatch || path.endsWith(suffixs[i]); - } - if (isMatch) { - DesignerContext.getDesignerFrame().openTemplate(new FileFILE(f)); + if (serverSocket != null) { + Socket socket = serverSocket.accept(); // 接收客户连接 + BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8)); + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith("demo")) { + DesignerEnvManager.getEnvManager().setCurrentEnv2Default(); + ServerStarter.browserDemoURL(); + } else if (StringUtils.isNotEmpty(line)) { + File f = new File(line); + String path = f.getAbsolutePath(); + + boolean isMatch = false; + for (int i = 0; i < suffixs.length; i++) { + isMatch = isMatch || path.endsWith(suffixs[i]); + } + if (isMatch) { + DesignerContext.getDesignerFrame().openTemplate(new FileFILE(f)); + } } } + reader.close(); + socket.close(); + } else { + FineLoggerFactory.getLogger().error("Cannot create server socket on " + port); + break; } - - reader.close(); - socket.close(); - } catch (IOException e) { - + } catch (IOException ignored) { } } } - }; - serverSocketThread.start(); + }); + } /** @@ -278,19 +284,18 @@ public class DesignUtils { */ public static void visitEnvServerByParameters(String baseRoute, String[] names, String[] values) { int len = Math.min(ArrayUtils.getLength(names), ArrayUtils.getLength(values)); - String[] segs = new String[len]; + String[] nameValuePairs = new String[len]; for (int i = 0; i < len; i++) { - try { - //设计器里面据说为了改什么界面统一, 把分隔符统一用File.separator, 意味着在windows里面报表路径变成了\ - //以前的超链, 以及预览url什么的都是/, 产品组的意思就是用到的地方替换下, 真恶心. - String value = values[i].replaceAll("\\\\", "/"); - segs[i] = URLEncoder.encode(CodeUtils.cjkEncode(names[i]), EncodeConstants.ENCODING_UTF_8) + "=" + URLEncoder.encode(CodeUtils.cjkEncode(value), "UTF-8"); - } catch (UnsupportedEncodingException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } + //设计器里面据说为了改什么界面统一, 把分隔符统一用File.separator, 意味着在windows里面报表路径变成了\ + //以前的超链, 以及预览url什么的都是/, 产品组的意思就是用到的地方替换下, 真恶心. + String value = values[i].replaceAll("\\\\", "/"); + // 两次 encode 支持中文和特殊符号,避免跳转登录后预览400报错 + nameValuePairs[i] = + CommonCodeUtils.encodeURIComponent(CommonCodeUtils.encodeURIComponent(names[i])) + + "=" + CommonCodeUtils.encodeURIComponent(CommonCodeUtils.encodeURIComponent(value)); } - String postfixOfUri = (segs.length > 0 ? "?" + StableUtils.join(segs, "&") : StringUtils.EMPTY); - + String postfixOfUri = (nameValuePairs.length > 0 ? "?" + StableUtils.join(nameValuePairs, "&") : StringUtils.EMPTY); + if (!WorkContext.getCurrent().isLocal()) { try { String urlPath = getWebBrowserPath(); @@ -305,8 +310,7 @@ public class DesignUtils { + "/" + web + "/" + ServerConfig.getInstance().getServletName() + baseRoute + postfixOfUri; ServerStarter.browserURLWithLocalEnv(url); - } catch (Throwable e) { - // + } catch (Throwable ignored) { } } } @@ -321,87 +325,6 @@ public class DesignUtils { return urlPath; } - //TODO:august:下个版本,要把下面的图片都放在一个preload文件夹下,表示可以预先加载。然后遍历一下就可以了,不用这么一个一个的写了 - - /** - * 预加载 - */ - public static void preLoadingImages() { - BaseUtils.readIcon("com/fr/design/images/custombtn/baobiaozhuti.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/baobiaozhuti_hover.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/baobiaozhuti_click.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/canshujiemian.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/canshujiemian_hover.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/canshujiemian_click.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/setting.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/setting_hover.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/setting_click.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/page.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/page_hover.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/page_click.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/form.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/form_hover.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/form_click.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/edit.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/edit_hover.png"); - BaseUtils.readIcon("com/fr/design/images/custombtn/edit_click.png"); - BaseUtils.readIcon("com/fr/base/images/oem/addworksheet.png"); - BaseUtils.readIcon("com/fr/design/images/sheet/addpolysheet.png"); - BaseUtils.readIcon("com/fr/base/images/oem/worksheet.png"); - BaseUtils.readIcon("com/fr/design/images/sheet/polysheet.png"); - BaseUtils.readIcon("com/fr/design/images/sheet/left_right_btn.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/cellPop.png"); - BaseUtils.readIcon("/com/fr/design/images/docking/right.gif"); - BaseUtils.readIcon("/com/fr/design/images/docking/left.gif"); - BaseUtils.readIcon("/com/fr/design/images/m_file/save.png"); - BaseUtils.readIcon("/com/fr/design/images/m_file/excel.png"); - BaseUtils.readIcon("/com/fr/design/images/m_file/pdf.png"); - BaseUtils.readIcon("/com/fr/design/images/m_file/word.png"); - BaseUtils.readIcon("/com/fr/design/images/m_file/svg.png"); - BaseUtils.readIcon("/com/fr/design/images/m_file/csv.png"); - BaseUtils.readIcon("/com/fr/design/images/m_file/text.png"); - BaseUtils.readIcon("/com/fr/design/images/m_web/datasource.png"); - BaseUtils.readIcon("/com/fr/design/images/m_report/webreportattribute.png"); - BaseUtils.readIcon("/com/fr/design/images/m_file/pageSetup.png"); - BaseUtils.readIcon("/com/fr/design/images/m_report/header.png"); - BaseUtils.readIcon("/com/fr/design/images/m_report/footer.png"); - BaseUtils.readIcon("/com/fr/design/images/m_file/saveAs.png"); - BaseUtils.readIcon("/com/fr/design/images/m_report/background.png"); - loadOtherImages(); - } - - - private static void loadOtherImages() { - BaseUtils.readIcon("/com/fr/design/images/m_report/reportWriteAttr.png"); - BaseUtils.readIcon("/com/fr/design/images/m_report/linearAttr.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/bindColumn.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/text.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/chart.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/image.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/bias.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/subReport.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/insertRow.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/insertColumn.png"); - BaseUtils.readIcon("/com/fr/design/images/m_format/highlight.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/hyperLink.png"); - BaseUtils.readIcon("/com/fr/design/images/m_edit/merge.png"); - BaseUtils.readIcon("/com/fr/design/images/m_edit/unmerge.png"); - BaseUtils.readIcon("/com/fr/design/images/m_file/export.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/cell.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/float.png"); - BaseUtils.readIcon("/com/fr/design/images/m_edit/undo.png"); - BaseUtils.readIcon("/com/fr/design/images/m_edit/redo.png"); - BaseUtils.readIcon("/com/fr/design/images/m_edit/cut.png"); - BaseUtils.readIcon("/com/fr/design/images/m_edit/paste.png"); - BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/leftAlignment.png"); - BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/centerAlignment.png"); - BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/rightAlignment.png"); - BaseUtils.readIcon("/com/fr/design/images/m_format/noboder.png"); - BaseUtils.readIcon("/com/fr/design/images/gui/color/background.png"); - BaseUtils.readIcon("/com/fr/design/images/m_insert/floatPop.png"); - } - - /** * 将用户反馈发送至服务器 * diff --git a/designer-base/src/main/java/com/fr/design/utils/DesignerPort.java b/designer-base/src/main/java/com/fr/design/utils/DesignerPort.java new file mode 100644 index 000000000..7c082800e --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/utils/DesignerPort.java @@ -0,0 +1,26 @@ +package com.fr.design.utils; + +/** + * 为的就是能替换 DesignPort.class 实现多开,因此避免编译器常量编译展开优化 + */ +public class DesignerPort { + private DesignerPort() { + } + + /** + * 设计器端口,避免编译期常量优化展开 + */ + public static final int MESSAGE_PORT = getMessagePort(); + /** + * 设计器端口,避免编译期常量优化展开 + */ + public static final int DEBUG_MESSAGE_PORT = getDebugMessagePort(); + + private static int getMessagePort() { + return 51462; + } + + private static int getDebugMessagePort() { + return 51463; + } +} diff --git a/designer-base/src/main/java/com/fr/env/RemoteEnvPane.java b/designer-base/src/main/java/com/fr/env/RemoteEnvPane.java index b0f3e9dd4..0d4839d6d 100644 --- a/designer-base/src/main/java/com/fr/env/RemoteEnvPane.java +++ b/designer-base/src/main/java/com/fr/env/RemoteEnvPane.java @@ -19,8 +19,8 @@ import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; import com.fr.third.guava.base.Strings; import com.fr.workspace.WorkContext; -import com.fr.workspace.connect.AuthException; import com.fr.workspace.connect.WorkspaceConnectionInfo; +import com.fr.workspace.engine.exception.WorkspaceAuthException; import javax.swing.BorderFactory; import javax.swing.BoxLayout; @@ -523,7 +523,7 @@ public class RemoteEnvPane extends BasicBeanPane { DesignerEnvManager.getEnvManager().setCertificatePass(connection.getCertSecretKey()); try { return WorkContext.getConnector().testConnection(connection); - } catch (AuthException ignored) { + } catch (WorkspaceAuthException ignored) { return null; } } @@ -532,27 +532,9 @@ public class RemoteEnvPane extends BasicBeanPane { protected void done() { okButton.setEnabled(true); try { - TestConnectionResult result = TestConnectionResult.parse(get(), connection); - if (result == TestConnectionResult.Fully_Success) { - message.setText(Toolkit.i18nText("Fine-Design_Basic_Remote_Connect_Successful")); - uiLabel.setIcon(UIManager.getIcon("OptionPane.informationIcon")); - } - - if (result == TestConnectionResult.Partly_Sucess) { - message.setText(Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Version_Inconsistence_Test")); - uiLabel.setIcon(UIManager.getIcon("OptionPane.warningIcon")); - } - - if (result == TestConnectionResult.Fully_Failed) { - message.setText(Toolkit.i18nText("Fine-Design_Basic_Remote_Connect_Failed")); - uiLabel.setIcon(UIManager.getIcon("OptionPane.errorIcon")); - } - - if (result == TestConnectionResult.Auth_Failed) { - message.setText(Toolkit.i18nText("Fine-Design_Basic_Remote_Connect_Auth_Failed")); - uiLabel.setIcon(UIManager.getIcon("OptionPane.errorIcon")); - } + message.setText(result.getText()); + uiLabel.setIcon(result.getIcon()); } catch (InterruptedException | ExecutionException e) { FineLoggerFactory.getLogger().error(e, e.getMessage()); message.setText(Toolkit.i18nText("Fine-Design_Basic_Remote_Connect_Failed")); diff --git a/designer-base/src/main/java/com/fr/env/TestConnectionResult.java b/designer-base/src/main/java/com/fr/env/TestConnectionResult.java index 357d4f38c..5362dbbd8 100644 --- a/designer-base/src/main/java/com/fr/env/TestConnectionResult.java +++ b/designer-base/src/main/java/com/fr/env/TestConnectionResult.java @@ -1,62 +1,104 @@ package com.fr.env; +import com.fr.design.i18n.Toolkit; import com.fr.log.FineLoggerFactory; import com.fr.stable.AssistUtils; import com.fr.workspace.WorkContext; import com.fr.workspace.connect.WorkspaceConnectionInfo; import com.fr.workspace.engine.channel.http.FunctionalHttpRequest; +import javax.swing.Icon; +import javax.swing.UIManager; + /** * 测试连接的结果。 * 不改变原有逻辑的情况下,加入一层转化。 * 根据这里的转化结果,判断需要提示哪些内容。 - * + *

* created by Harrison on 2018/12/20 **/ public enum TestConnectionResult { /** * 完全成功, 版本匹配,测试连接成功。 */ - Fully_Success, + FULLY_SUCCESS { + @Override + public Icon getIcon() { + return UIManager.getIcon("OptionPane.informationIcon"); + } + + @Override + public String getText() { + return Toolkit.i18nText("Fine-Design_Basic_Remote_Connect_Successful"); + } + }, /** * 不完全成功,版本不匹配,但测试连接成功。 */ - Partly_Sucess, + PARTLY_SUCCESS { + @Override + public Icon getIcon() { + return UIManager.getIcon("OptionPane.warningIcon"); + } + + @Override + public String getText() { + return Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Version_Inconsistence_Test"); + } + }, /** * 完全失败,直接没连上 */ - Fully_Failed, + FULLY_FAILED { + @Override + public Icon getIcon() { + return UIManager.getIcon("OptionPane.errorIcon"); + } + + @Override + public String getText() { + return Toolkit.i18nText("Fine-Design_Basic_Remote_Connect_Failed"); + } + }, /** * 验证 Token 失败 */ - Auth_Failed; + AUTH_FAILED { + @Override + public Icon getIcon() { + return UIManager.getIcon("OptionPane.errorIcon"); + } + + @Override + public String getText() { + return Toolkit.i18nText("Fine-Design_Basic_Remote_Connect_Auth_Failed"); + } + }; + + public abstract Icon getIcon(); + + public abstract String getText(); public static TestConnectionResult parse(Boolean value, WorkspaceConnectionInfo info) { if (value == null) { - return Auth_Failed; + return AUTH_FAILED; } - if (!value) { - return Fully_Failed; + return FULLY_FAILED; } try { - String serverVersion = new FunctionalHttpRequest(info).getServerVersion(); if (AssistUtils.equals(serverVersion, WorkContext.getVersion())) { - return Fully_Success; + return FULLY_SUCCESS; } - - return Partly_Sucess; + return PARTLY_SUCCESS; } catch (Exception e) { - // 发生异常,说明没连接上。返回完全失败。 FineLoggerFactory.getLogger().error(e.getMessage()); - return Fully_Failed; + return FULLY_FAILED; } - - } } diff --git a/designer-base/src/main/java/com/fr/start/OemHandler.java b/designer-base/src/main/java/com/fr/start/OemHandler.java new file mode 100644 index 000000000..b127e07f4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/start/OemHandler.java @@ -0,0 +1,14 @@ +package com.fr.start; + +import com.fr.design.fun.OemProcessor; +import com.fr.stable.bridge.StableFactory; + +/** + * OEM处理中心 + */ +public class OemHandler { + + public static OemProcessor findOem() { + return StableFactory.getMarkedInstanceObjectFromClass(OemProcessor.MARK_STRING, OemProcessor.class); + } +} \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/aspectj/designerbase/TemplateProcessTracker.aj b/designer-base/src/main/resources/com/fr/aspectj/designerbase/TemplateProcessTracker.aj deleted file mode 100644 index 1ab23100b..000000000 --- a/designer-base/src/main/resources/com/fr/aspectj/designerbase/TemplateProcessTracker.aj +++ /dev/null @@ -1,58 +0,0 @@ -package com.fr.aspectj.designerbase; - -/** - * 记录模板过程 - * Created by plough on 2017/3/3. - */ - -import org.aspectj.lang.reflect.SourceLocation; - -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; - -public aspect TemplateProcessTracker { - //声明一个pointcut,匹配你需要的方法 - pointcut onMouseClicked(MouseEvent e): - execution(* mouseClicked(MouseEvent)) && args(e); - pointcut onMousePressed(MouseEvent e): - execution(* mousePressed(MouseEvent)) && args(e); - pointcut onMouseReleased(MouseEvent e): - execution(* mouseReleased(MouseEvent)) && args(e); - pointcut onActionPerformed(ActionEvent e): - execution(* actionPerformed(ActionEvent)) && args(e); - pointcut onSetValueAt(Object v, int r, int c): - execution(* setValueAt(java.lang.Object, int, int)) && args(v, r, c); - - //before表示之前的意思 - //这整个表示在MouseAdapter的public void mouseXXX(MouseEvent)方法调用之前,你想要执行的代码 - before(MouseEvent e): onMouseClicked(e) || onMousePressed(e) || onMouseReleased(e) { - SourceLocation sl = thisJoinPoint.getSourceLocation();//切面对应的代码位置 - - //String log = String.format("%s:\n%s\n%s\n%s\n\n", new Date(), sl, e, e.getSource()); - String log = ""; - //TemplateInfoCollector.appendProcess(log); - } - //同上 - before(ActionEvent e): onActionPerformed(e) { - SourceLocation sl = thisJoinPoint.getSourceLocation(); - // !within(LogHandlerBar) 没用, 手动过滤 - if (e != null && e.getSource().toString().contains("javax.swing.Timer")) { - return; - } - - //String log = String.format("%s:\n%s\n%s\n%s\n\n", new Date(), sl, e, e.getSource()); - String log = ""; - //TemplateInfoCollector.appendProcess(log); - - } - //同上 - before(Object v, int r, int c): onSetValueAt(v, r, c) { - SourceLocation sl = thisJoinPoint.getSourceLocation(); - - //String log getSourceLocation= String.format("%s:\n%s\nset value: %s at (%d, %d)\n\n", new Date(), sl, v, r, c); - String log = ""; - // TemplateInfoCollector.appendProcess(log); - } - - -} diff --git a/designer-base/src/main/resources/com/fr/design/images/bbs/facebook.png b/designer-base/src/main/resources/com/fr/design/images/bbs/facebook.png new file mode 100644 index 000000000..9e5dc8af2 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/bbs/facebook.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_back_normal@2x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_back_normal@2x.png new file mode 100644 index 000000000..bb3fd50cd Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_back_normal@2x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_delete.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_delete.png new file mode 100755 index 000000000..6fb2baac5 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_delete.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_delete@2x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_delete@2x.png new file mode 100755 index 000000000..b98c9f4cd Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_delete@2x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_edit.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_edit.png new file mode 100755 index 000000000..7206039bf Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_edit.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_edit@2x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_edit@2x.png new file mode 100755 index 000000000..5993e4389 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_edit@2x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_filter@1x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_filter@1x.png new file mode 100755 index 000000000..7a8ec6287 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_filter@1x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_filter@2x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_filter@2x.png new file mode 100755 index 000000000..9b3a132a7 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_filter@2x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_list_disabled.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_list_disabled.png new file mode 100644 index 000000000..5325682ff Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_list_disabled.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_list_disabled@2x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_list_disabled@2x.png new file mode 100644 index 000000000..619551cc8 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_list_disabled@2x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_list_normal@2x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_list_normal@2x.png new file mode 100644 index 000000000..a400bffec Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_list_normal@2x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_revert.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_revert.png new file mode 100755 index 000000000..993ba3c21 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_revert.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_revert@2x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_revert@2x.png new file mode 100755 index 000000000..5f26df54c Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_revert@2x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_save_disabled.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_save_disabled.png new file mode 100644 index 000000000..3e164a0eb Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_save_disabled.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_save_disabled@2x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_save_disabled@2x.png new file mode 100644 index 000000000..70db7bcc4 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_save_disabled@2x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_save_normal@2x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_save_normal@2x.png new file mode 100644 index 000000000..34e94cb27 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_save_normal@2x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_user@1x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_user@1x.png new file mode 100755 index 000000000..7af8db572 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_user@1x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/icon_user@2x.png b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_user@2x.png new file mode 100755 index 000000000..872351544 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/icon_user@2x.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/vcs_back.png b/designer-base/src/main/resources/com/fr/design/images/vcs/vcs_back.png new file mode 100644 index 000000000..6b3a61b89 Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/vcs_back.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/vcs_list.png b/designer-base/src/main/resources/com/fr/design/images/vcs/vcs_list.png new file mode 100644 index 000000000..df6cd02de Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/vcs_list.png differ diff --git a/designer-base/src/main/resources/com/fr/design/images/vcs/vcs_save.png b/designer-base/src/main/resources/com/fr/design/images/vcs/vcs_save.png new file mode 100644 index 000000000..6783204cf Binary files /dev/null and b/designer-base/src/main/resources/com/fr/design/images/vcs/vcs_save.png differ 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 index 0274d5fa5..03b2bb32a 100644 --- a/designer-base/src/main/resources/com/fr/design/ui/InitNameSpace.js +++ b/designer-base/src/main/resources/com/fr/design/ui/InitNameSpace.js @@ -1,6 +1,6 @@ -var arr ="%s".split(".").reverse(); -var create = function (obj, names) { - var name = names.pop(); +let arr ="%s".split(".").reverse(); +let create = function (obj, names) { + let name = names.pop(); if (!name) { return; } 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..58c03ecba --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/ui/update/push/pushUpdate.css @@ -0,0 +1,88 @@ +body { + padding-left: 30px; + padding-top: 30px; + color: white; + background-size: 100% 100% !important; + -moz-background-size: 100% 100% !important; + + font-family: "PingFang SC", "Microsoft YaHei", "Myriad Pro", "OpenSans", Verdana, SimSun, sans-serif !important; +} + +.close-btn { + position: fixed !important; + font-size: 15px !important; + color: white !important; + top: 8px; + right: 10px; + width: 19px; +} + +.close-btn .b-font { + height: 19px !important; + line-height: 19px !important; +} + +.close-btn .b-font:before { + color: white !important; +} + +.font-bold { + font-weight: 500; +} + +.title { + font-size: 24px; + letter-spacing: 1.5px; + line-height: 24px; +} + +.version { + font-size: 12px; + line-height: 14px; + margin-top: 6px; +} + +.desc { + margin-top: 40px; + font-size: 13px; + width: 82%; + margin-left: 19px; + text-indent: -19px; + overflow: visible !important; +} + +.desc .bi-label { + overflow: visible !important; +} + +.moreInfo { + margin-top: 20px; + font-size: 13px; + text-decoration: underline; +} + +.buttonGroup { + position: absolute !important; + bottom: 60px; +} + +.buttonGroup .bi-button { + font-weight: 600; + font-size: 11px; + text-align: center; + line-height: 12px; + box-shadow: 0 2px 4px 0 rgba(0,82,169,0.20); + border-radius: 12px; +} + +.buttonGroup .button-ignore { + background-color: white !important; + border: 1px solid white !important; + color: #51A6FF; +} + +.buttonGroup .button-common { + background-color: #51A6FF !important; + border: 1px solid #51A6FF !important; +} + 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..f42fb1ac7 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/ui/update/push/pushUpdate.js @@ -0,0 +1,143 @@ +var MAX_DESC_NUM = 5; // 最多显示5条信息 + +function i18nText(key) { + return Pool.data.i18nText(key); +} + +function getDescArea(descList) { + var descItems = []; + for (var i in descList) { + var num = parseInt(i) + 1; + if (num > MAX_DESC_NUM) { + break; + } + descItems.push({ + type: "bi.label", + text: num + ")" + descList[i], + whiteSpace: "pre-wrap", + textAlign: "left" + }) + } + + return BI.createWidget({ + type: "bi.vertical", + cls: "desc", + items: descItems + }); +} + +function getTitleArea() { + return BI.createWidget({ + type: "bi.vertical", + items: [ + { + type: "bi.label", + text: i18nText("Fine-Design_Find_New_Version"), + cls: "title font-bold", + textAlign: "left" + }, + { + type: "bi.label", + text: Pool.data.getVersion(), + cls: "version font-bold", + textAlign: "left" + } + ] + }); +} + +function getButtonGroup() { + return BI.createWidget({ + type: 'bi.left', + cls: "buttonGroup", + items: [ + { + type: 'bi.button', + text: i18nText("Fine-Design_Update_Now"), + level: 'common', + height: 24, + handler: function () { + Pool.data.updateNow(); + } + }, + { + el: { + type: 'bi.button', + text: i18nText("Fine-Design_Remind_Me_Next_Time"), + level: 'ignore', + height: 24, + handler: function () { + Pool.data.remindNextTime(); + } + }, + lgap: 10 + }, + { + el: { + type: 'bi.button', + text: i18nText("Fine-Design_Skip_This_Version"), + level: 'ignore', + height: 24, + handler: function () { + Pool.data.skipThisVersion(); + } + }, + lgap: 10 + } + ] + }); +} + +function getMoreInfo() { + return BI.createWidget({ + type: "bi.text_button", + text: i18nText("Fine-Design_See_More_New_Features"), + cls: "moreInfo", + textAlign: "left", + handler: function () { + // 为了使用系统的浏览器,只能从 Java 那边打开网页 + Pool.data.browseMoreInfoUrl(); + } + }); +} + +function getCloseButton() { + return BI.createWidget({ + type: "bi.button", + text: "", + iconCls: "close-font", + cls: "close-btn", + clear: true, + handler: function () { + Pool.data.closeWindow(); + } + }); +} + +function getShowItems() { + var title = getTitleArea(); + + var closeButton = getCloseButton(); + + var descList = Pool.data.getContent().split("\n"); + var descArea = getDescArea(descList); + + var moreInfo = getMoreInfo(); + + var buttonGroup = getButtonGroup(); + + return [title, closeButton, descArea, moreInfo, buttonGroup]; +} + +window.addEventListener("load", function (ev) { + var showItems = getShowItems(); + + var container = BI.createWidget({ + type:"bi.vertical", + element: "body", + cls: "container", + items: showItems + }); + + container.element.css("background", "url(" + Pool.data.getBackgroundUrl() + ")"); +}); \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/upm/warn.js b/designer-base/src/main/resources/com/fr/design/upm/warn.js new file mode 100644 index 000000000..1eb5fb640 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/upm/warn.js @@ -0,0 +1,61 @@ +window.onload = function () { + let label = BI.createWidget({ + type: "bi.label", + text: PluginHelper.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Resource_Warn"), + height: 30 + }); + let callback = function(text) { + download.setValue(text); + }; + let buttonOK = BI.createWidget({ + type: "bi.button", + text: PluginHelper.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Download"), + level: 'common', + height: 30, + handler: function () { + PluginHelper.startDownload(callback); + } + }); + let buttonClose = BI.createWidget({ + type: "bi.button", + text: PluginHelper.i18nText("Fine-Design_Basic_Update_Plugin_Manager_Close"), + level: 'warning', + height: 30, + handler: function () { + PluginHelper.closeWindow(); + } + }); + + let download = BI.createWidget({ + type: "bi.label", + height: 30 + }); + let left = 300; + let top = 200; + BI.createWidget({ + type: "bi.absolute", + element: "body", + items: [ + { + el: label, + left: left, + top: top + }, + { + el : buttonOK, + left : left, + top : top + 40 + }, + { + el : buttonClose, + left : left + 100, + top : top + 40 + }, + { + el : download, + left : left, + top : top + 80 + } + ] + }); +}; \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/mainframe/template/info/DesignerOpenHistoryTest.java b/designer-base/src/test/java/com/fr/design/mainframe/template/info/DesignerOpenHistoryTest.java new file mode 100644 index 000000000..3e95cfec7 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/mainframe/template/info/DesignerOpenHistoryTest.java @@ -0,0 +1,120 @@ +package com.fr.design.mainframe.template.info; + +import com.fr.invoke.Reflect; +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.Before; +import org.junit.Test; + +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.Calendar; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Created by plough on 2019/4/21. + */ +public class DesignerOpenHistoryTest { + private DesignerOpenHistory openHistory; + private String[] mockHistory = new String[] { + "2019-04-08", "2019-04-03", "2019-03-29" + }; + + @Before + public void setUp() { + openHistory = DesignerOpenHistory.getInstance(); + Reflect.on(openHistory).set("history", mockHistory); + } + + @Test + public void testReadAndWrite() throws XMLStreamException { + // 写入 xml + StringWriter sw = new StringWriter(); + XMLPrintWriter writer = XMLPrintWriter.create(new PrintWriter(sw)); + openHistory.writeXML(writer); + writer.flush(); + writer.close(); + + String xmlText = sw.getBuffer().toString(); + + // 临时修改配置 + Reflect.on(openHistory).set("history", new String[] {"", "", ""}); + + // 从 xml 中读取 + StringReader sr = new StringReader(xmlText); + XMLableReader xmlReader = XMLableReader.createXMLableReader(sr); + xmlReader.readXMLObject(openHistory); + + // 验证:与写入时的配置一致 + assertArrayEquals(mockHistory, (String[])Reflect.on(openHistory).field("history").get()); + } + + @Test + public void testToString() { + assertEquals("2019-04-08,2019-04-03,2019-03-29", openHistory.toString()); + } + + @Test + public void testParseString() { + String[] mockDates = {"2020-04-08", "2019-04-03", "2016-03-29"}; + Reflect.on(openHistory).call("parseString", StringUtils.join(",", mockDates)); + assertArrayEquals(mockDates, (String[])Reflect.on(openHistory).field("history").get()); + } + + @Test + public void testGetHistorySpanDayCount() { + assertEquals(11, openHistory.getHistorySpanDayCount()); + + Reflect.on(openHistory).set("history", new String[] {"2019-05-03", "2019-05-02", ""}); + assertEquals(2, openHistory.getHistorySpanDayCount()); + + Reflect.on(openHistory).set("history", new String[] {"2019-05-03", "", ""}); + assertEquals(1, openHistory.getHistorySpanDayCount()); + + try { + Reflect.on(openHistory).set("history", new String[] {"", "", ""}); + fail("should not be here"); + } catch (AssertionError ignore) { + } + } + + @Test + public void testOpenEnoughTimesInPeriod() { + assertTrue(openHistory.isOpenEnoughTimesInPeriod(15)); + assertFalse(openHistory.isOpenEnoughTimesInPeriod(3)); + + Reflect.on(openHistory).set("history", new String[] {"2019-05-03", "2019-05-02", ""}); + assertFalse(openHistory.isOpenEnoughTimesInPeriod(15)); + + Reflect.on(openHistory).set("history", new String[] {"2019-05-03", "", ""}); + assertFalse(openHistory.isOpenEnoughTimesInPeriod(15)); + } + + @Test + public void testHasOpenedToday() { + assertFalse(openHistory.hasOpenedToday()); + + Reflect.on(openHistory).set("history", new String[] {getToday(), "2019-02-02", ""}); + assertTrue(openHistory.hasOpenedToday()); + } + + @Test + public void testUpdate() { + openHistory.update(); + String[] arr = { getToday(), "2019-04-08", "2019-04-03" }; + assertArrayEquals(arr, (String[])Reflect.on(openHistory).field("history").get()); + } + + private String getToday() { + return new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); + } +} diff --git a/designer-base/src/test/java/com/fr/design/mainframe/template/info/SendHelperTest.java b/designer-base/src/test/java/com/fr/design/mainframe/template/info/SendHelperTest.java new file mode 100644 index 000000000..fb89143d8 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/mainframe/template/info/SendHelperTest.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.template.info; + +import com.fr.invoke.Reflect; +import com.fr.stable.xml.XMLableReader; +import com.fr.third.javax.xml.stream.XMLStreamException; + +import java.io.StringReader; + +import static org.junit.Assert.assertTrue; + +/** + * Created by plough on 2019/4/25. + */ +public class SendHelperTest { + private static final String CONSUMING_URL = "http://cloud.fanruan.com/api/monitor/record_of_reports_consuming/single"; + private static final String PROCESS_URL = "http://cloud.fanruan.com/api/monitor/record_of_reports_process/single"; + + private static final String NORMAL_INFO = "\n" + + "\n" + + "\n" + + ""; + + // 只在调试的时候运行,不需要每次都自动运行 + public static void main(String[] args) throws XMLStreamException { + StringReader sr = new StringReader(NORMAL_INFO); + XMLableReader xmlReader = XMLableReader.createXMLableReader(sr); + TemplateInfo templateInfo = TemplateInfo.newInstanceByRead(xmlReader); + + boolean res = Reflect.on(SendHelper.class).call("sendSingleTemplateInfo", CONSUMING_URL, templateInfo.getConsumingMapJsonString()).get(); + assertTrue(res); + + boolean res2 = Reflect.on(SendHelper.class).call("sendSingleTemplateInfo", PROCESS_URL, templateInfo.getProcessMapJsonString()).get(); + assertTrue(res2); + } +} diff --git a/designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoCollectorTest.java b/designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoCollectorTest.java new file mode 100644 index 000000000..e83a523fc --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoCollectorTest.java @@ -0,0 +1,195 @@ +package com.fr.design.mainframe.template.info; + +import com.fr.config.MarketConfig; +import com.fr.general.GeneralUtils; +import com.fr.invoke.Reflect; +import com.fr.stable.ProductConstants; +import com.fr.stable.StringUtils; +import com.fr.third.org.apache.commons.io.FileUtils; +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.Before; +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 java.io.File; +import java.io.IOException; +import java.util.Map; + +import static com.fr.design.mainframe.template.info.TemplateInfoTestHelper.assertJsonStringEquals; +import static com.fr.design.mainframe.template.info.TemplateInfoTestHelper.setUpMockForNewInstance; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Created by plough on 2019/4/18. + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({ProductConstants.class, MarketConfig.class, ProductConstants.class, GeneralUtils.class}) +public class TemplateInfoCollectorTest { + private String filePath; + private String initialFileContent; + private TemplateProcessInfo mockProcessInfo; + + @Before + public void setUp() throws IOException { + PowerMock.mockStatic(ProductConstants.class); + + filePath = getClass().getResource("tpl.info").getPath(); + String dirPath = filePath.substring(0, filePath.indexOf("tpl.info")); + EasyMock.expect(ProductConstants.getEnvHome()).andReturn(dirPath).anyTimes(); + EasyMock.replay(); + PowerMock.replayAll(); + + mockProcessInfo = EasyMock.mock(TemplateProcessInfo.class); + EasyMock.expect(mockProcessInfo.getBlockCount()).andReturn(3).anyTimes(); + EasyMock.expect(mockProcessInfo.getCellCount()).andReturn(13).anyTimes(); + EasyMock.expect(mockProcessInfo.getFloatCount()).andReturn(1).anyTimes(); + EasyMock.expect(mockProcessInfo.getReportType()).andReturn(0).anyTimes(); + EasyMock.expect(mockProcessInfo.getWidgetCount()).andReturn(0).anyTimes(); + EasyMock.replay(mockProcessInfo); + + // 缓存 tpl.info + initialFileContent = FileUtils.readFileToString(new File(filePath), "utf-8"); + + Reflect.on(TemplateInfoCollector.class).set("instance", null); + } + + @After + public void tearDown() throws IOException { + // 恢复 tpl.info + FileUtils.writeStringToFile(new File(filePath), initialFileContent, "utf-8"); + } + + @Test + public void testReadXML() { + assertEquals(",,", DesignerOpenHistory.getInstance().toString()); + + TemplateInfoCollector collector = TemplateInfoCollector.getInstance(); + assertEquals(7, ((Map) Reflect.on(collector).field("templateInfoMap").get()).size()); + + assertEquals("2019-04-08,2019-04-03,2019-03-29", DesignerOpenHistory.getInstance().toString()); + } + + @Test + public void testCollectInfo() { + TemplateInfoCollector collector = TemplateInfoCollector.getInstance(); + + String templateID = "16a988ce-8529-42f5-b17c-2ee849355071"; + int timeConsume = 200; + + collector.collectInfo(templateID, StringUtils.EMPTY, mockProcessInfo, timeConsume); + + // 检查是否写入成功 + collector.loadFromFile(); + TemplateInfo templateInfo = collector.getOrCreateTemplateInfoByID(templateID); + + assertJsonStringEquals("{\"process\":\"\",\"float_count\":1,\"widget_count\":0," + + "\"cell_count\":13,\"block_count\":3,\"report_type\":0," + + "\"templateID\":\"16a988ce-8529-42f5-b17c-2ee849355071\"}",templateInfo.getProcessMapJsonString()); + + assertJsonStringEquals("{\"activitykey\":\"2e0ea413-fa9c241e0-9723-4354fce51e81\"," + + "\"jar_time\":\"不是安装版本\",\"create_time\":\"2019-03-26 16:13\"," + + "\"templateID\":\"16a988ce-8529-42f5-b17c-2ee849355071\",\"originID\":\"\"," + + "\"uuid\":\"476ca2cc-f789-4c5d-8e89-ef146580775c\",\"time_consume\":329,\"originTime\":0," + + "\"version\":\"10.0\",\"username\":\"plough\"}", templateInfo.getConsumingMapJsonString()); + } + + @Test + public void testCollectInfoForNewTemplate() throws Exception { + setUpMockForNewInstance(); + + TemplateInfoCollector collector = TemplateInfoCollector.getInstance(); + + String templateID = "73a97777-8jnk-47cd-b57c-2ee89991279796"; + int timeConsume = 200; + + collector.collectInfo(templateID, StringUtils.EMPTY, mockProcessInfo, timeConsume); + + // 检查是否写入成功 + collector.loadFromFile(); + assertTrue(collector.contains(templateID)); + + TemplateInfo templateInfo = collector.getOrCreateTemplateInfoByID(templateID); + assertEquals(templateID, templateInfo.getTemplateID()); + + assertJsonStringEquals("{\"process\":\"\",\"float_count\":1,\"widget_count\":0," + + "\"cell_count\":13,\"block_count\":3,\"report_type\":0," + + "\"templateID\":\"73a97777-8jnk-47cd-b57c-2ee89991279796\"}",templateInfo.getProcessMapJsonString()); + + Map consumingMap = Reflect.on(templateInfo).field("consumingMap").get(); + assertEquals(templateID, consumingMap.get("templateID")); + assertEquals(StringUtils.EMPTY, consumingMap.get("originID")); + assertEquals(200, consumingMap.get("time_consume")); + assertEquals(0, consumingMap.get("originTime")); + } + + @Test + public void testCollectInfoWhenSaveAs() throws Exception { + setUpMockForNewInstance(); + + TemplateInfoCollector collector = TemplateInfoCollector.getInstance(); + + String templateID = "423238d4-5223-22vj-vlsj-42jc49245iw3"; + String originID = "16a988ce-8529-42f5-b17c-2ee849355071"; + int timeConsume = 200; + + collector.collectInfo(templateID, originID, mockProcessInfo, timeConsume); + + // 检查是否写入成功 + collector.loadFromFile(); + TemplateInfo templateInfo = collector.getOrCreateTemplateInfoByID(templateID); + + assertJsonStringEquals("{\"process\":\"\",\"float_count\":1,\"widget_count\":0," + + "\"cell_count\":13,\"block_count\":3,\"report_type\":0," + + "\"templateID\":\"423238d4-5223-22vj-vlsj-42jc49245iw3\"}", templateInfo.getProcessMapJsonString()); + + Map consumingMap = Reflect.on(templateInfo).field("consumingMap").get(); + assertEquals(templateID, consumingMap.get("templateID")); + assertEquals(originID, consumingMap.get("originID")); + assertEquals(329, consumingMap.get("time_consume")); + assertEquals(129, consumingMap.get("originTime")); + } + + @Test + public void testCollectInfoWhenSaveAsWithNoTrackOriginID() throws Exception { + setUpMockForNewInstance(); + + TemplateInfoCollector collector = TemplateInfoCollector.getInstance(); + + String templateID = "423238d4-5223-22vj-vlsj-42jc49245iw3"; + String originID = "3kha8jcs-31xw-42f5-h2ww-2ee84935312z"; + int timeConsume = 200; + + collector.collectInfo(templateID, originID, mockProcessInfo, timeConsume); + + TemplateInfo templateInfo = collector.getOrCreateTemplateInfoByID(templateID); + assertEquals(templateID, templateInfo.getTemplateID()); + assertEquals(originID, templateInfo.getOriginID()); + + Map consumingMap = Reflect.on(templateInfo).field("consumingMap").get(); + assertEquals(templateID, consumingMap.get("templateID")); + assertEquals(originID, consumingMap.get("originID")); + assertEquals(200, consumingMap.get("time_consume")); + assertEquals(0, consumingMap.get("originTime")); + } + + @Test + public void testAddIdleDateCount() { + String templateID = "16a988ce-8529-42f5-b17c-2ee849355071"; + TemplateInfoCollector collecter = TemplateInfoCollector.getInstance(); + TemplateInfo templateInfo = collecter.getOrCreateTemplateInfoByID(templateID); + + assertEquals(9, templateInfo.getIdleDayCount()); + + Reflect.on(collecter).call("addIdleDayCount"); + assertEquals(10, templateInfo.getIdleDayCount()); + + // 同一天内多次调用无效 + Reflect.on(collecter).call("addIdleDayCount"); + assertEquals(10, templateInfo.getIdleDayCount()); + } +} diff --git a/designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoTest.java b/designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoTest.java new file mode 100644 index 000000000..19f6066ff --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoTest.java @@ -0,0 +1,125 @@ +package com.fr.design.mainframe.template.info; + +import com.fr.config.MarketConfig; +import com.fr.general.GeneralUtils; +import com.fr.invoke.Reflect; +import com.fr.stable.ProductConstants; +import com.fr.stable.StringUtils; +import com.fr.stable.xml.XMLableReader; +import com.fr.third.javax.xml.stream.XMLStreamException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.io.StringReader; +import java.util.Map; + +import static com.fr.design.mainframe.template.info.TemplateInfoTestHelper.assertJsonStringEquals; +import static com.fr.design.mainframe.template.info.TemplateInfoTestHelper.setUpMockForNewInstance; +import static org.junit.Assert.assertEquals; + +/** + * Created by plough on 2019/4/19. + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({MarketConfig.class, ProductConstants.class, GeneralUtils.class}) +public class TemplateInfoTest { + + private static final String NORMAL_INFO = "\n" + + "\n" + + "\n" + + ""; + + private static final String SAVE_AS_INFO = "\n" + + "\n" + + "\n" + + ""; + + private TemplateInfo templateInfo; + private TemplateInfo templateInfoSaveAs; // 另存为的模版记录 + + @Before + public void setUp() throws XMLStreamException { + templateInfo = createTemplateInfo(NORMAL_INFO); + templateInfoSaveAs = createTemplateInfo(SAVE_AS_INFO); + } + + @Test + public void testNewInstance() throws Exception { + setUpMockForNewInstance(); + + String templateID = "24avc8n2-1iq8-iuj2-wx24-8yy0i8132302"; + TemplateInfo templateInfo = TemplateInfo.newInstance(templateID); + assertEquals(templateID, templateInfo.getTemplateID()); + assertEquals(StringUtils.EMPTY, Reflect.on(templateInfo).field("originID").get()); + assertEquals(0, Reflect.on(templateInfo).field("idleDayCount").get()); + assertEquals("{}", templateInfo.getProcessMapJsonString()); + + Map consumingMap = Reflect.on(templateInfo).field("consumingMap").get(); + assertEquals(templateID, consumingMap.get("templateID")); + assertEquals(0, consumingMap.get("originTime")); + assertEquals(StringUtils.EMPTY, consumingMap.get("originID")); + assertEquals(0, consumingMap.get("time_consume")); + assertEquals("不是安装版本", consumingMap.get("jar_time")); + assertEquals("plough", consumingMap.get("username")); + assertEquals("10.0", consumingMap.get("version")); + } + + @Test + public void testNewInstanceWithMoreArgs() throws Exception { + setUpMockForNewInstance(); + + String templateID = "24121212-u2c8-ncd2-82nx-8ud0i8138888"; + String originID = "24avc8n2-1iq8-iuj2-wx24-8yy0i8132302"; + int originTime = 100; + TemplateInfo templateInfo = TemplateInfo.newInstance(templateID, originID, originTime); + assertEquals(templateID, templateInfo.getTemplateID()); + assertEquals(originID, Reflect.on(templateInfo).field("originID").get()); + assertEquals(0, Reflect.on(templateInfo).field("idleDayCount").get()); + assertEquals("{}", templateInfo.getProcessMapJsonString()); + + Map consumingMap = Reflect.on(templateInfo).field("consumingMap").get(); + assertEquals(templateID, consumingMap.get("templateID")); + assertEquals(originTime, consumingMap.get("originTime")); + assertEquals(originID, consumingMap.get("originID")); + assertEquals(originTime, consumingMap.get("time_consume")); + assertEquals("不是安装版本", consumingMap.get("jar_time")); + assertEquals("plough", consumingMap.get("username")); + assertEquals("10.0", consumingMap.get("version")); + } + + @Test + public void testGetTemplateID() { + assertEquals("16a988ce-8529-42f5-b17c-2ee849355071", templateInfo.getTemplateID()); + assertEquals("49avd2c4-1104-92j2-wx24-3dd0k2136080", templateInfoSaveAs.getTemplateID()); + } + + @Test + public void testGetConsumingMapJsonString() { + assertJsonStringEquals("{\"activitykey\":\"2e0ea413-fa9c241e0-9723-4354fce51e81\",\"jar_time\":\"不是安装版本\"," + + "\"create_time\":\"2019-03-26 16:13\",\"templateID\":\"16a988ce-8529-42f5-b17c-2ee849355071\",\"originID\":\"\"," + + "\"uuid\":\"476ca2cc-f789-4c5d-8e89-ef146580775c\",\"time_consume\":129,\"originTime\":0,\"version\":\"10.0\"," + + "\"username\":\"plough\"}", templateInfo.getConsumingMapJsonString()); + + assertJsonStringEquals("{\"activitykey\":\"2e0ea413-fa9c241e0-9723-4354fce51e81\",\"jar_time\":\"不是安装版本\"," + + "\"create_time\":\"2019-03-26 16:13\",\"templateID\":\"49avd2c4-1104-92j2-wx24-3dd0k2136080\",\"originID\":\"16a988ce-8529-42f5-b17c-2ee849355071\"," + + "\"uuid\":\"476ca2cc-f789-4c5d-8e89-ef146580775c\",\"time_consume\":429,\"originTime\":129,\"version\":\"10.0\"," + + "\"username\":\"plough\"}", templateInfoSaveAs.getConsumingMapJsonString()); + } + + @Test + public void testGetProcessMapJsonString() { + assertJsonStringEquals("{\"process\":\"\",\"float_count\":0,\"widget_count\":0,\"cell_count\":1," + + "\"block_count\":0,\"report_type\":0,\"templateID\":\"16a988ce-8529-42f5-b17c-2ee849355071\"}", templateInfo.getProcessMapJsonString()); + assertJsonStringEquals("{\"process\":\"\",\"float_count\":0,\"widget_count\":0,\"cell_count\":1," + + "\"block_count\":0,\"report_type\":0,\"templateID\":\"49avd2c4-1104-92j2-wx24-3dd0k2136080\"}", templateInfoSaveAs.getProcessMapJsonString()); + } + + private TemplateInfo createTemplateInfo(String xmlContent) throws XMLStreamException { + StringReader sr = new StringReader(xmlContent); + XMLableReader xmlReader = XMLableReader.createXMLableReader(sr); + return TemplateInfo.newInstanceByRead(xmlReader); + } +} diff --git a/designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoTestHelper.java b/designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoTestHelper.java new file mode 100644 index 000000000..be2b58989 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/mainframe/template/info/TemplateInfoTestHelper.java @@ -0,0 +1,49 @@ +package com.fr.design.mainframe.template.info; + +import com.fr.config.MarketConfig; +import com.fr.general.ComparatorUtils; +import com.fr.general.GeneralUtils; +import com.fr.json.JSONObject; +import com.fr.stable.ProductConstants; +import org.easymock.EasyMock; +import org.powermock.api.easymock.PowerMock; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import static org.junit.Assert.assertTrue; + +/** + * Created by plough on 2019/4/19. + */ +class TemplateInfoTestHelper { + static void assertJsonStringEquals(String jo1, String jo2) { + // HashMap 是无序的,所以不能直接比较它生成的 json 字符串 + assertTrue(ComparatorUtils.equals(new JSONObject(jo1), new JSONObject(jo2))); + } + + private static void setFinalStatic(Field field, Object newValue) throws Exception { + field.setAccessible(true); + // remove final modifier from field + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(null, newValue); + } + + static void setUpMockForNewInstance() throws Exception { + MarketConfig mockMarketConfig = EasyMock.mock(MarketConfig.class); + EasyMock.expect(mockMarketConfig.getBbsUsername()).andReturn("plough").anyTimes(); + + PowerMock.mockStatic(MarketConfig.class); + EasyMock.expect(MarketConfig.getInstance()).andReturn(mockMarketConfig).anyTimes(); + + PowerMock.mockStatic(GeneralUtils.class); + EasyMock.expect(GeneralUtils.readBuildNO()).andReturn("不是安装版本").anyTimes(); + + setFinalStatic(ProductConstants.class.getDeclaredField("VERSION"), "10.0"); + + EasyMock.replay(mockMarketConfig); + PowerMock.replayAll(); + } +} diff --git a/designer-base/src/test/java/com/fr/design/mainframe/template/info/TimeConsumeTimerTest.java b/designer-base/src/test/java/com/fr/design/mainframe/template/info/TimeConsumeTimerTest.java new file mode 100644 index 000000000..5dcf60e7f --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/mainframe/template/info/TimeConsumeTimerTest.java @@ -0,0 +1,62 @@ +package com.fr.design.mainframe.template.info; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Created by plough on 2019/4/19. + */ +public class TimeConsumeTimerTest { + + @Test + public void testNotEnabled() throws InterruptedException { + TimeConsumeTimer consumeTimer = new TimeConsumeTimer(); + consumeTimer.start(); + Thread.sleep(1100); + consumeTimer.stop(); + assertEquals(0, consumeTimer.popTime()); + } + + @Test + public void testEnabled() throws InterruptedException { + TimeConsumeTimer consumeTimer = new TimeConsumeTimer(); + consumeTimer.setEnabled(true); + consumeTimer.start(); + Thread.sleep(1100); + consumeTimer.stop(); + assertEquals(1, consumeTimer.popTime()); + assertEquals(0, consumeTimer.popTime()); + } + + @Test + public void testMultiTimes() throws InterruptedException { + TimeConsumeTimer consumeTimer = new TimeConsumeTimer(); + consumeTimer.setEnabled(true); + + consumeTimer.start(); + Thread.sleep(1010); + consumeTimer.stop(); + + Thread.sleep(2000); + + consumeTimer.start(); + Thread.sleep(1010); + assertEquals(2, consumeTimer.popTime()); + } + + @Test + public void testStartMultiTime() throws InterruptedException { + TimeConsumeTimer consumeTimer = new TimeConsumeTimer(); + consumeTimer.setEnabled(true); + + consumeTimer.start(); + Thread.sleep(1010); + consumeTimer.start(); + Thread.sleep(1010); + consumeTimer.start(); + Thread.sleep(1010); + + assertEquals(3, consumeTimer.popTime()); + } +} 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..bc194fe06 --- /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", "设计器改进:去除右击弹框,让操作过程更流畅;增加报表块缩放功能,利于从全局角度整体设计报表\n插件重构:插件支持热部署,即装即用,不再需要重启服务器;\nsapbw:可用于bwcube和bwquery;\n私有云认证:可在客户本地部署私有云认证服务器,业务服务器可到此服务器进行认证;\n开放:打通简道云,可以在简道云里创建项目,并将数据同步到客户的私有库\nshould not display"); + jo.put("more", "http://baidu.com"); + jo.put("background", "http://updateten.finereport.com/fr.png"); + 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/mainframe/template/info/tpl.info b/designer-base/src/test/resources/com/fr/design/mainframe/template/info/tpl.info new file mode 100644 index 000000000..eae77630f --- /dev/null +++ b/designer-base/src/test/resources/com/fr/design/mainframe/template/info/tpl.info @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 index 2beae25a7..9e5211c89 100644 --- a/designer-base/src/test/resources/com/fr/design/ui/demo.html +++ b/designer-base/src/test/resources/com/fr/design/ui/demo.html @@ -10,6 +10,12 @@ return Pool.data; }; +

测试页面,请点击最下面的按钮
diff --git a/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java b/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java index 3a8abb56e..1255d87d5 100644 --- a/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java +++ b/designer-chart/src/main/java/com/fr/design/ChartTypeInterfaceManager.java @@ -41,6 +41,7 @@ import com.fr.design.module.DesignModuleFactory; import com.fr.form.ui.ChartEditor; import com.fr.general.GeneralContext; import com.fr.general.IOUtils; +import com.fr.locale.InterProviderFactory; import com.fr.plugin.chart.PiePlot4VanChart; import com.fr.plugin.chart.area.VanChartAreaPlot; import com.fr.plugin.chart.bubble.VanChartBubblePlot; @@ -99,7 +100,8 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import static com.fr.chart.charttypes.ChartTypeManager.CHART_PRIORITY; +import static com.fr.chart.charttypes.ChartTypeManager.DEFAULT_PRIORITY; +import static com.fr.chart.charttypes.ChartTypeManager.DEPRECATED_CHART_PRIORITY; import static com.fr.chart.charttypes.ChartTypeManager.VAN_CHART_PRIORITY; /** @@ -165,7 +167,7 @@ public class ChartTypeInterfaceManager implements ExtraChartDesignClassManagerPr } String iconPath = ChartTypeInterfaceManager.getInstance().getIconPath(plotID); Icon icon = IOUtils.readIcon(iconPath); - child[index] = new ChartWidgetOption(com.fr.design.i18n.Toolkit.i18nText(bean.getName()), icon, ChartEditor.class, plotID); + child[index] = new ChartWidgetOption(InterProviderFactory.getProvider().getLocText(bean.getName()), icon, ChartEditor.class, plotID); index++; } @@ -198,23 +200,23 @@ public class ChartTypeInterfaceManager implements ExtraChartDesignClassManagerPr private static void readDefault() { - addChartTypeInterface(CHART_PRIORITY, ChartConstants.COLUMN_CHART, new ColumnIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.LINE_CHART, new LineIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.BAR_CHART, new BarIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.PIE_CHART, new PieIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.AREA_CHART, new AreaIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.SCATTER_CHART, new XYScatterIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.BUBBLE_CHART, new BubbleIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.RADAR_CHART, new RadarIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.STOCK_CHART, new StockIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.METER_CHART, new MeterIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.RANGE_CHART, new RangeIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.CUSTOM_CHART, new CustomIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.GANTT_CHART, new GanttIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.DONUT_CHART, new DonutIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.MAP_CHART, new MapIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.GIS_CHAER, new GisMapIndependentChartInterface()); - addChartTypeInterface(CHART_PRIORITY, ChartConstants.FUNNEL_CHART, new FunnelIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.COLUMN_CHART, new ColumnIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.LINE_CHART, new LineIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.BAR_CHART, new BarIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.PIE_CHART, new PieIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.AREA_CHART, new AreaIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.SCATTER_CHART, new XYScatterIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.BUBBLE_CHART, new BubbleIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.RADAR_CHART, new RadarIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.STOCK_CHART, new StockIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.METER_CHART, new MeterIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.RANGE_CHART, new RangeIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.CUSTOM_CHART, new CustomIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.GANTT_CHART, new GanttIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.DONUT_CHART, new DonutIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.MAP_CHART, new MapIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.GIS_CHAER, new GisMapIndependentChartInterface()); + addChartTypeInterface(DEPRECATED_CHART_PRIORITY, ChartConstants.FUNNEL_CHART, new FunnelIndependentChartInterface()); } private static void addChartTypeInterface(String priority, String plotID, IndependentChartUIProvider provider) { @@ -462,7 +464,7 @@ public class ChartTypeInterfaceManager implements ExtraChartDesignClassManagerPr public void mount(PluginSingleInjection injection) { if (isIndependentChartUIProvider(injection)) { - String priority = injection.getAttribute("priority", CHART_PRIORITY); + String priority = injection.getAttribute("priority", DEFAULT_PRIORITY); String plotID = injection.getAttribute("plotID"); IndependentChartUIProvider instance = (IndependentChartUIProvider) injection.getObject(); addChartTypeInterface(priority, plotID, instance); @@ -474,7 +476,7 @@ public class ChartTypeInterfaceManager implements ExtraChartDesignClassManagerPr public void demount(PluginSingleInjection injection) { if (isIndependentChartUIProvider(injection)) { - String priority = injection.getAttribute("priority", CHART_PRIORITY); + String priority = injection.getAttribute("priority", DEFAULT_PRIORITY); String plotID = injection.getAttribute("plotID"); removeChartTypeInterface(priority, plotID); } diff --git a/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java b/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java index de7d08a2b..d914a81e8 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/design/chart/ChartTypePane.java @@ -16,6 +16,7 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.license.exception.RegistEditionException; import com.fr.license.function.VT4FR; +import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; import javax.swing.BorderFactory; @@ -67,7 +68,7 @@ public class ChartTypePane extends ChartCommonWizardPane { mainTypeList = new JList(defaultListModel); for (int i = 0; i < typeName.length; i++) { - defaultListModel.insertElementAt(com.fr.design.i18n.Toolkit.i18nText(typeName[i].getName()), i); + defaultListModel.insertElementAt(InterProviderFactory.getProvider().getLocText(typeName[i].getName()), i); } mainTypeList.addListSelectionListener(listSelectionListener); diff --git a/designer-chart/src/main/java/com/fr/design/chart/axis/MinMaxValuePane.java b/designer-chart/src/main/java/com/fr/design/chart/axis/MinMaxValuePane.java index a84cfd693..79323d73d 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/axis/MinMaxValuePane.java +++ b/designer-chart/src/main/java/com/fr/design/chart/axis/MinMaxValuePane.java @@ -35,9 +35,9 @@ public class MinMaxValuePane extends JPanel { minValueField = new UITextField(6); maxCheckBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Custom_Max_Value")); maxValueField = new UITextField(6); - isCustomMainUnitBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Custom_Main_Graduation_Unit")); + isCustomMainUnitBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Custom_Main_Type")); mainUnitField = new UITextField(6); - isCustomSecUnitBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Custom_Second_Graduation_Unit")); + isCustomSecUnitBox = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Custom_Second_Type")); secUnitField = new UITextField(6); double p = TableLayout.PREFERRED; diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/AreaPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/AreaPlotPane.java index 42667ee9d..425f50807 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/AreaPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/AreaPlotPane.java @@ -8,6 +8,8 @@ import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.Plot; import com.fr.chart.chartglyph.ConditionCollection; import com.fr.chart.charttypes.AreaIndependentChart; +import com.fr.design.i18n.Toolkit; +import com.fr.locale.InterProviderFactory; /** @@ -33,10 +35,10 @@ public class AreaPlotPane extends AbstractChartTypePane{ @Override protected String[] getTypeTipName() { - String area = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Area"); - String stack = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Stacked"); - String percent = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Use_Percent"); - String td = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_3D"); + String area = InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Area"); + String stack = Toolkit.i18nText("Fine-Design_Chart_Stacked"); + String percent = Toolkit.i18nText("Fine-Design_Chart_Use_Percent"); + String td = Toolkit.i18nText("Fine-Design_Chart_3D"); return new String[]{ stack + area, percent + stack + area, @@ -139,7 +141,7 @@ public class AreaPlotPane extends AbstractChartTypePane{ * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Area"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Area"); } public Chart getDefaultChart() { diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/BarPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/BarPlotPane.java index 280fca724..cd5e1b4d6 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/BarPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/BarPlotPane.java @@ -6,6 +6,8 @@ import com.fr.chart.chartattr.BarPlot; import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.Plot; import com.fr.chart.charttypes.BarIndependentChart; +import com.fr.design.i18n.Toolkit; +import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; @@ -31,16 +33,16 @@ public class BarPlotPane extends AbstractBarPane{ @Override protected String[] getTypeTipName() { - String bar = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Bar"); - String stack = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Stacked"); - String percent = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Use_Percent"); - String td = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_3D"); + String bar = InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Bar"); + String stack = Toolkit.i18nText("Fine-Design_Chart_Stacked"); + String percent = Toolkit.i18nText("Fine-Design_Chart_Use_Percent"); + String td = Toolkit.i18nText("Fine-Design_Chart_3D"); return new String[]{ bar, stack + bar, percent + stack + bar, td + bar, - td + bar + "(" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Direction_Horizontal") + ")", + td + bar + "(" + Toolkit.i18nText("Fine-Design_Chart_Direction_Horizontal") + ")", td + stack + bar, td + percent + stack + bar }; @@ -65,8 +67,8 @@ public class BarPlotPane extends AbstractBarPane{ * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Bar"); - } + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Bar"); + } protected Plot getSelectedClonedPlot(){ Chart[] barChart = BarIndependentChart.barChartTypes; diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/BubblePlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/BubblePlotPane.java index 103dbd194..b3e7cd34a 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/BubblePlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/BubblePlotPane.java @@ -4,6 +4,7 @@ import com.fr.chart.base.ChartConstants; import com.fr.chart.chartattr.BubblePlot; import com.fr.chart.chartattr.Chart; import com.fr.chart.charttypes.BubbleIndependentChart; +import com.fr.locale.InterProviderFactory; /** @@ -25,9 +26,9 @@ public class BubblePlotPane extends AbstractChartTypePane { @Override protected String[] getTypeTipName() { return new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Bubble_Chart") + InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Bubble_Chart") }; - } + } @Override protected String[] getTypeLayoutPath() { @@ -44,7 +45,7 @@ public class BubblePlotPane extends AbstractChartTypePane { * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Bubble_Chart"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Bubble_Chart"); } /** diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/ColumnPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/ColumnPlotPane.java index 5f290d592..55de24714 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/ColumnPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/ColumnPlotPane.java @@ -5,6 +5,8 @@ import com.fr.chart.chartattr.BarPlot; import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.Plot; import com.fr.chart.charttypes.ColumnIndependentChart; +import com.fr.design.i18n.Toolkit; +import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; @@ -30,16 +32,16 @@ public class ColumnPlotPane extends AbstractBarPane{ @Override protected String[] getTypeTipName() { - String column = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Column"); - String stack = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Stacked"); - String percent = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Use_Percent"); - String td = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_3D"); + String column = InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Column"); + String stack = Toolkit.i18nText("Fine-Design_Chart_Stacked"); + String percent = Toolkit.i18nText("Fine-Design_Chart_Use_Percent"); + String td = Toolkit.i18nText("Fine-Design_Chart_3D"); return new String[]{ column, stack + column, percent + stack + column, td + column, - td + column + "(" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Direction_Horizontal") + ")", + td + column + "(" + Toolkit.i18nText("Fine-Design_Chart_Direction_Horizontal") + ")", td + stack + column, td + percent + stack + column }; @@ -63,8 +65,8 @@ public class ColumnPlotPane extends AbstractBarPane{ * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Column"); - } + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Column"); + } protected Plot getSelectedClonedPlot(){ Chart[] barChart = ColumnIndependentChart.columnChartTypes; diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/CustomPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/CustomPlotPane.java index d6a46df45..8e367444f 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/CustomPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/CustomPlotPane.java @@ -3,6 +3,7 @@ package com.fr.design.mainframe.chart.gui.type; import com.fr.chart.base.ChartConstants; import com.fr.chart.chartattr.Chart; import com.fr.chart.charttypes.CustomIndependentChart; +import com.fr.locale.InterProviderFactory; /** @@ -26,9 +27,9 @@ public class CustomPlotPane extends AbstractChartTypePane { @Override protected String[] getTypeTipName() { return new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Combine_Chart") + InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Combine") }; - } + } @Override protected String[] getTypeLayoutPath() { @@ -45,7 +46,7 @@ public class CustomPlotPane extends AbstractChartTypePane { * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Combine_Chart"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Combine"); } /** diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/DonutPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/DonutPlotPane.java index e8643c34f..c1cd47d78 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/DonutPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/DonutPlotPane.java @@ -10,10 +10,11 @@ import com.fr.chart.chartattr.Donut3DPlot; import com.fr.chart.chartattr.Plot; import com.fr.chart.chartglyph.ConditionCollection; import com.fr.chart.charttypes.DonutIndependentChart; - +import com.fr.design.i18n.Toolkit; +import com.fr.locale.InterProviderFactory; import com.fr.stable.Constants; -import java.awt.*; +import java.awt.Color; import java.text.DecimalFormat; /** @@ -35,10 +36,10 @@ public class DonutPlotPane extends AbstractChartTypePane{ @Override protected String[] getTypeTipName() { - String donut = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Donut_Chart"); + String donut = InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Donut"); return new String[]{ donut, - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_3D") + donut + Toolkit.i18nText("Fine-Design_Chart_3D") + donut }; } @@ -103,8 +104,8 @@ public class DonutPlotPane extends AbstractChartTypePane{ * @return 标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Donut_Chart"); - } + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Donut"); + } /** * 是否有坐标轴 diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/FunnelPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/FunnelPlotPane.java index 8f31c8c55..2de685cb8 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/FunnelPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/FunnelPlotPane.java @@ -7,7 +7,7 @@ import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.FunnelPlot; import com.fr.chart.chartattr.Plot; import com.fr.chart.charttypes.FunnelIndependentChart; - +import com.fr.locale.InterProviderFactory; import java.text.DecimalFormat; @@ -31,7 +31,7 @@ public class FunnelPlotPane extends AbstractChartTypePane{ @Override protected String[] getTypeTipName() { return new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Funnel") + InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Funnel") }; } @@ -50,7 +50,7 @@ public class FunnelPlotPane extends AbstractChartTypePane{ * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Funnel"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Funnel"); } /** diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/GanttPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/GanttPlotPane.java index 537fa4628..b1845bfe4 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/GanttPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/GanttPlotPane.java @@ -3,6 +3,7 @@ package com.fr.design.mainframe.chart.gui.type; import com.fr.chart.base.ChartConstants; import com.fr.chart.chartattr.Chart; import com.fr.chart.charttypes.GanttIndependentChart; +import com.fr.locale.InterProviderFactory; /** @@ -24,9 +25,9 @@ public class GanttPlotPane extends AbstractChartTypePane{ @Override protected String[] getTypeTipName() { return new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Gantt_Chart") + InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Gantt") }; - } + } @Override protected String getPlotTypeID() { @@ -47,7 +48,7 @@ public class GanttPlotPane extends AbstractChartTypePane{ * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Gantt_Chart"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Gantt"); } /** diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/GisMapPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/GisMapPlotPane.java index 25d2fa48f..9911ce4fb 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/GisMapPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/GisMapPlotPane.java @@ -11,11 +11,12 @@ import com.fr.design.gui.itextfield.UITextField; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; +import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; - -import javax.swing.*; -import java.awt.*; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; public class GisMapPlotPane extends AbstractChartTypePane{ @@ -72,9 +73,9 @@ public class GisMapPlotPane extends AbstractChartTypePane{ @Override protected String[] getTypeTipName() { return new String[]{ - "gis"+com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Map_Map") + InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_GIS_Map") }; - } + } @Override protected String getPlotTypeID() { @@ -172,7 +173,7 @@ public class GisMapPlotPane extends AbstractChartTypePane{ * @return 标题 */ public String title4PopupWindow() { - return "gis"+com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Map_Map"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_GIS_Map"); } /** diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/LinePlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/LinePlotPane.java index 5afd3e217..0f93938bb 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/LinePlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/LinePlotPane.java @@ -5,6 +5,7 @@ import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.LinePlot; import com.fr.chart.chartattr.Plot; import com.fr.chart.charttypes.LineIndependentChart; +import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; @@ -21,9 +22,9 @@ public class LinePlotPane extends AbstractChartTypePane{ @Override protected String[] getTypeTipName() { return new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Line_Chart") + InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Line") }; - } + } @Override protected String[] getTypeLayoutPath() { @@ -83,7 +84,7 @@ public class LinePlotPane extends AbstractChartTypePane{ } public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Line_Chart"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Line"); } public Chart getDefaultChart() { diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/MapPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/MapPlotPane.java index 6f9a55ab5..d761be371 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/MapPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/MapPlotPane.java @@ -10,6 +10,7 @@ import com.fr.chart.charttypes.MapIndependentChart; import com.fr.design.chart.series.PlotSeries.MapGroupExtensionPane; import com.fr.design.chart.series.PlotStyle.ChartSelectDemoPane; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; import javax.swing.JPanel; @@ -71,7 +72,7 @@ public class MapPlotPane extends AbstractChartTypePane { * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Map_Map"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_SVG_MAP"); } /** diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/MeterPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/MeterPlotPane.java index 811053641..10293b68c 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/MeterPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/MeterPlotPane.java @@ -6,6 +6,8 @@ import com.fr.chart.chartattr.MeterPlot; import com.fr.chart.chartattr.Plot; import com.fr.chart.chartglyph.MeterStyle; import com.fr.chart.charttypes.MeterIndependentChart; +import com.fr.design.i18n.Toolkit; +import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; @@ -31,9 +33,9 @@ public class MeterPlotPane extends AbstractChartTypePane { @Override protected String[] getTypeTipName() { - String meter = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Gauge"); + String meter = InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Meter"); return new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Mode_Custom") + meter, + Toolkit.i18nText("Fine-Design_Chart_Mode_Custom") + meter, meter + "1", meter + "2" }; @@ -77,13 +79,13 @@ public class MeterPlotPane extends AbstractChartTypePane { * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Gauge"); - } - - /** - * 保存界面属性 - */ - public void updateBean(Chart chart) { + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Meter"); + } + + /** + * 保存界面属性 + */ + public void updateBean(Chart chart) { if(needsResetChart(chart)){ resetChart(chart); } diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/PiePlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/PiePlotPane.java index 98ccb0e53..eeccd2246 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/PiePlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/PiePlotPane.java @@ -10,10 +10,10 @@ import com.fr.chart.chartattr.PiePlot; import com.fr.chart.chartattr.Plot; import com.fr.chart.chartglyph.ConditionCollection; import com.fr.chart.charttypes.PieIndependentChart; - +import com.fr.locale.InterProviderFactory; import com.fr.stable.Constants; -import java.awt.*; +import java.awt.Color; import java.text.DecimalFormat; /** @@ -36,11 +36,11 @@ public class PiePlotPane extends AbstractChartTypePane{ @Override protected String[] getTypeTipName() { - String pie = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Pie"); + String pie = InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Pie"); return new String[]{ - pie, - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_3D") + pie - }; + pie, + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_3D") + pie + }; } @Override @@ -63,7 +63,7 @@ public class PiePlotPane extends AbstractChartTypePane{ * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_New_Pie"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Pie"); } private void createPieCondition(Plot plot) { diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/RadarPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/RadarPlotPane.java index 631a4d9d4..50e4a756e 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/RadarPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/RadarPlotPane.java @@ -3,6 +3,7 @@ package com.fr.design.mainframe.chart.gui.type; import com.fr.chart.base.ChartConstants; import com.fr.chart.chartattr.Chart; import com.fr.chart.charttypes.RadarIndependentChart; +import com.fr.locale.InterProviderFactory; /** @@ -24,9 +25,9 @@ public class RadarPlotPane extends AbstractChartTypePane{ @Override protected String[] getTypeTipName() { return new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Radar_Chart") + InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Radar") }; - } + } @Override protected String getPlotTypeID() { @@ -48,7 +49,7 @@ public class RadarPlotPane extends AbstractChartTypePane{ * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Radar_Chart"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Radar"); } /** diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/RangePlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/RangePlotPane.java index 405f9aa4f..f87c6074d 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/RangePlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/RangePlotPane.java @@ -4,6 +4,7 @@ import com.fr.chart.base.ChartConstants; import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.RangePlot; import com.fr.chart.charttypes.RangeIndependentChart; +import com.fr.locale.InterProviderFactory; /** @@ -25,9 +26,9 @@ public class RangePlotPane extends AbstractChartTypePane{ @Override protected String[] getTypeTipName() { return new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Range_Chart") + InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Range") }; - } + } @Override protected String getPlotTypeID() { @@ -49,7 +50,7 @@ public class RangePlotPane extends AbstractChartTypePane{ * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Range_Chart"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Range"); } /** diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/StockPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/StockPlotPane.java index 567595703..63f4ead33 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/StockPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/StockPlotPane.java @@ -3,6 +3,7 @@ package com.fr.design.mainframe.chart.gui.type; import com.fr.chart.base.ChartConstants; import com.fr.chart.chartattr.Chart; import com.fr.chart.charttypes.StockIndependentChart; +import com.fr.locale.InterProviderFactory; /** @@ -24,9 +25,9 @@ public class StockPlotPane extends AbstractChartTypePane { @Override protected String[] getTypeTipName() { return new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Stock_Chart") + InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Stock") }; - } + } @Override protected String getPlotTypeID() { @@ -48,7 +49,7 @@ public class StockPlotPane extends AbstractChartTypePane { * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_Stock_Chart"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_Stock"); } /** diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/XYScatterPlotPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/XYScatterPlotPane.java index 0effae28e..46a5b13c0 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/XYScatterPlotPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/type/XYScatterPlotPane.java @@ -6,7 +6,7 @@ import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.XYScatterPlot; import com.fr.chart.chartglyph.ConditionAttr; import com.fr.chart.charttypes.XYScatterIndependentChart; - +import com.fr.locale.InterProviderFactory; import com.fr.stable.Constants; /** @@ -28,9 +28,9 @@ public class XYScatterPlotPane extends AbstractChartTypePane{ @Override protected String[] getTypeTipName() { return new String[]{ - com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_I_XYScatterStyle_Marker") + InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_XYScatter") }; - } + } @Override protected String[] getTypeLayoutPath() { @@ -47,7 +47,7 @@ public class XYScatterPlotPane extends AbstractChartTypePane{ * @return 界面标题 */ public String title4PopupWindow() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Chart_I_XYScatterStyle_Marker"); + return InterProviderFactory.getProvider().getLocText("Fine-Engine_Chart_Type_XYScatter"); } /** diff --git a/designer-chart/src/main/java/com/fr/extended/chart/ExtendedOtherPane.java b/designer-chart/src/main/java/com/fr/extended/chart/ExtendedOtherPane.java index 31aa2d003..6fba552b7 100644 --- a/designer-chart/src/main/java/com/fr/extended/chart/ExtendedOtherPane.java +++ b/designer-chart/src/main/java/com/fr/extended/chart/ExtendedOtherPane.java @@ -11,6 +11,7 @@ import com.fr.design.mainframe.chart.AbstractChartAttrPane; import com.fr.design.mainframe.chart.PaneTitleConstants; import com.fr.van.chart.designer.TableLayout4VanChartHelper; +import javax.swing.BorderFactory; import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -138,4 +139,10 @@ public class ExtendedOtherPane extends AbstractChartAtt return PaneTitleConstants.CHART_OTHER_TITLE; } + @Override + protected void initContentPane() { + leftContentPane = createContentPane(); + leftContentPane.setBorder(BorderFactory.createMatteBorder(10, 3, 0, 10, original)); + this.add(leftContentPane, BorderLayout.CENTER); + } } diff --git a/designer-chart/src/main/resources/com/fr/aspectj/designerchart/TemplateProcessTracker.aj b/designer-chart/src/main/resources/com/fr/aspectj/designerchart/TemplateProcessTracker.aj index 89ed91033..a2d2fb7b4 100644 --- a/designer-chart/src/main/resources/com/fr/aspectj/designerchart/TemplateProcessTracker.aj +++ b/designer-chart/src/main/resources/com/fr/aspectj/designerchart/TemplateProcessTracker.aj @@ -4,13 +4,10 @@ package com.fr.aspectj.designerchart; * Created by plough on 2017/3/3. */ import com.fr.chart.chartattr.Chart; -import com.fr.design.mainframe.templateinfo.TemplateInfoCollector; import org.aspectj.lang.reflect.SourceLocation; -import javax.swing.event.ListSelectionEvent; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; -import java.util.Date; public aspect TemplateProcessTracker { //声明一个pointcut,匹配你需要的方法 diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XTreeEditor.java b/designer-form/src/main/java/com/fr/design/designer/creator/XTreeEditor.java index c5672b389..bde83a176 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XTreeEditor.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XTreeEditor.java @@ -73,7 +73,7 @@ public class XTreeEditor extends XWidgetCreator { crp = (CRPropertyDescriptor[]) ArrayUtils.add(crp, new CRPropertyDescriptor("ajax", this.data.getClass()).setI18NName( com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Widget_Load_By_Async")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, - "Advanced")); + "Fine-Design_Basic_Advanced")); crp = this.addAllowEdit(crp); crp = this.addCustomData(crp); diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java b/designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java index c9b55b298..8d3d75a35 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XWFitLayout.java @@ -1,15 +1,5 @@ package com.fr.design.designer.creator; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.event.ContainerEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.adapters.layout.FRFitLayoutAdapter; import com.fr.design.designer.beans.location.Direction; @@ -24,17 +14,25 @@ import com.fr.design.mainframe.WidgetPropertyPane; import com.fr.design.utils.gui.LayoutUtils; import com.fr.form.ui.PaddingMargin; import com.fr.form.ui.Widget; +import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget; import com.fr.form.ui.container.WBodyLayoutType; import com.fr.form.ui.container.WFitLayout; import com.fr.form.ui.container.WLayout; import com.fr.general.FRLogger; import com.fr.general.FRScreen; -import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget; - import com.fr.stable.ArrayUtils; import edu.emory.mathcs.backport.java.util.Arrays; import javax.swing.JOptionPane; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.event.ContainerEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; /** diff --git a/designer-form/src/main/java/com/fr/design/designer/properties/mobile/BodyMobilePropertyUI.java b/designer-form/src/main/java/com/fr/design/designer/properties/mobile/BodyMobilePropertyUI.java index 5175b30dc..401f7d2f2 100644 --- a/designer-form/src/main/java/com/fr/design/designer/properties/mobile/BodyMobilePropertyUI.java +++ b/designer-form/src/main/java/com/fr/design/designer/properties/mobile/BodyMobilePropertyUI.java @@ -1,8 +1,7 @@ package com.fr.design.designer.properties.mobile; import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XWAbsoluteBodyLayout; -import com.fr.design.designer.creator.XWFitLayout; +import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.dialog.BasicPane; import com.fr.design.fun.impl.AbstractWidgetPropertyUIProvider; import com.fr.design.gui.itable.AbstractPropertyTable; @@ -16,19 +15,19 @@ public class BodyMobilePropertyUI extends AbstractWidgetPropertyUIProvider { private XCreator xCreator; - public BodyMobilePropertyUI(XWFitLayout xwFitLayout) { + public BodyMobilePropertyUI(XLayoutContainer xwFitLayout) { this.xCreator = xwFitLayout; } - public BodyMobilePropertyUI(XWAbsoluteBodyLayout xwAbsoluteBodyLayout) { - this.xCreator = xwAbsoluteBodyLayout; - } - @Override public AbstractPropertyTable createWidgetAttrTable() { return null; } + public XCreator getxCreator() { + return xCreator; + } + @Override public BasicPane createWidgetAttrPane() { return new BodyMobileDefinePane(xCreator); diff --git a/designer-form/src/main/java/com/fr/design/form/util/FormDesignerUtils.java b/designer-form/src/main/java/com/fr/design/form/util/FormDesignerUtils.java new file mode 100644 index 000000000..d976816f5 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/form/util/FormDesignerUtils.java @@ -0,0 +1,28 @@ +package com.fr.design.form.util; + +import com.fr.design.mainframe.FormDesigner; +import com.fr.form.ui.container.WFitLayout; + +public class FormDesignerUtils { + /** + * body布局是否设置了手机重布局 + * + * @param designer + * @return + */ + public static boolean isAppRelayout(FormDesigner designer) { + return ((WFitLayout) designer.getRootComponent().toData()).isAppRelayout(); + } + + /** + * body布局是否设置了绝对布局 + * + * @param designer + * @return + */ + public static boolean isBodyAbsolute(FormDesigner designer) { + WFitLayout root = ((WFitLayout) designer.getRootComponent().toData()); + return root.getBodyLayoutType() == com.fr.form.ui.container.WBodyLayoutType.ABSOLUTE; + } + +} \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java b/designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java index 670c2fa48..090969d34 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormModelAdapter.java @@ -78,6 +78,10 @@ public class FormModelAdapter extends DesignModelAdapter> list.add(new WidgetName(widget.getWidgetName())); } } + @Override + public boolean dealWithAllCards() { + return true; + } }); return list; } @@ -135,4 +139,4 @@ public class FormModelAdapter extends DesignModelAdapter> protected Parameter[] getLatestParameters() { return this.getBook().getParameters(); } -} \ No newline at end of file +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/JForm.java b/designer-form/src/main/java/com/fr/design/mainframe/JForm.java index d25ba6fee..bcf761fac 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/JForm.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/JForm.java @@ -37,8 +37,8 @@ import com.fr.design.gui.xpane.FormHyperlinkGroupPaneNoPop; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.form.FormECCompositeProvider; import com.fr.design.mainframe.form.FormECDesignerProvider; -import com.fr.design.mainframe.templateinfo.JFormProcessInfo; -import com.fr.design.mainframe.templateinfo.TemplateProcessInfo; +import com.fr.design.mainframe.template.info.JFormProcessInfo; +import com.fr.design.mainframe.template.info.TemplateProcessInfo; import com.fr.design.mainframe.toolbar.ToolBarMenuDock; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.menu.KeySetUtils; diff --git a/designer-form/src/main/java/com/fr/design/mainframe/templateinfo/JFormProcessInfo.java b/designer-form/src/main/java/com/fr/design/mainframe/template/info/JFormProcessInfo.java similarity index 95% rename from designer-form/src/main/java/com/fr/design/mainframe/templateinfo/JFormProcessInfo.java rename to designer-form/src/main/java/com/fr/design/mainframe/template/info/JFormProcessInfo.java index 15f501b13..fce5ab809 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/templateinfo/JFormProcessInfo.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/template/info/JFormProcessInfo.java @@ -1,4 +1,4 @@ -package com.fr.design.mainframe.templateinfo; +package com.fr.design.mainframe.template.info; import com.fr.form.main.Form; import com.fr.form.ui.container.WLayout; diff --git a/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormWidgetCardPane.java b/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormWidgetCardPane.java index 65e2f6659..3e70f7d0f 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormWidgetCardPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/widget/ui/FormWidgetCardPane.java @@ -28,6 +28,7 @@ import com.fr.design.widget.Operator; import com.fr.design.widget.ui.designer.component.WidgetAbsoluteBoundPane; import com.fr.design.widget.ui.designer.component.WidgetBoundPane; import com.fr.design.widget.ui.designer.component.WidgetCardTagBoundPane; +import com.fr.form.ui.FormWidgetHelper; import com.fr.form.ui.Widget; import com.fr.form.ui.container.WScaleLayout; import com.fr.form.ui.container.WTitleLayout; @@ -102,6 +103,7 @@ public class FormWidgetCardPane extends AbstractAttrNoScrollPane { /** * 后台初始化所有事件. */ + @Override public void initAllListeners() { } @@ -113,7 +115,7 @@ public class FormWidgetCardPane extends AbstractAttrNoScrollPane { initListener(this); } - + @Override protected void initContentPane() { } @@ -214,13 +216,23 @@ public class FormWidgetCardPane extends AbstractAttrNoScrollPane { Widget widget = currentEditorDefinePane.updateBean(); if (ComparatorUtils.equals(getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Basic")) && widgetPropertyPane != null) { UITextField widgetNameField = widgetPropertyPane.getWidgetNameField(); - if (designer.getTarget().isNameExist(widgetNameField.getText()) && !ComparatorUtils.equals(widgetNameField.getText(), widget.getWidgetName())) { - widgetNameField.setText(widget.getWidgetName()); + String toSetWidgetName = widgetNameField.getText(); + String currentWidgetName = widget.getWidgetName(); + // 设置的组件名和当前组件名相同 直接返回 + if (ComparatorUtils.equals(toSetWidgetName, currentWidgetName)) { + return; + } + String containerName = designer.getTarget().getContainer().getWidgetName(); + Widget existWidget = FormWidgetHelper.findWidgetByName(widget, widgetNameField.getText()); + // 判断设置的组件名是否和容器同名以及组件是否在容器在存在 满足任何其一 抛出提示 + boolean exist = ComparatorUtils.equals(containerName, toSetWidgetName) || existWidget != null; + if (exist) { + widgetNameField.setText(currentWidgetName); JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Rename_Failure"), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Joption_News"), JOptionPane.ERROR_MESSAGE, BaseUtils.readIcon("com/fr/design/form/images/joption_failure.png")); return; } widgetPropertyPane.update(widget); - xCreator.resetCreatorName(widget.getWidgetName()); + xCreator.resetCreatorName(toSetWidgetName); xCreator.resetVisible(widget.isVisible()); designer.getEditListenerTable().fireCreatorModified(xCreator, DesignerEvent.CREATOR_RENAMED); return; diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/XmlRelationedBasicPane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/XmlRelationedBasicPane.java new file mode 100644 index 000000000..1f9b13693 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/XmlRelationedBasicPane.java @@ -0,0 +1,18 @@ +package com.fr.design.widget.ui.designer; + +import com.fr.design.dialog.BasicPane; + +/** + * 有些控件在不同终端需要对相同的属性分别进行设置,基础设置面板是一样的但是映射到控件上的属性又是不一样的,为了重用面板,这边加上xmltag做区分 + */ +public abstract class XmlRelationedBasicPane extends BasicPane{ + private String xmlTag; + + public XmlRelationedBasicPane(String xmlTag) { + this.xmlTag = xmlTag; + } + + public String getXmlTag() { + return xmlTag; + } +} \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/PaddingBoundPane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/PaddingBoundPane.java index 9b4a432a2..856ff6a0c 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/PaddingBoundPane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/component/PaddingBoundPane.java @@ -21,22 +21,26 @@ import java.awt.Component; /** * Created by ibm on 2017/8/3. */ -public class PaddingBoundPane extends BasicPane{ +public class PaddingBoundPane extends BasicPane { protected UISpinner top; protected UISpinner bottom; protected UISpinner left; protected UISpinner right; public PaddingBoundPane() { - initBoundPane(); + initBoundPane(0, 0, 0, 0); } - public void initBoundPane() { + public PaddingBoundPane(int top, int bottom, int left, int right) { + initBoundPane(top, bottom, left, right); + } + + public void initBoundPane(int t, int b, int l, int r) { this.setLayout(FRGUIPaneFactory.createBorderLayout()); - top = new UISpinner(0, Integer.MAX_VALUE, 1, 0); - bottom = new UISpinner(0, Integer.MAX_VALUE, 1, 0); - left = new UISpinner(0, Integer.MAX_VALUE, 1, 0); - right = new UISpinner(0, Integer.MAX_VALUE, 1, 0); + top = new UISpinner(0, Integer.MAX_VALUE, 1, t); + bottom = new UISpinner(0, Integer.MAX_VALUE, 1, b); + left = new UISpinner(0, Integer.MAX_VALUE, 1, l); + right = new UISpinner(0, Integer.MAX_VALUE, 1, r); top.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); bottom.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); left.setGlobalName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout_Padding_Duplicate")); @@ -45,12 +49,12 @@ public class PaddingBoundPane extends BasicPane{ label.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, 0, 0)); label.setVerticalAlignment(SwingConstants.TOP); JPanel panel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{ - new Component[]{label, createRightPane()}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W2, IntervalConstants.INTERVAL_L1 ); + new Component[]{label, createRightPane()}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_W2, IntervalConstants.INTERVAL_L1); this.add(panel); } - public JPanel createRightPane(){ + public JPanel createRightPane() { double f = TableLayout.FILL; double p = TableLayout.PREFERRED; double[] rowSize = {p, p}; @@ -67,7 +71,7 @@ public class PaddingBoundPane extends BasicPane{ JPanel northPanel = TableLayoutHelper.createGapTableLayoutPane(components1, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_L6, IntervalConstants.INTERVAL_L6); northPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, IntervalConstants.INTERVAL_L1, 0)); JPanel centerPanel = TableLayoutHelper.createGapTableLayoutPane(components2, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_L6, IntervalConstants.INTERVAL_L6); - JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); panel.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, 0, IntervalConstants.INTERVAL_L1, 0)); panel.add(northPanel, BorderLayout.NORTH); panel.add(centerPanel, BorderLayout.CENTER); @@ -75,20 +79,26 @@ public class PaddingBoundPane extends BasicPane{ } public void update(RichStyleWidgetProvider marginWidget) { - marginWidget.setMargin(new PaddingMargin((int)top.getValue(), (int)left.getValue(), (int)bottom.getValue(), (int)right.getValue() )); + marginWidget.setMargin(updateBean()); + } + + public PaddingMargin updateBean() { + return new PaddingMargin((int) top.getValue(), (int) left.getValue(), (int) bottom.getValue(), (int) right.getValue()); } + @Override protected String title4PopupWindow() { return "PaddingBoundPane"; } public void populate(RichStyleWidgetProvider marginWidget) { - PaddingMargin paddingMargin = marginWidget.getMargin(); - top.setValue(paddingMargin.getTop()); - bottom.setValue(paddingMargin.getBottom()); - left.setValue(paddingMargin.getLeft()); - right.setValue(paddingMargin.getRight()); + populateBean(marginWidget.getMargin()); } - + public void populateBean(PaddingMargin paddingMargin) { + top.setValueWithoutEvent(paddingMargin.getTop()); + bottom.setValueWithoutEvent(paddingMargin.getBottom()); + left.setValueWithoutEvent(paddingMargin.getLeft()); + right.setValueWithoutEvent(paddingMargin.getRight()); + } } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/BodyMobileDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/BodyMobileDefinePane.java index 11c5023ef..b91e1d7b6 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/BodyMobileDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/BodyMobileDefinePane.java @@ -1,21 +1,25 @@ package com.fr.design.widget.ui.designer.mobile; +import com.fr.base.iofile.attr.FormBodyPaddingAttrMark; import com.fr.design.designer.beans.events.DesignerEvent; import com.fr.design.designer.creator.XCreator; import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.form.util.FormDesignerUtils; import com.fr.design.gui.frpane.AttributeChangeListener; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.MobileWidgetListPane; import com.fr.design.mainframe.WidgetPropertyPane; +import com.fr.design.widget.ui.designer.mobile.component.MobileComponentAdvancePane; +import com.fr.design.widget.ui.designer.mobile.component.MobileComponentLayoutIntervalPane; +import com.fr.form.ui.RichStyleWidgetProvider; +import com.fr.form.ui.container.WFitLayout; import com.fr.form.ui.container.WSortLayout; - import javax.swing.BorderFactory; import javax.swing.JPanel; import java.awt.BorderLayout; -import java.lang.reflect.Method; /** * Created by plough on 2018/2/1. @@ -26,22 +30,40 @@ public class BodyMobileDefinePane extends MobileWidgetDefinePane { private AttributeChangeListener changeListener; private UICheckBox appRelayoutCheck; private MobileWidgetListPane mobileWidgetListPane; + private MobileComponentAdvancePane advancePane; + private MobileComponentLayoutIntervalPane intervalPane; public BodyMobileDefinePane(XCreator xCreator) { this.bodyCreator = xCreator; } + public XCreator getBodyCreator() { + return bodyCreator; + } + + public void setBodyCreator(XCreator bodyCreator) { + this.bodyCreator = bodyCreator; + } + + public FormDesigner getDesigner() { + return designer; + } + + public void setDesigner(FormDesigner designer) { + this.designer = designer; + } + @Override public void initPropertyGroups(Object source) { this.setLayout(FRGUIPaneFactory.createBorderLayout()); this.designer = WidgetPropertyPane.getInstance().getEditingFormDesigner(); - this.add(getMobilePropertyPane(), BorderLayout.NORTH); + this.add(createNorthPane(), BorderLayout.NORTH); this.add(getMobileWidgetListPane(), BorderLayout.CENTER); this.repaint(); } // 手机属性 - private UIExpandablePane getMobilePropertyPane() { + public UIExpandablePane getMobilePropertyPane() { JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane(); appRelayoutCheck = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_App_ReLayout"), true); appRelayoutCheck.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); @@ -55,7 +77,7 @@ public class BodyMobileDefinePane extends MobileWidgetDefinePane { } // 控件顺序 - private UIExpandablePane getMobileWidgetListPane() { + public UIExpandablePane getMobileWidgetListPane() { mobileWidgetListPane = new MobileWidgetListPane(designer, (WSortLayout) bodyCreator.toData()); mobileWidgetListPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 5, 0)); JPanel panelWrapper = FRGUIPaneFactory.createBorderLayout_S_Pane(); @@ -64,6 +86,24 @@ public class BodyMobileDefinePane extends MobileWidgetDefinePane { return new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Order"), 280, 20, panelWrapper); } + private JPanel createNorthPane() { + JPanel holder = FRGUIPaneFactory.createBorderLayout_S_Pane(); + holder.add(getMobilePropertyPane(), BorderLayout.NORTH); + + advancePane = new MobileComponentAdvancePane(FormBodyPaddingAttrMark.XML_TAG); + intervalPane = new MobileComponentLayoutIntervalPane(FormBodyPaddingAttrMark.XML_TAG); + //高级 + holder.add(advancePane, BorderLayout.CENTER); + //布局 + holder.add(intervalPane, BorderLayout.SOUTH); + + advancePane.setVisible(!shouldHidePadding(designer)); + intervalPane.setVisible(!shouldHidePadding(designer)); + + return holder; + } + + private void bindListeners2Widgets() { reInitAllListeners(); this.changeListener = new AttributeChangeListener() { @@ -81,25 +121,13 @@ public class BodyMobileDefinePane extends MobileWidgetDefinePane { initListener(this); } - // body是否开启手机重布局 - private boolean isAppRelayout() { - boolean result = false; - try { - Method m = bodyCreator.toData().getClass().getMethod("isAppRelayout"); - result = (boolean)m.invoke(bodyCreator.toData()); - } catch (Exception e) { - // do nothing - } - return result; - } private void setAppRelayout(boolean appRelayoutSeleted) { - if (appRelayoutSeleted == isAppRelayout()) { + if (appRelayoutSeleted == FormDesignerUtils.isAppRelayout(designer)) { return; } try { - Method m = bodyCreator.toData().getClass().getMethod("setAppRelayout", boolean.class); - m.invoke(bodyCreator.toData(), appRelayoutSeleted); + ((WFitLayout) designer.getRootComponent().toData()).setAppRelayout(appRelayoutSeleted); } catch (Exception e) { // do nothing } @@ -108,17 +136,31 @@ public class BodyMobileDefinePane extends MobileWidgetDefinePane { @Override public void populate(FormDesigner designer) { this.designer = designer; - appRelayoutCheck.setSelected(isAppRelayout()); + appRelayoutCheck.setSelected(FormDesignerUtils.isAppRelayout(designer)); // 数据 populate 完成后,再设置监听 this.bindListeners2Widgets(); this.addAttributeChangeListener(changeListener); + + advancePane.populate((RichStyleWidgetProvider) getBodyCreator().toData()); + intervalPane.populate((RichStyleWidgetProvider) getBodyCreator().toData()); } @Override public void update() { + boolean appRelayout = appRelayoutCheck.isSelected(); setAppRelayout(appRelayoutCheck.isSelected()); + boolean appPaddingVisible = appRelayout || !FormDesignerUtils.isBodyAbsolute(designer); + advancePane.setVisible(appPaddingVisible); + intervalPane.setVisible(appPaddingVisible); mobileWidgetListPane.updateToDesigner(); designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED); + + if (advancePane.isVisible()) { + advancePane.update((RichStyleWidgetProvider) getBodyCreator().toData()); + } + if (intervalPane.isVisible()) { + intervalPane.update((RichStyleWidgetProvider) getBodyCreator().toData()); + } } } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ChartEditorDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ChartEditorDefinePane.java index 86df38abc..b9ae12e20 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ChartEditorDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/ChartEditorDefinePane.java @@ -9,6 +9,7 @@ import com.fr.design.designer.creator.XWAbsoluteBodyLayout; import com.fr.design.designer.creator.XWAbsoluteLayout; import com.fr.design.designer.properties.items.Item; import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.form.util.FormDesignerUtils; import com.fr.design.gui.frpane.AttributeChangeListener; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icombobox.UIComboBox; @@ -20,11 +21,14 @@ import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.WidgetPropertyPane; import com.fr.form.ui.BaseChartEditor; -import com.fr.form.ui.container.WFitLayout; - -import javax.swing.*; -import java.awt.*; +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; @@ -56,7 +60,7 @@ public class ChartEditorDefinePane extends MobileWidgetDefinePane { JPanel mobileSettingsPane; if (isInAbsoluteLayout()) { mobileSettingsPane = getUnavailableTipPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Tip_Chart_Adaptivity_Unavailable_In_Absolute_Layout")); - } else if (!isAppRelayout()) { + } else if (!FormDesignerUtils.isAppRelayout(designer)) { mobileSettingsPane = getUnavailableTipPane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Tip_Chart_Adaptivity_Unavailable")); } else { mobileSettingsPane = getMobileSettingsPane(); @@ -76,11 +80,6 @@ public class ChartEditorDefinePane extends MobileWidgetDefinePane { return false; } - // body是否开启手机重布局 - private boolean isAppRelayout() { - return ((WFitLayout)designer.getRootComponent().toData()).isAppRelayout(); - } - private JPanel getUnavailableTipPane(String tipText) { JPanel panel = new JPanel(new BorderLayout()); UILabel unavailableTipLabel = new UILabel(); @@ -158,7 +157,7 @@ public class ChartEditorDefinePane extends MobileWidgetDefinePane { this.bindListeners2Widgets(); this.addAttributeChangeListener(changeListener); - if (!isAppRelayout() || isInAbsoluteLayout()) { + if (!FormDesignerUtils.isAppRelayout(designer) || isInAbsoluteLayout()) { return; } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/MobileWidgetDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/MobileWidgetDefinePane.java index ac4de096a..d44707181 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/MobileWidgetDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/MobileWidgetDefinePane.java @@ -1,5 +1,6 @@ package com.fr.design.widget.ui.designer.mobile; +import com.fr.design.form.util.FormDesignerUtils; import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; import com.fr.design.mainframe.FormDesigner; @@ -7,10 +8,10 @@ import javax.swing.*; /** * 所有移动端需要拓展的属性面板均继承此类 - * + *

* Created by fanglei on 2017/8/8. */ -public abstract class MobileWidgetDefinePane extends AbstractAttrNoScrollPane{ +public abstract class MobileWidgetDefinePane extends AbstractAttrNoScrollPane { //初始化panel数据再repaint public abstract void initPropertyGroups(Object source); @@ -28,11 +29,21 @@ public abstract class MobileWidgetDefinePane extends AbstractAttrNoScrollPane{ // 暂不需要此方法 @Override - protected void initContentPane() {} + protected void initContentPane() { + } // 暂不需要此方法 @Override protected JPanel createContentPane() { return new JPanel(); } + + /** + * 绝对布局且不勾选手机重布局 的时候不支持边距设置 + * + * @return + */ + public boolean shouldHidePadding(FormDesigner designer) { + return !FormDesignerUtils.isAppRelayout(designer) && FormDesignerUtils.isBodyAbsolute(designer); + } } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/TabMobileWidgetDefinePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/TabMobileWidgetDefinePane.java index f6d94da06..8a795b887 100644 --- a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/TabMobileWidgetDefinePane.java +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/TabMobileWidgetDefinePane.java @@ -1,5 +1,6 @@ package com.fr.design.widget.ui.designer.mobile; +import com.fr.base.iofile.attr.FormTabPaddingAttrMark; import com.fr.design.constants.LayoutConstants; import com.fr.design.designer.IntervalConstants; import com.fr.design.designer.creator.XCreator; @@ -9,8 +10,11 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.WidgetPropertyPane; import com.fr.design.mainframe.widget.accessibles.AccessibleTemplateStyleEditor; import com.fr.design.mainframe.widget.accessibles.MobileTemplateStylePane; +import com.fr.design.widget.ui.designer.mobile.component.MobileComponentAdvancePane; +import com.fr.design.widget.ui.designer.mobile.component.MobileComponentLayoutIntervalPane; import com.fr.form.ui.container.cardlayout.WCardTagLayout; import com.fr.general.cardtag.mobile.MobileTemplateStyle; @@ -20,8 +24,11 @@ import java.awt.Component; public class TabMobileWidgetDefinePane extends MobileWidgetDefinePane { private XCreator xCreator; + private FormDesigner designer; // 当前设计器 private AccessibleTemplateStyleEditor templateStyleEditor; private AttributeChangeListener changeListener; + private MobileComponentAdvancePane advancePane; + private MobileComponentLayoutIntervalPane intervalPane; public TabMobileWidgetDefinePane(XCreator xCreator) { this.xCreator = xCreator; @@ -36,6 +43,7 @@ public class TabMobileWidgetDefinePane extends MobileWidgetDefinePane { } }; } + /** * 后台初始化所有事件. */ @@ -46,24 +54,47 @@ public class TabMobileWidgetDefinePane extends MobileWidgetDefinePane { @Override public void initPropertyGroups(Object source) { this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.designer = WidgetPropertyPane.getInstance().getEditingFormDesigner(); UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Tab_Style_Template")); templateStyleEditor = new AccessibleTemplateStyleEditor(new MobileTemplateStylePane((WCardTagLayout) xCreator.toData())); - JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{label, templateStyleEditor}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_MEDIUM); - this.add(jPanel, BorderLayout.CENTER); + JPanel jPanel = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{label, templateStyleEditor}, {new UILabel()}}, TableLayoutHelper.FILL_LASTCOLUMN, IntervalConstants.INTERVAL_L1, LayoutConstants.VGAP_LARGE); + JPanel holder = FRGUIPaneFactory.createBorderLayout_S_Pane(); + holder.add(jPanel, BorderLayout.NORTH); + if (!shouldHidePadding(designer)) { + advancePane = new MobileComponentAdvancePane(FormTabPaddingAttrMark.XML_TAG); + intervalPane = new MobileComponentLayoutIntervalPane(FormTabPaddingAttrMark.XML_TAG); + //高级 + holder.add(advancePane, BorderLayout.CENTER); + //布局 + holder.add(intervalPane, BorderLayout.SOUTH); + } + + this.add(holder, BorderLayout.NORTH); } @Override public void populate(FormDesigner designer) { - templateStyleEditor.setValue(((WCardTagLayout)xCreator.toData()).getMobileTemplateStyle()); + templateStyleEditor.setValue(((WCardTagLayout) xCreator.toData()).getMobileTemplateStyle()); // 数据 populate 完成后,再设置监听 this.bindListeners2Widgets(); this.addAttributeChangeListener(changeListener); + if (advancePane != null) {//业务层面可以写成shouldHidePadding但是这样写应该性能差点 + advancePane.populate((WCardTagLayout) xCreator.toData()); + } + if (intervalPane != null) { + intervalPane.populate((WCardTagLayout) xCreator.toData()); + } } @Override public void update() { - ((WCardTagLayout)xCreator.toData()).setMobileTemplateStyle((MobileTemplateStyle) templateStyleEditor.getValue()); + ((WCardTagLayout) xCreator.toData()).setMobileTemplateStyle((MobileTemplateStyle) templateStyleEditor.getValue()); DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified(); // 触发设计器保存按钮亮起来 - + if (advancePane != null) { + advancePane.update((WCardTagLayout) xCreator.toData()); + } + if (intervalPane != null) { + intervalPane.update((WCardTagLayout) xCreator.toData()); + } } } diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileComponentAdvancePane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileComponentAdvancePane.java new file mode 100644 index 000000000..f94d57907 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileComponentAdvancePane.java @@ -0,0 +1,45 @@ +package com.fr.design.widget.ui.designer.mobile.component; + +import com.fr.base.iofile.attr.AttrMarkFactory; +import com.fr.base.iofile.attr.FormBodyPaddingAttrMark; +import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.widget.ui.designer.XmlRelationedBasicPane; +import com.fr.design.widget.ui.designer.component.PaddingBoundPane; +import com.fr.form.ui.RichStyleWidgetProvider; + +import java.awt.BorderLayout; + +/** + * 只有内边距设置的高级设置 + */ +public class MobileComponentAdvancePane extends XmlRelationedBasicPane { + private PaddingBoundPane paddingBound; + + public MobileComponentAdvancePane(String xmlTag) { + super(xmlTag); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + paddingBound = new PaddingBoundPane(FormBodyPaddingAttrMark.DEFAULT_SIZE, FormBodyPaddingAttrMark.DEFAULT_SIZE, FormBodyPaddingAttrMark.DEFAULT_SIZE, FormBodyPaddingAttrMark.DEFAULT_SIZE); + UIExpandablePane advanceExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Advanced"), 280, 20, paddingBound); + this.add(advanceExpandablePane, BorderLayout.NORTH); + } + + @Override + protected String title4PopupWindow() { + return "ComponentAdvancePane"; + } + + public void update(RichStyleWidgetProvider marginWidget) { + FormBodyPaddingAttrMark attrMark = marginWidget.getWidgetAttrMark(getXmlTag()); + attrMark = attrMark == null ? (FormBodyPaddingAttrMark) AttrMarkFactory.createAttrMark(getXmlTag()) : attrMark; + attrMark.setPaddingMargin(paddingBound.updateBean()); + marginWidget.addWidgetAttrMark(attrMark); + } + + public void populate(RichStyleWidgetProvider marginWidget) { + FormBodyPaddingAttrMark attrMark = marginWidget.getWidgetAttrMark(getXmlTag()); + if (attrMark != null) { + paddingBound.populateBean(attrMark.getPaddingMargin()); + } + } +} \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileComponentLayoutIntervalPane.java b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileComponentLayoutIntervalPane.java new file mode 100644 index 000000000..5a565373d --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/widget/ui/designer/mobile/component/MobileComponentLayoutIntervalPane.java @@ -0,0 +1,71 @@ +package com.fr.design.widget.ui.designer.mobile.component; + +import com.fr.base.iofile.attr.AttrMarkFactory; +import com.fr.base.iofile.attr.FormBodyPaddingAttrMark; +import com.fr.design.designer.IntervalConstants; +import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.utils.gui.UIComponentUtils; +import com.fr.design.widget.FRWidgetFactory; +import com.fr.design.widget.ui.designer.XmlRelationedBasicPane; +import com.fr.form.ui.RichStyleWidgetProvider; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; + +/** + * 只有组件间隔的布局设置 + */ +public class MobileComponentLayoutIntervalPane extends XmlRelationedBasicPane { + private UISpinner componentIntervel; + + public MobileComponentLayoutIntervalPane(String xmlTag) { + super(xmlTag); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + UILabel intervalLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Component_Interval")); + + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p}; + double[] columnSize = {p, f}; + int[][] rowCount = {{1, 1}, {1, 1}}; + componentIntervel = new UISpinner(0, Integer.MAX_VALUE, 1, FormBodyPaddingAttrMark.DEFAULT_SIZE); + JPanel componentIntervelPane = UIComponentUtils.wrapWithBorderLayoutPane(componentIntervel); + + Component[][] components = new Component[][]{ + new Component[]{intervalLabel, componentIntervelPane} + }; + JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, IntervalConstants.INTERVAL_W1, IntervalConstants.INTERVAL_L1); + centerPane.setBorder(BorderFactory.createEmptyBorder(IntervalConstants.INTERVAL_L1, IntervalConstants.INTERVAL_L5, 0, 0)); + JPanel holder = FRGUIPaneFactory.createBorderLayout_S_Pane(); + holder.add(centerPane, BorderLayout.NORTH); + UIExpandablePane layoutExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Layout"), 280, 20, holder); + this.add(layoutExpandablePane, BorderLayout.NORTH); + } + + @Override + protected String title4PopupWindow() { + return "ComponentIntervelPane"; + } + + public void update(RichStyleWidgetProvider marginWidget) { + + FormBodyPaddingAttrMark attrMark = marginWidget.getWidgetAttrMark(getXmlTag()); + attrMark = attrMark == null ? (FormBodyPaddingAttrMark) AttrMarkFactory.createAttrMark(getXmlTag()) : attrMark; + attrMark.setInterval((int) componentIntervel.getValue()); + marginWidget.addWidgetAttrMark(attrMark); + } + + public void populate(RichStyleWidgetProvider marginWidget) { + FormBodyPaddingAttrMark attrMark = marginWidget.getWidgetAttrMark(getXmlTag()); + if (attrMark != null) { + componentIntervel.setValueWithoutEvent(attrMark.getInterval()); + } + } +} \ No newline at end of file diff --git a/designer-form/src/main/resources/com/fr/aspectj/designerform/TemplateProcessTracker.aj b/designer-form/src/main/resources/com/fr/aspectj/designerform/TemplateProcessTracker.aj index 3be1a77fa..9daec5009 100644 --- a/designer-form/src/main/resources/com/fr/aspectj/designerform/TemplateProcessTracker.aj +++ b/designer-form/src/main/resources/com/fr/aspectj/designerform/TemplateProcessTracker.aj @@ -3,12 +3,10 @@ package com.fr.aspectj.designerform; /** * Created by plough on 2017/3/3. */ -import com.fr.design.mainframe.templateinfo.TemplateInfoCollector; import org.aspectj.lang.reflect.SourceLocation; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; -import java.util.Date; public aspect TemplateProcessTracker { //声明一个pointcut,匹配你需要的方法 diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePane.java index db91d0a39..b16aa1b42 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/ElementCasePane.java @@ -174,6 +174,7 @@ public abstract class ElementCasePane extends Tar private CellSelection cellNeedTOFormat = null; private FormatBrushAction formatBrushAction; private ActionListener keyListener = new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { if (!formatBrush.isSelected()) { DesignerContext.setFormatState(DesignerContext.FORMAT_STATE_ONCE); @@ -188,6 +189,7 @@ public abstract class ElementCasePane extends Tar } }; private ActionListener escKey = new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { cancelFormatBrush(); } @@ -212,6 +214,7 @@ public abstract class ElementCasePane extends Tar /** * 取消格式化 */ + @Override public void cancelFormat() { return; } @@ -240,7 +243,6 @@ public abstract class ElementCasePane extends Tar verScrollBar = new DynamicScrollBar(Adjustable.VERTICAL, this, this.resolution); horScrollBar = new DynamicScrollBar(Adjustable.HORIZONTAL, this, this.resolution); this.add(RGridLayout.VerticalBar, this.verScrollBar); -// this.add(RGridLayout.HorizontalBar, this.horScrollBar); // Init input/action map defaultly. initInputActionMap(); @@ -253,7 +255,7 @@ public abstract class ElementCasePane extends Tar initFormatBrush(); } - + @Override public int getMenuState() { return DesignState.WORK_SHEET; } @@ -265,6 +267,7 @@ public abstract class ElementCasePane extends Tar formatBrush.setSelected(DesignerContext.getFormatState() != DesignerContext.FORMAT_STATE_NULL); formatBrush.removeActionListener(formatBrushAction); formatBrush.addMouseListener(new MouseAdapter() { + @Override public void mouseClicked(MouseEvent e) { //如果没有格式刷,点击时就是想使用格式刷 if (e.getClickCount() == 1) { @@ -528,8 +531,8 @@ public abstract class ElementCasePane extends Tar FineLoggerFactory.getLogger().info("Nothing to release"); } this.selection = selection; - fireSelectionChanged(); } + fireSelectionChanged(); } @@ -1210,6 +1213,7 @@ public abstract class ElementCasePane extends Tar /** * 请求焦点 */ + @Override public void requestFocus() { super.requestFocus(); this.getGrid().requestFocus(); @@ -1338,6 +1342,7 @@ public abstract class ElementCasePane extends Tar * * @return 返回正在编辑的状态. */ + @Override public EditingState createEditingState() { return new ElementCaseEditingState(this.selection, this.verScrollBar.getValue(), this.horScrollBar.getValue(), this.resolution); } @@ -1380,7 +1385,6 @@ public abstract class ElementCasePane extends Tar ElementCasePane.this.getVerticalScrollBar().setValue(this.verticalValue); ElementCasePane.this.getHorizontalScrollBar().setValue(this.horizontalValue); -// ElementCasePane.this.setResolution(this.resolution); HistoryTemplateListPane.getInstance().getCurrentEditingTemplate().setScale(this.resolution); // 重绘. ElementCasePane.this.repaint(); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/InformationCollector.java b/designer-realize/src/main/java/com/fr/design/mainframe/InformationCollector.java index 8a3f4bb25..83cb7dd33 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/InformationCollector.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/InformationCollector.java @@ -7,7 +7,8 @@ import com.fr.base.FRContext; import com.fr.config.MarketConfig; import com.fr.design.DesignerEnvManager; import com.fr.design.mainframe.errorinfo.ErrorInfoUploader; -import com.fr.design.mainframe.templateinfo.TemplateInfoCollector; +import com.fr.design.mainframe.messagecollect.impl.FocusPointMessageUploader; +import com.fr.design.mainframe.template.info.TemplateInfoCollector; import com.fr.general.CloudCenter; import com.fr.general.ComparatorUtils; import com.fr.general.DateUtils; @@ -15,20 +16,13 @@ import com.fr.general.DesUtils; import com.fr.general.GeneralUtils; import com.fr.general.IOUtils; import com.fr.general.http.HttpToolbox; -import com.fr.intelli.record.FocusPoint; -import com.fr.intelli.record.MetricRegistry; import com.fr.json.JSONArray; -import com.fr.json.JSONException; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; import com.fr.stable.EncodeConstants; import com.fr.stable.ProductConstants; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; -import com.fr.stable.query.QueryFactory; -import com.fr.stable.query.condition.QueryCondition; -import com.fr.stable.query.data.DataList; -import com.fr.stable.query.restriction.RestrictionFactory; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLReadable; import com.fr.stable.xml.XMLTools; @@ -53,7 +47,6 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -81,24 +74,6 @@ public class InformationCollector implements XMLReadable, XMLWriter { private static final String XML_KEY = "ActiveKey"; private static final String XML_OS = "OS"; - public static final String TABLE_NAME = "fr_functionrecord"; - public static final String FUNC_COLUMNNAME = "func"; - public static final String COLUMN_TIME = "time"; - public static final String TABLE_FUNCTION_RECORD = "function.record"; - private static final String ATTR_ID = "id"; - private static final String ATTR_TEXT = "text"; - private static final String ATTR_SOURCE = "source"; - private static final String ATTR_TIME = "time"; - private static final String ATTR_TIMES = "times"; - private static final String ATTR_TITLE = "title"; - private static final String ATTR_USER_NAME = "username"; - private static final String ATTR_UUID = "uuid"; - private static final String ATTR_ITEMS = "items"; - private static final String ATTR_FUNCTION_ARRAY = "functionArray"; - private static final int MAX_EACH_REQUEST_RECORD_COUNT = 200; - private static final int PAGE_SIZE = 200; - private long totalCount = -1; - private static InformationCollector collector; //启动时间与关闭时间列表 @@ -184,6 +159,12 @@ public class InformationCollector implements XMLReadable, XMLWriter { } private void sendUserInfo(){ + long currentTime = new Date().getTime(); + long lastTime = getLastTimeMillis(); + + if (currentTime - lastTime <= DELTA) { + return; + } JSONObject content = getJSONContentAsByte(); String url = CloudCenter.getInstance().acquireUrlByKind("user.info.v10"); boolean success = false; @@ -201,135 +182,9 @@ public class InformationCollector implements XMLReadable, XMLWriter { } } - private void sendFunctionsInfo(long currentTime, long lastTime){ - FineLoggerFactory.getLogger().info("Start sent function records to the cloud center..."); - queryAndSendOnePageFunctionContent(currentTime, lastTime, 0); - long page = (totalCount/PAGE_SIZE) + 1; - for(int i=1; i focusPoints = MetricRegistry.getMetric().find(FocusPoint.class,condition); - //第一次查询获取总记录数 - if(page == 0){ - totalCount = focusPoints.getTotalCount(); - } - sendThisPageFunctionContent(focusPoints); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } - - private void sendThisPageFunctionContent(DataList focusPoints) { - String url = CloudCenter.getInstance().acquireUrlByKind(TABLE_FUNCTION_RECORD); - try { - JSONObject jsonObject = dealWithSendFunctionContent(focusPoints); - sendFunctionRecord(url, jsonObject); - } catch (JSONException e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } - - private JSONObject dealWithSendFunctionContent(DataList focusPoints) throws JSONException { - JSONObject jsonObject = new JSONObject(); - Map map = new HashMap<>(); - if(!focusPoints.isEmpty()){ - DesignerEnvManager envManager = DesignerEnvManager.getEnvManager(); - String bbsUserName = MarketConfig.getInstance().getBbsUsername(); - String uuid = envManager.getUUID(); - jsonObject.put(ATTR_UUID, uuid); - jsonObject.put(ATTR_USER_NAME, bbsUserName); - for(FocusPoint focusPoint : focusPoints.getList()) { - FunctionRecord functionRecord = getOneRecord(focusPoint); - if (map.containsKey(focusPoint.getId())) { - int times = ((FunctionRecord)map.get(focusPoint.getId())).getTimes() + 1; - functionRecord.setTimes(times); - map.put(focusPoint.getId(), functionRecord); - } else { - map.put(focusPoint.getId(), functionRecord); - } - } - jsonObject.put(ATTR_ITEMS, mapToJSONArray(map)); - } - return jsonObject; - } - - private JSONArray mapToJSONArray(Map map) throws JSONException { - JSONArray jsonArray = new JSONArray(); - for(String keys : map.keySet()){ - FunctionRecord functionRecord = (FunctionRecord)map.get(keys); - JSONObject jo = new JSONObject(); - jo.put(ATTR_ID, functionRecord.getId()); - jo.put(ATTR_TEXT, functionRecord.getText()); - jo.put(ATTR_SOURCE, functionRecord.getSource()); - jo.put(ATTR_TIME, functionRecord.getTime()); - jo.put(ATTR_TITLE, functionRecord.getTitle()); - jo.put(ATTR_TIMES, functionRecord.getTimes()); - jsonArray.put(jo); - } - return jsonArray; - } - - private void sendFunctionRecord(String url, JSONObject record) { - boolean success = false; - try { - HashMap para = new HashMap<>(); - para.put("token", SiteCenterToken.generateToken()); - para.put("content", record); - String res = HttpToolbox.post(url, para); - success = ComparatorUtils.equals(new JSONObject(res).get("status"), "success"); - if (success) { - this.lastTime = dateToString(); - } else { - FineLoggerFactory.getLogger().error("Error occured when sent function records to the cloud center."); - } - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - } - - private FunctionRecord getOneRecord(FocusPoint focusPoint) { - FunctionRecord functionRecord = new FunctionRecord(); - functionRecord.setId(focusPoint.getId() == null?StringUtils.EMPTY : focusPoint.getId()); - functionRecord.setText(focusPoint.getText() == null?StringUtils.EMPTY : focusPoint.getText()); - functionRecord.setSource(focusPoint.getSource()); - functionRecord.setTime(focusPoint.getTime().getTime()); - functionRecord.setTitle(focusPoint.getTitle() == null?StringUtils.EMPTY : focusPoint.getTitle()); - functionRecord.setUsername(MarketConfig.getInstance().getBbsUsername() == null?StringUtils.EMPTY : MarketConfig.getInstance().getBbsUsername()); - functionRecord.setUuid(DesignerEnvManager.getEnvManager().getUUID() == null?StringUtils.EMPTY : DesignerEnvManager.getEnvManager().getUUID()); - return functionRecord; - } - - /** - * 收集开始使用时间,发送信息 - */ + /** + * 收集开始使用时间,发送信息 + */ public void collectStartTime(){ this.current.setStartDate(dateToString()); @@ -345,18 +200,12 @@ public class InformationCollector implements XMLReadable, XMLWriter { service.schedule(new Runnable() { @Override public void run() { - long currentTime = new Date().getTime(); - long lastTime = getLastTimeMillis(); - if (currentTime - lastTime > DELTA) { - sendUserInfo(); - sendFunctionsInfo(currentTime, lastTime); - } - + sendUserInfo(); + FocusPointMessageUploader.getInstance().sendToCloudCenter(); TemplateInfoCollector.getInstance().sendTemplateInfo(); ErrorInfoUploader.getInstance().sendErrorInfo(); } - }, SEND_DELAY, TimeUnit.SECONDS); - + }, SEND_DELAY, TimeUnit.MILLISECONDS); } /** @@ -524,94 +373,4 @@ public class InformationCollector implements XMLReadable, XMLWriter { } } - - private class FunctionRecord implements Comparable{ - private String id; - private String text; - private int source; - private long time; - private int times = 1; - private String title; - private String username; - private String uuid; - - public FunctionRecord(){ - - } - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public int getTimes() { - return times; - } - - public void setTimes(int times) { - this.times = times; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public int getSource() { - return source; - } - - public void setSource(int source) { - this.source = source; - } - - public long getTime() { - return time; - } - - public void setTime(long time) { - this.time = time; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - @Override - public int compareTo(Object o) { - FunctionRecord functionRecord = (FunctionRecord) o; - if(this.getId().equals((functionRecord.getId())) && this.getText().equals(functionRecord.getText()) - && this.getSource() == functionRecord.getSource() && this.getTime() == functionRecord.getTime() - && this.getTitle().equals(functionRecord.getTitle()) && this.getUsername().equals(functionRecord.getUsername()) - && this.getUuid().equals(functionRecord.getUuid())){ - return 0; - } - return 1; - } - } } \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java b/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java index 44becbd9c..07136bc1e 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java @@ -41,8 +41,8 @@ import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icontainer.UIModeControlContainer; import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.mainframe.cell.QuickEditorRegion; -import com.fr.design.mainframe.templateinfo.JWorkBookProcessInfo; -import com.fr.design.mainframe.templateinfo.TemplateProcessInfo; +import com.fr.design.mainframe.template.info.JWorkBookProcessInfo; +import com.fr.design.mainframe.template.info.TemplateProcessInfo; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.menu.KeySetUtils; import com.fr.design.menu.MenuDef; diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/SheetNameTabPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/SheetNameTabPane.java index 09f1ff9e1..9fdc9d5a8 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/SheetNameTabPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/SheetNameTabPane.java @@ -3,6 +3,8 @@ package com.fr.design.mainframe; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; @@ -24,7 +26,7 @@ import com.fr.base.GraphHelper; import com.fr.base.vcs.DesignerMode; import com.fr.design.actions.UpdateAction; import com.fr.design.constants.UIConstants; -import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIButtonUI; import com.fr.design.menu.MenuDef; @@ -35,6 +37,7 @@ import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.utils.gui.GUIPaintUtils; import com.fr.general.ComparatorUtils; +import com.fr.general.IOUtils; import com.fr.main.impl.WorkBook; import com.fr.poly.PolyDesigner; import com.fr.report.poly.PolyWorkSheet; @@ -52,15 +55,15 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse private static final Color LINE_COLOR = new Color(0xababab); - private static final Icon ADD_WORK_SHEET = BaseUtils.readIcon("com/fr/base/images/oem/addworksheet.png"); - protected static final Icon ADD_POLY_SHEET = BaseUtils.readIcon("com/fr/design/images/sheet/addpolysheet.png"); - private static final Icon WORK_SHEET_ICON = BaseUtils.readIcon("com/fr/base/images/oem/worksheet.png"); - private static final Icon POLY_SHEET_ICON = BaseUtils.readIcon("com/fr/design/images/sheet/polysheet.png"); - private static final Image DESIGN_IMAGE = BaseUtils.readImage("com/fr/design/images/sheet/left_right_btn.png"); - private static final Icon LEFT_ICON = BaseUtils.readIcon("com/fr/design/images/sheet/left_normal@1x.png"); - private static final Icon RIGHT_ICON = BaseUtils.readIcon("com/fr/design/images/sheet/right_normal@1x.png"); - private static final Icon DISABLED_LEFT_ICON = BaseUtils.readIcon("com/fr/design/images/sheet/left_hover@1x.png"); - private static final Icon DISABLED_RIGHT_ICON = BaseUtils.readIcon("com/fr/design/images/sheet/right_hover@1x.png"); + private static final Icon ADD_WORK_SHEET = IOUtils.readIcon("com/fr/base/images/oem/addworksheet.png"); + protected static final Icon ADD_POLY_SHEET = IOUtils.readIcon("com/fr/design/images/sheet/addpolysheet.png"); + private static final Icon WORK_SHEET_ICON = IOUtils.readIcon("com/fr/base/images/oem/worksheet.png"); + private static final Icon POLY_SHEET_ICON = IOUtils.readIcon("com/fr/design/images/sheet/polysheet.png"); + private static final Icon LEFT_ICON = IOUtils.readIcon("com/fr/design/images/sheet/left_normal@1x.png"); + private static final Icon RIGHT_ICON = IOUtils.readIcon("com/fr/design/images/sheet/right_normal@1x.png"); + private static final Icon DISABLED_LEFT_ICON = IOUtils.readIcon("com/fr/design/images/sheet/left_hover@1x.png"); + private static final Icon DISABLED_RIGHT_ICON = IOUtils.readIcon("com/fr/design/images/sheet/right_hover@1x.png"); + private static final int NUM = 10; private static final int ICON_SEP_DISTANCE = 8; private static final int TOOLBAR_HEIGHT = 16; @@ -144,6 +147,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse this.setBorder(null); this.setForeground(new Color(99, 99, 99)); leftButton = new UIButton(LEFT_ICON) { + @Override public Dimension getPreferredSize() { return new Dimension(super.getPreferredSize().width, TOOLBAR_HEIGHT); } @@ -163,6 +167,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse leftButton.set4ToolbarButton(); leftButton.setDisabledIcon(DISABLED_LEFT_ICON); rightButton = new UIButton(RIGHT_ICON) { + @Override public Dimension getPreferredSize() { return new Dimension(super.getPreferredSize().width, TOOLBAR_HEIGHT); } @@ -197,7 +202,14 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse } } }); - + + DesignerContext.getDesignerFrame().addComponentListener(new ComponentAdapter(){ + @Override public void componentResized(ComponentEvent e) { + for (int i = 0; i < lastOneIndex * NUM; i++) { + moveLeft(); + } + } + }); } private ActionListener createLeftButtonActionListener() { @@ -205,27 +217,31 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse @Override public void actionPerformed(ActionEvent e) { - int s = scrollIndex; - if (s == lastOneIndex && s != 0) { - scrollIndex--; - lastOneIndex--; - repaint(); - } else { - while (s > lastOneIndex && showCount != 0) { - scrollIndex++; - lastOneIndex++; - repaint(); - } - while (s < lastOneIndex && scrollIndex > 0) { - scrollIndex--; - lastOneIndex--; - repaint(); - } - } + moveLeft(); } }; } + private void moveLeft() { + int s = scrollIndex; + if (s == lastOneIndex && s != 0) { + scrollIndex--; + lastOneIndex--; + repaint(); + } else { + while (s > lastOneIndex && showCount != 0) { + scrollIndex++; + lastOneIndex++; + repaint(); + } + while (s < lastOneIndex && scrollIndex > 0) { + scrollIndex--; + lastOneIndex--; + repaint(); + } + } + } + /** * 设置选择index * @@ -282,6 +298,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse * * @param e 鼠标事件 */ + @Override public void mouseDragged(MouseEvent e) { if (isAuthorityEditing) { return; @@ -295,6 +312,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse * * @param e 鼠标事件 */ + @Override public void mouseMoved(MouseEvent e) { } @@ -423,15 +441,6 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse } generalPath.closePath(); g2d.fill(generalPath); -// g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); -// g2d.setPaint(UIConstants.LINE_COLOR); -// if (selectedIndex == scrollIndex) { -// g2d.draw(new Line2D.Double(x[0], y[0], x[1], y[1])); -// } -// g2d.draw(new Line2D.Double(x[1], y[1], x[2], y[2])); -// g2d.draw(new Line2D.Double(x[2], y[2], x[3], y[3])); -// g2d.draw(new Line2D.Double(x[3], y[3], x[4], y[4])); -// g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); sheeticon.paintIcon(this, g2d, (int) textX + charWidth, 2); // peter:画字符 g2d.setPaint(getForeground()); @@ -470,13 +479,6 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse g2d.fill(generalPath); g2d.setPaint(LINE_COLOR); -// if (i == scrollIndex) { -// g2d.draw(new Line2D.Double(x[0], y[0], x[1], y[1])); -// } -// g2d.draw(new Line2D.Double(x[1], y[1], x[2], y[2])); -// g2d.draw(new Line2D.Double(x[2], y[2], x[3], y[3])); -// g2d.draw(new Line2D.Double(x[3], y[3], x[4], y[4])); -// g2d.draw(new Line2D.Double(x[4], y[4], x[5], y[5])); double startX = textX > 0 ? textX - 1 : textX; g2d.drawRect((int)startX, 0, width, (int)textHeight); @@ -560,6 +562,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse * * @param e 鼠标事件 */ + @Override public void mouseClicked(MouseEvent e) { } @@ -568,6 +571,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse * * @param evt 鼠标事件 */ + @Override public void mousePressed(MouseEvent evt) { isReleased = false; int reportcount = reportComposite.getEditingWorkBook().getReportCount(); @@ -586,7 +590,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse boolean needRefreshPropertiesPane = getSelectedIndex() != i; setSelectedIndex(i); if (needRefreshPropertiesPane) { - HistoryTemplateListPane.getInstance().getCurrentEditingTemplate().refreshEastPropertiesPane(); + HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().refreshEastPropertiesPane(); } isBlank = false; @@ -629,11 +633,11 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse } } - + protected void addInsertGridShortCut(MenuDef def){ def.addShortCut(new GridReportInsertAction()); } - + protected void firstInsertActionPerformed(){ new GridReportInsertAction().actionPerformed(null); } @@ -644,6 +648,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse * * @param e 鼠标事件 */ + @Override public void mouseReleased(MouseEvent e) { this.isReleased = true; this.setReleasedXY(e.getX(), e.getY()); @@ -737,6 +742,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse * * @param e 鼠标事件 */ + @Override public void mouseEntered(MouseEvent e) { } @@ -745,6 +751,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse * * @param e 鼠标事件 */ + @Override public void mouseExited(MouseEvent e) { } @@ -772,7 +779,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse protected abstract class SheetInsertAction extends UpdateAction { SheetInsertAction() { this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Insert") + getTemplateReportType()); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/add.png")); + this.setSmallIcon(IOUtils.readIcon("/com/fr/base/images/cell/control/add.png")); } @Override @@ -945,7 +952,7 @@ public class SheetNameTabPane extends JComponent implements MouseListener, Mouse private class CopySheetAction extends UpdateAction { CopySheetAction() { this.setName(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Copy")); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); + this.setSmallIcon(IOUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); } @Override diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineDialog.java b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineDialog.java index c8ecd9303..044a484b1 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineDialog.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/alphafine/component/AlphaFineDialog.java @@ -33,15 +33,12 @@ import com.fr.design.mainframe.alphafine.search.manager.impl.RecentSearchManager import com.fr.design.mainframe.alphafine.search.manager.impl.RecommendSearchManager; import com.fr.design.mainframe.alphafine.search.manager.impl.SegmentationManager; import com.fr.design.mainframe.alphafine.search.manager.impl.SimilarSearchManager; -import com.fr.design.mainframe.errorinfo.ErrorInfoUploader; -import com.fr.design.mainframe.templateinfo.TemplateInfoCollector; import com.fr.form.main.Form; import com.fr.form.main.FormIO; import com.fr.general.ComparatorUtils; import com.fr.general.http.HttpClient; import com.fr.io.TemplateWorkBookIO; import com.fr.io.exporter.ImageExporter; -import com.fr.json.JSONException; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; import com.fr.main.impl.WorkBook; @@ -958,8 +955,6 @@ public class AlphaFineDialog extends UIDialog { RecentSearchManager searchManager = RecentSearchManager.getInstance(); searchManager.addModel(storeText, cellModel); sendDataToServer(storeText, cellModel); - TemplateInfoCollector.getInstance().sendTemplateInfo(); - ErrorInfoUploader.getInstance().sendErrorInfo(); } } }); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/bbs/UserInfoLabel.java b/designer-realize/src/main/java/com/fr/design/mainframe/bbs/UserInfoLabel.java index 6f329c39d..7fe8b8ff8 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/bbs/UserInfoLabel.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/bbs/UserInfoLabel.java @@ -16,8 +16,12 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.upm.event.CertificateEvent; import com.fr.design.utils.concurrent.ThreadFactoryBuilder; import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; import com.fr.general.CloudCenter; import com.fr.general.ComparatorUtils; import com.fr.general.DateUtils; @@ -208,6 +212,18 @@ public class UserInfoLabel extends UILabel { updateInfoPane(); } }); + EventDispatcher.listen(CertificateEvent.LOGIN, new Listener() { + @Override + public void on(Event event, String text) { + setText(text); + } + }); + EventDispatcher.listen(CertificateEvent.LOGOUT, new Listener() { + @Override + public void on(Event event, String text) { + setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Base_UnSignIn")); + } + }); } private void clearLoginInformation() { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfo.java b/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfo.java index 052aaef9f..d22bcf75b 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfo.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfo.java @@ -25,6 +25,7 @@ public class ErrorInfo { private String templateid; private String logid; private String log; + private String stackTrace; public ErrorInfo(String username, String uuid, String activekey) { this.username = username; @@ -89,6 +90,14 @@ public class ErrorInfo { this.log = log; } + public String getStackTrace() { + return stackTrace; + } + + public void setStackTrace(String stackTrace) { + this.stackTrace = stackTrace; + } + private String dateToString(){ DateFormat df = FRContext.getDefaultValues().getDateTimeFormat(); return df.format(new Date()); @@ -107,6 +116,7 @@ public class ErrorInfo { jo.put("uploadtime", uploadtime); jo.put("logid", logid); jo.put("log", log); + jo.put("stacktrace", stackTrace); saveFileToCache(jo); } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoLogAppender.java b/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoLogAppender.java index 8d4970a86..bcdea3e5a 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoLogAppender.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoLogAppender.java @@ -30,6 +30,7 @@ import java.io.InputStream; public class ErrorInfoLogAppender extends AppenderSkeleton { private static final int ERROR_LEN = 8; + private static final int ERROR_STACK_TRACE = 15; // 缓存下不变的, 没必要频繁取. private String username; @@ -73,10 +74,23 @@ public class ErrorInfoLogAppender extends AppenderSkeleton { errorInfo.setTemplateid(templateid); errorInfo.setLog(msg); errorInfo.setLogid(logid); + errorInfo.setStackTrace(readStackTrace(event)); errorInfo.saveAsJSON(); } } + private String readStackTrace(LoggingEvent event) { + String[] s = event.getThrowableStrRep(); + StringBuilder sb = new StringBuilder(); + if (s != null) { + int len = Math.min(s.length, ERROR_STACK_TRACE); + for (int i = 0; i < len; i++) { + sb.append(s[i]).append("\n"); + } + } + return sb.toString(); + } + private String readLogID(String log) { String errorCode = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Engine_ErrorCode_Prefix"); // 报错信息国际化不规范, 有些是中文分号, 有些是英文 diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/entity/FileEntityBuilder.java b/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/entity/FileEntityBuilder.java new file mode 100644 index 000000000..c8ac3b32c --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/entity/FileEntityBuilder.java @@ -0,0 +1,137 @@ +package com.fr.design.mainframe.messagecollect.entity; + +import com.fr.config.MarketConfig; +import com.fr.design.DesignerEnvManager; +import com.fr.general.CloudCenter; +import com.fr.general.CloudClient; +import com.fr.general.IOUtils; +import com.fr.general.http.HttpToolbox; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.CommonUtils; +import com.fr.stable.CoreConstants; +import com.fr.stable.EncodeConstants; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import com.fr.third.jodd.datetime.JDateTime; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.UUID; + +/** + * @author alex sung + * @date 2019/4/8 + */ +public class FileEntityBuilder { + + private static final String FOCUS_POINT_FILE_ROOT_PATH = "FocusPoint"; + private static final String FOCUS_POINT_FILE_UPLOAD_TOPIC = "__fine_intelli_file_upload__"; + private static final String FILE_FROM = "design"; + private static final String FOCUS_POINT_FILE_UPLOAD_TYPE = "FocusPoint"; + private static final String FOCUS_POINT_FILE_UPLOAD_URL = CloudCenter.getInstance().acquireUrlByKind("design.feedback"); + private static final String FOCUS_POINT_URL_KEY = "focuspoint"; + + /** + * 文件夹路径 + */ + private String folderName; + + public FileEntityBuilder(String folderName) { + this.folderName = folderName; + } + + public String getFolderName() { + return folderName; + } + + public void setFolderName(String folderName) { + this.folderName = folderName; + } + + public File generateZipFile(String pathName) { + if (pathName == null) { + return null; + } + File zipFile = null; + try { + zipFile = new File(pathName + ".zip"); + java.util.zip.ZipOutputStream zipOut = new java.util.zip.ZipOutputStream(new FileOutputStream(zipFile)); + IOUtils.zip(zipOut, new File(pathName)); + zipOut.close(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return zipFile; + } + + public void generateFile(JSONArray jsonArray, String folderName) { + if (jsonArray.size() == 0) { + return; + } + try { + String content = jsonArray.toString(); + String fileName = String.valueOf(UUID.randomUUID()); + File file = new File(folderName + File.separator + fileName + ".json"); + StableUtils.makesureFileExist(file); + FileOutputStream out = new FileOutputStream(file); + InputStream in = new ByteArrayInputStream(content.getBytes(EncodeConstants.ENCODING_UTF_8)); + IOUtils.copyBinaryTo(in, out); + in.close(); + out.close(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + public void deleteFileAndZipFile(File zipFile, String pathName) { + File file = new File(pathName); + CommonUtils.deleteFile(file); + CommonUtils.deleteFile(zipFile); + } + + /** + * 上传文件到云中心 + * + * @param file 待上传文件 + * @param keyFileName 目标文件 + * @throws IOException + */ + public static void uploadFile(File file, String keyFileName) throws IOException { + CloudClient client = CloudClient.getInstance(); + String today = new JDateTime().toString("YYYY-MM-DD"); + String filePath = FOCUS_POINT_FILE_ROOT_PATH + CoreConstants.SEPARATOR + today + CoreConstants.SEPARATOR + keyFileName; + String bbsUserName = MarketConfig.getInstance().getBbsUsername(); + String uuid = DesignerEnvManager.getEnvManager().getUUID(); + String name = bbsUserName == null ? uuid : bbsUserName; + + client.uploadFile(file, filePath, name, FILE_FROM); + addMessageQueue(filePath, bbsUserName, uuid); + } + + private static void addMessageQueue(String filePath, String userName, String uuid) { + JSONObject uploadInfo = new JSONObject(FOCUS_POINT_FILE_UPLOAD_URL); + String focusPointUrl = uploadInfo.optString(FOCUS_POINT_URL_KEY); + try { + HashMap params = new HashMap<>(); + params.put("topic", FOCUS_POINT_FILE_UPLOAD_TOPIC); + params.put("username", URLEncoder.encode(userName, EncodeConstants.ENCODING_UTF_8)); + params.put("uuid", uuid); + params.put("filepath", filePath); + params.put("timestamp", String.valueOf(System.currentTimeMillis())); + params.put("signature", String.valueOf(CommonUtils.signature())); + params.put("type", FOCUS_POINT_FILE_UPLOAD_TYPE); + if(StringUtils.isNotEmpty(focusPointUrl)){ + HttpToolbox.post(focusPointUrl, params); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/impl/AbstractSendDataToCloud.java b/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/impl/AbstractSendDataToCloud.java new file mode 100644 index 000000000..da98e4778 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/impl/AbstractSendDataToCloud.java @@ -0,0 +1,133 @@ +package com.fr.design.mainframe.messagecollect.impl; + +import com.fr.design.mainframe.messagecollect.entity.FileEntityBuilder; +import com.fr.design.mainframe.messagecollect.utils.MessageCollectUtils; +import com.fr.intelli.record.MetricRegistry; +import com.fr.json.JSONArray; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ProductConstants; +import com.fr.stable.StableUtils; +import com.fr.stable.query.QueryFactory; +import com.fr.stable.query.condition.QueryCondition; +import com.fr.stable.query.data.DataList; +import com.fr.stable.query.restriction.RestrictionFactory; +import com.fr.stable.xml.XMLTools; +import com.fr.stable.xml.XMLable; + +import java.io.File; +import java.io.FileOutputStream; + +/** + * @author alex sung + * @date 2019/3/22 + */ +public abstract class AbstractSendDataToCloud implements XMLable { + private static final String FILE_NAME = "messagecollect.info"; + private static final String COLUMN_TIME = "time"; + + protected String lastTime; + private static final int PAGE_SIZE = 10000; + private long totalCount = -1; + private FileEntityBuilder fileEntityBuilder; + + public FileEntityBuilder getFileEntityBuilder() { + return fileEntityBuilder; + } + + public void setFileEntityBuilder(FileEntityBuilder fileEntityBuilder) { + this.fileEntityBuilder = fileEntityBuilder; + } + + public String getLastTime() { + return lastTime; + } + + public void setLastTime(String lastTime) { + this.lastTime = lastTime; + } + + public void saveLastTime() { + setLastTime(MessageCollectUtils.dateToString()); + try { + FileOutputStream out = new FileOutputStream(getLastTimeFile()); + XMLTools.writeOutputStreamXML(this, out); + } catch (Exception ex) { + FineLoggerFactory.getLogger().error(ex.getMessage()); + } + } + + public static File getLastTimeFile() { + return new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), FILE_NAME)); + } + + public void queryData(long currentTime, long lastTime, Class tClass) { + queryAndSendOnePageFunctionContent(currentTime, lastTime, 0, tClass); + long page = (totalCount / PAGE_SIZE) + 1; + for (int i = 1; i < page; i++) { + queryAndSendOnePageFunctionContent(currentTime, lastTime, i, tClass); + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + private void queryAndSendOnePageFunctionContent(long current, long last, int page, Class tClass) { + QueryCondition condition = QueryFactory.create() + .skip(page * PAGE_SIZE) + .count(PAGE_SIZE) + .addSort(COLUMN_TIME, true) + .addRestriction(RestrictionFactory.lte(COLUMN_TIME, current)) + .addRestriction(RestrictionFactory.gte(COLUMN_TIME, last)); + try { + DataList points = MetricRegistry.getMetric().find(tClass, condition); + //第一次查询获取总记录数 + if (page == 0) { + totalCount = points.getTotalCount(); + } + dealWithData(points); + + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + public void dealWithData(DataList tDataList) throws Exception { + generateThisPageFile(tDataList); + } + + private void generateThisPageFile(DataList points) { + File file = null; + try { + JSONArray jsonArray = dealWithSendFunctionContent(points); + //生成json文件 + fileEntityBuilder.generateFile(jsonArray, getFileEntityBuilder().getFolderName()); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + public abstract JSONArray dealWithSendFunctionContent(DataList focusPoints); + + /** + * 生成zip并发送zip文件 + * @param pathName zip文件路径 + */ + protected void sendZipFile(String pathName) { + + File file = null; + try { + file = fileEntityBuilder.generateZipFile(pathName); + if (file != null) { + fileEntityBuilder.uploadFile(file, file.getName()); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return; + } + fileEntityBuilder.deleteFileAndZipFile(file, pathName); + } + + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/impl/FocusPointMessageUploader.java b/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/impl/FocusPointMessageUploader.java new file mode 100644 index 000000000..214806c2e --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/impl/FocusPointMessageUploader.java @@ -0,0 +1,94 @@ +package com.fr.design.mainframe.messagecollect.impl; + +import com.fr.design.mainframe.messagecollect.entity.FileEntityBuilder; +import com.fr.design.mainframe.messagecollect.utils.MessageCollectUtils; +import com.fr.intelli.record.FocusPoint; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.ProductConstants; +import com.fr.stable.StableUtils; +import com.fr.stable.query.data.DataList; +import com.fr.stable.xml.XMLPrintWriter; +import com.fr.stable.xml.XMLableReader; + +import java.util.Date; +import java.util.UUID; + +/** + * @author alex sung + * @date 2019/3/22 + */ +public class FocusPointMessageUploader extends AbstractSendDataToCloud { + + private static final String TAG = "FocusPointMessageTag"; + private static final long DELTA = 24 * 3600 * 1000L; + private static volatile FocusPointMessageUploader instance; + + public static FocusPointMessageUploader getInstance() { + if (instance == null) { + synchronized (FocusPointMessageUploader.class) { + if (instance == null) { + instance = new FocusPointMessageUploader(); + } + } + } + return instance; + } + + @Override + public JSONArray dealWithSendFunctionContent(DataList focusPoints) { + JSONArray ja = new JSONArray(); + for(T t:focusPoints.getList()){ + FocusPoint focusPoint = (FocusPoint)t; + JSONObject jo = new JSONObject(); + jo.put("id",focusPoint.getId()); + jo.put("text",focusPoint.getText()); + jo.put("source",focusPoint.getSource()); + jo.put("time",focusPoint.getTime()); + jo.put("username",focusPoint.getUsername()); + jo.put("ip",focusPoint.getIp()); + jo.put("title",focusPoint.getTitle()); + jo.put("body",focusPoint.getBody()); + ja.put(jo); + } + return ja; + } + + public void sendToCloudCenter() { + MessageCollectUtils.readXMLFile(instance, getLastTimeFile()); + long currentTime = new Date().getTime(); + long lastTime = MessageCollectUtils.getLastTimeMillis(this.lastTime); + if (currentTime - lastTime <= DELTA) { + return; + } + try { + generatePath(); + queryData(currentTime, lastTime, FocusPoint.class); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage()); + } + sendZipFile(getFileEntityBuilder().getFolderName()); + saveLastTime(); + } + + @Override + public void readXML(XMLableReader reader) { + if (reader.isAttr()) { + this.setLastTime(reader.getAttrAsString("focusPointLastTime", null)); + } + } + + @Override + public void writeXML(XMLPrintWriter writer) { + writer.startTAG(TAG); + writer.attr("focusPointLastTime", lastTime); + writer.end(); + } + + private void generatePath() { + //文件夹名称是uuid.zip,版本信息已经在edition中体现了 + String folderName = StableUtils.pathJoin(ProductConstants.getEnvHome(), String.valueOf(UUID.randomUUID())); + setFileEntityBuilder(new FileEntityBuilder(folderName)); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/utils/MessageCollectUtils.java b/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/utils/MessageCollectUtils.java new file mode 100644 index 000000000..738942208 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/messagecollect/utils/MessageCollectUtils.java @@ -0,0 +1,63 @@ +package com.fr.design.mainframe.messagecollect.utils; + +import com.fr.base.FRContext; +import com.fr.general.DateUtils; +import com.fr.general.IOUtils; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.EncodeConstants; +import com.fr.stable.StringUtils; +import com.fr.stable.xml.XMLReadable; +import com.fr.stable.xml.XMLableReader; +import com.fr.third.javax.xml.stream.XMLStreamException; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.text.DateFormat; +import java.util.Date; + +/** + * @author alex sung + * @date 2019/3/26 + */ +public class MessageCollectUtils { + + public static void readXMLFile(XMLReadable xmlReadable, File xmlFile) { + if (xmlFile == null || !xmlFile.exists()) { + return; + } + String charset = EncodeConstants.ENCODING_UTF_8; + try { + InputStream is = new FileInputStream(xmlFile); + String fileContent = IOUtils.inputStream2String(is); + InputStream xmlInputStream = new ByteArrayInputStream(fileContent.getBytes(charset)); + InputStreamReader inputStreamReader = new InputStreamReader(xmlInputStream, charset); + XMLableReader xmlReader = XMLableReader.createXMLableReader(inputStreamReader); + if (xmlReader != null) { + xmlReader.readXMLObject(xmlReadable); + } + xmlInputStream.close(); + } catch (IOException | XMLStreamException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + public static long getLastTimeMillis(String lastTime) { + if (StringUtils.isEmpty(lastTime)) { + return 0; + } + try { + return DateUtils.string2Date(lastTime, true).getTime(); + } catch (Exception e) { + return -1; + } + } + + public static String dateToString(){ + DateFormat df = FRContext.getDefaultValues().getDateTimeFormat(); + return df.format(new Date()); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/templateinfo/JWorkBookProcessInfo.java b/designer-realize/src/main/java/com/fr/design/mainframe/template/info/JWorkBookProcessInfo.java similarity index 98% rename from designer-realize/src/main/java/com/fr/design/mainframe/templateinfo/JWorkBookProcessInfo.java rename to designer-realize/src/main/java/com/fr/design/mainframe/template/info/JWorkBookProcessInfo.java index 306c6b0d1..eec777328 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/templateinfo/JWorkBookProcessInfo.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/template/info/JWorkBookProcessInfo.java @@ -1,4 +1,4 @@ -package com.fr.design.mainframe.templateinfo; +package com.fr.design.mainframe.template.info; import com.fr.base.parameter.ParameterUI; import com.fr.main.impl.WorkBook; diff --git a/designer-realize/src/main/java/com/fr/design/report/freeze/RepeatColPane.java b/designer-realize/src/main/java/com/fr/design/report/freeze/RepeatColPane.java index 100b306d8..b4ff4f9ef 100644 --- a/designer-realize/src/main/java/com/fr/design/report/freeze/RepeatColPane.java +++ b/designer-realize/src/main/java/com/fr/design/report/freeze/RepeatColPane.java @@ -21,8 +21,10 @@ public class RepeatColPane extends FreezeAndRepeatPane { @Override public void populateBean(FT ob) { - ((ColSpinner)start).setValue((ob.getFrom() + 1)); - ((ColSpinner)end).setValue((ob.getTo() + 1)); + if (ob.getFrom() <= ob.getTo()) { + ((ColSpinner)start).setValue((ob.getFrom() + 1)); + ((ColSpinner)end).setValue((ob.getTo() + 1)); + } } @Override diff --git a/designer-realize/src/main/java/com/fr/design/report/freeze/RepeatRowPane.java b/designer-realize/src/main/java/com/fr/design/report/freeze/RepeatRowPane.java index e46a59a6e..5ae39ec25 100644 --- a/designer-realize/src/main/java/com/fr/design/report/freeze/RepeatRowPane.java +++ b/designer-realize/src/main/java/com/fr/design/report/freeze/RepeatRowPane.java @@ -21,8 +21,10 @@ public class RepeatRowPane extends FreezeAndRepeatPane { @Override public void populateBean(FT ob) { - ((RowSpinner)start).setValue((ob.getFrom() + 1)); - ((RowSpinner)end).setValue((ob.getTo() + 1)); + if (ob.getFrom() <= ob.getTo()) { + ((RowSpinner)start).setValue((ob.getFrom() + 1)); + ((RowSpinner)end).setValue((ob.getTo() + 1)); + } } @Override diff --git a/designer-realize/src/main/java/com/fr/grid/GridUtils.java b/designer-realize/src/main/java/com/fr/grid/GridUtils.java index dfe7a5f2d..11e907fc6 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridUtils.java +++ b/designer-realize/src/main/java/com/fr/grid/GridUtils.java @@ -12,6 +12,7 @@ import com.fr.general.ComparatorUtils; import com.fr.grid.selection.CellSelection; import com.fr.grid.selection.FloatSelection; import com.fr.grid.selection.Selection; +import com.fr.poly.creator.ECBlockPane; import com.fr.report.ReportHelper; import com.fr.report.cell.CellElement; import com.fr.report.cell.FloatElement; @@ -48,8 +49,7 @@ public class GridUtils { //peter:下面这几个量是在Drag列的时候用. public final static int DRAG_CELL_SIZE = 1; //peter:drag的时候改变格子的宽度. - public final static int DRAG_SELECT_UNITS = 2; //peter:drag的时候,选中单元格. -// public static int resolution = (int) (ScreenResolution.getScreenResolution()* JSliderPane.getInstance().resolutionTimes); + public final static int DRAG_SELECT_UNITS = 2; //peter:drag的时候,选中单元格.// public static int resolution = (int) (ScreenResolution.getScreenResolution()* JSliderPane.getInstance().resolutionTimes); /** * Is above float element.(the return may be null).
@@ -125,7 +125,6 @@ public class GridUtils { */ public static double[] caculateFloatElementLocations(FloatElement floatElement, DynamicUnitList columnWidthList, DynamicUnitList rowHeightList, int verticalValue, int horizentalValue) { -// int resolution = ScreenResolution.getScreenResolution(); int resolution = (int) (ScreenResolution.getScreenResolution() * JSliderPane.getInstance().resolutionTimes); double floatX = columnWidthList.getRangeValue(horizentalValue, 0).toPixD(resolution) + floatElement.getLeftDistance().toPixD(resolution); @@ -180,7 +179,6 @@ public class GridUtils { private static int cc_selected_column_or_row(double mouseEvtPosition, int beginValue, int value, DynamicUnitList sizeList) { double tmpIntIndex = 0; int selectedCellIndex = 0; -// int resolution = ScreenResolution.getScreenResolution(); int resolution = (int) (ScreenResolution.getScreenResolution() * JSliderPane.getInstance().resolutionTimes); if (mouseEvtPosition < 0) { selectedCellIndex = value; @@ -239,7 +237,6 @@ public class GridUtils { private static int cc_selected_column_or_row_withresolution(double mouseEvtPosition, int beginValue, int value, DynamicUnitList sizeList, int resolution) { double tmpIntIndex = 0; int selectedCellIndex = 0; -// int resolution = ScreenResolution.getScreenResolution(); if (mouseEvtPosition < 0) { selectedCellIndex = value; for (; true; selectedCellIndex--) { @@ -311,6 +308,7 @@ public class GridUtils { public static boolean canMove(ElementCasePane reportPane, int cellColumn, int cellRow) { if (reportPane.mustInVisibleRange()) { Grid grid = reportPane.getGrid(); + checkGridCount(reportPane); int verticalEndValue = grid.getVerticalValue() + grid.getVerticalExtent() - 1; int horizontalEndValue = grid.getHorizontalValue() + grid.getHorizontalExtent() - 1; if (cellColumn > horizontalEndValue) { @@ -323,6 +321,16 @@ public class GridUtils { return true; } + /** + *聚合报表的报表块增加单元格的数量时 当单元格拉动一半会自动扩展成完整的单元格 + * 该单元格不被记录 check下重新计算下单元格数量 + */ + private static void checkGridCount(Object obj) { + if (obj instanceof ECBlockPane) { + ((ECBlockPane) obj).getTarget().firePropertyChange(); + } + } + /** * 选择一个Cell, 支持Merge. */ diff --git a/designer-realize/src/main/java/com/fr/poly/PolyComponentsBar.java b/designer-realize/src/main/java/com/fr/poly/PolyComponentsBar.java index 3130a4b86..564a3ae6a 100644 --- a/designer-realize/src/main/java/com/fr/poly/PolyComponentsBar.java +++ b/designer-realize/src/main/java/com/fr/poly/PolyComponentsBar.java @@ -12,6 +12,7 @@ import com.fr.design.gui.itooltip.MultiLineToolTip; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.dnd.SerializableTransferable; +import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; import com.fr.report.poly.PolyECBlock; import com.sun.java.swing.plaf.windows.WindowsLookAndFeel; @@ -65,7 +66,7 @@ public class PolyComponentsBar extends JToolBar { for (int i = 0; i < typeLen; i++) { BaseChart[] rowChart = BaseChartGetter.getStaticChartTypes(typeName[i].getPlotID()); String iconPath = ChartTypeInterfaceManager.getInstance().getIconPath(typeName[i].getPlotID()); - serIcons[i + 1] = new SerIcon(rowChart[0], Toolkit.i18nText(typeName[i].getName()), iconPath); + serIcons[i + 1] = new SerIcon(rowChart[0], InterProviderFactory.getProvider().getLocText(typeName[i].getName()), iconPath); this.add(serIcons[i + 1]); } diff --git a/designer-realize/src/main/java/com/fr/start/Designer.java b/designer-realize/src/main/java/com/fr/start/Designer.java index d262359dd..2c8e030e3 100644 --- a/designer-realize/src/main/java/com/fr/start/Designer.java +++ b/designer-realize/src/main/java/com/fr/start/Designer.java @@ -3,7 +3,6 @@ package com.fr.start; import com.fr.base.BaseUtils; import com.fr.base.vcs.DesignerMode; import com.fr.design.DesignerEnvManager; -import com.fr.design.RestartHelper; import com.fr.design.actions.core.ActionFactory; import com.fr.design.actions.file.WebPreviewUtils; import com.fr.design.actions.file.newReport.NewPolyReportAction; @@ -11,7 +10,9 @@ import com.fr.design.actions.file.newReport.NewWorkBookAction; import com.fr.design.actions.server.ServerConfigManagerAction; import com.fr.design.actions.server.StyleListAction; import com.fr.design.actions.server.WidgetManagerAction; +import com.fr.design.base.mode.DesignModeContext; import com.fr.design.constants.UIConstants; +import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.MutilTempalteTabPane; import com.fr.design.fun.MenuHandler; @@ -28,14 +29,12 @@ import com.fr.design.mainframe.JWorkBook; import com.fr.design.mainframe.alphafine.component.AlphaFinePane; import com.fr.design.mainframe.bbs.UserInfoLabel; import com.fr.design.mainframe.bbs.UserInfoPane; -import com.fr.design.mainframe.templateinfo.TemplateInfoCollector; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.menu.KeySetUtils; import com.fr.design.menu.MenuDef; import com.fr.design.menu.SeparatorDef; import com.fr.design.menu.ShortCut; import com.fr.design.module.DesignModuleFactory; -import com.fr.design.utils.DesignUtils; import com.fr.design.utils.concurrent.ThreadFactoryBuilder; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.ComparatorUtils; @@ -43,17 +42,12 @@ import com.fr.log.FineLoggerFactory; import com.fr.module.Module; import com.fr.module.ModuleContext; import com.fr.runtime.FineRuntime; -import com.fr.stable.BuildContext; -import com.fr.stable.OperatingSystem; import com.fr.stable.ProductConstants; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; import com.fr.stable.lifecycle.LifecycleFatalError; import com.fr.stable.xml.XMLTools; -import com.fr.start.fx.SplashFx; -import com.fr.start.jni.SplashMac; import com.fr.start.module.StartupArgs; -import com.fr.start.preload.ImagePreLoader; import com.fr.start.server.ServerTray; import com.fr.workspace.WorkContext; @@ -69,8 +63,6 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.util.ArrayList; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; @@ -90,31 +82,19 @@ public class Designer extends BaseDesigner { private UIButton redo; private UIPreviewButton run; + public Designer(String[] args) { + super(args); + } + /** * 设计器启动的Main方法 * * @param args 参数 */ public static void main(String[] args) { - + //启动运行时 FineRuntime.start(); - BuildContext.setBuildFilePath("/com/fr/stable/build.properties"); - // 如果端口被占用了 说明程序已经运行了一次,也就是说,已经建立一个监听服务器,现在只要给服务器发送命令就好了 - if (DesignUtils.isStarted()) { - DesignUtils.clientSend(args); - FineLoggerFactory.getLogger().error("Designer port not available."); - System.exit(0); - return; - } - - RestartHelper.deleteRecordFilesWhenStart(); - - preloadResource(); - - SplashContext.getInstance().registerSplash(createSplash()); - - SplashContext.getInstance().show(); Module designerRoot = ModuleContext.parseRoot("designer-startup.xml"); //传递启动参数 designerRoot.setSingleton(StartupArgs.class, new StartupArgs(args)); @@ -134,40 +114,6 @@ public class Designer extends BaseDesigner { } - private static void preloadResource() { - ExecutorService service = Executors.newCachedThreadPool(); - - service.submit(new Runnable() { - @Override - public void run() { - new ImagePreLoader(); - } - }); - - service.submit(new Runnable() { - @Override - public void run() { - TemplateInfoCollector.getInstance(); - } - }); - service.shutdown(); - } - - private static SplashStrategy createSplash() { - // 这里可以开接口加载自定义启动画面 - if (OperatingSystem.isWindows()) { - return new SplashFx(); - } else if (OperatingSystem.isMacOS()) { - return new SplashMac(); - } - return new SplashFx(); - } - - public Designer(String[] args) { - super(args); - } - - /** * 创建新建文件的快捷方式数组。 * @@ -270,7 +216,7 @@ public class Designer extends BaseDesigner { saveButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); jt.stopEditing(); jt.saveTemplate(); jt.requestFocus(); @@ -279,6 +225,7 @@ public class Designer extends BaseDesigner { return saveButton; } + private UIButton createUndoButton() { undo = new UIButton(BaseUtils.readIcon("/com/fr/design/images/buttonicon/undo.png")); undo.setToolTipText(KeySetUtils.UNDO.getMenuKeySetName()); @@ -326,7 +273,7 @@ public class Designer extends BaseDesigner { ) { @Override protected void upButtonClickEvent() { - JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); if (jt == null) { return; } @@ -335,7 +282,7 @@ public class Designer extends BaseDesigner { @Override protected void downButtonClickEvent() { - final JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + final JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); if (jt == null) { return; } @@ -363,12 +310,12 @@ public class Designer extends BaseDesigner { @Override protected void refreshLargeToolbarState() { - JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); if (jt == null) { return; } - saveButton.setEnabled(!jt.isSaved() && !DesignerMode.isVcsMode()); - MutilTempalteTabPane.getInstance().refreshOpenedTemplate(HistoryTemplateListPane.getInstance().getHistoryList()); + saveButton.setEnabled(!jt.isSaved() && !DesignModeContext.isVcsMode()); + MutilTempalteTabPane.getInstance().refreshOpenedTemplate(HistoryTemplateListCache.getInstance().getHistoryList()); MutilTempalteTabPane.getInstance().repaint(); if (DesignerEnvManager.getEnvManager().isSupportUndo()) { undo.setEnabled(jt.canUndo()); diff --git a/designer-realize/src/main/java/com/fr/start/SplashContext.java b/designer-realize/src/main/java/com/fr/start/SplashContext.java index cea537592..17eff62ba 100644 --- a/designer-realize/src/main/java/com/fr/start/SplashContext.java +++ b/designer-realize/src/main/java/com/fr/start/SplashContext.java @@ -167,7 +167,7 @@ public class SplashContext { private static String getSplashPath() { Locale locale = DesignerEnvManager.getEnvManager().getLanguage(); - if (Locale.US.equals(locale) || Locale.KOREA.equals(locale)) { + if (Locale.US.equals(locale) || Locale.KOREA.equals(locale) || Locale.TAIWAN.equals(locale)) { return "/com/fr/design/images/splash_10_en.gif"; } else if (Locale.JAPAN.equals(locale)) { return "/com/fr/design/images/splash_10_jp.gif"; diff --git a/designer-realize/src/main/java/com/fr/start/module/PreStartActivator.java b/designer-realize/src/main/java/com/fr/start/module/PreStartActivator.java index c4eea3bad..72d3217be 100644 --- a/designer-realize/src/main/java/com/fr/start/module/PreStartActivator.java +++ b/designer-realize/src/main/java/com/fr/start/module/PreStartActivator.java @@ -2,63 +2,99 @@ package com.fr.start.module; import com.fr.design.DesignerEnvManager; import com.fr.design.RestartHelper; +import com.fr.design.fun.OemProcessor; +import com.fr.design.mainframe.template.info.TemplateInfoCollector; import com.fr.design.utils.DesignUtils; +import com.fr.design.utils.DesignerPort; import com.fr.general.CloudCenter; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; +import com.fr.log.FineLoggerFactory; import com.fr.module.Activator; +import com.fr.stable.BuildContext; +import com.fr.stable.OperatingSystem; import com.fr.stable.ProductConstants; +import com.fr.stable.StableUtils; +import com.fr.start.OemHandler; +import com.fr.start.SplashContext; +import com.fr.start.SplashStrategy; +import com.fr.start.fx.SplashFx; +import com.fr.start.jni.SplashMac; +import com.fr.start.preload.ImagePreLoader; import java.io.File; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * Created by juhaoyu on 2018/1/8. */ public class PreStartActivator extends Activator { - private static final int MESSAGE_PORT = 51462; - - private static final int DEBUG_PORT = 51463; - @Override public void start() { - CloudCenter.getInstance(); - if (checkMultiStart()) { + BuildContext.setBuildFilePath("/com/fr/stable/build.properties"); + // 如果端口被占用了 说明程序已经运行了一次,也就是说,已经建立一个监听服务器,现在只要给服务器发送命令就好了 + final String[] args = getModule().upFindSingleton(StartupArgs.class).get(); + // 检查是否是-Ddebug = true 启动 并切换对应的端口以及环境配置文件 + checkDebugStart(); + if (DesignUtils.isStarted()) { + DesignUtils.clientSend(args); + FineLoggerFactory.getLogger().info("The Designer Has Been Started"); + System.exit(0); return; } + + RestartHelper.deleteRecordFilesWhenStart(); + + preloadResource(); + + SplashContext.getInstance().registerSplash(createSplash()); + + SplashContext.getInstance().show(); + + // 完成初始化 + //noinspection ResultOfMethodCallIgnored + CloudCenter.getInstance(); + + // 创建监听服务 + DesignUtils.createListeningServer(DesignUtils.getPort(), startFileSuffix()); + initLanguage(); } - private boolean checkMultiStart() { + @Override + public void stop() { + + } + private void checkDebugStart() { if (isDebug()) { setDebugEnv(); - } else { - DesignUtils.setPort(getStartPort()); } - - return false; } - private int getStartPort() { - - return MESSAGE_PORT; - } - - //在VM options里加入-Ddebug=true激活 + /** + * 在VM options里加入-Ddebug=true激活 + * + * @return isDebug + */ private boolean isDebug() { - return ComparatorUtils.equals("true", System.getProperty("debug")); } //端口改一下,环境配置文件改一下。便于启动两个设计器,进行对比调试 private void setDebugEnv() { - - DesignUtils.setPort(DEBUG_PORT); - DesignerEnvManager.setEnvFile(new File(ProductConstants.getEnvHome() + File.separator + ProductConstants.APP_NAME + "Env_debug.xml")); + DesignUtils.setPort(DesignerPort.DEBUG_MESSAGE_PORT); + String debugXMlFilePath = StableUtils.pathJoin( + ProductConstants.getEnvHome(), + ProductConstants.APP_NAME + "Env_debug.xml" + ); + DesignerEnvManager.setEnvFile( + new File(debugXMlFilePath)); } private void initLanguage() { @@ -66,8 +102,48 @@ public class PreStartActivator extends Activator { GeneralContext.setLocale(DesignerEnvManager.getEnvManager(false).getLanguage()); } - @Override - public void stop() { + private String[] startFileSuffix() { + return new String[]{".cpt", ".xls", ".xlsx", ".frm", ".form", ".cht", ".chart"}; + } + private static void preloadResource() { + ExecutorService service = Executors.newCachedThreadPool(); + + service.submit(new Runnable() { + @Override + public void run() { + new ImagePreLoader(); + } + }); + + service.submit(new Runnable() { + @Override + public void run() { + TemplateInfoCollector.getInstance(); + } + }); + service.shutdown(); + } + + private SplashStrategy createSplash() { + OemProcessor oemProcessor = OemHandler.findOem(); + if (oemProcessor != null) { + SplashStrategy splashStrategy = null; + try { + splashStrategy = oemProcessor.createSplashStrategy(); + } catch (Throwable e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + if (splashStrategy != null) { + return splashStrategy; + } + } + // 这里可以开接口加载自定义启动画面 + if (OperatingSystem.isWindows()) { + return new SplashFx(); + } else if (OperatingSystem.isMacOS()) { + return new SplashMac(); + } + return new SplashFx(); } } diff --git a/designer-realize/src/main/java/com/fr/start/module/StartFinishActivator.java b/designer-realize/src/main/java/com/fr/start/module/StartFinishActivator.java index b9e165b26..41f662a88 100644 --- a/designer-realize/src/main/java/com/fr/start/module/StartFinishActivator.java +++ b/designer-realize/src/main/java/com/fr/start/module/StartFinishActivator.java @@ -1,36 +1,19 @@ package com.fr.start.module; import com.fr.design.fun.impl.GlobalListenerProviderManager; -import com.fr.design.utils.DesignUtils; import com.fr.module.Activator; /** * Created by juhaoyu on 2018/1/8. */ public class StartFinishActivator extends Activator { - - private static final int MESSAGE_PORT = 51462; - + @Override public void start() { - - DesignUtils.creatListeningServer(getStartPort(), startFileSuffix()); GlobalListenerProviderManager.getInstance().init(); } - - private int getStartPort() { - - return MESSAGE_PORT; - } - - - private String[] startFileSuffix() { - - return new String[]{".cpt", ".xls", ".xlsx", ".frm", ".form", ".cht", ".chart"}; - } - + @Override public void stop() { - } } diff --git a/designer-realize/src/main/resources/com/fr/aspectj/designer/TemplateProcessTracker.aj b/designer-realize/src/main/resources/com/fr/aspectj/designer/TemplateProcessTracker.aj index 8e4eeb716..2c5433818 100644 --- a/designer-realize/src/main/resources/com/fr/aspectj/designer/TemplateProcessTracker.aj +++ b/designer-realize/src/main/resources/com/fr/aspectj/designer/TemplateProcessTracker.aj @@ -5,13 +5,11 @@ package com.fr.aspectj.designer; * Created by plough on 2017/3/3. */ -import com.fr.design.mainframe.templateinfo.TemplateInfoCollector; import com.fr.grid.Grid; import org.aspectj.lang.reflect.SourceLocation; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; -import java.util.Date; public aspect TemplateProcessTracker { //声明一个pointcut,匹配你需要的方法