Browse Source

Merge pull request #898 in DESIGN/design from ~NEIL/design:final/10.0 to final/10.0

* commit '7f53870106670f46d1f62c8234792b24dfcedc0e': (196 commits)
  改一下label 继承 下actionlabel
  rt
  REPORT-14835 过滤逻辑修改
  修改editor
  rt
  REPORT-14835 日期控件自定义
  REPORT-17096 同步到10.0
  REPORT-16985 先屏蔽开发者调试
  REPORT-16567 设计器社区菜单修改 添加新子菜单
  REPORT-16029 繁体版本启动画面改成英文
  依然使用FileExtension
  误删了sort
  REPORT-16997 FileExtension支持接口扩展
  更新下topic
  encode一下,防止乱码
  REPORT-15987 这边也一起改下
  REPORT-14835 交互优化
  update
  update
  update
  ...
final/10.0
Kara 5 years ago
parent
commit
63e0577414
  1. 51
      designer-base/src/main/java/com/fr/design/DesignerEnvManager.java
  2. 4
      designer-base/src/main/java/com/fr/design/EnvChangeEntrance.java
  3. 41
      designer-base/src/main/java/com/fr/design/actions/community/FacebookFansAction.java
  4. 6
      designer-base/src/main/java/com/fr/design/actions/file/PreferenceAction.java
  5. 139
      designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java
  6. 38
      designer-base/src/main/java/com/fr/design/actions/help/TutorialAction.java
  7. 14
      designer-base/src/main/java/com/fr/design/actions/server/PluginManagerAction.java
  8. 17
      designer-base/src/main/java/com/fr/design/bridge/exec/JSBridge.java
  9. 18
      designer-base/src/main/java/com/fr/design/bridge/exec/JSCallback.java
  10. 2
      designer-base/src/main/java/com/fr/design/bridge/exec/JSExecutor.java
  11. 58
      designer-base/src/main/java/com/fr/design/bridge/exec/JSUtils.java
  12. 1
      designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java
  13. 27
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  14. 26
      designer-base/src/main/java/com/fr/design/dialog/BasicPane.java
  15. 4
      designer-base/src/main/java/com/fr/design/editor/editor/DateEditor.java
  16. 42
      designer-base/src/main/java/com/fr/design/extra/PluginJavaFxExecutor.java
  17. 2
      designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java
  18. 20
      designer-base/src/main/java/com/fr/design/extra/PluginWebBridge.java
  19. 1
      designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallFromDiskCallback.java
  20. 1
      designer-base/src/main/java/com/fr/design/extra/exe/callback/InstallOnlineCallback.java
  21. 1
      designer-base/src/main/java/com/fr/design/extra/exe/callback/ModifyStatusCallback.java
  22. 1
      designer-base/src/main/java/com/fr/design/extra/exe/callback/UninstallPluginCallback.java
  23. 1
      designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateFromDiskCallback.java
  24. 1
      designer-base/src/main/java/com/fr/design/extra/exe/callback/UpdateOnlineCallback.java
  25. 14
      designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java
  26. 7
      designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java
  27. 38
      designer-base/src/main/java/com/fr/design/fun/OemProcessor.java
  28. 25
      designer-base/src/main/java/com/fr/design/fun/impl/AbstractOemProcessor.java
  29. 4
      designer-base/src/main/java/com/fr/design/gui/date/SingleObjectComboBoxModel.java
  30. 14
      designer-base/src/main/java/com/fr/design/gui/date/UIDatePicker.java
  31. 44
      designer-base/src/main/java/com/fr/design/gui/ibutton/UIToggleButton.java
  32. 17
      designer-base/src/main/java/com/fr/design/gui/ispinner/UISpinner.java
  33. 23
      designer-base/src/main/java/com/fr/design/gui/style/AlignmentPane.java
  34. 9
      designer-base/src/main/java/com/fr/design/icon/BorderIcon.java
  35. 32
      designer-base/src/main/java/com/fr/design/javascript/beautify/JavaScriptFormatHelper.java
  36. 28
      designer-base/src/main/java/com/fr/design/layout/FRGUIPaneFactory.java
  37. 19
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java
  38. 205
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java
  39. 7
      designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java
  40. 74
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  41. 2
      designer-base/src/main/java/com/fr/design/mainframe/JVirtualTemplate.java
  42. 9
      designer-base/src/main/java/com/fr/design/mainframe/mobile/ui/DownMenuStyleDefinePane.java
  43. 129
      designer-base/src/main/java/com/fr/design/mainframe/template/info/DesignerOpenHistory.java
  44. 47
      designer-base/src/main/java/com/fr/design/mainframe/template/info/SendHelper.java
  45. 260
      designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfo.java
  46. 252
      designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateInfoCollector.java
  47. 6
      designer-base/src/main/java/com/fr/design/mainframe/template/info/TemplateProcessInfo.java
  48. 69
      designer-base/src/main/java/com/fr/design/mainframe/template/info/TimeConsumeTimer.java
  49. 550
      designer-base/src/main/java/com/fr/design/mainframe/templateinfo/TemplateInfoCollector.java
  50. 22
      designer-base/src/main/java/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java
  51. 74
      designer-base/src/main/java/com/fr/design/mainframe/vcs/VcsConfigManager.java
  52. 75
      designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsCacheFileNodeFile.java
  53. 177
      designer-base/src/main/java/com/fr/design/mainframe/vcs/common/VcsHelper.java
  54. 104
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/EditFileVersionDialog.java
  55. 80
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionCellEditor.java
  56. 44
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionCellRender.java
  57. 112
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionDialog.java
  58. 21
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionFirstRowPanel.java
  59. 151
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionRowPanel.java
  60. 79
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionTable.java
  61. 201
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/FileVersionsPanel.java
  62. 37
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsDateEditor.java
  63. 32
      designer-base/src/main/java/com/fr/design/mainframe/vcs/ui/VcsLabel.java
  64. 1
      designer-base/src/main/java/com/fr/design/ui/Assistant.java
  65. 34
      designer-base/src/main/java/com/fr/design/ui/EmbProtocolHandler.java
  66. 40
      designer-base/src/main/java/com/fr/design/ui/ModernUIPane.java
  67. 6
      designer-base/src/main/java/com/fr/design/update/actions/FileDownloader.java
  68. 5
      designer-base/src/main/java/com/fr/design/update/actions/SoftwareUpdateAction.java
  69. 2
      designer-base/src/main/java/com/fr/design/update/domain/DownloadItem.java
  70. 2
      designer-base/src/main/java/com/fr/design/update/domain/UpdateConstants.java
  71. 2
      designer-base/src/main/java/com/fr/design/update/domain/UpdateInfoCachePropertyManager.java
  72. 2
      designer-base/src/main/java/com/fr/design/update/factory/DirectoryOperationFactory.java
  73. 61
      designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateConfigManager.java
  74. 196
      designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateDialog.java
  75. 168
      designer-base/src/main/java/com/fr/design/update/push/DesignerPushUpdateManager.java
  76. 91
      designer-base/src/main/java/com/fr/design/update/push/DesignerUpdateInfo.java
  77. 2
      designer-base/src/main/java/com/fr/design/update/ui/dialog/EncodingDetect.java
  78. 9
      designer-base/src/main/java/com/fr/design/update/ui/dialog/RestoreDialog.java
  79. 4
      designer-base/src/main/java/com/fr/design/update/ui/dialog/RestoreResultDialog.java
  80. 49
      designer-base/src/main/java/com/fr/design/update/ui/dialog/UpdateMainDialog.java
  81. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/ColorfulCellRender.java
  82. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/LoadingLabel.java
  83. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateActionLabel.java
  84. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTable.java
  85. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableCellRender.java
  86. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTableModel.java
  87. 2
      designer-base/src/main/java/com/fr/design/update/ui/widget/UpdateInfoTextAreaCellRender.java
  88. 406
      designer-base/src/main/java/com/fr/design/upm/UpmBridge.java
  89. 68
      designer-base/src/main/java/com/fr/design/upm/UpmFinder.java
  90. 34
      designer-base/src/main/java/com/fr/design/upm/UpmShowDialog.java
  91. 63
      designer-base/src/main/java/com/fr/design/upm/UpmShowPane.java
  92. 21
      designer-base/src/main/java/com/fr/design/upm/UpmUtils.java
  93. 33
      designer-base/src/main/java/com/fr/design/upm/WarnComponent.java
  94. 12
      designer-base/src/main/java/com/fr/design/upm/event/CertificateEvent.java
  95. 13
      designer-base/src/main/java/com/fr/design/upm/event/DownloadEvent.java
  96. 30
      designer-base/src/main/java/com/fr/design/upm/exec/UpmBrowserExecutor.java
  97. 27
      designer-base/src/main/java/com/fr/design/upm/loader/UpmDesignResourceLoader.java
  98. 52
      designer-base/src/main/java/com/fr/design/upm/task/UpmTaskWorker.java
  99. 203
      designer-base/src/main/java/com/fr/design/utils/DesignUtils.java
  100. 26
      designer-base/src/main/java/com/fr/design/utils/DesignerPort.java
  101. Some files were not shown because too many files have changed in this diff Show More

51
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.<br>
* The method will be invoked when save data to XML file.<br>
@ -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;
}
}

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

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

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

139
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<? extends Configuration>[] targets() {
return new Class[] {ServerPreferenceConfig.class};
}
});
}

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

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

17
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 {
}

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

2
designer-base/src/main/java/com/fr/design/extra/exe/callback/JSExecutor.java → 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.

58
designer-base/src/main/java/com/fr/design/extra/exe/callback/JSCallback.java → 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<String> list = new ArrayList<>();
for (int i = 0; i < len; i++) {
list.add(obj.getSlot(i).toString());
}
return list.toArray(new String[len]);
}
}

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

27
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<String, String> map = new HashMap<String, String>();
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);
}
}

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

4
designer-base/src/main/java/com/fr/design/editor/editor/DateEditor.java

@ -153,6 +153,10 @@ public class DateEditor extends Editor<Date> {
this.uiDatePicker.setSelectedItem(new Date());
}
public UIDatePicker getUiDatePicker() {
return uiDatePicker;
}
/**
* Request focus
*/

42
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() + "\")");
}
}
});
}
}

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

20
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<PluginMarker> pluginMarkerList = new ArrayList<PluginMarker>();
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);
}

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

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

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

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

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

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

14
designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java

@ -41,17 +41,17 @@ public class HistoryTemplateListCache implements CallbackEvent {
private List<JTemplate<?, ?>> 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) {

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

38
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<BufferedImage> createTitleIcon();
/**
* 处理设计器菜单增删改
*
* @param menuDefs 已加载的菜单
* @return 新的菜单数组
*/
MenuDef[] dealWithMenuDef(MenuDef[] menuDefs);
}

25
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<BufferedImage> createTitleIcon() {
return null;
}
@Override
public SplashStrategy createSplashStrategy() {
return null;
}
}

4
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) {

14
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) {

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

17
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){

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

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

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

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

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

19
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<BufferedImage> image = ICODecoder.read(DesignerFrame.class
.getResourceAsStream("/com/fr/base/images/oem/logo.ico"));
OemProcessor oemProcessor = OemHandler.findOem();
List<BufferedImage> 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();

205
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<FileToolbarStateChangeListener> 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;
}
/**
* 重命名对话框
* 支持快捷键EnterESC

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

74
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<T extends BaseBook, U extends BaseUndoState<?>>
private static short currentIndex = 0;// 此变量用于多次新建模板时,让名字不重复
private DesignModelAdapter<T, ?> 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<T extends BaseBook, U extends BaseUndoState<?>>
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<T extends BaseBook, U extends BaseUndoState<?>>
// 判断是否切换设计器状态到禁止拷贝剪切
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<T extends BaseBook, U extends BaseUndoState<?>>
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<T extends BaseBook, U extends BaseUndoState<?>>
// 为收集模版信息作准备
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<T> 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<T extends BaseBook, U extends BaseUndoState<?>>
}
}
// 保存新模板时会进入此方法(新建模板直接保存,或者另存为)
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<T extends BaseBook, U extends BaseUndoState<?>>
this.saved = true;
this.authoritySaved = true;
DesignerContext.getDesignerFrame().setTitle();
this.fireJTemplateSaved();
return true;
}
@ -819,7 +827,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
// 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);
}

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

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

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

47
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<String, Object> 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;
}
}

260
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<String, Object> processMap = new HashMap<>();
private Map<String, Object> 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<String, Object> 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<String, Object> 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;
}
}

252
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<String, TemplateInfo> 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<String> 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<String> 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();
}
}

6
designer-base/src/main/java/com/fr/design/mainframe/templateinfo/TemplateProcessInfo.java → 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<T extends BaseBook> {
protected T template;

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

550
designer-base/src/main/java/com/fr/design/mainframe/templateinfo/TemplateInfoCollector.java

@ -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<T extends BaseBook> 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<String, HashMap<String, Object>> 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<String, Object> processMap = (HashMap<String, Object>) 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<String, Object> 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<String, Object> templateInfo;
long timeConsume = ((saveTime - openTime) / ONE_THOUSAND); // 制作模板耗时(单位:s)
String templateID = t.getTemplateID();
if (inList(t)) { // 已有记录
templateInfo = templateInfoList.get(templateID);
// 更新 conusmingMap
HashMap<String, Object> consumingMap = (HashMap<String, Object>) 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<String, Object> getNewConsumingMap(String templateID, long openTime, long timeConsume) {
HashMap<String, Object> 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<String, Object> getProcessMap(String templateID, JTemplate jt) {
HashMap<String, Object> 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<HashMap<String, String>> completeTemplatesInfo = getCompleteTemplatesInfo();
for (HashMap<String, String> 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<String, String> 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<HashMap<String, String>> getCompleteTemplatesInfo() {
ArrayList<HashMap<String, String>> completeTemplatesInfo = new ArrayList<>();
ArrayList<String> testTemplateKeys = new ArrayList<>(); // 保存测试模板的key
for (String key : templateInfoList.keySet()) {
HashMap<String, Object> templateInfo = templateInfoList.get(key);
if ((int) templateInfo.get(ATTR_DAY_COUNT) <= COMPLETE_DAY_COUNT) { // 未完成模板
continue;
}
if (isTestTemplate(templateInfo)) {
testTemplateKeys.add(key);
continue;
}
HashMap<String, Object> consumingMap = (HashMap<String, Object>) templateInfo.get(XML_CONSUMING_MAP);
HashMap<String, Object> processMap = (HashMap<String, Object>) templateInfo.get(XML_PROCESS_MAP);
String jsonConsumingMap = new JSONObject(consumingMap).toString();
String jsonProcessMap = new JSONObject(processMap).toString();
HashMap<String, String> 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<String, Object> templateInfo) {
HashMap<String, Object> processMap = (HashMap<String, Object>) 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<String, Object> processMap = new HashMap<>();
private HashMap<String, Object> consumingMap = new HashMap<>();
@SuppressWarnings("unchecked")
public TemplateInfo(HashMap<String, Object> templateInfo) {
this.dayCount = (int) templateInfo.get(ATTR_DAY_COUNT);
this.processMap = (HashMap<String, Object>) templateInfo.get(XML_PROCESS_MAP);
this.consumingMap = (HashMap<String, Object>) templateInfo.get(XML_CONSUMING_MAP);
this.templateID = (String) processMap.get(ATTR_TEMPLATE_ID);
}
public TemplateInfo() {
}
public String getTemplateID() {
return templateID;
}
public HashMap<String, Object> getTemplateInfo() {
HashMap<String, Object> 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) {
// 什么也不做,使用默认值
}
}
}
}
}

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

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

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

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

104
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 {
}
}

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

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

112
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<VcsEntity> 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 {
}
}

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

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

79
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<VcsEntity>()));
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<VcsEntity> 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<VcsEntity> vcsEntities;
CellModel(List<VcsEntity> 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;
}
}
}

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

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

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

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

34
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<String, String> map;
public EmbProtocolHandler() {
@ -30,17 +40,35 @@ public class EmbProtocolHandler implements ProtocolHandler {
this.component = component;
}
public EmbProtocolHandler(AssembleComponent component, Map<String, String> map) {
this.component = component;
this.map = map;
}
public EmbProtocolHandler(Map<String, String> 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;
}

40
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<T> 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<T> 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<T> extends BasicPane {
return this;
}
/**
* 加载url指向的资源
* @param url 文件的地址
*/
public Builder<T> withURL(final String url, Map<String, String> 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<T> extends BasicPane {
return this;
}
/**
* 加载Atom组件
* @param component Atom组件
*/
public Builder<T> withComponent(AssembleComponent component, Map<String, String> map) {
Assistant.setEmbProtocolHandler(pane.browser, new EmbProtocolHandler(component, map));
pane.browser.loadURL("emb:dynamic");
return this;
}
/**
* 加载html文本内容
* @param html 要加载html文本内容

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

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

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

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

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

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

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

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

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

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

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

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

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

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

196
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<Model> 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<Model>()
.withComponent(new AssembleComponent() {
@Override
public ScriptPath script(RequestClient req) {
return ScriptPath.build("/com/fr/design/ui/update/push/pushUpdate.js");
}
@Override
public StylePath style(RequestClient req) {
return StylePath.build("/com/fr/design/ui/update/push/pushUpdate.css");
}
@Override
public Atom[] refer() {
return new Atom[]{FineUI.KEY};
}
}).namespace("Pool").build();
contentPane.add(jsPane);
}
private void populate(DesignerUpdateInfo updateInfo) {
Model model = createModel(updateInfo);
jsPane.populate(model);
}
private Model createModel(DesignerUpdateInfo updateInfo) {
Model model = new Model();
model.setVersion(updateInfo.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);
}
}
}

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

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

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

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

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

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

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

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

@ -1,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;

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

@ -1,4 +1,4 @@
package com.fr.design.onlineupdate.ui.dialog;
package com.fr.design.update.ui.dialog;
import com.fr.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();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

406
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<Void, Void>(){
@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<Void> 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<Void> task = new UpmTaskWorker<>(new JSCallback(UpmBrowserExecutor.create(window, callback)), new GetPluginFromStoreExecutor(new JSONObject(info)));
task.execute();
}
/**
* 已安装插件检查更新
*/
@JSBridge
public void readUpdateOnline(final JSFunction callback) {
UpmTaskWorker<Void> task = new UpmTaskWorker<>(new JSCallback(UpmBrowserExecutor.create(window, callback)), new ReadUpdateOnlineExecutor());
task.execute();
}
/**
* 获取已经安装的插件的数组
*/
@JSBridge
public void getInstalledPlugins(final JSFunction callback) {
UpmTaskWorker<Void> 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<PluginMarker> 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<Void> 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<String> future = new FutureTask<>(new Callable<String>() {
@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<String> future = new FutureTask<>(new Callable<String>() {
@Override
public String call() {
JFileChooser fileChooser = new JFileChooser();
List<String> 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<Void> 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());
}
}
}

68
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<Workspace>() {
@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;
}
}
}

34
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 {
}
}

63
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<Object> 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<String>() {
@Override
public void on(Event event, String param) {
modernUIPane.redirect(UpmFinder.getMainResourcePath());
}
});
}
add(modernUIPane, BorderLayout.CENTER);
}
}

21
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<String> list = new ArrayList<>();
for (String ext : extensions) {
String[] arr = ext.split("\\.");
list.add(arr[arr.length - 1]);
}
return list.toArray(new String[0]);
}
}

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

12
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<String> {
LOGIN,LOGOUT
}

13
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<String> {
SUCCESS, ERROR
}

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

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

52
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<V> extends SwingWorker<V, String> {
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<String>() {
@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);
}
}

203
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");
}
/**
* 将用户反馈发送至服务器
*

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

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

Loading…
Cancel
Save