Browse Source

Merge pull request #6835 in DESIGN/design from feature/x to release/11.0

* commit 'a0bdf7d7ec70b37cf3ffd681c60a2bf80aeb7335': (44 commits)
  REPORT-62808 公式编辑器优化,辅助框内选择函数后,函数名没有正确跳转 1.修复单击实现偶然失效的bug; 2.修复上下键不生效的bug。
  REPORT-62808 公式编辑器优化,辅助框内选择函数后,函数名没有正确跳转 1.修复单击实现偶然失效的bug; 2.修复上下键不生效的bug。
  REPORT-62964【接触点优化】视觉调整
  REPORT-60163 公式编辑器优化2.0 1.修改一些测试问题
  REPORT-62398 【接触点优化】筛选面板存在时,上下滑动鼠标显示异常
  REPORT-62984 设计器触摸板问题-双指向右滑动时,设计器界面同时向右下滑动
  REPORT-62970【接触点优化】筛选动效问题,交互看下
  REPORT-62926 && REPORT-62920 && REPORT-62967 && REPORT-62964
  REPORT-62972 【接触点优化】跟组件可更新的交互提示问题
  REPORT-62809 && REPORT-62814 && REPORT-62815 && REPORT-62816 && REPORT-62817 1.修改布局与一些错误
  REPORT-62780【阻塞】【接触点优化】收起筛选面板,开始轮播加载时,最新版本会提示网络连接失败导致无法正常轮播
  REPORT-60154【来源于迭代任务】【V3.1.0】【无需适配】复用组件接触点优化二期
  REPORT-62596 远程设计websocket断开提示优化-远程正常状态下启动设计器时出现toast弹窗
  REPORT-62398  && REPORT-62397【接触点优化】查看推荐组件按钮,显示不全;【接触点优化】筛选面板存在时,上下滑动鼠标显示异常
  REPORT-62653 【组件可更新提醒】组件复用-组件上“版本不兼容”提示文字不明显
  REPORT-62677 组件复用-在线组件页面数据加载失败
  REPORT-62576 【组件可更新提醒】组件复用-更新过程中取消更新失败
  REPORT-62652 【组件可更新提醒】组件复用-不兼容弹窗图标应该是红色标识
  REPORT-62647 组件更新成功后可更新标志应该消失
  REPORT-62623 && REPORT-62399 && REPORT-62547 && REPORT-62626 && REPORT-62400 && REPORT-62542 && REPORT-62544
  ...
bugfix/11.0
superman 3 years ago
parent
commit
5ca0868146
  1. 193
      designer-base/src/main/java/com/fr/design/DesignerCloudURLManager.java
  2. 33
      designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java
  3. 17
      designer-base/src/main/java/com/fr/design/dialog/BasicPane.java
  4. 26
      designer-base/src/main/java/com/fr/design/dialog/UIDialog.java
  5. 81
      designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java
  6. 346
      designer-base/src/main/java/com/fr/design/formula/FormulaPane.java
  7. 9
      designer-base/src/main/java/com/fr/design/formula/FormulaPaneWhenReserveFormula.java
  8. 48
      designer-base/src/main/java/com/fr/design/formula/exception/FormulaExceptionTipsProcessor.java
  9. 14
      designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckConstants.java
  10. 78
      designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckWrongFunction.java
  11. 104
      designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedCharFunction.java
  12. 140
      designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedTokenFunction.java
  13. 44
      designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltForCharFunction.java
  14. 41
      designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltFunction.java
  15. 1003
      designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaAutoCompletePopupWindow.java
  16. 22
      designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaCompletion.java
  17. 1311
      designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java
  18. 28
      designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java
  19. 3
      designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java
  20. 26
      designer-base/src/main/java/com/fr/design/locale/impl/ShowOnlineWidgetMark.java
  21. 11
      designer-base/src/main/java/com/fr/design/mainframe/EastRegionContainerPane.java
  22. 8
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  23. 2
      designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleBlock.java
  24. 97
      designer-base/src/main/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfo.java
  25. 169
      designer-base/src/main/java/com/fr/design/mainframe/reuse/ReuseGuideDialog.java
  26. 99
      designer-base/src/main/java/com/fr/design/mainframe/share/ComponentShareUtil.java
  27. 102
      designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java
  28. 2
      designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java
  29. 14
      designer-base/src/main/java/com/fr/design/mainframe/toast/DesignerToastMsgUtil.java
  30. 7
      designer-base/src/main/java/com/fr/design/mainframe/toast/ToastMsgDialog.java
  31. BIN
      designer-base/src/main/resources/com/fr/design/images/m_file/formula.png
  32. BIN
      designer-base/src/main/resources/com/fr/design/images/m_file/param.png
  33. 7
      designer-base/src/test/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfoTest.java
  34. 2
      designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java
  35. 50
      designer-form/src/main/java/com/fr/design/mainframe/FormWidgetDetailPane.java
  36. 19
      designer-form/src/main/java/com/fr/design/mainframe/JForm.java
  37. 217
      designer-form/src/main/java/com/fr/design/mainframe/ReuseTriggerPointManager.java
  38. 30
      designer-form/src/main/java/com/fr/design/mainframe/adaptve/config/ReuseNotifyInfo.java
  39. 20
      designer-form/src/main/java/com/fr/design/mainframe/adaptve/config/TriggerPointProvider.java
  40. 28
      designer-form/src/main/java/com/fr/design/mainframe/adaptve/config/impl/CellStyleTriggerPoint.java
  41. 27
      designer-form/src/main/java/com/fr/design/mainframe/adaptve/config/impl/CellValueImageChangeTriggerPoint.java
  42. 3
      designer-form/src/main/java/com/fr/design/mainframe/share/AbstractWidgetSelectPane.java
  43. 44
      designer-form/src/main/java/com/fr/design/mainframe/share/Bean/FilterTypeInfo.java
  44. 60
      designer-form/src/main/java/com/fr/design/mainframe/share/Bean/WidgetFilterInfo.java
  45. 93
      designer-form/src/main/java/com/fr/design/mainframe/share/Bean/WidgetFilterTypeInfo.java
  46. 1
      designer-form/src/main/java/com/fr/design/mainframe/share/action/InstallComponentAction.java
  47. 82
      designer-form/src/main/java/com/fr/design/mainframe/share/config/ComponentReuseConfigManager.java
  48. 14
      designer-form/src/main/java/com/fr/design/mainframe/share/constants/StyleTheme.java
  49. 2
      designer-form/src/main/java/com/fr/design/mainframe/share/generate/task/ComponentUploader.java
  50. 4
      designer-form/src/main/java/com/fr/design/mainframe/share/sort/OnlineWidgetSortType.java
  51. 2
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/DownloadSuitableThemeAction.java
  52. 2
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/Jump2DetailAction.java
  53. 26
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/AbstractOnlineWidgetBlock.java
  54. 53
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/BezierCubic.java
  55. 182
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java
  56. 178
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetUpdater.java
  57. 118
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java
  58. 134
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/PreviewWidgetBlock.java
  59. 30
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/FramePane.java
  60. 34
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/GroupPane.java
  61. 299
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoPane.java
  62. 144
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoUpdater.java
  63. 2
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/ManagePane.java
  64. 8
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/ToolbarPane.java
  65. 11
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/WidgetSelectedManager.java
  66. 248
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/AbstractOnlineWidgetSelectPane.java
  67. 96
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/AbstractOnlineWidgetShowPane.java
  68. 74
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/CarouselStateManger.java
  69. 79
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetPopupPreviewPane.java
  70. 22
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java
  71. 212
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetSelectPane.java
  72. 30
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetShowPane.java
  73. 27
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetTabPane.java
  74. 41
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/PreviewImagePane.java
  75. 46
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/AnimatePopupDialog.java
  76. 201
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/EmbedPane.java
  77. 44
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/FirstDragAnimateStateManager.java
  78. 209
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/OnlineEmbedFilterSelectPane.java
  79. 62
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/OnlineEmbedFilterShowPane.java
  80. 37
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/PreviewDialog.java
  81. 31
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/resource/OnlineResourceManager.java
  82. 2
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/resource/ResourceLoader.java
  83. 12
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/widgetpackage/OnlineWidgetPackagesShowPane.java
  84. 285
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/FilterConfigPane.java
  85. 25
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/FilterPane.java
  86. 192
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/FilterPopupPane.java
  87. 6
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/LocalFilterPopupPane.java
  88. 2
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/LocalWidgetFilter.java
  89. 118
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/LocalWidgetFilterCategory.java
  90. 10
      designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/OnlineFilterPopupPane.java
  91. 17
      designer-form/src/main/java/com/fr/design/mainframe/share/util/DownloadUtils.java
  92. 2
      designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallUtils.java
  93. 349
      designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java
  94. 17
      designer-form/src/main/java/com/fr/design/mainframe/share/util/ShareFilterConstants.java
  95. 3
      designer-form/src/main/java/com/fr/design/widget/ui/designer/NewFormPane.java
  96. BIN
      designer-form/src/main/resources/com/fr/design/form/images/drag_hand.png
  97. 45
      designer-form/src/test/java/com/fr/design/mainframe/ReuseTriggerPointManagerTest.java
  98. 4
      designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/theme/DownloadComponentPackageGuide.java
  99. 129
      designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java
  100. 32
      designer-realize/src/main/java/com/fr/design/share/ui/generate/ShareGeneratePane.java
  101. Some files were not shown because too many files have changed in this diff Show More

193
designer-base/src/main/java/com/fr/design/DesignerCloudURLManager.java

@ -0,0 +1,193 @@
package com.fr.design;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.general.CloudCenter;
import com.fr.general.CloudCenterConfig;
import com.fr.general.http.HttpToolbox;
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.XMLReaderHelper;
import com.fr.stable.xml.XMLTools;
import com.fr.stable.xml.XMLable;
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.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by kerry on 2021/10/22
*/
public class DesignerCloudURLManager implements XMLable {
private static final String CLOUD_URL_INFO = "cloudUrl.info";
private static final String ROOT_XML_TAG = "CloudUrlInfoList";
private static final String CHILD_XML_TAG = "CloudUrlInfo";
private final Map<String, String> urlMap = new HashMap<>();
public static DesignerCloudURLManager getInstance() {
return DesignerCloudURLManager.HOLDER.singleton;
}
private final ExecutorService executorService = Executors.newSingleThreadExecutor(new NamedThreadFactory("TestCloudConnectThread"));
private volatile boolean testResult;
private static class HOLDER {
private static final DesignerCloudURLManager singleton = new DesignerCloudURLManager();
}
private DesignerCloudURLManager() {
loadURLXMLFile();
}
public String acquireUrlByKind(String key) {
String url = urlMap.getOrDefault(key, StringUtils.EMPTY);
if (StringUtils.isEmpty(url)) {
//本地缓存中为空时,直接从云中心获取,获取完成后异步更新本地缓存文件
String latestUrl = CloudCenter.getInstance().acquireConf(key, StringUtils.EMPTY);
executorService.submit(() -> {
updateURLXMLFile(key, latestUrl);
});
return latestUrl;
}
//本地缓存不为空时,直接返回对应 url,同时异步更新
executorService.submit(() -> {
String latestUrl = CloudCenter.getInstance().acquireConf(key, StringUtils.EMPTY);
updateURLXMLFile(key, latestUrl);
});
return url;
}
private synchronized void updateURLXMLFile(String key, String url) {
if (StringUtils.isNotEmpty(url) && (!urlMap.containsKey(key) || !url.equals(urlMap.get(key)))) {
urlMap.put(key, url);
saveURLXMLFile();
}
}
public void testConnect() {
executorService.submit(() -> {
testResult = isOnline();
});
}
public boolean isConnected() {
return testResult;
}
public boolean isOnline() {
if (CloudCenterConfig.getInstance().isOnline()) {
String ping = acquireUrlByKind("ping");
if (StringUtils.isNotEmpty(ping)) {
try {
return StringUtils.isEmpty(HttpToolbox.get(ping));
} catch (Exception ignore) {
}
}
}
return false;
}
/**
* 加载本地 url 管理文件
*/
private void loadURLXMLFile() {
if (!getInfoFile().exists()) {
return;
}
XMLableReader reader = null;
try (InputStream in = new FileInputStream(getInfoFile())) {
// XMLableReader 还是应该考虑实现 Closable 接口的,这样就能使用 try-with 语句了
reader = XMLReaderHelper.createXMLableReader(in, XMLPrintWriter.XML_ENCODER);
if (reader == null) {
return;
}
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);
}
}
}
private File getInfoFile() {
File file = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), CLOUD_URL_INFO));
try {
if (!file.exists()) {
file.createNewFile();
}
} catch (Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
return file;
}
/**
* 保存到本地 URL 管理文件中存放在 .Finereport110
*/
void saveURLXMLFile() {
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());
}
}
@Override
public void readXML(XMLableReader reader) {
String tagName = reader.getTagName();
if (tagName.equals(CHILD_XML_TAG)) {
String key = reader.getAttrAsString("key", StringUtils.EMPTY);
String value = reader.getAttrAsString("url", StringUtils.EMPTY);
this.urlMap.put(key, value);
}
}
@Override
public void writeXML(XMLPrintWriter xmlPrintWriter) {
xmlPrintWriter.startTAG(ROOT_XML_TAG);
Iterator<Map.Entry<String, String>> iterable = urlMap.entrySet().iterator();
while (iterable.hasNext()) {
Map.Entry<String, String> entry = iterable.next();
xmlPrintWriter.startTAG(CHILD_XML_TAG).attr("key", entry.getKey()).attr("url", entry.getValue()).end();
}
xmlPrintWriter.end();
}
@Override
public Object clone() throws CloneNotSupportedException {
return null;
}
}

33
designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java

@ -12,6 +12,7 @@ import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
/**
@ -44,21 +45,18 @@ public class CellStylePreviewPane extends JPanel {
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g.clearRect(0, 0, getWidth(), getHeight());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
paintTransparentBackground(g2d, style);
paintCellStyle(g2d, style);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
}
private void paintTransparentBackground(Graphics2D g2d, Style style) {
Color fontColor = style.getFRFont().getForeground();
float g = fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F * fontColor.getBlue() * 0.114F;
float alpha = 1.0F;
if (g < 50) {
alpha = 0.2F;
} else if (g < 160){
alpha = 0.5F;
}
float alpha = computeTransparentBackgroundAlpha(style);
float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth;
float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight;
@ -76,6 +74,23 @@ public class CellStylePreviewPane extends JPanel {
g2d.setComposite(oldComposite);
}
private float computeTextColorBrightness(Style style) {
Color fontColor = style.getFRFont().getForeground();
return fontColor.getRed() * 0.299F + fontColor.getGreen() * 0.587F + fontColor.getBlue() * 0.114F;
}
private float computeTransparentBackgroundAlpha(Style style) {
float textBrightness = computeTextColorBrightness(style);
float alpha = 1.0F;
if (textBrightness < 50) {
alpha = 0.2F;
} else if (textBrightness < 160){
alpha = 0.5F;
}
return alpha;
}
private void paintCellStyle(Graphics2D g2d, Style style) {
int resolution = ScreenResolution.getScreenResolution();

17
designer-base/src/main/java/com/fr/design/dialog/BasicPane.java

@ -8,9 +8,14 @@ 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;
@Open
public abstract class BasicPane extends JPanel {
@ -262,6 +267,10 @@ public abstract class BasicPane extends JPanel {
public void checkValid() throws Exception {
}
public boolean confirmContinueBeforeDoOK() {
return true;
}
public static class NamePane extends BasicPane {
private UITextField nameTextField;
private UILabel Name;
@ -390,6 +399,10 @@ public abstract class BasicPane extends JPanel {
BasicPane.this.checkValid();
}
public boolean confirmContinueBeforeDoOK() {
return BasicPane.this.confirmContinueBeforeDoOK();
}
}
private class UnsizedDialog extends UIDialog {

26
designer-base/src/main/java/com/fr/design/dialog/UIDialog.java

@ -33,6 +33,7 @@ public abstract class UIDialog extends JDialog {
private BasicPane pane;
private java.util.List<DialogActionListener> listeners = new ArrayList<DialogActionListener>();
private boolean isDoOKSucceed;
private boolean needExceptionCheck = true;
public UIDialog(Frame parent) {
@ -151,6 +152,10 @@ public abstract class UIDialog extends JDialog {
});
}
public void setNeedExceptionCheck(boolean needExceptionCheck) {
this.needExceptionCheck = needExceptionCheck;
}
/**
* 添加监听器
@ -172,14 +177,21 @@ public abstract class UIDialog extends JDialog {
* 确定操作
*/
public void doOK() {
//由于checkValid不可以加入自定义的弹窗以及操作,添加一个接口
if (!confirmContinueBeforeDoOK()) {
return;
}
try {
checkValid();
} catch (Exception exp) {
FineJOptionPane.showMessageDialog(
this,
exp.getMessage(),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"),
JOptionPane.WARNING_MESSAGE);
if (needExceptionCheck) {
FineJOptionPane.showMessageDialog(
this,
exp.getMessage(),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"),
JOptionPane.WARNING_MESSAGE);
}
return;
}
@ -253,6 +265,10 @@ public abstract class UIDialog extends JDialog {
*/
public abstract void checkValid() throws Exception;
public boolean confirmContinueBeforeDoOK() {
return true;
}
public void setButtonEnabled(boolean b) {
this.okButton.setEnabled(b);
}

81
designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java

@ -1,91 +1,48 @@
package com.fr.design.formula;
import com.fr.design.formula.exception.FormulaExceptionTipsProcessor;
import com.fr.design.i18n.Toolkit;
import com.fr.log.FineLoggerFactory;
import com.fr.parser.FRLexer;
import com.fr.parser.FRParser;
import com.fr.script.checker.FunctionCheckerDispatcher;
import com.fr.script.checker.exception.ConditionCheckWrongException;
import com.fr.script.checker.exception.FunctionCheckWrongException;
import com.fr.script.rules.FunctionParameterType;
import com.fr.script.rules.FunctionRule;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.stable.StringUtils;
import com.fr.stable.script.Expression;
import com.fr.stable.script.Node;
import com.fr.third.antlr.TokenStreamRecognitionException;
import java.io.StringReader;
import java.util.List;
/**
* @author Hoky
* @date 2021/9/28
*/
public class FormulaChecker {
private static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula");
private static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula");
public static final String COLON = ":";
public static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula");
public static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula");
private static FormulaExceptionTipsProcessor processor = FormulaExceptionTipsProcessor.getProcessor();
public static String check(String formulaText) throws FormulaCheckerException {
public static FormulaCheckResult check(String formulaText) {
if (StringUtils.isEmpty(formulaText) || formulaText.equals(Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Tips"))) {
return new FormulaCheckResult(true, VALID_FORMULA, FormulaCoordinates.INVALID, true);
}
//过滤一些空格等符号
StringReader in = new StringReader(formulaText);
FRLexer lexer = new FRLexer(in);
FRParser parser = new FRParser(lexer);
try {
Expression expression = parser.parse();
Node node = expression.getConditionalExpression();
boolean valid = FunctionCheckerDispatcher.getInstance().getFunctionChecker(node).checkFunction(node);
if (valid) {
return VALID_FORMULA;
} else {
throw new FormulaCheckerException(INVALID_FORMULA);
}
} catch (ConditionCheckWrongException cce) {
String functionName = cce.getFunctionName();
throw new FormulaCheckerException(functionName + Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Condition_Tips") + COLON);
} catch (FunctionCheckWrongException ce) {
List<FunctionRule> rules = ce.getRules();
String functionName = ce.getFunctionName();
StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + COLON);
for (int i = 0; i < rules.size(); i++) {
errorMsg.append("(");
if (rules.get(i).getParameterList().isEmpty()) {
errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param"));
}
for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) {
errorMsg.append(getTypeString(functionParameterType)).append(",");
}
if (",".equals(errorMsg.charAt(errorMsg.length() - 1) + "")) {
errorMsg.deleteCharAt(errorMsg.length() - 1);
}
errorMsg.append(")");
if (i != rules.size() - 1) {
errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or"));
}
}
throw new FormulaCheckerException(errorMsg.toString());
boolean valid = FunctionCheckerDispatcher.getInstance().getFunctionChecker(node).checkFunction(formulaText, node);
return new FormulaCheckResult(valid, valid ? Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula") :
Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula"), FormulaCoordinates.INVALID, true);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
throw new FormulaCheckerException(INVALID_FORMULA);
// alex:继续往下面走,expression为null时告知不合法公式
}
}
private static String getTypeString(FunctionParameterType type) {
switch (type) {
case NUMBER:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number");
case STRING:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String");
case ANY:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any");
case DATE:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date");
case BOOLEAN:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean");
case ARRAY:
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array");
if (e instanceof TokenStreamRecognitionException) {
return processor.getExceptionTips(((TokenStreamRecognitionException) e).recog);
}
return processor.getExceptionTips(e);
}
return StringUtils.EMPTY;
}
}

346
designer-base/src/main/java/com/fr/design/formula/FormulaPane.java

@ -16,7 +16,13 @@ import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.autocomplete.CompletionCellRenderer;
import com.fr.design.gui.autocomplete.CompletionProvider;
import com.fr.design.gui.autocomplete.DefaultCompletionProvider;
import com.fr.design.gui.autocomplete.FormulaCompletion;
import com.fr.design.gui.autocomplete.FormulaPaneAutoCompletion;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ilist.QuickList;
@ -43,6 +49,7 @@ import com.fr.parser.SheetIntervalLiteral;
import com.fr.report.core.namespace.SimpleCellValueNameSpace;
import com.fr.script.Calculator;
import com.fr.script.ScriptConstants;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.stable.EncodeConstants;
import com.fr.stable.EssentialUtils;
import com.fr.stable.ParameterProvider;
@ -65,6 +72,7 @@ import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
@ -80,8 +88,11 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
@ -112,17 +123,21 @@ import java.util.Set;
* @since 2012-3-29下午1:50:53
*/
public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
public static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula");
public static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula");
public static final int DEFUAL_FOMULA_LENGTH = 103;
public static final String ELLIPSIS = "...";
public static final char KEY_CODE_A = 'A';
public static final char KEY_CODE_Z = 'z';
public static final String NEWLINE = "\n";
public static final String FORMULA_ICON = "/com/fr/design/images/m_file/formula.png";
public static final String PARAM_ICON = "/com/fr/design/images/m_file/param.png";
private VariableTreeAndDescriptionArea variableTreeAndDescriptionArea;
private RSyntaxTextArea formulaTextArea;
private UITextField keyWordTextField = new UITextField(18);
private int currentPosition = 0;
private int beginPosition = 0;
private int insertPosition = 0;
protected static UICheckBox autoCompletionCheck;
protected static UICheckBox checkBeforeColse;
private JList tipsList;
protected DefaultListModel listModel = new DefaultListModel();
private int ifHasBeenWriten = 0;
@ -131,6 +146,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private DefaultListModel functionNameModel;
private JList functionNameList;
private UITableEditorPane<ParameterProvider> editor4CalPane;
private FormulaPaneAutoCompletion autoCompletion;
private DefaultCompletionProvider completionProvider;
private static final Map<String, String> PARAM_PREFIX_MAP = new HashMap<>();
public FormulaPane() {
initComponents();
@ -139,6 +157,20 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initFormulaTextAreaKeyListener() {
formulaTextArea.addKeyListener(this);
formulaTextArea.addKeyListener(new KeyAdapter() {
//用来判断一下是不是组合键
@Override
public void keyTyped(KeyEvent e) {
if (inKeyCodeRange(e) && autoCompletionCheck.isSelected()) {
autoCompletion.doCompletion();
}
}
private boolean inKeyCodeRange(KeyEvent e) {
return (e.getKeyChar() >= KEY_CODE_A && e.getKeyChar() <= KEY_CODE_Z);
}
@Override
public void keyReleased(KeyEvent e) {
formulaTextArea.setForeground(Color.black);
String text = formulaTextArea.getText();
@ -174,7 +206,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition();
insertPosition = beginPosition;
firstStepToFindTips(beginPosition);
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
}
}
});
@ -204,7 +238,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
String toFind = keyWordTextField.getText();
search(toFind, false);
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
e.consume();
}
}
@ -213,28 +249,35 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initTipsPane() {
// tipsPane
JPanel tipsPane = new JPanel(new BorderLayout(4, 4));
this.add(tipsPane, BorderLayout.EAST);
JPanel containerSPane = new JPanel(new BorderLayout(4, 1));
JPanel labelPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0), true);
JPanel searchPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0), true);
containerSPane.setPreferredSize(new Dimension(892, 23));
this.add(containerSPane, BorderLayout.NORTH);
JPanel searchPane = new JPanel(new BorderLayout(4, 4));
searchPane.add(keyWordTextField, BorderLayout.CENTER);
UIButton searchButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaPane_Search"));
UILabel formulaLabel = new UILabel(
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Input_Formula_In_The_Text_Area_Below") + ":");
formulaLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
labelPane.add(formulaLabel, BorderLayout.WEST);
keyWordTextField.setPreferredSize(new Dimension(240, 23));
searchPane.add(keyWordTextField, BorderLayout.EAST);
searchPane.add(searchButton, BorderLayout.EAST);
tipsPane.add(searchPane, BorderLayout.NORTH);
containerSPane.add(labelPane, BorderLayout.WEST);
containerSPane.add(searchPane, BorderLayout.EAST);
initKeyWordTextFieldKeyListener();
tipsList = new JList(listModel);
tipsList.addMouseListener(new DoubleClick());
UIScrollPane tipsScrollPane = new UIScrollPane(tipsList);
tipsScrollPane.setPreferredSize(new Dimension(170, 75));
tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
tipsPane.add(tipsScrollPane, BorderLayout.CENTER);
searchButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String toFind = keyWordTextField.getText();
search(toFind, false);
formulaTextArea.requestFocusInWindow();
fixFunctionNameList();
searchButton.addActionListener(e -> {
String toFind = keyWordTextField.getText();
search(toFind, false);
popTips();
formulaTextArea.requestFocusInWindow();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
});
}
@ -254,18 +297,13 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initTextPane() {
// text
JPanel textPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
this.add(textPane, BorderLayout.CENTER);
JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
UILabel formulaLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Input_Formula_In_The_Text_Area_Below") + ":"
+ " ");
formulaLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane();
initFormulaTextArea();
UIScrollPane formulaTextAreaScrollPane = new UIScrollPane(formulaTextArea);
formulaTextAreaScrollPane.setBorder(null);
textPane.add(formulaLabel, BorderLayout.NORTH);
textPane.add(formulaTextAreaScrollPane, BorderLayout.CENTER);
textPane.add(checkBoxandbuttonPane, BorderLayout.SOUTH);
@ -275,19 +313,104 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
checkValidButton.addActionListener(checkValidActionListener);
calButton.addActionListener(calculateActionListener);
//靠左流式布局
JPanel checkBoxPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
checkBoxPane.setPreferredSize(new Dimension(450, 30));
checkBoxandbuttonPane.add(checkBoxPane, BorderLayout.WEST);
checkBoxandbuttonPane.add(checkValidButton, BorderLayout.EAST);
checkBoxandbuttonPane.add(calButton, BorderLayout.EAST);
//靠右流式布局
JPanel buttonPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane();
buttonPane.add(checkValidButton, BorderLayout.EAST);
buttonPane.add(calButton, BorderLayout.EAST);
checkBoxandbuttonPane.add(buttonPane, BorderLayout.EAST);
if (autoCompletionCheck == null) {
autoCompletionCheck = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_AutoCompletion"));
autoCompletionCheck.setSelected(true);
}
if (checkBeforeColse == null) {
checkBeforeColse = new UICheckBox(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Before_Closed"));
checkBeforeColse.setSelected(true);
}
checkBoxPane.add(autoCompletionCheck, BorderLayout.WEST);
checkBoxPane.add(checkBeforeColse, BorderLayout.WEST);
extendCheckBoxPane(checkBoxPane);
ParameterTableModel model = new ParameterTableModel(0);
editor4CalPane = new UITableEditorPane<>(model);
formulaTextArea.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// 获得焦点时 安装
if (autoCompletion == null && autoCompletionCheck.isSelected()) {
CompletionProvider provider = createCompletionProvider();
autoCompletion = new FormulaPaneAutoCompletion(provider);
autoCompletion.setListCellRenderer(new CompletionCellRenderer());
autoCompletion.install(formulaTextArea);
autoCompletion.installVariableTree(variableTreeAndDescriptionArea);
}
}
@Override
public void focusLost(FocusEvent e) {
// 失去焦点时 卸载
uninstallAutoCompletion();
}
});
}
private CompletionProvider createCompletionProvider() {
if (completionProvider == null) {
completionProvider = new DefaultCompletionProvider();
NameAndDescription[] nameAndDescriptions = FunctionConstants.ALL.getDescriptions();
for (NameAndDescription nameAndDescription : nameAndDescriptions) {
completionProvider.addCompletion(new FormulaCompletion(completionProvider, nameAndDescription.getName(), BaseUtils.readIcon(FORMULA_ICON)));
}
VariableResolver variableResolver = VariableResolver.DEFAULT;
List<String> allParameters = new ArrayList<>();
allParameters.addAll(Arrays.asList(variableResolver.resolveCurReportVariables()));
allParameters.addAll(Arrays.asList(variableResolver.resolveColumnNames()));
allParameters.addAll(Arrays.asList(variableResolver.resolveGlobalParameterVariables()));
allParameters.addAll(Arrays.asList(variableResolver.resolveReportParameterVariables()));
allParameters.addAll(Arrays.asList(variableResolver.resolveTableDataParameterVariables()));
//先把参数前缀拿出来
for (String parameter : allParameters) {
String paramWithoutPre;
if (parameter.startsWith("$$")) {
paramWithoutPre = parameter.substring(2);
PARAM_PREFIX_MAP.put(paramWithoutPre, "$$");
} else if (parameter.startsWith("$")) {
paramWithoutPre = parameter.substring(1);
PARAM_PREFIX_MAP.put(paramWithoutPre, "$");
} else {
paramWithoutPre = parameter;
PARAM_PREFIX_MAP.put(paramWithoutPre, StringUtils.EMPTY);
}
completionProvider.addCompletion(new FormulaCompletion(completionProvider, paramWithoutPre, BaseUtils.readIcon(PARAM_ICON)));
}
return completionProvider;
}
return completionProvider;
}
public static boolean containsParam(String param) {
return PARAM_PREFIX_MAP.containsKey(param);
}
public static String getParamPrefix(String param) {
return PARAM_PREFIX_MAP.getOrDefault(param, StringUtils.EMPTY);
}
private void uninstallAutoCompletion() {
if (autoCompletion != null) {
autoCompletion.uninstall();
autoCompletion = null;
}
}
protected void extendCheckBoxPane(JPanel checkBoxPane) {
// do nothing
}
@ -341,7 +464,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void singleClickActuator(String currentLineContent) {
refreshDescriptionTextArea(currentLineContent);
formulaTextArea.requestFocusInWindow();
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
}
private void doubleClickActuator(String currentLineContent) {
@ -405,43 +530,41 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition();
insertPosition = beginPosition;
firstStepToFindTips(beginPosition);
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
ifHasBeenWriten = 1;
}
}
}
private void fixFunctionNameList() {
if (tipsList.getSelectedValue() != null) {
int signOfContinue = 1;
int indexOfFunction = 0;
for (int i = 0; i < functionTypeListModel.size(); i++) {
int signOfType = 0;
FunctionGroup functionType = (FunctionGroup) functionTypeListModel.getElementAt(i);
NameAndDescription[] nads = functionType.getDescriptions();
if (signOfContinue == 1) {
functionNameModel.removeAllElements();
String functionName = ((String) tipsList.getSelectedValue());
for (int k = 0; k < nads.length; k++) {
functionNameModel.addElement(nads[k]);
if (functionName.equals(nads[k].getName()))//若相等,找出显示的函数的index,setSelectedIndex()
{
signOfType = 1;
signOfContinue = 0;
indexOfFunction = k;
}
private void fixFunctionNameList(String functionName) {
int signOfContinue = 1;
int indexOfFunction = 0;
for (int i = 0; i < functionTypeListModel.size(); i++) {
int signOfType = 0;
FunctionGroup functionType = (FunctionGroup) functionTypeListModel.getElementAt(i);
NameAndDescription[] nads = functionType.getDescriptions();
if (signOfContinue == 1) {
functionNameModel.removeAllElements();
for (int k = 0; k < nads.length; k++) {
functionNameModel.addElement(nads[k]);
if (functionName.equals(nads[k].getName()))//若相等,找出显示的函数的index,setSelectedIndex()
{
signOfType = 1;
signOfContinue = 0;
indexOfFunction = k;
}
}
if (signOfType == 1) {
functionTypeList.setSelectedIndex(i);
signOfType = 0;
}
if (signOfType == 1) {
functionTypeList.setSelectedIndex(i);
signOfType = 0;
}
}
functionNameList.setSelectedIndex(indexOfFunction);
functionNameList.ensureIndexIsVisible(indexOfFunction);
}
functionNameList.setSelectedIndex(indexOfFunction);
functionNameList.ensureIndexIsVisible(indexOfFunction);
}
private int getBeginPosition() {
@ -492,9 +615,17 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
// do nothing
}
private void popTips() {
JPopupMenu popupMenu = new JPopupMenu();
JScrollPane tipsScrollPane = new JScrollPane(tipsList);
popupMenu.add(tipsScrollPane);
tipsScrollPane.setPreferredSize(new Dimension(240, 146));
tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
popupMenu.show(keyWordTextField, 0, 23);
}
protected void search(String keyWord, boolean findDescription) {
listModel.removeAllElements();
keyWord = removeAllSpace(keyWord);
if (keyWord.length() != 0) {
NameAndDescription[] descriptions = FunctionConstants.ALL.getDescriptions();
@ -610,7 +741,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition();
insertPosition = beginPosition;
firstStepToFindTips(beginPosition);
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
ifHasBeenWriten = 1;
} else {
this.formulaTextArea.setText(content);
@ -618,7 +751,9 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
beginPosition = getBeginPosition();
insertPosition = beginPosition;
firstStepToFindTips(beginPosition);
fixFunctionNameList();
if (tipsList.getSelectedValue() != null) {
fixFunctionNameList(tipsList.getSelectedValue().toString());
}
ifHasBeenWriten = 1;
}
}
@ -650,17 +785,12 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
public void actionPerformed(ActionEvent evt) {
// Execute Formula default cell element.
String formulaText = formulaTextArea.getText().trim();
String formulaValidMessage;
try {
formulaValidMessage = FormulaChecker.check(formulaText);
showMessageDialog(formulaValidMessage + ".");
} catch (FormulaCheckerException e) {
formulaValidMessage = e.getMessage();
showMessageDialog(formulaValidMessage + ".", false);
}
FormulaCheckResult checkResult = FormulaChecker.check(formulaText);
confirmCheckResult(checkResult, checkResult.getTips());
}
};
private final ActionListener calculateActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@ -671,20 +801,10 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
return;
}
String formulaValidMessage;
boolean formulaValid;
try {
formulaValidMessage = FormulaChecker.check(formulaText);
formulaValid = true;
} catch (FormulaCheckerException formulaCheckerException) {
formulaValidMessage = formulaCheckerException.getMessage();
formulaValid = false;
}
String messageTips;
if (ComparatorUtils.equals(formulaValidMessage, INVALID_FORMULA)) {
messageTips = INVALID_FORMULA;
} else {
messageTips = ComparatorUtils.equals(formulaValidMessage, VALID_FORMULA) ? "" : formulaValidMessage + "\n";
FormulaCheckResult checkResult = FormulaChecker.check(formulaText);
if (checkResult.grammarValid()) {
messageTips = checkResult.getTips() + NEWLINE;
Map<String, Object> paramsMap = setParamsIfExist(formulaText);
Calculator calculator = Calculator.createCalculator();
ParameterMapNameSpace parameterMapNameSpace = ParameterMapNameSpace.create(paramsMap);
@ -704,19 +824,44 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
String objectToString = EssentialUtils.objectToString(value);
String result = objectToString.length() > DEFUAL_FOMULA_LENGTH ?
objectToString.substring(0, DEFUAL_FOMULA_LENGTH - ELLIPSIS.length()) + ELLIPSIS : objectToString;
messageTips = messageTips +
Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Result") + ":" + result;
messageTips = messageTips + Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Result") + ":" + result;
FineLoggerFactory.getLogger().info("value:{}", value);
} catch (UtilEvalError utilEvalError) {
FineLoggerFactory.getLogger().error("", utilEvalError);
FineLoggerFactory.getLogger().error(utilEvalError.getMessage(), utilEvalError);
}
} else {
messageTips = checkResult.getTips();
}
if (checkResult.isValid()) {
showMessageDialog(messageTips, checkResult.isValid());
} else {
confirmCheckResult(checkResult, messageTips);
}
showMessageDialog(messageTips, formulaValid);
}
};
private void showMessageDialog(String message) {
showMessageDialog(message, true);
private boolean confirmCheckResult(FormulaCheckResult checkResult, String messageTips) {
if (checkResult.isValid()) {
showMessageDialog(checkResult.getTips(), checkResult.isValid());
} else {
String position = Toolkit.i18nText("Fine-Design_Basic_Formula_The") + (checkResult.getFormulaCoordinates().getColumns())
+ Toolkit.i18nText("Fine-Design_Basic_Formula_Error_Position") + " ";
int confirmDialog = FineJOptionPane.showConfirmDialog(
FormulaPane.this,
position + messageTips,
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Tool_Tips"),
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
new String[]{Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Result"), Toolkit.i18nText("Fine-Design_Basic_Formula_Continue")},
Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Result"));
if (confirmDialog == 0) {
formulaTextArea.setCaretPosition(checkResult.getFormulaCoordinates().getColumns());
formulaTextArea.requestFocus();
return false;
}
}
return true;
}
private void showMessageDialog(String message, boolean formulaValid) {
@ -750,6 +895,18 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
return null;
}
@Override
public boolean confirmContinueBeforeDoOK() {
if (checkBeforeColse.isSelected()) {
String formula = formulaTextArea.getText().trim();
FormulaCheckResult checkResult = FormulaChecker.check(formula);
if (!checkResult.isValid()) {
return confirmCheckResult(checkResult, checkResult.getTips());
}
}
return true;
}
private Map<String, Object> setParamsIfExist(String formulaText) {
Map<String, Object> parameterMap = new HashMap<>();
try {
@ -990,7 +1147,8 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void initDescriptionTextArea() {
// Description
descriptionTextArea = new UITextArea(16, 27);
descriptionTextArea = new UITextArea();
descriptionTextArea.setPreferredSize(new Dimension(350, 200));
UIScrollPane desScrollPane = new UIScrollPane(descriptionTextArea);
desScrollPane.setBorder(null);
@ -1118,7 +1276,6 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
};
basicPane.setLayout(FRGUIPaneFactory.createBorderLayout());
UITextArea desArea = new UITextArea();
// desArea。setEnabled(false);
desArea.setText(this.getTextAreaText());
basicPane.add(new UIScrollPane(desArea), BorderLayout.CENTER);
BasicDialog dialog = basicPane.showWindow(DesignerContext.getDesignerFrame());
@ -1191,6 +1348,11 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
}
};
public void refreshText(String line) {
fixFunctionNameList(line);
refreshDescriptionTextArea(line);
}
public void populate(VariableResolver variableResolver) {
// varibale tree.
DefaultTreeModel variableModel = (DefaultTreeModel) variablesTree.getModel();
@ -1326,12 +1488,12 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
buffer.append(name.toUpperCase());
buffer.append("\"");
buffer.append("|");
buffer.append("\n");
buffer.append(NEWLINE);
buffer.append("\"");
buffer.append(name.toLowerCase());
buffer.append("\"");
buffer.append("|");
buffer.append("\n");
buffer.append(NEWLINE);
}
FineLoggerFactory.getLogger().debug(buffer.toString());
}

9
designer-base/src/main/java/com/fr/design/formula/FormulaPaneWhenReserveFormula.java

@ -3,11 +3,10 @@ package com.fr.design.formula;
import com.fr.base.BaseFormula;
import com.fr.design.gui.icheckbox.UICheckBox;
import javax.swing.*;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.BorderLayout;
/**
* @author richie
@ -41,8 +40,8 @@ public class FormulaPaneWhenReserveFormula extends FormulaPane {
reserveCheckBox4Write = new UICheckBox(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Write_Save_Formula"));
reserveCheckBox4Write.setSelected(false);
checkBoxPane.add(reserveCheckBox4Result, BorderLayout.CENTER);
checkBoxPane.add(reserveCheckBox4Write, BorderLayout.SOUTH);
checkBoxPane.add(reserveCheckBox4Result, BorderLayout.WEST);
checkBoxPane.add(reserveCheckBox4Write, BorderLayout.WEST);
}
@Override

48
designer-base/src/main/java/com/fr/design/formula/exception/FormulaExceptionTipsProcessor.java

@ -0,0 +1,48 @@
package com.fr.design.formula.exception;
import com.fr.design.formula.FormulaChecker;
import com.fr.design.formula.exception.function.FormulaCheckWrongFunction;
import com.fr.design.formula.exception.function.MismatchedCharFunction;
import com.fr.design.formula.exception.function.MismatchedTokenFunction;
import com.fr.design.formula.exception.function.NoViableAltForCharFunction;
import com.fr.design.formula.exception.function.NoViableAltFunction;
import com.fr.script.checker.exception.FunctionCheckWrongException;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.third.antlr.MismatchedCharException;
import com.fr.third.antlr.MismatchedTokenException;
import com.fr.third.antlr.NoViableAltException;
import com.fr.third.antlr.NoViableAltForCharException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/26
*/
public class FormulaExceptionTipsProcessor {
private static final Map<Class, Function<Exception, FormulaCheckResult>> EXCEPTION_TIPS = new ConcurrentHashMap<>();
private static final FormulaExceptionTipsProcessor PROCESSOR = new FormulaExceptionTipsProcessor();
static {
EXCEPTION_TIPS.put(FunctionCheckWrongException.class, FormulaCheckWrongFunction.getFunction());
EXCEPTION_TIPS.put(MismatchedCharException.class, MismatchedCharFunction.getFunction());
EXCEPTION_TIPS.put(MismatchedTokenException.class, MismatchedTokenFunction.getFunction());
EXCEPTION_TIPS.put(NoViableAltException.class, NoViableAltFunction.getFunction());
EXCEPTION_TIPS.put(NoViableAltForCharException.class, NoViableAltForCharFunction.getFunction());
}
public FormulaCheckResult getExceptionTips(Exception e) {
return EXCEPTION_TIPS.getOrDefault(e.getClass(),
e1 -> new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false))
.apply(e);
}
public static FormulaExceptionTipsProcessor getProcessor() {
return PROCESSOR;
}
}

14
designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckConstants.java

@ -0,0 +1,14 @@
package com.fr.design.formula.exception.function;
/**
* @author Hoky
* @date 2021/10/28
*/
public class FormulaCheckConstants {
public static final String COLON = ":";
public static final String LEFT = "(";
public static final String COMMON = ",";
public static final String RIGHT = ")";
public static final String BLANK = " ";
public static final String SINGLE_QUOTES = "'";
}

78
designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckWrongFunction.java

@ -0,0 +1,78 @@
package com.fr.design.formula.exception.function;
import com.fr.design.i18n.Toolkit;
import com.fr.script.checker.exception.FunctionCheckWrongException;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.script.rules.FunctionParameterType;
import com.fr.script.rules.FunctionRule;
import com.fr.stable.StringUtils;
import java.util.List;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/26
*/
public class FormulaCheckWrongFunction implements Function<Exception, FormulaCheckResult> {
private final static FormulaCheckWrongFunction FUNCTION = new FormulaCheckWrongFunction();
@Override
public FormulaCheckResult apply(Exception e) {
if (e instanceof FunctionCheckWrongException) {
FunctionCheckWrongException ce = (FunctionCheckWrongException) e;
List<FunctionRule> rules = ce.getRules();
String functionName = ce.getFunctionName();
StringBuilder errorMsg = new StringBuilder(functionName + Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + FormulaCheckConstants.COLON);
for (int i = 0; i < rules.size(); i++) {
errorMsg.append(FormulaCheckConstants.LEFT);
if (rules.get(i).getParameterList().isEmpty()) {
errorMsg.append(Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param"));
}
for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) {
errorMsg.append(getTypeString(functionParameterType)).append(FormulaCheckConstants.COMMON);
}
if (FormulaCheckConstants.COMMON.equals(errorMsg.charAt(errorMsg.length() - 1) + StringUtils.EMPTY)) {
errorMsg.deleteCharAt(errorMsg.length() - 1);
}
errorMsg.append(FormulaCheckConstants.RIGHT);
if (i != rules.size() - 1) {
errorMsg.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or"));
}
}
return new FormulaCheckResult(false, errorMsg.toString(), new FormulaCoordinates(1, indexPosition(ce.getFormulaText(), ce.getNode().toString())), true);
}
return new FormulaCheckResult(false, StringUtils.EMPTY, new FormulaCoordinates(-1, -1), true);
}
private static String getTypeString(FunctionParameterType type) {
switch (type) {
case NUMBER:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number");
case STRING:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String");
case ANY:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any");
case DATE:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date");
case BOOLEAN:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean");
case ARRAY:
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array");
}
return StringUtils.EMPTY;
}
public static Function<Exception, FormulaCheckResult> getFunction() {
return FUNCTION;
}
private int indexPosition(String formulaText, String invalidFormula) {
//处理一下自己FunctionCall自己拼的逗号逻辑
if (invalidFormula.contains(",")) {
invalidFormula = invalidFormula.substring(0, invalidFormula.indexOf(","));
}
return formulaText.indexOf(invalidFormula);
}
}

104
designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedCharFunction.java

@ -0,0 +1,104 @@
package com.fr.design.formula.exception.function;
import com.fr.design.formula.FormulaChecker;
import com.fr.design.i18n.Toolkit;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.third.antlr.MismatchedCharException;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/28
*/
public class MismatchedCharFunction implements Function<Exception, FormulaCheckResult> {
private final static MismatchedCharFunction FUNCTION = new MismatchedCharFunction();
@Override
public FormulaCheckResult apply(Exception e) {
if (e instanceof MismatchedCharException) {
MismatchedCharException charException = (MismatchedCharException) e;
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1);
return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates, false);
}
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false);
}
public static Function<Exception, FormulaCheckResult> getFunction() {
return FUNCTION;
}
private String getMessage(MismatchedCharException charException) {
StringBuffer sb = new StringBuffer();
switch (charException.mismatchType) {
case 1:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ");
appendCharName(sb, charException.expecting);
sb.append(FormulaCheckConstants.COMMON)
.append(FormulaCheckConstants.BLANK)
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Found"));
appendCharName(sb, charException.foundChar);
break;
case 2:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting_Anything") + ": ")
.append(FormulaCheckConstants.BLANK)
.append(FormulaCheckConstants.SINGLE_QUOTES);
appendCharName(sb, charException.expecting);
sb.append("';").append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_GotItAnyway"));
break;
case 3:
case 4:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ").append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Token"));
if (charException.mismatchType == 4) {
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not"));
}
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_In_Range")).append(": ");
appendCharName(sb, charException.expecting);
sb.append("..");
appendCharName(sb, charException.upper);
sb.append(", ").append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Found"));
appendCharName(sb, charException.foundChar);
break;
case 5:
case 6:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ")
.append(charException.mismatchType == 6 ? Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not") : FormulaCheckConstants.BLANK)
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ONE_OF")).append(" (");
int[] elems = charException.set.toArray();
for (int i = 0; i < elems.length; ++i) {
appendCharName(sb, elems[i]);
}
sb.append("), ").append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Found"));
appendCharName(sb, charException.foundChar);
break;
default:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_Char"));
}
return sb.toString();
}
private void appendCharName(StringBuffer sb, int c) {
switch (c) {
case 9:
sb.append("'\\t'");
break;
case 10:
sb.append("'\\n'");
break;
case 13:
sb.append("'\\r'");
break;
case 65535:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_EOF"));
break;
default:
sb.append((char) c);
}
}
}

140
designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedTokenFunction.java

@ -0,0 +1,140 @@
package com.fr.design.formula.exception.function;
import com.fr.design.formula.FormulaChecker;
import com.fr.design.i18n.Toolkit;
import com.fr.log.FineLoggerFactory;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.stable.StringUtils;
import com.fr.third.antlr.MismatchedTokenException;
import java.lang.reflect.Field;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/28
*/
public class MismatchedTokenFunction implements Function<Exception, FormulaCheckResult> {
private final static MismatchedTokenFunction FUNCTION = new MismatchedTokenFunction();
public static final String NULL_STRING = "null";
@Override
public FormulaCheckResult apply(Exception e) {
if (e instanceof MismatchedTokenException) {
MismatchedTokenException charException = (MismatchedTokenException) e;
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1);
return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates, false);
}
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false);
}
public static Function<Exception, FormulaCheckResult> getFunction() {
return FUNCTION;
}
public String getMessage(MismatchedTokenException exception) {
StringBuilder sb = new StringBuilder();
Object fieldValue = getFieldValue(exception, "tokenText");
String tokenText = fieldValue == null ? NULL_STRING : fieldValue.toString();
switch (exception.mismatchType) {
case 1:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ")
.append(tokenName(exception.expecting, exception))
.append(", ")
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Found"))
.append(FormulaCheckConstants.BLANK + FormulaCheckConstants.SINGLE_QUOTES)
.append(tokenText).append("'");
break;
case 2:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting_Anything") + ": ")
.append(tokenName(exception.expecting, exception))
.append("; ")
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_GotItAnyway"));
break;
case 3:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ")
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Token"))
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_In_Range"))
.append(": ")
.append(tokenName(exception.expecting, exception))
.append("..")
.append(tokenName(exception.upper, exception))
.append(", ").append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Found"))
.append("'").append(tokenText).append("'");
break;
case 4:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ")
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Token"))
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not"))
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_In_Range"))
.append(": ")
.append(tokenName(exception.expecting, exception))
.append("..")
.append(tokenName(exception.upper, exception))
.append(",").
append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Found"))
.append(" '")
.append(tokenText)
.append("'");
break;
case 5:
case 6:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ")
.append(exception.mismatchType == 6 ? Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Not") : FormulaCheckConstants.BLANK)
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ONE_OF")).append("(");
int[] elms = exception.set.toArray();
for (int i = 0; i < elms.length; ++i) {
sb.append(' ');
sb.append(tokenName(elms[i], exception));
}
sb.append("),")
.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Found"))
.append("'")
.append(tokenText)
.append("'");
break;
default:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_Token"));
}
return sb.toString();
}
private String tokenName(int tokenType, MismatchedTokenException exception) {
if (tokenType == 0) {
return "<Set of tokens>";
} else {
String[] tokenNames = (String[]) getFieldValue(exception, "tokenNames");
return tokenType >= 0 && tokenType < tokenNames.length ? translateToken(tokenNames[tokenType]) : "<" + tokenType + ">";
}
}
private String translateToken(String token) {
switch (token) {
case ("RPAREN"):
return ")";
case ("LPAREN"):
return "(";
case ("COMMA"):
return ",";
case ("COLON"):
return ":";
default:
return token;
}
}
private Object getFieldValue(Object object, String fieldName) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(object);
} catch (Exception e) {
FineLoggerFactory.getLogger().warn(e.getMessage(), e);
return StringUtils.EMPTY;
}
}
}

44
designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltForCharFunction.java

@ -0,0 +1,44 @@
package com.fr.design.formula.exception.function;
import com.fr.design.formula.FormulaChecker;
import com.fr.design.i18n.Toolkit;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.third.antlr.NoViableAltForCharException;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/28
*/
public class NoViableAltForCharFunction implements Function<Exception, FormulaCheckResult> {
private final static NoViableAltForCharFunction FUNCTION = new NoViableAltForCharFunction();
@Override
public FormulaCheckResult apply(Exception e) {
if (e instanceof NoViableAltForCharException) {
NoViableAltForCharException charException = (NoViableAltForCharException) e;
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(charException.line, charException.column - 1);
return new FormulaCheckResult(false, getMessage(charException), formulaCoordinates, false);
}
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false);
}
public static Function<Exception, FormulaCheckResult> getFunction() {
return FUNCTION;
}
public String getMessage(NoViableAltForCharException exception) {
String mesg = Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_Char") + ": ";
if (exception.foundChar >= ' ' && exception.foundChar <= '~') {
mesg = mesg + '\'';
mesg = mesg + exception.foundChar;
mesg = mesg + '\'';
} else {
mesg = mesg + exception.foundChar;
}
return mesg;
}
}

41
designer-base/src/main/java/com/fr/design/formula/exception/function/NoViableAltFunction.java

@ -0,0 +1,41 @@
package com.fr.design.formula.exception.function;
import com.fr.design.formula.FormulaChecker;
import com.fr.design.i18n.Toolkit;
import com.fr.script.checker.result.FormulaCheckResult;
import com.fr.script.checker.result.FormulaCoordinates;
import com.fr.third.antlr.NoViableAltException;
import com.fr.third.antlr.TreeParser;
import java.util.function.Function;
/**
* @author Hoky
* @date 2021/10/28
*/
public class NoViableAltFunction implements Function<Exception, FormulaCheckResult> {
private final static NoViableAltFunction FUNCTION = new NoViableAltFunction();
@Override
public FormulaCheckResult apply(Exception e) {
if (e instanceof NoViableAltException) {
NoViableAltException altException = (NoViableAltException) e;
FormulaCoordinates formulaCoordinates = new FormulaCoordinates(altException.line, altException.column - 1);
return new FormulaCheckResult(false, getMessage(altException), formulaCoordinates, false);
}
return new FormulaCheckResult(false, FormulaChecker.INVALID_FORMULA, FormulaCoordinates.INVALID, false);
}
public static Function<Exception, FormulaCheckResult> getFunction() {
return FUNCTION;
}
public String getMessage(NoViableAltException exception) {
if (exception.token != null) {
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_Token") + ": " + exception.token.getText();
} else {
return exception.node == TreeParser.ASTNULL ? Toolkit.i18nText("Fine-Design_Basic_Formula_Check_End_Of_Subtree") :
Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Unexpected_AST_Node") + ": " + exception.node.toString();
}
}
}

1003
designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaAutoCompletePopupWindow.java

File diff suppressed because it is too large Load Diff

22
designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaCompletion.java

@ -0,0 +1,22 @@
package com.fr.design.gui.autocomplete;
import javax.swing.Icon;
/**
* @author Hoky
* @date 2021/11/5
*/
public class FormulaCompletion extends BasicCompletion {
private Icon icon;
public FormulaCompletion(CompletionProvider provider, String replacementText, Icon icon) {
super(provider, replacementText);
this.icon = icon;
}
@Override
public Icon getIcon() {
return icon;
}
}

1311
designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java

File diff suppressed because it is too large Load Diff

28
designer-base/src/main/java/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java

@ -16,16 +16,34 @@ import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea;
import com.fr.design.gui.syntax.ui.rtextarea.ChangeableHighlightPainter;
import com.fr.log.FineLoggerFactory;
import javax.swing.*;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.*;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.Highlighter.Highlight;
import javax.swing.text.Highlighter.HighlightPainter;
import java.awt.*;
import java.awt.event.*;
import javax.swing.text.JTextComponent;
import javax.swing.text.Position;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
@ -41,7 +59,7 @@ import java.util.List;
* @author Robert Futrell
* @version 1.0
*/
class ParameterizedCompletionContext {
public class ParameterizedCompletionContext {
/**
* The parent window.

3
designer-base/src/main/java/com/fr/design/gui/style/TranslucentBorderSpecialPane.java

@ -26,6 +26,7 @@ import com.fr.design.style.color.NewColorSelectBox;
import com.fr.env.utils.DesignerInteractionHistory;
import com.fr.general.Background;
import com.fr.general.IOUtils;
import com.fr.i18n.UrlI18nManager;
import com.fr.general.act.BorderPacker;
import com.fr.stable.Constants;
import com.fr.stable.GraphDrawHelper;
@ -117,7 +118,7 @@ public class TranslucentBorderSpecialPane extends AbstractBorderPackerPane imple
public void actionPerformed(ActionEvent e) {
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(new URI(TWEAK_NINE_POINT_HELP_URL));
desktop.browse(new URI(UrlI18nManager.getInstance().getI18nUrl("nine.point.help")));
} catch (IOException | URISyntaxException ioException) {
ioException.printStackTrace();
}

26
designer-base/src/main/java/com/fr/design/locale/impl/ShowOnlineWidgetMark.java

@ -0,0 +1,26 @@
package com.fr.design.locale.impl;
import com.fr.general.GeneralContext;
import com.fr.general.locale.LocaleMark;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class ShowOnlineWidgetMark implements LocaleMark<Boolean> {
private Map<Locale, Boolean> map = new HashMap<>();
public ShowOnlineWidgetMark() {
map.put(Locale.CHINA, true);
map.put(Locale.TAIWAN, true);
map.put(Locale.US, false);
map.put(Locale.KOREA, false);
map.put(Locale.JAPAN, false);
}
@Override
public Boolean getValue() {
Boolean result = map.get(GeneralContext.getLocale());
return result == null ? false : result;
}
}

11
designer-base/src/main/java/com/fr/design/mainframe/EastRegionContainerPane.java

@ -13,7 +13,6 @@ import com.fr.design.gui.ibutton.UIButtonUI;
import com.fr.design.gui.icontainer.UIEastResizableContainer;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.mainframe.reuse.ReuseGuideDialog;
import com.fr.design.mainframe.reuse.SnapChatKeys;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.notification.SnapChat;
@ -292,7 +291,12 @@ public class EastRegionContainerPane extends UIEastResizableContainer {
// 控件设置
PropertyItem widgetSettings = new PropertyItem(KEY_WIDGET_SETTINGS, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Component_Settings"),
"widgetsettings", new PropertyMode[]{PropertyMode.REPORT, PropertyMode.REPORT_PARA, PropertyMode.REPORT_PARA_WIDGET, PropertyMode.REPORT_FLOAT, PropertyMode.FORM, PropertyMode.POLY},
new PropertyMode[]{PropertyMode.REPORT, PropertyMode.REPORT_PARA, PropertyMode.REPORT_PARA_WIDGET, PropertyMode.FORM, PropertyMode.POLY_REPORT, PropertyMode.POLY_CHART});
new PropertyMode[]{PropertyMode.REPORT, PropertyMode.REPORT_PARA, PropertyMode.REPORT_PARA_WIDGET, PropertyMode.FORM, PropertyMode.POLY_REPORT, PropertyMode.POLY_CHART}, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ComponentCollector.getInstance().clickComponentSetting();
}
});
// 条件属性
PropertyItem conditionAttr = new PropertyItem(KEY_CONDITION_ATTR, com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Condition_Attributes"),
"conditionattr", new PropertyMode[]{PropertyMode.REPORT, PropertyMode.REPORT_PARA, PropertyMode.REPORT_PARA_WIDGET, PropertyMode.REPORT_FLOAT, PropertyMode.POLY, PropertyMode.POLY_CHART},
@ -538,9 +542,6 @@ public class EastRegionContainerPane extends UIEastResizableContainer {
}
public PromptWindow getWidgetLibPromptWindow() {
if (!getWidgetLibSnapChat().hasRead()) {
return new ReuseGuideDialog(DesignerContext.getDesignerFrame());
}
return null;
}

8
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -123,6 +123,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
protected U undoState;
protected U authorityUndoState = null;
protected T template; // 当前模板
private boolean isNewCreateTpl = false; //当前模板是否为新建模板
/**
* 模板过程的相关信息
*
@ -197,7 +198,8 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
designModel = createDesignModel(parameters);
}
addCenterPane();
if (isNewFile) {
isNewCreateTpl = isNewFile;
if (isNewCreateTpl) {
// REPORT-58486: 必须在初始的UndoState创建前设置主题,使得初始的UndoState就包含了主题效果
setUpTheme4NewTemplate();
}
@ -971,6 +973,10 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
return true;
}
public boolean isNewCreateTpl(){
return isNewCreateTpl;
}
protected boolean export() throws Exception {
return this.getTarget().export(TemplateResourceManager.getResource().saveTemplate(getEditingFILE()));

2
designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleBlock.java

@ -32,7 +32,7 @@ import java.awt.event.MouseListener;
public class PredefinedStyleBlock extends JPanel {
private PredefinedStyle previewObject;
private PredefinedStyleSelectPane parentPane;
private Icon markedMode = IOUtils.readIcon("/com/fr/design/form/images/marked.png");
private Icon markedMode = IOUtils.readIcon("/com/fr/design/form/images/marker_selected.png");
private static final Color BORDER_COLOR = new Color(141, 194, 249);
private boolean mouseOver = false;

97
designer-base/src/main/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfo.java

@ -1,6 +1,5 @@
package com.fr.design.mainframe.reuse;
import com.fr.design.DesignerEnvManager;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLable;
import com.fr.stable.xml.XMLableReader;
@ -10,6 +9,7 @@ import com.fr.stable.xml.XMLableReader;
*/
public class ComponentReuseNotificationInfo implements XMLable {
public static final String XML_TAG = "ComponentReuseNotificationInfo";
private static final int INVALID_NUM = -1;
private static final ComponentReuseNotificationInfo INSTANCE = new ComponentReuseNotificationInfo();
@ -17,51 +17,66 @@ public class ComponentReuseNotificationInfo implements XMLable {
return INSTANCE;
}
private long lastNotifyTime = 0;
private boolean clickedWidgetLib = false;
private int notifiedNumber = 0;
private long firstDragEndTime = 0L;
private boolean clickedWidgetLib = false;
private boolean completeEmbedFilter = false;
private long lastGuidePopUpTime = 0;
private boolean firstDrag = true;
private String historyCreatedReuses = "[]";
public long getLastNotifyTime() {
return lastNotifyTime;
private boolean widgetLibHasRefreshed = false;
private boolean completeFirstShowComponentLib = false;
public boolean isClickedWidgetLib() {
return clickedWidgetLib;
}
public void setLastNotifyTime(long lastNotifyTime) {
this.lastNotifyTime = lastNotifyTime;
public void setClickedWidgetLib(boolean clickedWidgetLib) {
this.clickedWidgetLib = clickedWidgetLib;
}
public int getNotifiedNumber() {
return notifiedNumber;
public boolean isCompleteEmbedFilter() {
return completeEmbedFilter;
}
public void setNotifiedNumber(int notifiedNumber) {
this.notifiedNumber = notifiedNumber;
public void setCompleteEmbedFilter(boolean completeEmbedFilter) {
this.completeEmbedFilter = completeEmbedFilter;
}
public boolean isClickedWidgetLib() {
return clickedWidgetLib;
public long getFirstDragEndTime() {
return firstDragEndTime;
}
public void setClickedWidgetLib(boolean clickedWidgetLib) {
this.clickedWidgetLib = clickedWidgetLib;
public void setFirstDragEndTime(long firstDragEndTime) {
this.firstDragEndTime = firstDragEndTime;
}
public long getLastGuidePopUpTime() {
return lastGuidePopUpTime;
public boolean isFirstDrag() {
return firstDrag;
}
public void setLastGuidePopUpTime(long lastGuidePopUpTime) {
this.lastGuidePopUpTime = lastGuidePopUpTime;
public void setFirstDrag(boolean firstDrag) {
this.firstDrag = firstDrag;
}
public void updateLastGuidePopUpTime() {
this.setLastGuidePopUpTime(System.currentTimeMillis());
DesignerEnvManager.getEnvManager().saveXMLFile();
public boolean isWidgetLibHasRefreshed() {
return widgetLibHasRefreshed;
}
public void setWidgetLibHasRefreshed(boolean widgetLibHasRefreshed) {
this.widgetLibHasRefreshed = widgetLibHasRefreshed;
}
public boolean isCompleteFirstShowComponentLib() {
return completeFirstShowComponentLib;
}
public void setCompleteFirstShowComponentLib(boolean completeFirstShowComponentLib) {
this.completeFirstShowComponentLib = completeFirstShowComponentLib;
}
public String getHistoryCreatedReuses() {
@ -72,23 +87,41 @@ public class ComponentReuseNotificationInfo implements XMLable {
this.historyCreatedReuses = historyCreatedReuses;
}
//兼容老版本云端埋点的记录
public long getLastNotifyTime() {
return INVALID_NUM;
}
public int getNotifiedNumber() {
return INVALID_NUM;
}
public long getLastGuidePopUpTime() {
return INVALID_NUM;
}
@Override
public void readXML(XMLableReader reader) {
this.setLastNotifyTime(reader.getAttrAsLong("lastNotifyTime", 0L));
this.setNotifiedNumber(reader.getAttrAsInt("notifiedNumber", 0));
this.setClickedWidgetLib(reader.getAttrAsBoolean("clickedWidgetLib", false));
this.setLastGuidePopUpTime(reader.getAttrAsLong("lastGuidePopUpTime", 0L));
this.setCompleteEmbedFilter(reader.getAttrAsBoolean("completeEmbedFilter", false));
this.setCompleteFirstShowComponentLib(reader.getAttrAsBoolean("completeFirstShowComponentLib", false));
this.setWidgetLibHasRefreshed(reader.getAttrAsBoolean("widgetLibHasRefreshed", false));
this.setFirstDrag(reader.getAttrAsBoolean("firstDrag", true));
this.setHistoryCreatedReuses(reader.getAttrAsString("historyCreatedReuses", "[]"));
this.setFirstDragEndTime(reader.getAttrAsLong("firstDragEndTime", 0L));
}
@Override
public void writeXML(XMLPrintWriter writer) {
writer.startTAG("ComponentReuseNotificationInfo");
writer.attr("lastNotifyTime", this.lastNotifyTime)
.attr("notifiedNumber", this.notifiedNumber)
.attr("clickedWidgetLib", this.clickedWidgetLib)
.attr("lastGuidePopUpTime", this.lastGuidePopUpTime)
.attr("historyCreatedReuses", this.historyCreatedReuses);;
writer.attr("clickedWidgetLib", this.clickedWidgetLib)
.attr("completeEmbedFilter", this.completeEmbedFilter)
.attr("completeFirstShowComponentLib", this.completeFirstShowComponentLib)
.attr("firstDrag", this.firstDrag)
.attr("widgetLibHasRefreshed", this.widgetLibHasRefreshed)
.attr("firstDragEndTime", this.firstDragEndTime)
.attr("historyCreatedReuses", this.historyCreatedReuses);
;
writer.end();
}

169
designer-base/src/main/java/com/fr/design/mainframe/reuse/ReuseGuideDialog.java

@ -1,169 +0,0 @@
package com.fr.design.mainframe.reuse;
import com.fr.base.background.ColorBackground;
import com.fr.design.dialog.UIDialog;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.PromptWindow;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.IOUtils;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.geom.RoundRectangle2D;
public class ReuseGuideDialog extends UIDialog implements PromptWindow {
InnerDialog innerDialog;
private static final Dimension DEFAULT = new Dimension(735, 510);
public ReuseGuideDialog(Frame parent) {
super(parent);
}
@Override
public void showWindow() {
innerDialog = new InnerDialog(this);
JPanel backGroundPane = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
Image icon = IOUtils.readImage("com/fr/base/images/share/background.png");// 003.jpg是测试图片在项目的根目录下
g.drawImage(icon, 0, 0, getSize().width, getSize().height, this);// 图片会自动缩放
}
};
add(backGroundPane, BorderLayout.CENTER);
initStyle();
innerDialog.showWindow();
}
private void initStyle() {
setSize(DEFAULT);
setUndecorated(true);
setBackground(new Color(0, 0, 0, 0));
GUICoreUtils.centerWindow(this);
}
@Override
public void hideWindow() {
ComponentReuseNotificationInfo.getInstance().updateLastGuidePopUpTime();
this.setVisible(false);
if (innerDialog != null) {
innerDialog.setVisible(false);
innerDialog.dispose();
innerDialog = null;
}
this.dispose();
}
@Override
public void checkValid() {
}
class InnerDialog extends UIDialog {
private final Dimension DEFAULT = new Dimension(700, 475);
private static final int TITLE_FONT_SIZE = 20;
public InnerDialog(Dialog dialog) {
super(dialog);
}
public void showWindow() {
add(createCenterPanel(), BorderLayout.CENTER);
add(createSouthPanel(), BorderLayout.SOUTH);
add(createNorthPanel(), BorderLayout.NORTH);
showDialog();
}
private JPanel createNorthPanel() {
JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
//右上角关闭按钮
JButton button = new JButton(new ImageIcon(IOUtils.readImage("/com/fr/base/images/share/close.png").getScaledInstance(15, 15, Image.SCALE_SMOOTH)));
button.setBorder(null);
button.setOpaque(false);
button.addActionListener(e -> ReuseGuideDialog.this.hideWindow());
northPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 15));
northPanel.setOpaque(false);
northPanel.add(button);
return northPanel;
}
private JPanel createCenterPanel() {
JPanel centerPanel = new JPanel(new BorderLayout());
UILabel titleLabel = new UILabel(Toolkit.i18nText("Fine-Design_Share_Drag_And_Make_Component"));
UILabel imageLabel = new UILabel(new ImageIcon(IOUtils.readImage("com/fr/design/images/dashboard/guide.png").getScaledInstance(DEFAULT.width, DEFAULT.height, Image.SCALE_SMOOTH)));
titleLabel.setFont(new Font(titleLabel.getFont().getName(), Font.BOLD, TITLE_FONT_SIZE));
titleLabel.setBorder(BorderFactory.createEmptyBorder());
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
panel.setOpaque(false);
panel.add(titleLabel);
centerPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
centerPanel.setOpaque(false);
centerPanel.add(imageLabel, BorderLayout.CENTER);
centerPanel.add(panel, BorderLayout.NORTH);
return centerPanel;
}
private JPanel createSouthPanel() {
JPanel southPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
JButton button = new JButton(Toolkit.i18nText("Fine-Design_Share_Try_Drag")) {
@Override
public void paint(Graphics g) {
ColorBackground buttonBackground = ColorBackground.getInstance(Color.decode("#419BF9"));
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
buttonBackground.paint(g2d, new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), 8, 8));
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
super.paint(g);
}
};
button.setBorder(null);
button.setForeground(Color.WHITE);
button.setOpaque(false);
button.addActionListener(e -> ReuseGuideDialog.this.hideWindow());
southPanel.setBorder(BorderFactory.createEmptyBorder(0, 290, 19, 290));
southPanel.setPreferredSize(new Dimension(DEFAULT.width, 51));
southPanel.setOpaque(false);
southPanel.add(button);
return southPanel;
}
/**
* 显示窗口
*/
private void showDialog() {
setSize(DEFAULT);
setUndecorated(true);
GUICoreUtils.centerWindow(this);
setModalityType(ModalityType.APPLICATION_MODAL);
ReuseGuideDialog.this.setVisible(true);
setVisible(true);
}
@Override
public void checkValid() {
}
}
}

99
designer-base/src/main/java/com/fr/design/mainframe/share/ComponentShareUtil.java

@ -0,0 +1,99 @@
package com.fr.design.mainframe.share;
import com.fr.design.DesignerEnvManager;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo;
import com.fr.form.share.constants.ComponentPath;
import com.fr.form.share.group.filter.ReuFilter;
import com.fr.design.DesignerCloudURLManager;
import com.fr.workspace.WorkContext;
/**
* Created by kerry on 2021/10/27
*/
public class ComponentShareUtil {
private ComponentShareUtil() {
}
/**
* 判断是否需要切换到在线组件库
*
* @return
*/
public static boolean needSwitch2OnlineTab() {
return DesignerCloudURLManager.getInstance().isConnected() && !hasTouched() && isCurrentTplNewCreate();
}
/**
* 判断是否可触达
*
* @return boolean
*/
public static boolean hasTouched() {
String sharePath = ComponentPath.SHARE_PATH.path();
String[] components = WorkContext.getWorkResource().list(sharePath, new ReuFilter());
return components != null && components.length > 6;
}
/**
* 判断当前模板是否是新建模板
*
* @return boolean
*/
public static boolean isCurrentTplNewCreate() {
JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
return jTemplate.isNewCreateTpl();
}
/**
* 判断是否在需要展示组件库界面
*
* @return boolean
*/
public static boolean needShowEmbedFilterPane() {
return !ComponentReuseNotificationInfo.getInstance().isCompleteEmbedFilter() && !hasTouched() && isCurrentTplNewCreate();
}
public static boolean needShowComponentLib() {
return !ComponentReuseNotificationInfo.getInstance().isCompleteFirstShowComponentLib() && !hasTouched() && isCurrentTplNewCreate();
}
/**
* 判断是否需要展示首次拖拽动效
*
* @return boolean
*/
public static boolean needShowFirstDragAnimate() {
return ComponentReuseNotificationInfo.getInstance().isFirstDrag();
}
/**
* 完成嵌入式筛选
*/
public static void completeEmbedFilter() {
boolean changed = false;
if (!ComponentReuseNotificationInfo.getInstance().isWidgetLibHasRefreshed()) {
ComponentReuseNotificationInfo.getInstance().setWidgetLibHasRefreshed(true);
changed = true;
}
if (!ComponentReuseNotificationInfo.getInstance().isCompleteEmbedFilter()) {
ComponentReuseNotificationInfo.getInstance().setCompleteEmbedFilter(true);
changed = true;
}
if (changed) {
DesignerEnvManager.getEnvManager().saveXMLFile();
}
}
/**
* 记录组件库刷新
*/
public static void recordWidgetLibHasRefreshed() {
if (!ComponentReuseNotificationInfo.getInstance().isWidgetLibHasRefreshed()) {
ComponentReuseNotificationInfo.getInstance().setWidgetLibHasRefreshed(true);
DesignerEnvManager.getEnvManager().saveXMLFile();
}
}
}

102
designer-base/src/main/java/com/fr/design/mainframe/share/collect/ComponentCollector.java

@ -4,6 +4,7 @@ import com.fr.base.io.XMLReadHelper;
import com.fr.config.MarketConfig;
import com.fr.design.DesignerEnvManager;
import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo;
import com.fr.design.mainframe.share.ComponentShareUtil;
import com.fr.form.share.DefaultSharableWidget;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.constants.ComponentPath;
@ -19,7 +20,6 @@ import com.fr.json.JSONException;
import com.fr.json.JSONFactory;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.context.PluginContexts;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
@ -48,10 +48,6 @@ import java.util.Iterator;
public class ComponentCollector implements XMLable {
private static final long ONE_MINUTE = 60 * 1000L;
private static final int REUSE_INFO_FIRST_POPUP = 1;
private static final int REUSE_INFO_SECOND_POPUP = 2;
private static final String SIMPLE_DATE_PATTERN = "yyyy-MM-dd";
private static final String XML = "ComponentCollector";
@ -98,11 +94,11 @@ public class ComponentCollector implements XMLable {
private static final String MARKET_CLICK = "marketClick";
private static final String PROMPT_JUMP = "promptJump";
private static final String FIRST_SHOW_REACT = "firstShowReact";
private static final String TOOLBAR_JUMP = "toolbarJump";
private static final String EMBEDED_FILTER_REACT = "embededFilterReact";
private static final String POPUP_JUMP = "popupJump";
private static final String DYNAMIC_EFFECT_REACT = "dynamicEffectReact";
private static final String uuid = DesignerEnvManager.getEnvManager().getUUID();
@ -116,11 +112,11 @@ public class ComponentCollector implements XMLable {
private int cmpBoardClick = 0;
private int promptJump = 0;
private int firstShowReact = 0;
private int toolbarJump = 0;
private int embededFilterReact = 0;
private int popupJump = 0;
private int dynamicEffectReact = 0;
private JSONArray activateRecord = JSONFactory.createJSON(JSON.ARRAY);
@ -291,7 +287,7 @@ public class ComponentCollector implements XMLable {
try {
DefaultShareGroupManager.getInstance().refresh();
Group[] groups = DefaultShareGroupManager.getInstance().getAllGroup();
for(Group group : groups) {
for (Group group : groups) {
JSONObject jo = JSONFactory.createJSON(JSON.OBJECT);
jo.put(GROUP_NAME, group.getGroupName());
jo.put(CONTAIN_AMOUNT, group.getAllBindInfoList().length);
@ -338,37 +334,47 @@ public class ComponentCollector implements XMLable {
saveInfo();
}
public void collectPromptJumpWhenJump(){
if (ComponentReuseNotificationInfo.getInstance().getNotifiedNumber() == REUSE_INFO_FIRST_POPUP) {
this.promptJump = 1;
saveInfo();
}else if(ComponentReuseNotificationInfo.getInstance().getNotifiedNumber() == REUSE_INFO_SECOND_POPUP){
this.promptJump = 2;
saveInfo();
public void collectFirstShowReact(int flag) {
if (this.firstShowReact == flag) {
return;
}
this.firstShowReact = flag;
saveInfo();
}
public void collectPromptJumpWhenShow() {
if (ComponentReuseNotificationInfo.getInstance().getNotifiedNumber() == REUSE_INFO_SECOND_POPUP) {
this.promptJump = -1;
public void clickComponentSetting() {
if (!ComponentShareUtil.needShowEmbedFilterPane()) {
return;
}
boolean changed = false;
int firstShowReact = ComponentReuseNotificationInfo.getInstance().isWidgetLibHasRefreshed() ? 2 : -1;
if (this.firstShowReact != firstShowReact) {
this.firstShowReact = firstShowReact;
changed = true;
}
if (this.embededFilterReact == 0 && ComponentReuseNotificationInfo.getInstance().isWidgetLibHasRefreshed()) {
this.embededFilterReact = -1;
changed = true;
}
if (changed) {
saveInfo();
}
}
public void collectToolbarJump() {
if (this.toolbarJump == 0) {
this.toolbarJump = 1;
saveInfo();
public void collectEmbededFilterReact(int flag) {
if (this.embededFilterReact == flag) {
return;
}
this.embededFilterReact = flag;
saveInfo();
}
public void collectPopupJump() {
long currentTime = System.currentTimeMillis();
long lastGuidePopUpTime = ComponentReuseNotificationInfo.getInstance().getLastGuidePopUpTime();
if (currentTime - lastGuidePopUpTime <= ONE_MINUTE && this.popupJump == 0) {
this.popupJump = 1;
public void collectDynamicEffectReact() {
if (this.dynamicEffectReact == 1) {
return;
}
if (System.currentTimeMillis() - ComponentReuseNotificationInfo.getInstance().getFirstDragEndTime() <= ONE_MINUTE) {
this.dynamicEffectReact = 1;
saveInfo();
}
}
@ -468,6 +474,10 @@ public class ComponentCollector implements XMLable {
this.generateCmpNumber = reader.getAttrAsInt("generateCmpNumber", 0);
this.uploadCmpNumber = reader.getAttrAsInt("uploadCmpNumber", 0);
this.firstShowReact = reader.getAttrAsInt(FIRST_SHOW_REACT, 0);
this.embededFilterReact = reader.getAttrAsInt(EMBEDED_FILTER_REACT, 0);
this.dynamicEffectReact = reader.getAttrAsInt(DYNAMIC_EFFECT_REACT, 0);
String activateRecordStr = reader.getAttrAsString("activateRecord", StringUtils.EMPTY);
activateRecord = parseJSONArray(activateRecordStr);
String generateCmpRecordStr = reader.getAttrAsString("generateCmpRecord", StringUtils.EMPTY);
@ -475,13 +485,9 @@ public class ComponentCollector implements XMLable {
this.helpConfigInfo = parseJSONArray(reader.getAttrAsString(HELP_CONFIG_INFO, StringUtils.EMPTY));
this.helpConfigUseInfo = parseJSONArray(reader.getAttrAsString(HELP_CONFIG_USE_INFO, StringUtils.EMPTY));
this.searchContent = parseJSONArray(reader.getAttrAsString(SEARCH_CONTENT,StringUtils.EMPTY));
this.searchContent = parseJSONArray(reader.getAttrAsString(SEARCH_CONTENT, StringUtils.EMPTY));
this.filterContent = parseJSONArray(reader.getAttrAsString(FILTER_CONTENT, StringUtils.EMPTY));
this.sortType = parseJSONArray(reader.getAttrAsString(SORT_TYPE, StringUtils.EMPTY));
this.promptJump = reader.getAttrAsInt(PROMPT_JUMP, 0);
this.toolbarJump = reader.getAttrAsInt(TOOLBAR_JUMP, 0);
this.popupJump = reader.getAttrAsInt(POPUP_JUMP, 0);
}
}
@ -515,9 +521,9 @@ public class ComponentCollector implements XMLable {
.attr(SEARCH_CONTENT, searchContent.toString())
.attr(FILTER_CONTENT, filterContent.toString())
.attr(SORT_TYPE, sortType.toString())
.attr(PROMPT_JUMP, promptJump)
.attr(TOOLBAR_JUMP, toolbarJump)
.attr(POPUP_JUMP, popupJump)
.attr(FIRST_SHOW_REACT, firstShowReact)
.attr(EMBEDED_FILTER_REACT, embededFilterReact)
.attr(DYNAMIC_EFFECT_REACT, dynamicEffectReact)
.end();
}
@ -542,15 +548,9 @@ public class ComponentCollector implements XMLable {
jo.put(SEARCH_CONTENT, searchContent.toString());
jo.put(FILTER_CONTENT, filterContent.toString());
jo.put(SORT_TYPE, sortType.toString());
jo.put("guideInfo", assembleGuideInfo());
return jo.toString();
}
private String assembleGuideInfo() {
JSONObject jo = JSONFactory.createJSON(JSON.OBJECT);
jo.put(PROMPT_JUMP, promptJump)
.put(TOOLBAR_JUMP, toolbarJump)
.put(POPUP_JUMP, popupJump);
jo.put(FIRST_SHOW_REACT, firstShowReact);
jo.put(EMBEDED_FILTER_REACT, embededFilterReact);
jo.put(DYNAMIC_EFFECT_REACT, dynamicEffectReact);
return jo.toString();
}
@ -603,7 +603,7 @@ public class ComponentCollector implements XMLable {
return JSONFactory.createJSON(JSON.ARRAY);
}
public void clear(){
public void clear() {
clearActiveRecord();
clearGenerateCmpRecord();
clearFilterContent();

2
designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java

@ -37,7 +37,7 @@ public class LabelUtils {
Font newFont = FRFont.getInstance(tipLabel.getFont().getFontName(), Font.PLAIN, 12);
tipLabel.setFont(newFont);
tipLabel.setBorder(BorderFactory.createEmptyBorder());
tipLabel.setEnabled(false);
tipLabel.setEditable(false);
tipLabel.setText(title);
tipLabel.setLineWrap(true);
tipLabel.setWrapStyleWord(true);

14
designer-base/src/main/java/com/fr/design/mainframe/toast/DesignerToastMsgUtil.java

@ -31,6 +31,13 @@ public class DesignerToastMsgUtil {
}
public static ToastMsgDialog createPromptDialog(String text) {
return createDialog(PROMPT_ICON, toastPane(text), DesignerContext.getDesignerFrame());
}
public static ToastMsgDialog createPromptDialog(JPanel contentPane) {
return createDialog(PROMPT_ICON, contentPane, DesignerContext.getDesignerFrame());
}
public static void toastPrompt(JPanel contendPane) {
toastPane(PROMPT_ICON, contendPane, DesignerContext.getDesignerFrame());
@ -69,6 +76,11 @@ public class DesignerToastMsgUtil {
}
private static void toastPane(Icon icon, JPanel contendPane, Window parent) {
ToastMsgDialog dialog = createDialog(icon, contendPane, parent);
dialog.setVisible(true);
}
private static ToastMsgDialog createDialog(Icon icon, JPanel contendPane, Window parent) {
JPanel pane = FRGUIPaneFactory.createBorderLayout_S_Pane();
UILabel uiLabel = new UILabel(icon);
uiLabel.setVerticalAlignment(SwingConstants.TOP);
@ -83,7 +95,7 @@ public class DesignerToastMsgUtil {
} else {
dialog = new ToastMsgDialog((Frame) parent, pane);
}
dialog.setVisible(true);
return dialog;
}

7
designer-base/src/main/java/com/fr/design/mainframe/toast/ToastMsgDialog.java

@ -24,6 +24,7 @@ public class ToastMsgDialog extends UIDialog {
private ScheduledExecutorService TIMER;
private int hide_height = 0;
private JPanel contentPane;
private boolean show = false;
public ToastMsgDialog(Frame parent, JPanel panel) {
super(parent);
@ -65,6 +66,7 @@ public class ToastMsgDialog extends UIDialog {
public void display(JPanel outerJPanel) {
show = true;
outerJPanel.setLocation(0, -hide_height);
ScheduledExecutorService TIP_TOOL_TIMER = createToastScheduleExecutorService();
TIP_TOOL_TIMER.scheduleAtFixedRate(new Runnable() {
@ -98,6 +100,7 @@ public class ToastMsgDialog extends UIDialog {
TIP_TOOL_TIMER.shutdown();
ToastMsgDialog.this.setVisible(false);
ToastMsgDialog.this.dispose();
ToastMsgDialog.this.show = false;
}
outerJPanel.setLocation(point.x, point.y - 5);
Dimension dimension = ToastMsgDialog.this.getSize();
@ -159,5 +162,7 @@ public class ToastMsgDialog extends UIDialog {
super.dispose();
}
public boolean isShow() {
return show;
}
}

BIN
designer-base/src/main/resources/com/fr/design/images/m_file/formula.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

BIN
designer-base/src/main/resources/com/fr/design/images/m_file/param.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

7
designer-base/src/test/java/com/fr/design/mainframe/reuse/ComponentReuseNotificationInfoTest.java

@ -18,13 +18,11 @@ public class ComponentReuseNotificationInfoTest {
@Test
public void testReadXML() {
try {
XMLableReader xmlReader = XMLableReader.createXMLableReader(new StringReader("<ComponentReuseNotificationInfo lastNotifyTime=\"1620612153215\" notifiedNumber=\"2\" clickedWidgetLib=\"true\"/>\n"));
XMLableReader xmlReader = XMLableReader.createXMLableReader(new StringReader("<ComponentReuseNotificationInfo lastNotifyTime=\"1620612153215\" clickedWidgetLib=\"true\"/>\n"));
ComponentReuseNotificationInfo notificationInfo = ComponentReuseNotificationInfo.getInstance();
notificationInfo.readXML(xmlReader);
xmlReader.close();
Assert.assertEquals(2, notificationInfo.getNotifiedNumber());
Assert.assertEquals(true, notificationInfo.isClickedWidgetLib());
Assert.assertEquals(1620612153215L, notificationInfo.getLastNotifyTime());
} catch (XMLStreamException e) {
Assert.fail(e.getMessage());
}
@ -35,12 +33,11 @@ public class ComponentReuseNotificationInfoTest {
StringWriter sw = new StringWriter();
XMLPrintWriter writer = XMLPrintWriter.create(new PrintWriter(sw));
ComponentReuseNotificationInfo notificationInfo = ComponentReuseNotificationInfo.getInstance();
notificationInfo.setNotifiedNumber(1);
notificationInfo.writeXML(writer);
writer.flush();
writer.close();
Assert.assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<ComponentReuseNotificationInfo xmlVersion=\"20170720\" releaseVersion=\"\" lastNotifyTime=\"0\" notifiedNumber=\"1\" clickedWidgetLib=\"false\"/>\n", sw.toString());
"<ComponentReuseNotificationInfo xmlVersion=\"20170720\" releaseVersion=\"\" clickedWidgetLib=\"false\" hasCompleteEmbedFilter=\"false\" firstDrag=\"true\" widgetLibHasRefreshed=\"false\" firstDragEndTime=\"0\" historyCreatedReuses=\"[]\"/>\n", sw.toString());
}
}

2
designer-form/src/main/java/com/fr/design/mainframe/FormParaWidgetPane.java

@ -17,7 +17,6 @@ import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.module.DesignModuleFactory;
import com.fr.design.utils.gui.LayoutUtils;
import com.fr.form.ui.UserDefinedWidgetConfig;
@ -253,7 +252,6 @@ public class FormParaWidgetPane extends JPanel {
@Override
public void mouseClicked(MouseEvent e) {
FormWidgetDetailPane.getInstance().enterWidgetLib();
ComponentCollector.getInstance().collectToolbarJump();
}
@Override

50
designer-form/src/main/java/com/fr/design/mainframe/FormWidgetDetailPane.java

@ -6,11 +6,13 @@ import com.fr.design.gui.ibutton.UIHeadGroup;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo;
import com.fr.design.locale.impl.ShowOnlineWidgetMark;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.ComponentShareUtil;
import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane;
import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane;
import com.fr.general.locale.LocaleCenter;
import com.fr.general.locale.LocaleMark;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JPanel;
@ -30,7 +32,7 @@ import java.util.List;
* Date: 14-7-8
* Time: 下午8:18
*/
public class FormWidgetDetailPane extends FormDockView{
public class FormWidgetDetailPane extends FormDockView {
private static final int LOCAL_TAB = 0;
private static final int ONLINE_TAB = 1;
@ -38,6 +40,8 @@ public class FormWidgetDetailPane extends FormDockView{
private UIHeadGroup headGroup;
private List<BasicPane> paneList;
private CardLayout cardLayout;
//用来标记当前组件库界面是否处于已触达状态
private boolean hasTouched = false;
private boolean isEmptyPane = false;
@ -48,7 +52,7 @@ public class FormWidgetDetailPane extends FormDockView{
return HOLDER.singleton;
}
private FormWidgetDetailPane(){
private FormWidgetDetailPane() {
setLayout(FRGUIPaneFactory.createBorderLayout());
}
@ -75,7 +79,7 @@ public class FormWidgetDetailPane extends FormDockView{
/**
* 初始化
*/
public void refreshDockingView(){
public void refreshDockingView() {
if (isEmptyPane) {
return;
}
@ -85,18 +89,18 @@ public class FormWidgetDetailPane extends FormDockView{
clearDockingView();
return;
}
hasTouched = ComponentShareUtil.hasTouched();
initPaneList();
this.setBorder(null);
cardLayout = new CardLayout();
centerPane = new JPanel(cardLayout);
String[] paneNames = new String[paneList.size()];
for (int i = 0; i < paneList.size(); i++) {
String title = paneList.get(i).getTitle();
String title = paneList.get(i).getTitle();
paneNames[i] = title;
centerPane.add(paneList.get(i), title);
}
headGroup = new UIHeadGroup(paneNames) {
headGroup = new UIHeadGroup(paneNames) {
protected void tabChanged(int newSelectedIndex) {
//初始化还未展示的时候不需要收集其 marketClick
if (this.isShowing() && newSelectedIndex == 1) {
@ -105,12 +109,23 @@ public class FormWidgetDetailPane extends FormDockView{
cardLayout.show(centerPane, paneList.get(newSelectedIndex).getTitle());
}
};
headGroup.setSelectedIndex(ComponentReuseNotificationInfo.getInstance().isClickedWidgetLib() ? LOCAL_TAB : ONLINE_TAB);
headGroup.setSelectedIndex(ComponentShareUtil.needSwitch2OnlineTab() ? ONLINE_TAB : LOCAL_TAB);
this.add(headGroup, BorderLayout.NORTH);
this.add(centerPane, BorderLayout.CENTER);
}
public void resetEmptyPane(){
/**
* 判断是否可触达
*
* @return boolean
*/
public boolean hasTouched() {
return hasTouched;
}
public void resetEmptyPane() {
this.isEmptyPane = false;
}
@ -124,7 +139,7 @@ public class FormWidgetDetailPane extends FormDockView{
this.add(psp, BorderLayout.CENTER);
}
public void switch2Empty(){
public void switch2Empty() {
isEmptyPane = true;
this.removeAll();
JPanel panel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 5);
@ -157,7 +172,7 @@ public class FormWidgetDetailPane extends FormDockView{
}
public void enterWidgetLib() {
public void enterWidgetLib() {
ComponentReuseNotifyUtil.enterWidgetLibExtraAction();
EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_LIB);
}
@ -175,7 +190,14 @@ public class FormWidgetDetailPane extends FormDockView{
private void initPaneList() {
paneList = new ArrayList<>();
paneList.add(LocalWidgetRepoPane.getInstance());
paneList.add(OnlineWidgetRepoPane.getInstance());
if (isShowOnlineWidgetRepoPane()) {
OnlineWidgetRepoPane.getInstance().refresh();
paneList.add(OnlineWidgetRepoPane.getInstance());
}
}
}
private boolean isShowOnlineWidgetRepoPane() {
LocaleMark<Boolean> localeMark = LocaleCenter.getMark(ShowOnlineWidgetMark.class);
return localeMark.getValue();
}
}

19
designer-form/src/main/java/com/fr/design/mainframe/JForm.java

@ -7,13 +7,13 @@ import com.fr.base.Releasable;
import com.fr.base.extension.FileExtension;
import com.fr.base.iofile.attr.ExtendSharableAttrMark;
import com.fr.base.theme.FormTheme;
import com.fr.base.theme.FormThemeConfig;
import com.fr.base.theme.TemplateTheme;
import com.fr.base.theme.TemplateThemeCompatible;
import com.fr.base.theme.TemplateThemeConfig;
import com.fr.base.vcs.DesignerMode;
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.FormMobileAttrAction;
import com.fr.design.actions.TemplateParameterAction;
@ -50,6 +50,9 @@ import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.form.FormECCompositeProvider;
import com.fr.design.mainframe.form.FormECDesignerProvider;
import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.ComponentShareUtil;
import com.fr.design.mainframe.template.info.JFormProcessInfo;
import com.fr.design.mainframe.template.info.TemplateProcessInfo;
import com.fr.design.mainframe.theme.dialog.TemplateThemeUsingDialog;
@ -350,13 +353,6 @@ public class JForm extends JTemplate<Form, FormUndoState> implements BaseJForm<F
}
String key = jt.getEditingFILE().getPath() + "-" + jt.getTarget().getTemplateID();
FormHierarchyTreePane.getInstance().removeTreePath(key);
ReuseTriggerPointManager.getInstance().removeJForm(JForm.this);
}
@Override
public void templateOpened(JTemplate<?, ?> jt) {
ReuseTriggerPointManager.getInstance().registerJForm(JForm.this);
}
@Override
@ -900,9 +896,16 @@ public class JForm extends JTemplate<Form, FormUndoState> implements BaseJForm<F
pane.setLayout(new BorderLayout());
pane.add(FormWidgetDetailPane.getInstance(formDesign), BorderLayout.CENTER);
EastRegionContainerPane.getInstance().replaceWidgetLibPane(pane);
if (ComponentShareUtil.needShowComponentLib()) {
ComponentCollector.getInstance().collectFirstShowReact(1);
ComponentReuseNotificationInfo.getInstance().setCompleteFirstShowComponentLib(true);
DesignerEnvManager.getEnvManager().saveXMLFile();
EastRegionContainerPane.getInstance().switchTabTo(EastRegionContainerPane.KEY_WIDGET_LIB);
}
}
}
public String getEditingCreatorName() {
return formDesign.getSelectionModel().getSelection().getSelectedCreator().toData().getWidgetName();
}

217
designer-form/src/main/java/com/fr/design/mainframe/ReuseTriggerPointManager.java

@ -1,217 +0,0 @@
package com.fr.design.mainframe;
import com.fr.base.iofile.attr.ExtendSharableAttrMark;
import com.fr.design.DesignerEnvManager;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.adaptve.config.TriggerPointProvider;
import com.fr.design.mainframe.adaptve.config.impl.CellStyleTriggerPoint;
import com.fr.design.mainframe.adaptve.config.impl.CellValueImageChangeTriggerPoint;
import com.fr.design.mainframe.adaptve.config.ReuseNotifyInfo;
import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.toast.DesignerToastMsgUtil;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.form.main.Form;
import com.fr.form.main.WidgetGather;
import com.fr.form.ui.AbstractBorderStyleWidget;
import com.fr.form.ui.Widget;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Created by kerry on 4/28/21
*/
public class ReuseTriggerPointManager {
private static final long ONE_WEEK_TIME = 7 * 24 * 3600 * 1000L;
private static class Holder {
private static final ReuseTriggerPointManager HOLDER = new ReuseTriggerPointManager();
}
public static ReuseTriggerPointManager getInstance() {
return Holder.HOLDER;
}
private Map<JForm, ReuseNotifyInfo> map = new HashMap<>();
private List<Listener> listeners = new ArrayList<>();
private ReuseTriggerPointManager() {
if (!hasNotifiedTwice()) {
List<TriggerPointProvider> list = getTriggerPoints();
for (TriggerPointProvider triggerPoint : list) {
Listener listener = new Listener<Null>() {
@Override
public void on(Event event, Null o) {
triggerPoint.triggerAction();
}
};
EventDispatcher.listen(triggerPoint.triggerEvent(), listener);
listeners.add(listener);
}
}
}
private List<TriggerPointProvider> getTriggerPoints() {
List<TriggerPointProvider> list = new ArrayList<>();
list.add(new CellStyleTriggerPoint());
list.add(new CellValueImageChangeTriggerPoint());
return list;
}
public boolean hasNotifiedTwice() {
return ComponentReuseNotificationInfo.getInstance().getNotifiedNumber() >= 2;
}
private void reCount() {
//重新计次数
Iterator<Map.Entry<JForm, ReuseNotifyInfo>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
iterator.next().getValue().reset();
}
}
private void writeTriggerInfo2xml() {
int number = ComponentReuseNotificationInfo.getInstance().getNotifiedNumber() + 1;
ComponentReuseNotificationInfo.getInstance().setNotifiedNumber(number);
ComponentReuseNotificationInfo.getInstance().setLastNotifyTime(System.currentTimeMillis());
DesignerEnvManager.getEnvManager().saveXMLFile();
//如果已经提示过两次了
if (hasNotifiedTwice()) {
for (Listener listener : listeners) {
EventDispatcher.stopListen(listener);
}
this.map.clear();
}
}
public boolean needTrigger() {
boolean result = true;
if (ComponentReuseNotificationInfo.getInstance().getLastNotifyTime() > 0L) {
result = System.currentTimeMillis() - ComponentReuseNotificationInfo.getInstance().getLastNotifyTime() > ONE_WEEK_TIME;
}
return !hasNotifiedTwice() && result;
}
public void registerJForm(JForm jForm) {
if (!hasNotifiedTwice()) {
this.map.put(jForm, new ReuseNotifyInfo());
}
}
public void removeJForm(JForm jForm) {
if (!hasNotifiedTwice()) {
this.map.remove(jForm);
}
}
public ReuseNotifyInfo getReuseNotifyInfo() {
JTemplate currentJTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (!(currentJTemplate instanceof JForm && hasUseReuseComponent((JForm) currentJTemplate))
&& !ReuseTriggerPointManager.getInstance().needTrigger()) {
return null;
}
return map.get(currentJTemplate);
}
public void reuseNotify(ReuseNotifyInfo notifyInfo) {
if (notifyInfo.matchCondition()) {
ReuseTriggerPointManager.getInstance().reCount();
//弹出提示框
JTemplate currentJTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
DesignerToastMsgUtil.toastPrompt(createReusePrompt((JForm) currentJTemplate));
ReuseTriggerPointManager.getInstance().writeTriggerInfo2xml();
ComponentCollector.getInstance().collectPromptJumpWhenShow();
}
}
private boolean hasUseReuseComponent(JForm jForm) {
Form form = jForm.getTarget();
List<Widget> extendSharableWidgetList = new ArrayList<>();
Form.traversalWidget(form.getContainer(), new WidgetGather() {
@Override
public void dealWith(Widget widget) {
ExtendSharableAttrMark attrMark = ((AbstractBorderStyleWidget) widget).getWidgetAttrMark(ExtendSharableAttrMark.XML_TAG);
if (attrMark != null && StringUtils.isNotEmpty(attrMark.getShareId())) {
extendSharableWidgetList.add(widget);
}
}
@Override
public boolean dealWithAllCards() {
return true;
}
}, AbstractBorderStyleWidget.class);
return extendSharableWidgetList.size() > 0;
}
private JPanel createReusePrompt(JForm jForm) {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.add(new UILabel(Toolkit.i18nText("Fine-Design_Component_Reuse_Try_Prompt")), BorderLayout.WEST);
UILabel reuseLabel = new UILabel(Toolkit.i18nText("Fine-Design_Share_Component"));
reuseLabel.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
jForm.tabChanged(0);
FormWidgetDetailPane.getInstance().enterWidgetLib();
ComponentCollector.getInstance().collectPromptJumpWhenJump();
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
reuseLabel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
reuseLabel.setForeground(Color.BLUE);
reuseLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
jPanel.add(reuseLabel, BorderLayout.CENTER);
return jPanel;
}
}

30
designer-form/src/main/java/com/fr/design/mainframe/adaptve/config/ReuseNotifyInfo.java

@ -1,30 +0,0 @@
package com.fr.design.mainframe.adaptve.config;
/**
* Created by kerry on 5/7/21
*/
public class ReuseNotifyInfo {
private static final int CELL_STYLE_MODIFY_MAX_NUMBER = 3;
private static final int CELL_IMAGE_VALUE_MODIFY_MAX_NUMBER = 1;
private int cellStyleModifiedNumber = 0;
private int cellImageValueNumber = 0;
public void addCellStyleModify() {
cellStyleModifiedNumber++;
}
public void addCellImageValueModify() {
cellImageValueNumber++;
}
public boolean matchCondition() {
return cellStyleModifiedNumber >= CELL_STYLE_MODIFY_MAX_NUMBER
|| cellImageValueNumber >= CELL_IMAGE_VALUE_MODIFY_MAX_NUMBER;
}
public void reset() {
this.cellImageValueNumber = 0;
this.cellStyleModifiedNumber = 0;
}
}

20
designer-form/src/main/java/com/fr/design/mainframe/adaptve/config/TriggerPointProvider.java

@ -1,20 +0,0 @@
package com.fr.design.mainframe.adaptve.config;
import com.fr.event.Event;
/**
* Created by kerry on 4/29/21
*/
public interface TriggerPointProvider {
/**
* 触发后的操作
*/
void triggerAction();
/**
* 触发事件
* @return
*/
Event triggerEvent();
}

28
designer-form/src/main/java/com/fr/design/mainframe/adaptve/config/impl/CellStyleTriggerPoint.java

@ -1,28 +0,0 @@
package com.fr.design.mainframe.adaptve.config.impl;
import com.fr.design.mainframe.DesignOperationEvent;
import com.fr.design.mainframe.ReuseTriggerPointManager;
import com.fr.design.mainframe.adaptve.config.ReuseNotifyInfo;
import com.fr.design.mainframe.adaptve.config.TriggerPointProvider;
import com.fr.event.Event;
/**
* Created by kerry on 5/7/21
*/
public class CellStyleTriggerPoint implements TriggerPointProvider {
@Override
public void triggerAction() {
ReuseNotifyInfo notifyInfo = ReuseTriggerPointManager.getInstance().getReuseNotifyInfo();
if (notifyInfo == null) {
return;
}
notifyInfo.addCellStyleModify();
ReuseTriggerPointManager.getInstance().reuseNotify(notifyInfo);
}
@Override
public Event triggerEvent() {
return DesignOperationEvent.CELL_STYLE_MODIFY;
}
}

27
designer-form/src/main/java/com/fr/design/mainframe/adaptve/config/impl/CellValueImageChangeTriggerPoint.java

@ -1,27 +0,0 @@
package com.fr.design.mainframe.adaptve.config.impl;
import com.fr.design.mainframe.DesignOperationEvent;
import com.fr.design.mainframe.ReuseTriggerPointManager;
import com.fr.design.mainframe.adaptve.config.ReuseNotifyInfo;
import com.fr.design.mainframe.adaptve.config.TriggerPointProvider;
import com.fr.event.Event;
/**
* Created by kerry on 5/7/21
*/
public class CellValueImageChangeTriggerPoint implements TriggerPointProvider {
@Override
public void triggerAction() {
ReuseNotifyInfo notifyInfo = ReuseTriggerPointManager.getInstance().getReuseNotifyInfo();
if (notifyInfo == null) {
return;
}
notifyInfo.addCellImageValueModify();
ReuseTriggerPointManager.getInstance().reuseNotify(notifyInfo);
}
@Override
public Event triggerEvent() {
return DesignOperationEvent.CELL_IMAGE_VALUE_MODIFY;
}
}

3
designer-form/src/main/java/com/fr/design/mainframe/share/AbstractWidgetSelectPane.java

@ -1,7 +1,6 @@
package com.fr.design.mainframe.share;
import com.fr.design.mainframe.share.ui.base.AbstractWidgetPopupPreviewPane;
import com.fr.design.mainframe.share.ui.base.LocalWidgetPopupPreviewPane;
import com.fr.design.mainframe.share.ui.block.PreviewWidgetBlock;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.ComparatorUtils;
@ -44,7 +43,7 @@ public abstract class AbstractWidgetSelectPane<T> extends JPanel {
if (!previewPane.isVisible() && comp.getWidth() != 0 && comp.getHeight() != 0) {
//父容器是GroupPane,要获得的是GroupPane的父容器
Container parentContainer =getParentContainer();
Container parentContainer = getParentContainer();
previewPane.populateBean(comp);
int popupPosY = comp.getLocationOnScreen().y - parentContainer.getLocationOnScreen().y;
if (previewPane.getHeight() + popupPosY > parentContainer.getHeight() + SCROLL_BAR_HEIGHT) {

44
designer-form/src/main/java/com/fr/design/mainframe/share/Bean/FilterTypeInfo.java

@ -0,0 +1,44 @@
package com.fr.design.mainframe.share.Bean;
import java.util.ArrayList;
import java.util.List;
/**
* Created by kerry on 2021/11/1
*/
public class FilterTypeInfo {
private String title;
private String key;
private final List<WidgetFilterTypeInfo> filterTypeInfos = new ArrayList<>();
public FilterTypeInfo(String title, String key){
this.title = title;
this.key = key;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public void addFilterType(WidgetFilterTypeInfo info){
this.filterTypeInfos.add(info);
}
public List<WidgetFilterTypeInfo> getFilterTypeInfos(){
return filterTypeInfos;
}
}

60
designer-form/src/main/java/com/fr/design/mainframe/share/Bean/WidgetFilterInfo.java

@ -0,0 +1,60 @@
package com.fr.design.mainframe.share.Bean;
import java.util.ArrayList;
import java.util.List;
/**
* Created by kerry on 2020-10-23
*/
public class WidgetFilterInfo {
private String name;
private String id;
private String type;
private List<WidgetFilterInfo> childFilterInfo = new ArrayList<>();
public WidgetFilterInfo(String name, String id, String type) {
this.name = name;
this.id = id;
this.type = type;
}
public WidgetFilterInfo() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public void addChildFilterInfo(WidgetFilterInfo filterInfo) {
this.childFilterInfo.add(filterInfo);
}
public List<WidgetFilterInfo> getInnerFilterInfo() {
return childFilterInfo;
}
public boolean hasChildFilter() {
return childFilterInfo.size() > 0;
}
}

93
designer-form/src/main/java/com/fr/design/mainframe/share/Bean/WidgetFilterTypeInfo.java

@ -0,0 +1,93 @@
package com.fr.design.mainframe.share.Bean;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.util.ShareFilterConstants;
import com.fr.general.ComparatorUtils;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
/**
* Created by kerry on 2020-10-21
*/
public class WidgetFilterTypeInfo {
private static final String KEY_SPLIT_CHAR = "@";
private String title;
private String key;
private List<WidgetFilterInfo> filterItems = new ArrayList<>();
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public List<WidgetFilterInfo> getFilterItems() {
return filterItems;
}
public void addFilterItem(WidgetFilterInfo filterInfo) {
this.filterItems.add(filterInfo);
}
public static WidgetFilterTypeInfo parseFromJSONObject(JSONObject jsonObject) {
WidgetFilterTypeInfo typeInfo = new WidgetFilterTypeInfo();
typeInfo.setTitle(jsonObject.getString("title"));
typeInfo.setKey(jsonObject.getString("key"));
JSONArray ja = jsonObject.getJSONArray("items");
if (ComparatorUtils.equals(typeInfo.getKey(), ShareFilterConstants.STYLE_FILTER_KEY)) {
createStyleFilterType(ja, typeInfo);
} else {
for (int i = 0; i < ja.size(); i++) {
JSONObject jo = ja.getJSONObject(i);
WidgetFilterInfo info = new WidgetFilterInfo();
info.setId(jo.getString("id"));
info.setName(jo.optString("name"));
info.setType(parseType(typeInfo.getKey()));
typeInfo.addFilterItem(info);
}
}
return typeInfo;
}
private static void createStyleFilterType(JSONArray ja, WidgetFilterTypeInfo typeInfo) {
WidgetFilterInfo dark = new WidgetFilterInfo();
dark.setName(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Dark_Style"));
WidgetFilterInfo light = new WidgetFilterInfo();
light.setName(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Light_Style"));
typeInfo.addFilterItem(dark);
typeInfo.addFilterItem(light);
for (int i = 0; i < ja.size(); i++) {
JSONObject jo = ja.getJSONObject(i);
WidgetFilterInfo info = new WidgetFilterInfo();
info.setId(jo.getString("id"));
info.setName(jo.optString("name"));
info.setType(parseType(typeInfo.getKey()));
if (ComparatorUtils.equals(jo.getInt("themeColor"), 0)) {
dark.addChildFilterInfo(info);
} else {
light.addChildFilterInfo(info);
}
}
}
private static String parseType(String text) {
return text.split(KEY_SPLIT_CHAR)[1];
}
}

1
designer-form/src/main/java/com/fr/design/mainframe/share/action/InstallComponentAction.java

@ -76,6 +76,7 @@ public class InstallComponentAction extends UpdateAction {
try {
InstallBackInfo info = get();
LocalWidgetRepoPane.getInstance().refreshAllGroupPane();
LocalWidgetRepoPane.getInstance().doFetchAndCheckUpdate();
showMessageDialog(info);
} catch (InterruptedException | ExecutionException e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());

82
designer-form/src/main/java/com/fr/design/mainframe/share/config/ComponentReuseConfigManager.java

@ -0,0 +1,82 @@
package com.fr.design.mainframe.share.config;
import com.fr.design.DesignerCloudURLManager;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
/**
* Created by kerry on 2020-12-14
*/
public class ComponentReuseConfigManager {
private static class Holder {
private static final ComponentReuseConfigManager HOLDER = new ComponentReuseConfigManager();
}
private static final String PROPERTIES_FILE_NAME = "reuse.properties";
private static final String MINI_SHOP_URL = "MINI_SHOP_URL";
private static final String COMPONENT_UPLOAD_URL = "COMPONENT_UPLOAD_URL";
private static final String MARKET_LOGIN_URL = "MARKET_LOGIN_URL";
private static final String UPLOAD_REU_SUPPORT = "UPLOAD_REU_SUPPORT";
public static ComponentReuseConfigManager getInstance() {
return ComponentReuseConfigManager.Holder.HOLDER;
}
private Properties properties;
private ComponentReuseConfigManager() {
}
private File getReusePropertyFile() {
File file = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), PROPERTIES_FILE_NAME));
return file;
}
private String loadAttribute(String key, String defaultValue) {
if (properties == null) {
properties = new Properties();
File file = getReusePropertyFile();
if (!file.exists()) {
return defaultValue;
}
try {
InputStream in = new FileInputStream(file);
properties.load(in);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
String p = properties.getProperty(key);
if (StringUtils.isEmpty(p)) {
p = defaultValue;
}
return p;
}
public String getMiniShopUrl() {
return loadAttribute(MINI_SHOP_URL, DesignerCloudURLManager.getInstance().acquireUrlByKind("af.reuseInfo"));
}
public String getComponentUploadUrl() {
//云中心暂时没有上传网址,这边默认值为空,后续再添加
return loadAttribute(COMPONENT_UPLOAD_URL, StringUtils.EMPTY);
}
public String getMarketLoginUrl() {
return loadAttribute(MARKET_LOGIN_URL, DesignerCloudURLManager.getInstance().acquireUrlByKind("market.login"));
}
public boolean supportUploadReu() {
String uploadReuSupport = loadAttribute(UPLOAD_REU_SUPPORT, "false");
return Boolean.valueOf(uploadReuSupport);
}
}

14
designer-form/src/main/java/com/fr/design/mainframe/share/constants/StyleTheme.java

@ -1,11 +1,11 @@
package com.fr.design.mainframe.share.constants;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.design.mainframe.share.util.ShareFilterConstants;
import com.fr.form.share.bean.StyleThemeBean;
import com.fr.form.share.bean.WidgetFilterInfo;
import com.fr.form.share.bean.WidgetFilterTypeInfo;
import com.fr.form.share.constants.ShareComponentConstants;
import com.fr.form.share.utils.ShareUtils;
import com.fr.design.mainframe.share.Bean.WidgetFilterInfo;
import com.fr.design.mainframe.share.Bean.WidgetFilterTypeInfo;
import com.fr.general.ComparatorUtils;
import java.util.ArrayList;
@ -54,13 +54,13 @@ public enum StyleTheme {
* @return List
*/
public static List<StyleThemeBean> getStyleThemeTypeInfo() {
List<WidgetFilterTypeInfo> widgetFilterTypeInfos = ShareUtils.getWidgetFilterTypeInfos();
List<WidgetFilterTypeInfo> widgetFilterTypeInfos = OnlineShopUtils.getWidgetFilterTypeInfos();
if (widgetFilterTypeInfos.isEmpty()) {
return types();
}
WidgetFilterTypeInfo styleThemeFilterInfo = new WidgetFilterTypeInfo();
for (WidgetFilterTypeInfo typeInfo : widgetFilterTypeInfos) {
if (ComparatorUtils.equals(ShareComponentConstants.STYLE_THEME_KEY, typeInfo.getKey())) {
if (ComparatorUtils.equals(ShareFilterConstants.STYLE_FILTER_KEY, typeInfo.getKey())) {
styleThemeFilterInfo = typeInfo;
break;
}
@ -70,7 +70,7 @@ public enum StyleTheme {
Iterator<WidgetFilterInfo> infoIterator = filterInfoList.iterator();
while (infoIterator.hasNext()) {
WidgetFilterInfo filterInfo = infoIterator.next();
if (!ComparatorUtils.equals(ShareComponentConstants.ALL_STYLE_THEME, filterInfo.getId())) {
if (!ComparatorUtils.equals(ShareFilterConstants.ALL_STYLE_THEME, filterInfo.getId())) {
resultList.add(new StyleThemeBean(filterInfo.getId(), filterInfo.getName()));
}
}

2
designer-form/src/main/java/com/fr/design/mainframe/share/generate/task/ComponentUploader.java

@ -2,7 +2,7 @@ package com.fr.design.mainframe.share.generate.task;
import com.fr.config.MarketConfig;
import com.fr.design.i18n.Toolkit;
import com.fr.form.share.config.ComponentReuseConfigManager;
import com.fr.design.mainframe.share.config.ComponentReuseConfigManager;
import com.fr.design.mainframe.share.generate.ComponentBanner;
import com.fr.io.utils.ResourceIOUtils;
import com.fr.log.FineLoggerFactory;

4
designer-form/src/main/java/com/fr/design/mainframe/share/sort/OnlineWidgetSortType.java

@ -1,9 +1,9 @@
package com.fr.design.mainframe.share.sort;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.bean.SortParameter;
import com.fr.form.share.utils.ShareUtils;
import com.fr.general.ComparatorUtils;
import com.fr.general.GeneralContext;
@ -21,7 +21,7 @@ public enum OnlineWidgetSortType implements SortType<OnlineShareWidget> {
COMPOSITE {
@Override
public void sort(OnlineShareWidget[] widgetProviders) {
Map<String, SortParameter> parameterMap = ShareUtils.getCompositeSortPara();
Map<String, SortParameter> parameterMap = OnlineShopUtils.getCompositeSortPara();
Arrays.sort(widgetProviders, new Comparator<OnlineShareWidget>() {
@Override
public int compare(OnlineShareWidget o1, OnlineShareWidget o2) {

2
designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/DownloadSuitableThemeAction.java

@ -17,6 +17,7 @@ import com.fr.design.login.DesignerLoginSource;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.share.ui.constants.ColorConstants;
import com.fr.design.mainframe.share.ui.online.CarouselStateManger;
import com.fr.design.mainframe.share.util.DownloadUtils;
import com.fr.design.mainframe.theme.dialog.TemplateThemeUsingDialog;
import com.fr.stable.StringUtils;
@ -75,6 +76,7 @@ public class DownloadSuitableThemeAction extends SharedComponentPopupAction {
public void actionPerformed(ActionEvent e) {
currentTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
fetchTheme();
CarouselStateManger.getInstance().start(CarouselStateManger.RIGHT_CLICK);
}
private boolean checkAuthority() {

2
designer-form/src/main/java/com/fr/design/mainframe/share/ui/actions/Jump2DetailAction.java

@ -5,6 +5,7 @@ import com.fr.design.gui.imenu.UIMenuItem;
import com.fr.design.gui.imenu.UIMenuItemUI;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.ui.constants.ColorConstants;
import com.fr.design.mainframe.share.ui.online.CarouselStateManger;
import com.fr.stable.StringUtils;
import javax.swing.Action;
@ -41,6 +42,7 @@ public class Jump2DetailAction extends SharedComponentPopupAction {
} catch (IOException | URISyntaxException ioException) {
ioException.printStackTrace();
}
CarouselStateManger.getInstance().start(CarouselStateManger.RIGHT_CLICK);
}
}
}

26
designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/AbstractOnlineWidgetBlock.java

@ -4,9 +4,10 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.mainframe.share.ui.actions.DownloadSuitableThemeAction;
import com.fr.design.mainframe.share.ui.actions.Jump2DetailAction;
import com.fr.design.mainframe.share.ui.actions.SharedComponentPopupMenu;
import com.fr.design.mainframe.share.ui.online.OnlineResourceManager;
import com.fr.design.mainframe.share.ui.online.OnlineWidgetSelectPane;
import com.fr.design.mainframe.share.ui.online.ResourceLoader;
import com.fr.design.mainframe.share.ui.online.AbstractOnlineWidgetSelectPane;
import com.fr.design.mainframe.share.ui.online.CarouselStateManger;
import com.fr.design.mainframe.share.ui.online.resource.OnlineResourceManager;
import com.fr.design.mainframe.share.ui.online.resource.ResourceLoader;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.constants.ShareComponentConstants;
@ -30,10 +31,11 @@ import java.net.URL;
*/
public abstract class AbstractOnlineWidgetBlock extends PreviewWidgetBlock<OnlineShareWidget> implements ResourceLoader {
private final OnlineWidgetSelectPane parentPane;
protected final AbstractOnlineWidgetSelectPane parentPane;
private UILabel coverLabel;
private Image coverImage;
public AbstractOnlineWidgetBlock(OnlineShareWidget widget, OnlineWidgetSelectPane parentPane) {
public AbstractOnlineWidgetBlock(OnlineShareWidget widget, AbstractOnlineWidgetSelectPane parentPane) {
super(widget);
this.parentPane = parentPane;
}
@ -61,8 +63,12 @@ public abstract class AbstractOnlineWidgetBlock extends PreviewWidgetBlock<Onlin
@Override
@NotNull
protected Image getCoverImage() {
if (coverImage != null) {
return coverImage;
}
OnlineResourceManager.getInstance().addLoader(this);
return getDefaultDisplayImage();
coverImage = getDefaultDisplayImage();
return coverImage;
}
@Override
@ -78,7 +84,6 @@ public abstract class AbstractOnlineWidgetBlock extends PreviewWidgetBlock<Onlin
public void load() {
Image image;
try {
Dimension coverDimension = getCoverDimension();
String previewURI = UriUtils.encodePath(widget.getPicPath(), EncodeConstants.ENCODING_UTF_8) + "?x-oss-process=image/resize,m_fixed," + "w_" + coverDimension.width +
",h_" + coverDimension.height;
@ -96,15 +101,16 @@ public abstract class AbstractOnlineWidgetBlock extends PreviewWidgetBlock<Onlin
public void resetCover(Image image) {
coverLabel.setIcon(new ImageIcon(image));
this.parentPane.validate();
this.parentPane.repaint();
coverImage = image;
coverLabel.setIcon(new ImageIcon(coverImage));
this.repaint();
}
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (e.getButton() == MouseEvent.BUTTON3) {
CarouselStateManger.getInstance().suspend(CarouselStateManger.MOUSE_HOVER);
this.parentPane.hidePreviewPane();
JPopupMenu rightClickPopupMenu = getRightClickPopupMenu();
GUICoreUtils.showPopupMenu(rightClickPopupMenu, this, e.getX(), e.getY());

53
designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/BezierCubic.java

@ -0,0 +1,53 @@
package com.fr.design.mainframe.share.ui.block;
/**
* Created by kerry on 2021/10/29
* 贝塞尔缓动函数实现 https://www.xuanfengge.com/easeing/easeing/
*/
public class BezierCubic {
private final double px1;
private final double px2;
private final double px3;
private final double py1;
private final double py2;
private final double py3;
private final double epsilon;
public BezierCubic(double a, double b, double c, double d) {
this.px3 = 3 * a;
this.px2 = 3 * (c - a) - this.px3;
this.px1 = 1 - this.px3 - this.px2;
this.py3 = 3 * b;
this.py2 = 3 * (d - b) - this.py3;
this.py1 = 1 - this.py3 - this.py2;
this.epsilon = 1e-7; // 目标精度
}
public double getX(double t) {
return ((this.px1 * t + this.px2) * t + this.px3) * t;
}
public double getY(double t) {
return ((this.py1 * t + this.py2) * t + this.py3) * t;
}
public double solve(double x) {
if (x == 0 || x == 1) { // 对 0 和 1 两个特殊 t 不做计算
return this.getY(x);
}
double t = x;
for (int i = 0; i < 8; i++) { // 进行 8 次迭代
double g = this.getX(t) - x;
if (Math.abs(g) < this.epsilon) { // 检测误差到可以接受的范围
return this.getY(t);
}
double d = (3 * this.px1 * t + 2 * this.px2) * t + this.px3; // 对 x 求导
if (Math.abs(d) < 1e-6) { // 如果梯度过低,说明牛顿迭代法无法达到更高精度
break;
}
t = t - g / d;
}
return this.getY(t); // 对得到的近似 t 求 y
}
}

182
designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java

@ -1,24 +1,22 @@
package com.fr.design.mainframe.share.ui.block;
import com.fr.base.FRContext;
import com.fr.base.GraphHelper;
import com.fr.base.iofile.attr.SharableAttrMark;
import com.fr.design.actions.UpdateAction;
import com.fr.design.base.mode.DesignModeContext;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.form.util.XCreatorConstants;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.imenu.UIMenuItem;
import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.WidgetToolBarPane;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.group.ui.GroupMoveDialog;
import com.fr.design.mainframe.share.ui.actions.SharedComponentMenuItemUI;
import com.fr.design.mainframe.share.ui.actions.SharedComponentPopupAction;
import com.fr.design.mainframe.share.ui.actions.SharedComponentPopupMenu;
import com.fr.design.mainframe.share.ui.constants.ColorConstants;
import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoUpdater;
import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane;
import com.fr.design.mainframe.share.ui.local.LocalWidgetSelectPane;
import com.fr.design.mainframe.share.ui.local.WidgetSelectedManager;
@ -26,13 +24,14 @@ import com.fr.design.mainframe.share.util.ShareComponentUtils;
import com.fr.design.mainframe.share.util.ShareUIUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.form.share.DefaultSharableWidget;
import com.fr.form.share.Group;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.constants.ShareComponentConstants;
import com.fr.form.share.Group;
import com.fr.form.share.record.ShareWidgetInfoManager;
import com.fr.form.ui.AbstractBorderStyleWidget;
import com.fr.form.ui.Widget;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.stable.Constants;
import org.jetbrains.annotations.NotNull;
@ -40,18 +39,30 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.UIManager;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.dnd.DnDConstants;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.util.UUID;
/**
@ -68,14 +79,21 @@ public class LocalWidgetBlock extends PreviewWidgetBlock<DefaultSharableWidget>
private boolean isEdit;
private boolean isMarked;
private boolean pressed;
private boolean hover;
private final Icon markedMode = IOUtils.readIcon("/com/fr/base/images/share/marked.png");
private final Icon unMarkedMode = IOUtils.readIcon("/com/fr/base/images/share/unmarked.png");
private final Color COVER_COLOR = Color.decode("#333334");
private final BufferedImage WIDGET_DOWNLOADING_ICON = IOUtils.readImage("/com/fr/base/images/share/downloading.png");
private final BufferedImage WIDGET_UPDATABLE_ICON = IOUtils.readImage("/com/fr/base/images/share/updatable.png");
private final Icon selectedMarker = IOUtils.readIcon("/com/fr/base/images/share/marker_selected.png");
private final Icon unselectedMarker = IOUtils.readIcon("/com/fr/base/images/share/marker_unselected.png");
private final Icon incompatibleMarker = IOUtils.readIcon("/com/fr/base/images/share/marker_incompatible.png");
private final LocalWidgetUpdater updater;
public LocalWidgetBlock(DefaultSharableWidget provider, LocalWidgetSelectPane parentPane) {
super(provider);
this.parentPane = parentPane;
new DragAndDropDragGestureListener(this, DnDConstants.ACTION_COPY_OR_MOVE);
updater = new LocalWidgetUpdater(this);
initUI();
}
@ -107,6 +125,10 @@ public class LocalWidgetBlock extends PreviewWidgetBlock<DefaultSharableWidget>
return this.getWidget();
}
public LocalWidgetUpdater getUpdater() {
return updater;
}
@Override
protected void showPreview(DefaultSharableWidget widget) {
this.parentPane.showPreviewPane(this, widget.getId());
@ -152,6 +174,7 @@ public class LocalWidgetBlock extends PreviewWidgetBlock<DefaultSharableWidget>
pressed = true;
}
@Override
public void mouseReleased(MouseEvent e) {
super.mouseReleased(e);
@ -174,7 +197,7 @@ public class LocalWidgetBlock extends PreviewWidgetBlock<DefaultSharableWidget>
@Override
public void mouseEntered(MouseEvent e) {
super.mouseEntered(e);
hover = true;
}
@Override
@ -182,25 +205,37 @@ public class LocalWidgetBlock extends PreviewWidgetBlock<DefaultSharableWidget>
super.mouseExited(e);
this.mouseHover = false;
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
hover = false;
this.repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
super.mouseDragged(e);
if (DesignModeContext.isAuthorityEditing() || lastPressEvent == null || isEdit) {
return;
}
hidePreview();
ComponentCollector.getInstance().collectPopupJump();
Object source = e.getSource();
if (source instanceof LocalWidgetBlock) {
LocalWidgetBlock no = (LocalWidgetBlock) e.getSource();
if (no == null) {
LocalWidgetBlock widgetBlock = (LocalWidgetBlock) e.getSource();
if (widgetBlock == null) {
return;
}
SharableWidgetProvider widget = widgetBlock.getWidget();
if (widget == null) {
return;
}
if (!widget.isCompatibleWithCurrentEnv()) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Share_Drag_And_Make_Incompatible_Component_Tip"),
Toolkit.i18nText("Fine-Design_Basic_Error"),
JOptionPane.ERROR_MESSAGE,
UIManager.getIcon("OptionPane.errorIcon")
);
return;
}
XCreator xCreator= transformXCreator(no);
XCreator xCreator = transformXCreator(widgetBlock);
if (xCreator == null) {
return;
}
@ -228,20 +263,121 @@ public class LocalWidgetBlock extends PreviewWidgetBlock<DefaultSharableWidget>
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
boolean isUnusable = !getWidget().isCompatibleWithCurrentEnv();
if (isUnusable) {
paintUnusableMask(g2d);
}
//绘制删除标志
if (isEdit) {
Icon icon = isMarked ? markedMode : unMarkedMode;
icon.paintIcon(this, g, MARK_START_X, 0);
paintEditingMarker(g2d);
}
boolean ishHighlighting = ComparatorUtils.equals(this, this.parentPane.getSelectedBlock()) || this.mouseHover;
if (ishHighlighting) {
paintHighlightBorder(g2d);
}
if (ComparatorUtils.equals(this, this.parentPane.getSelectedBlock()) || this.mouseHover) {
g.setColor(XCreatorConstants.FORM_BORDER_COLOR);
Rectangle rectangle = new Rectangle();
rectangle.width = this.getWidth();
rectangle.height = this.getHeight();
GraphHelper.draw(g, rectangle, Constants.LINE_LARGE);
if (getUpdater().isUpdating()) {
paintLoadingIndicator(g2d, getUpdater().getProcessValue());
} else if (LocalWidgetRepoUpdater.getInstance().checkUpdatable(getWidget())) {
paintUpdatableMarker(g2d);
}
}
protected void paintUnusableMask(Graphics2D g2d) {
Color oldColor = g2d.getColor();
Font oldFont = g2d.getFont();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Dimension coverDim = getCoverDimension();
double canvasX = 0;
double canvasY = 0;
double canvasW = coverDim.getWidth();
double canvasH = coverDim.getHeight();
g2d.setColor(new Color(0.0F, 0.0F, 0.0F, 0.4F));
GraphHelper.fillRect(g2d, canvasX, canvasY, canvasW, canvasH);
g2d.setColor(new Color(0.0F, 0.0F, 0.0F, 0.5F));
GraphHelper.fillRect(g2d, canvasX, canvasH - 16, canvasW, 16);
String tipText = Toolkit.i18nText("Fine-Design_Share_Incompatible_Version_Tip");
Font tipFont = FRContext.getDefaultValues().getFRFont().deriveFont(8.0F);
FontRenderContext frc = g2d.getFontRenderContext();
double tipTextWidth = GraphHelper.stringWidth(tipText, tipFont, frc);
LineMetrics metrics = tipFont.getLineMetrics(tipText, frc);
double tipTextHeight = metrics.getHeight();
g2d.setColor(Color.WHITE);
g2d.setFont(tipFont);
GraphHelper.drawString(g2d, tipText, canvasX + (canvasW - tipTextWidth) / 2.0F, canvasY + canvasH - (16 - tipTextHeight) / 2.0F);
int markerX = (int) (canvasX + (canvasW - incompatibleMarker.getIconWidth()) / 2);
int markerY = (int) (canvasY + (canvasH - incompatibleMarker.getIconHeight()) / 2);
incompatibleMarker.paintIcon(this, g2d, markerX, markerY);
g2d.setColor(oldColor);
g2d.setFont(oldFont);
}
protected void paintEditingMarker(Graphics2D g2d) {
Icon icon = isMarked ? selectedMarker : unselectedMarker;
icon.paintIcon(this, g2d, MARK_START_X, 0);
}
protected void paintHighlightBorder(Graphics2D g2d) {
g2d.setColor(XCreatorConstants.FORM_BORDER_COLOR);
Rectangle rectangle = new Rectangle();
rectangle.width = this.getWidth();
rectangle.height = this.getHeight();
GraphHelper.draw(g2d, rectangle, Constants.LINE_LARGE);
}
protected void paintUpdatableMarker(Graphics2D g2d) {
g2d.drawImage(WIDGET_UPDATABLE_ICON, 0, 0, 25, 14, null);
}
protected void paintLoadingIndicator(Graphics2D g2d, double processValue) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
Color oldColor = g2d.getColor();
Stroke oldStroke = g2d.getStroke();
Composite oldComposite = g2d.getComposite();
int x = 0;
int y = 0;
int w = getWidth();
int h = getHeight();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 20 / 100.0F));
g2d.setColor(COVER_COLOR);
g2d.fillRect(x, y, w, h);
g2d.setComposite(oldComposite);
BufferedImage image = WIDGET_DOWNLOADING_ICON;
g2d.drawImage(
image,
(x + w / 2 - 12),
(y + h / 2 - 16),
image.getWidth(),
image.getHeight(),
null,
this
);
g2d.setStroke(XCreatorConstants.STROKE);
g2d.setColor(Color.decode("#419BF9"));
double arcAngle = 36 + 360 * 0.9 * processValue;
g2d.drawArc(x + w / 2 - 12, y + h / 2 - 16, 24, 24, 90, -(int) arcAngle);
g2d.setColor(oldColor);
g2d.setStroke(oldStroke);
}
/**
* 由鼠标释放时调用该方法来触发左键点击事件
*/
@ -263,7 +399,7 @@ public class LocalWidgetBlock extends PreviewWidgetBlock<DefaultSharableWidget>
}
}
private Group getGroup() {
public Group getGroup() {
return parentPane.getGroup();
}

178
designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetUpdater.java

@ -0,0 +1,178 @@
package com.fr.design.mainframe.share.ui.block;
import com.fr.design.DesignerEnvManager;
import com.fr.design.extra.Process;
import com.fr.design.login.DesignerLoginHelper;
import com.fr.design.login.DesignerLoginSource;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane;
import com.fr.design.mainframe.share.util.DownloadUtils;
import com.fr.design.mainframe.share.util.ShareComponentUtils;
import com.fr.design.ui.util.UIUtil;
import com.fr.form.share.DefaultSharableWidget;
import com.fr.form.share.Group;
import com.fr.form.share.GroupManege;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.group.DefaultShareGroupManager;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import javax.swing.SwingWorker;
import java.awt.Component;
import java.awt.Container;
import java.io.File;
import java.io.IOException;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/10/26
*/
public class LocalWidgetUpdater implements Process<Double> {
private double processValue = -1;
public LocalWidgetBlock widgetBlock;
private SwingWorker<Boolean, Void> worker;
public LocalWidgetUpdater(LocalWidgetBlock widgetBlock) {
this.widgetBlock = widgetBlock;
}
private DefaultSharableWidget getWidget() {
return this.widgetBlock.getWidget();
}
private Group getGroup() {
return this.widgetBlock.getGroup();
}
public double getProcessValue() {
return processValue;
}
public boolean isUpdating() {
return 0 <= processValue && processValue <= 1;
}
public void updateWidget(String remoteLatestWidgetId, UpdateListener updateListener) {
if (OnlineWidgetRepoPane.getInstance().isShowPackagePanel()) {
ComponentCollector.getInstance().collectDownloadPktNum();
}
LocalWidgetUpdater.this.process(0.0D);
String userName = DesignerEnvManager.getEnvManager().getDesignerLoginUsername();
if (StringUtils.isEmpty(userName)) {
DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL);
return;
}
final DefaultSharableWidget widget = getWidget();
worker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() {
if (isCancelled()) {
return false;
}
String filePath;
try {
filePath = DownloadUtils.download(remoteLatestWidgetId, widget.getName() + "." + widget.getId(), LocalWidgetUpdater.this);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return false;
}
ShareComponentUtils.checkReadMe();
//安装
File file = new File(filePath);
try {
if (file.exists()) {
getGroup().installUniqueIdModule(file);
}
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} finally {
//删掉下载组件的目录
StableUtils.deleteFile(file);
}
return true;
}
@Override
protected void done() {
LocalWidgetUpdater.this.process(-1.0);
boolean success = false;
try {
success = get();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
if (success) {
resetWidgetOfBlock();
}
if (updateListener != null) {
updateListener.onUpdated(success, getGroup().getGroupName(), widget.getId());
}
}
};
worker.execute();
}
private void resetWidgetOfBlock() {
GroupManege groupManege = DefaultShareGroupManager.getInstance();
Group group = groupManege.getGroup(getGroup().getGroupName());
if (group != null) {
String id = widgetBlock.getWidgetUuid();
if (StringUtils.isNotEmpty(id)) {
SharableWidgetProvider localLatestWidget = group.getElCaseBindInfoById(widgetBlock.getWidgetUuid());
if (localLatestWidget instanceof DefaultSharableWidget) {
widgetBlock.widget = (DefaultSharableWidget) localLatestWidget;
repaintBlockAndOverlay();
}
}
}
}
public void cancelUpdate() {
if (worker != null && !worker.isDone()) {
worker.cancel(true);
worker = null;
}
process(-1.0);
}
@Override
public void process(Double processValue) {
this.processValue = processValue;
repaintBlockAndOverlay();
}
private void repaintBlockAndOverlay() {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
Container absoluteLayoutParent = getAbsoluteLayoutAncestor(widgetBlock);
widgetBlock.repaint();
if (absoluteLayoutParent != null) {
// 位于Block上方的遮罩层也要重绘下,否则Block的内容会绘制到遮罩层上方
absoluteLayoutParent.repaint();
}
}
});
}
public Container getAbsoluteLayoutAncestor(Component component) {
Container container = component.getParent();
while (container != null && container.getLayout() != null) {
container = container.getParent();
}
return container;
}
public interface UpdateListener {
void onUpdated(boolean success, String group, String id);
}
}

118
designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java

@ -1,5 +1,6 @@
package com.fr.design.mainframe.share.ui.block;
import com.fr.base.GraphHelper;
import com.fr.base.iofile.attr.SharableAttrMark;
import com.fr.design.DesignerEnvManager;
import com.fr.design.base.mode.DesignModeContext;
@ -12,11 +13,12 @@ import com.fr.design.login.DesignerLoginHelper;
import com.fr.design.login.DesignerLoginSource;
import com.fr.design.mainframe.WidgetToolBarPane;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.ui.online.AbstractOnlineWidgetSelectPane;
import com.fr.design.mainframe.share.ui.online.CarouselStateManger;
import com.fr.form.share.DefaultSharableWidget;
import com.fr.form.share.group.DefaultShareGroup;
import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane;
import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane;
import com.fr.design.mainframe.share.ui.online.OnlineWidgetSelectPane;
import com.fr.design.mainframe.share.util.DownloadUtils;
import com.fr.design.mainframe.share.util.ShareComponentUtils;
import com.fr.design.mainframe.share.util.ShareUIUtils;
@ -29,11 +31,13 @@ import com.fr.form.share.Group;
import com.fr.form.share.utils.ShareUtils;
import com.fr.form.ui.AbstractBorderStyleWidget;
import com.fr.form.ui.Widget;
import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import javax.swing.Icon;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingConstants;
@ -46,6 +50,7 @@ import java.awt.Color;
import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
@ -53,6 +58,8 @@ import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.dnd.DnDConstants;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
@ -72,8 +79,9 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
private static final BufferedImage WIDGET_INSTALLED_ICON = IOUtils.readImage("/com/fr/base/images/share/widget_installed.png");
private static final BufferedImage WIDGET_DOWNLOAD_ICON = IOUtils.readImage("/com/fr/base/images/share/download.png");
private static final BufferedImage WIDGET_DOWNLOADING_ICON = IOUtils.readImage("/com/fr/base/images/share/downloading.png");
private static final Icon incompatibleMarker = IOUtils.readIcon("/com/fr/base/images/share/marker_incompatible.png");
public OnlineWidgetBlock(OnlineShareWidget widget, OnlineWidgetSelectPane parentPane) {
public OnlineWidgetBlock(OnlineShareWidget widget, AbstractOnlineWidgetSelectPane parentPane) {
super(widget, parentPane);
this.add(createSouthPane(widget), BorderLayout.SOUTH);
new DragAndDropDragGestureListener(this, DnDConstants.ACTION_COPY_OR_MOVE);
@ -116,6 +124,9 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
@Override
public void mouseEntered(MouseEvent e) {
if (!getWidget().isCompatibleWithCurrentEnv()) {
return;
}
super.mouseEntered(e);
this.isMouseEnter = true;
this.repaint();
@ -123,6 +134,9 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
@Override
public void mouseExited(MouseEvent e) {
if (!getWidget().isCompatibleWithCurrentEnv()) {
return;
}
super.mouseExited(e);
this.isMouseEnter = false;
this.repaint();
@ -130,12 +144,18 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
@Override
public void mousePressed(MouseEvent e) {
if (!getWidget().isCompatibleWithCurrentEnv()) {
return;
}
super.mousePressed(e);
this.lastPressEvent = e;
}
@Override
public void mouseClicked(MouseEvent e) {
if (!getWidget().isCompatibleWithCurrentEnv()) {
return;
}
super.mouseClicked(e);
boolean isLeftClickDownloadIcon = e.getButton() != MouseEvent.BUTTON3 && getDownloadIconRec().contains(e.getX(), e.getY());
if (!isRightClickPopupMenuVisible() && isLeftClickDownloadIcon && !checkWidgetInstalled()) {
@ -145,13 +165,16 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
@Override
public void mouseDragged(MouseEvent e) {
if (!getWidget().isCompatibleWithCurrentEnv()) {
return;
}
super.mouseDragged(e);
if (DesignModeContext.isAuthorityEditing() || !checkWidgetInstalled()) {
return;
}
if (lastPressEvent == null) {
return;
}
ComponentCollector.getInstance().collectPopupJump();
Object source = e.getSource();
Widget creatorSource;
String shareId;
@ -183,7 +206,23 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
}
}
@Override
public void mouseMoved(MouseEvent e) {
if (!getWidget().isCompatibleWithCurrentEnv()) {
return;
}
super.mouseMoved(e);
if (checkWidgetInstalled()) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
} else if (getDownloadIconRec().contains(e.getX(), e.getY())) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
} else {
this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
private void downLoadWidget() {
CarouselStateManger.getInstance().suspend(CarouselStateManger.DOWNLOAD_COMPONENT);
if (OnlineWidgetRepoPane.getInstance().isShowPackagePanel()) {
ComponentCollector.getInstance().collectDownloadPktNum();
}
@ -212,7 +251,7 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
//安装
File file = new File(filePath);
try {
if (file.exists() && getDefaultGroup().installModule(file)) {
if (file.exists() && getDefaultGroup().installUniqueIdModule(file)) {
ShareUtils.recordInstallTime(file.getName(), System.currentTimeMillis());
ComponentCollector.getInstance().collectCmpDownLoad(widget.getUuid());
}
@ -233,6 +272,7 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
try {
if (get()) {
LocalWidgetRepoPane.getInstance().refreshShowPanel();
CarouselStateManger.getInstance().start(CarouselStateManger.DOWNLOAD_COMPONENT);
} else {
ShareUIUtils.showErrorMessageDialog(Toolkit.i18nText("Fine-Design_Share_Download_Failed"));
}
@ -244,21 +284,6 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
}
}
}.execute();
}
@Override
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
if (checkWidgetInstalled()) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
} else if (getDownloadIconRec().contains(e.getX(), e.getY())) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
} else {
this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
private Rectangle getDownloadIconRec() {
@ -269,6 +294,11 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
return ShareUtils.getElCaseBindInfoById(widget.getUuid()) != null;
}
protected boolean checkWidget() {
return checkWidgetInstalled();
}
private Group getDefaultGroup() {
return DefaultShareGroupManager.getInstance().getGroup(DefaultShareGroup.GROUP_NAME);
}
@ -322,6 +352,56 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock {
g2d.setColor(Color.WHITE);
g2d.setStroke(oldStroke);
}
boolean isUnusable = !getWidget().isCompatibleWithCurrentEnv();
if (isUnusable) {
paintUnusableMask((Graphics2D) g);
}
if (this.parentPane != null) {
this.parentPane.refreshShowPaneUI();
}
}
protected void paintUnusableMask(Graphics2D g2d) {
Color oldColor = g2d.getColor();
Font oldFont = g2d.getFont();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Dimension coverDim = getCoverDimension();
double canvasX = 0;
double canvasY = 0;
double canvasW = coverDim.getWidth();
double canvasH = coverDim.getHeight();
g2d.setColor(new Color(0.0F, 0.0F, 0.0F, 0.4F));
GraphHelper.fillRect(g2d, canvasX, canvasY, canvasW, canvasH - 16);
g2d.setColor(new Color(0.0F, 0.0F, 0.0F, 0.5F));
GraphHelper.fillRect(g2d, canvasX, canvasH - 16, canvasW, 16);
String tipText = Toolkit.i18nText("Fine-Design_Share_Incompatible_Version_Tip");
Font tipFont = FRFont.getInstance().deriveFont(8F);
FontRenderContext frc = g2d.getFontRenderContext();
double tipTextWidth = GraphHelper.stringWidth(tipText, tipFont, frc);
Dimension2D dim = GraphHelper.stringDimensionWithRotation(tipText, tipFont, 0, frc);
double tipTextHeight = dim.getHeight();
g2d.setColor(Color.WHITE);
g2d.setFont(tipFont);
GraphHelper.drawString(g2d, tipText, canvasX + (canvasW - tipTextWidth) / 2.0F, canvasY + canvasH - (16 - tipTextHeight) / 2.0F);
int markerX = (int) (canvasX + (canvasW - incompatibleMarker.getIconWidth()) / 2);
int markerY = (int) (canvasY + (canvasH - incompatibleMarker.getIconHeight()) / 2);
incompatibleMarker.paintIcon(this, g2d, markerX, markerY);
g2d.setColor(oldColor);
g2d.setFont(oldFont);
}
@Override
public void repaint() {
super.repaint();
}
class WidgetDownloadProcess implements com.fr.design.extra.Process<Double> {

134
designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/PreviewWidgetBlock.java

@ -1,24 +1,41 @@
package com.fr.design.mainframe.share.ui.block;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.DesignerEnvManager;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.EastRegionContainerPane;
import com.fr.design.mainframe.FormWidgetDetailPane;
import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo;
import com.fr.design.mainframe.share.ComponentShareUtil;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.ui.online.CarouselStateManger;
import com.fr.design.mainframe.share.ui.online.embed.AnimatePopupDialog;
import com.fr.design.mainframe.share.ui.online.embed.FirstDragAnimateStateManager;
import com.fr.form.share.constants.ShareComponentConstants;
import com.fr.module.ModuleContext;
import org.jetbrains.annotations.NotNull;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.Serializable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by kerry on 2020-10-21
@ -27,6 +44,17 @@ public abstract class PreviewWidgetBlock<T> extends JPanel implements MouseListe
protected T widget;
private boolean showing = false;
private final JPopupMenu rightClickPopupMenu;
private long lastStallTime = 0;
protected boolean hover;
private static final int ANIMATE_START_TIME = 1000;
private static final int ANIMATE_TIME = 2000;
private AnimatePopupDialog animatePopupDialog;
private AWTEventListener awtEventListener;
private static final double[] ANIMATE_CONTROL_VALUE = {0.23, 1, 0.32, 1};
private static final String FIRST_DRAG_ANIMATE = "first_drag_animate";
private final ScheduledExecutorService firstDragCheckService = ModuleContext.getExecutor().newSingleThreadScheduledExecutor(new NamedThreadFactory("first_drag_check"));
public PreviewWidgetBlock(T widget) {
this.widget = widget;
@ -76,12 +104,14 @@ public abstract class PreviewWidgetBlock<T> extends JPanel implements MouseListe
private void showPreviewPane() {
synchronized (this) {
CarouselStateManger.getInstance().suspend(CarouselStateManger.MOUSE_HOVER);
if (!showing) {
showPreview(widget);
showing = true;
}
}
}
protected abstract String getWidgetUuid();
protected abstract void showPreview(T widget);
@ -99,6 +129,9 @@ public abstract class PreviewWidgetBlock<T> extends JPanel implements MouseListe
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e) && FirstDragAnimateStateManager.getInstance().animating()) {
FirstDragAnimateStateManager.getInstance().stopAnimate();
}
this.hidePreviewPane();
}
@ -114,24 +147,97 @@ public abstract class PreviewWidgetBlock<T> extends JPanel implements MouseListe
@Override
public void mouseEntered(MouseEvent e) {
hover = true;
if (ComponentShareUtil.needShowFirstDragAnimate() && !FormWidgetDetailPane.getInstance().hasTouched() && checkWidget()) {
schedule(ANIMATE_START_TIME);
awtEventListener = event -> {
if (!this.isShowing()) {
return;
}
if (event instanceof MouseEvent) {
Point selectPanePoint = this.getLocationOnScreen();
Dimension selectPaneDimension = this.getSize();
Rectangle selectPaneRec = new Rectangle(selectPanePoint.x, selectPanePoint.y, selectPaneDimension.width, selectPaneDimension.height);
if (FirstDragAnimateStateManager.getInstance().animating() &&
!selectPaneRec.contains(((MouseEvent) event).getLocationOnScreen())) {
FirstDragAnimateStateManager.getInstance().stopAnimate();
}
}
};
java.awt.Toolkit.getDefaultToolkit().addAWTEventListener(awtEventListener, AWTEvent.MOUSE_EVENT_MASK);
}
}
protected boolean checkWidget() {
return true;
}
private void animate(ScheduledExecutorService service) {
CarouselStateManger.getInstance().suspend(CarouselStateManger.FIRST_DRAG_ANIMATE);
AtomicInteger atomicInteger = new AtomicInteger(0);
BezierCubic cubic = new BezierCubic(ANIMATE_CONTROL_VALUE[0], ANIMATE_CONTROL_VALUE[1], ANIMATE_CONTROL_VALUE[2], ANIMATE_CONTROL_VALUE[3]);
Point startPoint = new Point(this.getLocationOnScreen().x - 5, this.getLocationOnScreen().y - 5);
Point endPoint = calculateEndPoint();
ComponentReuseNotificationInfo.getInstance().setFirstDrag(false);
DesignerEnvManager.getEnvManager().saveXMLFile();
FirstDragAnimateStateManager.getInstance().startAnimate();
service.scheduleAtFixedRate(() -> {
if (FirstDragAnimateStateManager.getInstance().isStop()) {
service.shutdown();
if (animatePopupDialog != null) {
animatePopupDialog.setVisible(false);
}
ComponentReuseNotificationInfo.getInstance().setFirstDragEndTime(System.currentTimeMillis());
DesignerEnvManager.getEnvManager().saveXMLFile();
java.awt.Toolkit.getDefaultToolkit().removeAWTEventListener(awtEventListener);
CarouselStateManger.getInstance().start(CarouselStateManger.FIRST_DRAG_ANIMATE);
return;
}
double progress = calXProgress(atomicInteger.getAndIncrement() * 20, cubic);
if (progress >= 1) {
atomicInteger.set(0);
}
double x = startPoint.x * 1D + (endPoint.x - startPoint.x) * progress;
double y = ((endPoint.y - startPoint.y) * 1D / (endPoint.x - startPoint.x)) * ((int) x - startPoint.x) + startPoint.y;
animatePopupDialog.setLocation((int) x, (int) y);
}, 0, 20, TimeUnit.MILLISECONDS);
}
private Point calculateEndPoint() {
Point basePoint = EastRegionContainerPane.getInstance().getLocationOnScreen();
Dimension dimension = EastRegionContainerPane.getInstance().getSize();
return new Point(basePoint.x + 20 - this.getWidth() / 2, basePoint.y + dimension.height / 3 - this.getHeight() / 2);
}
public double calXProgress(int time, BezierCubic cubic) {
return cubic.solve(time * 1D / ANIMATE_TIME);
}
@Override
public void mouseExited(MouseEvent e) {
hover = false;
this.hidePreviewPane();
if(!FirstDragAnimateStateManager.getInstance().animating()){
CarouselStateManger.getInstance().start(CarouselStateManger.MOUSE_HOVER);
}
}
@Override
public void mouseDragged(MouseEvent e) {
ComponentCollector.getInstance().collectDynamicEffectReact();
if (FirstDragAnimateStateManager.getInstance().animating()) {
FirstDragAnimateStateManager.getInstance().stopAnimate();
}
}
@Override
public void mouseMoved(MouseEvent e) {
lastStallTime = System.currentTimeMillis();
Dimension dimension = getCoverDimension();
Rectangle containerRec = new Rectangle(0, 0, dimension.width, dimension.height);
if (!isRightClickPopupMenuVisible()) {
if (!isRightClickPopupMenuVisible() && !FirstDragAnimateStateManager.getInstance().animating()) {
if (containerRec.contains(e.getX(), e.getY())) {
this.showPreviewPane();
} else {
@ -140,6 +246,26 @@ public abstract class PreviewWidgetBlock<T> extends JPanel implements MouseListe
}
}
private void schedule(long timeOut) {
firstDragCheckService.schedule(new Runnable() {
@Override
public void run() {
if (!hover) {
return;
}
long interval = System.currentTimeMillis() - lastStallTime;
if (interval < timeOut) {
schedule(ANIMATE_START_TIME - interval);
return;
}
animatePopupDialog = new AnimatePopupDialog(getCoverImage(), new Point(PreviewWidgetBlock.this.getLocationOnScreen().x, PreviewWidgetBlock.this.getLocationOnScreen().y));
ScheduledExecutorService service = ModuleContext.getExecutor().newSingleThreadScheduledExecutor(new NamedThreadFactory(FIRST_DRAG_ANIMATE));
animate(service);
}
}, timeOut, TimeUnit.MILLISECONDS);
}
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
@ -152,4 +278,6 @@ public abstract class PreviewWidgetBlock<T> extends JPanel implements MouseListe
this.removeMouseListener(this);
this.removeMouseMotionListener(this);
}
}

30
designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/FramePane.java

@ -0,0 +1,30 @@
package com.fr.design.mainframe.share.ui.local;
import javax.swing.JPanel;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager2;
import java.io.Serializable;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/11/2
*/
public class FramePane extends JPanel {
public FramePane() {
setLayout(null);
}
@Override
public void doLayout() {
super.doLayout();
for (int i = 0; i < getComponentCount(); i++) {
getComponent(i).setSize(getSize());
getComponent(i).setPreferredSize(getSize());
getComponent(i).setBounds(0, 0, getWidth(), getHeight());
}
}
}

34
designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/GroupPane.java

@ -15,9 +15,9 @@ import com.fr.design.mainframe.share.ui.base.PopupMenuItem;
import com.fr.design.mainframe.share.ui.widgetfilter.LocalWidgetFilter;
import com.fr.design.mainframe.share.util.ShareUIUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.form.share.Group;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.group.DefaultShareGroupManager;
import com.fr.form.share.Group;
import com.fr.form.share.record.ShareWidgetInfoManager;
import com.fr.general.IOUtils;
import com.fr.stable.StringUtils;
@ -53,10 +53,6 @@ public class GroupPane extends JPanel {
private SharableWidgetProvider[] elCaseBindInfoList;
private SortType sortType = WidgetSortType.INSTALL_TIME;
private GroupPane(Group group) {
this(group, DEFAULT_HEIGHT, group.isDefaultExpend());
}
private GroupPane(Group group, boolean expendStatus) {
this(group, DEFAULT_HEIGHT, expendStatus);
}
@ -90,7 +86,9 @@ public class GroupPane extends JPanel {
//按照筛选条件进行过滤
elCaseBindInfoList = LocalWidgetFilter.getInstance().filter(elCaseBindInfoList);
boolean needExpendGroup = expendStatus || (isFiltering() && elCaseBindInfoList.length > 0);
boolean needExpendGroup = expendStatus
|| (isFiltering() && elCaseBindInfoList.length > 0)
|| hasUpdatableWidget();
if (elCaseBindInfoList.length == 0 && isFiltering()) {
this.setVisible(false);
}
@ -107,6 +105,20 @@ public class GroupPane extends JPanel {
expendGroup(needExpendGroup);
}
private boolean hasUpdatableWidget() {
for (SharableWidgetProvider provider: elCaseBindInfoList) {
boolean updatable = LocalWidgetRepoUpdater.getInstance().checkUpdatable(provider);
if (updatable) {
return true;
}
}
return false;
}
public LocalWidgetSelectPane getWidgetListPane() {
return contentPanel;
}
public void reCreateShowPane(SharableWidgetProvider[] widgets) {
if (contentPanel != null) {
contentPanel.hidePreviewPane();
@ -371,10 +383,16 @@ public class GroupPane extends JPanel {
DEFAULT {
@Override
public GroupPane creteGroupPane(Group group) {
return new GroupPane(group);
return new GroupPane(group, group.isDefaultExpend());
}
},
EXPANDED {
@Override
public GroupPane creteGroupPane(Group group) {
return new GroupPane(group, true);
}
},
CLOSURE {
COLLAPSED {
@Override
public GroupPane creteGroupPane(Group group) {
return new GroupPane(group, false);

299
designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoPane.java

@ -1,17 +1,27 @@
package com.fr.design.mainframe.share.ui.local;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.FormWidgetDetailPane;
import com.fr.design.mainframe.share.sort.WidgetSortType;
import com.fr.design.mainframe.share.ui.base.DownloadProgressPane;
import com.fr.design.mainframe.share.ui.base.MouseClickListener;
import com.fr.design.mainframe.share.ui.block.LocalWidgetBlock;
import com.fr.design.mainframe.share.ui.block.LocalWidgetUpdater;
import com.fr.design.mainframe.share.ui.widgetfilter.LocalWidgetFilter;
import com.fr.design.mainframe.share.util.InstallComponentHelper;
import com.fr.design.mainframe.share.util.ShareComponentUtils;
import com.fr.form.share.group.DefaultShareGroupManager;
import com.fr.design.mainframe.theme.edit.ui.LabelUtils;
import com.fr.form.share.Group;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.group.DefaultShareGroupManager;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
@ -21,7 +31,17 @@ import javax.swing.JScrollPane;
import javax.swing.SwingWorker;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
@ -30,10 +50,21 @@ import java.util.concurrent.atomic.AtomicBoolean;
* Created by kerry on 2020-10-16
*/
public class LocalWidgetRepoPane extends BasicPane {
private static class HOLDER {
private static final LocalWidgetRepoPane singleton = new LocalWidgetRepoPane();
}
public static LocalWidgetRepoPane getInstance() {
return HOLDER.singleton;
}
private int updateGuard = 0;
private Component updateTipPane;
private DownloadProgressPane updateProgressPane;
private JPanel centerPane;
private UIScrollPane groupsScrollPane;
private JPanel groupsPane;
private ToolbarPane toolbarPane;
private ManagePane managePane;
private final Map<String, GroupPane> groupPaneMap = new HashMap<>();
@ -43,16 +74,10 @@ public class LocalWidgetRepoPane extends BasicPane {
private String keyWord4Searching = StringUtils.EMPTY;
private LocalWidgetRepoPane() {
setLayout(FRGUIPaneFactory.createBorderLayout());
initPane();
}
public static LocalWidgetRepoPane getInstance() {
return HOLDER.singleton;
}
private static class HOLDER {
private static final LocalWidgetRepoPane singleton = new LocalWidgetRepoPane();
initializePane(this);
//新用户预装组件
InstallComponentHelper.installPreComponent();
doRefresh();
}
public boolean isEditable() {
@ -63,16 +88,119 @@ public class LocalWidgetRepoPane extends BasicPane {
return keyWord4Searching;
}
/**
* 初始化
*/
public void initPane() {
//新用户预装组件
InstallComponentHelper.installPreComponent();
private void initializePane(Container container) {
container.setLayout(new BorderLayout());
updateTipPane = createUpdateTipPane();
updateTipPane.setVisible(false);
container.add(updateTipPane, BorderLayout.NORTH);
updateProgressPane = createUpdateMaskPane();
FramePane framePane = new FramePane();
framePane.add(updateProgressPane);
framePane.add(createControlledMainPane(), BorderLayout.CENTER);
add(framePane, BorderLayout.CENTER);
}
private Component createUpdateTipPane() {
JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane();
container.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10, 10, 5, 10),
BorderFactory.createLineBorder(new Color(0xD9DADD), 1, true)
));
final JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane();
content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
content.setBackground(Color.WHITE);
content.setOpaque(true);
content.add(LabelUtils.createAutoWrapLabel(Toolkit.i18nText("Fine-Design_Share_Upgrade_Tip"), new Color(0x333334)), BorderLayout.CENTER);
JPanel actionsPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
actionsPane.setOpaque(false);
actionsPane.setBackground(null);
UIButton cancelUpgradeButton = new UIButton(Toolkit.i18nText("Fine-Design_Share_Upgrade_Cancel"));
cancelUpgradeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doQuitUpdateComponents();
}
});
UIButton startUpgradeButton = new UIButton(Toolkit.i18nText("Fine-Design_Share_Upgrade_All"));
startUpgradeButton.setSelected(true);
startUpgradeButton.setForeground(Color.WHITE);
startUpgradeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
doUpdateComponents();
}
});
actionsPane.add(cancelUpgradeButton);
actionsPane.add(startUpgradeButton);
content.add(actionsPane, BorderLayout.SOUTH);
container.add(content, BorderLayout.NORTH);
DefaultShareGroupManager.getInstance().setChangeListener(new DefaultShareGroupManager.ComponentChangeListener() {
@Override
public void onComponentRemoved(String group, String id) {
List<SharableWidgetProvider> updatableWidgetProviders = LocalWidgetRepoUpdater.getInstance().getUpdatableWidgetProviders();
if (updatableWidgetProviders.size() == 0 && updateTipPane != null) {
updateTipPane.setVisible(false);
}
}
});
return container;
}
private DownloadProgressPane createUpdateMaskPane() {
DownloadProgressPane progressPane = new DownloadProgressPane(new MouseClickListener() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
int returnVal = FineJOptionPane.showConfirmDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Share_Download_Cancel_Confirm"),
Toolkit.i18nText("Fine-Design_Share_Group_Confirm"),
FineJOptionPane.OK_CANCEL_OPTION
);
if (returnVal == FineJOptionPane.OK_OPTION) {
List<LocalWidgetBlock> blockList = getUpdatableBlocks();
for (LocalWidgetBlock block: blockList) {
block.getUpdater().cancelUpdate();
}
updateGuard = 0;
updateProgressPane.setVisible(false);
LocalWidgetRepoUpdater updater = LocalWidgetRepoUpdater.getInstance();
updater.clearUpdate();
refreshAllGroupPane();
}
}
});
// 屏蔽被遮罩内容的鼠标处理,避免鼠标透穿
progressPane.addMouseListener(new MouseAdapter() {});
progressPane.updateProgress(0);
progressPane.setOpaque(true);
progressPane.setBackground(new Color(0.25F, 0.25F, 0.25F, 0.65F));
// 更新遮罩层初始不可见
progressPane.setVisible(false);
return progressPane;
}
public Component createControlledMainPane() {
Container container = FRGUIPaneFactory.createBorderLayout_S_Pane();
JPanel componentLibPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
componentLibPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 15, 0));
ToolbarPane toolbarPane = new ToolbarPane();
toolbarPane = new ToolbarPane();
toolbarPane.addFilterPopupStateChangeListener(state -> setWidgetPaneScrollEnable(!state));
managePane = new ManagePane();
JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
@ -85,21 +213,27 @@ public class LocalWidgetRepoPane extends BasicPane {
centerPane.add(LocalPaneStatus.EMPTY.getPanel(), LocalPaneStatus.EMPTY.name());
centerPane.add(LocalPaneStatus.LOADING.getPanel(), LocalPaneStatus.LOADING.name());
centerPane.add(LocalPaneStatus.INSTALLING.getPanel(), LocalPaneStatus.INSTALLING.name());
cardLayout.show(centerPane, LocalPaneStatus.LOADING.name());
componentLibPanel.add(northPane, BorderLayout.NORTH);
componentLibPanel.add(centerPane, BorderLayout.CENTER);
add(componentLibPanel, BorderLayout.CENTER);
cardLayout.show(centerPane, LocalPaneStatus.LOADING.name());
toolbarPane.addFilterPopupStateChangeListener(state -> setWidgetPaneScrollEnable(!state));
doRefresh();
container.add(componentLibPanel, BorderLayout.CENTER);
return container;
}
public void refreshAllGroupPane() {
if (isUpdating()) {
return;
}
refreshAllGroupPane(GroupPane.GroupCreateStrategy.DEFAULT);
}
public void refreshAllGroupPane(GroupPane.GroupCreateStrategy createStrategy) {
if (isUpdating()) {
return;
}
editable = false;
groupPaneMap.clear();
if (groupsScrollPane != null) {
@ -122,21 +256,33 @@ public class LocalWidgetRepoPane extends BasicPane {
}
public void refreshPane() {
if (isUpdating()) {
return;
}
managePane.switchPanel(false);
switchPane(LocalPaneStatus.LOADING);
doRefresh();
}
public void switch2InstallingPane() {
if (isUpdating()) {
return;
}
switchPane(LocalPaneStatus.INSTALLING);
}
public void refreshShowPanel(boolean isEdit) {
if (isUpdating()) {
return;
}
this.editable = isEdit;
refreshShowPanel();
}
public void refreshShowPanel() {
if (isUpdating()) {
return;
}
for (GroupPane groupPane : groupPaneMap.values()) {
groupPane.refreshShowPanel();
}
@ -144,6 +290,9 @@ public class LocalWidgetRepoPane extends BasicPane {
}
public void refreshShowPanel(Group group) {
if (isUpdating()) {
return;
}
if (groupPaneMap.containsKey(group.getGroupName())) {
groupPaneMap.get(group.getGroupName()).refreshShowPanel();
}
@ -159,12 +308,18 @@ public class LocalWidgetRepoPane extends BasicPane {
}
public void removeGroup(String groupName) {
if (isUpdating()) {
return;
}
JPanel jPanel = groupPaneMap.remove(groupName);
groupsPane.remove(jPanel);
switchPane();
}
public void addGroup(Group group) {
if (isUpdating()) {
return;
}
GroupPane groupPane = GroupPane.GroupCreateStrategy.DEFAULT.creteGroupPane(group);
groupPaneMap.put(group.getGroupName(), groupPane);
groupsPane.add(groupPane);
@ -208,6 +363,7 @@ public class LocalWidgetRepoPane extends BasicPane {
try {
if (get()) {
refreshAllGroupPane();
doFetchAndCheckUpdate();
}
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
@ -222,10 +378,81 @@ public class LocalWidgetRepoPane extends BasicPane {
}.execute();
}
public void doFetchAndCheckUpdate() {
LocalWidgetRepoUpdater.getInstance().fetchComponentUpdates(new LocalWidgetRepoUpdater.FetchComponentUpdatesListener() {
@Override
public void onFetchedBefore() {
updateTipPane.setVisible(false);
}
@Override
public void onFetchedAfter(boolean success, Map<String, OnlineShareWidget> remoteLatestWidgets) {
if (success) {
List<SharableWidgetProvider> updatableWidgetProviders = LocalWidgetRepoUpdater.getInstance().getUpdatableWidgetProviders();
updateTipPane.setVisible(updatableWidgetProviders.size() > 0);
if (updatableWidgetProviders.size() > 0) {
refreshAllGroupPane(GroupPane.GroupCreateStrategy.DEFAULT);
}
}
}
});
}
public void doQuitUpdateComponents() {
LocalWidgetRepoUpdater updater = LocalWidgetRepoUpdater.getInstance();
updater.clearUpdate();
if (updateTipPane != null) {
updateTipPane.setVisible(false);
}
}
public void doUpdateComponents() {
if (updateGuard > 0) {
return;
}
toolbarPane.reset();
managePane.switchPanel(false);
switchPane(LocalPaneStatus.NORMAL);
refreshAllGroupPane(GroupPane.GroupCreateStrategy.DEFAULT);
List<LocalWidgetBlock> blockList = getUpdatableBlocks();
if (blockList.size() == 0) {
return;
}
updateGuard = blockList.size();
updateTipPane.setVisible(false);
updateProgressPane.updateProgress(0.0F);
updateProgressPane.setVisible(true);
LocalWidgetRepoUpdater updater = LocalWidgetRepoUpdater.getInstance();
for (LocalWidgetBlock block: blockList) {
OnlineShareWidget remoteLatestWidget = updater.findLatestRemoteWidget(block.getWidget());
block.getUpdater().updateWidget(remoteLatestWidget.getId(), new LocalWidgetUpdater.UpdateListener() {
@Override
public void onUpdated(boolean success, String group, String id) {
updateGuard -= 1;
updateProgressPane.updateProgress(1.0F - 1.0F * updateGuard / blockList.size());
if (updateGuard == 0) {
updater.clearUpdate();
updateProgressPane.setVisible(false);
refreshAllGroupPane();
}
}
});
}
}
/**
* 切换为要显示的面板
*/
private void switchPane() {
if (isUpdating()) {
return;
}
switchPane(getStatus());
}
@ -261,6 +488,34 @@ public class LocalWidgetRepoPane extends BasicPane {
return groups.length == 1 && groups[0].getAllBindInfoList().length == 0;
}
private boolean isUpdating() {
return updateGuard > 0;
}
private List<LocalWidgetBlock> getUpdatableBlocks() {
List<LocalWidgetBlock> blockList = new ArrayList<>();
LocalWidgetRepoUpdater updater = LocalWidgetRepoUpdater.getInstance();
for (GroupPane groupPane : groupPaneMap.values()) {
LocalWidgetSelectPane widgetListPane = groupPane.getWidgetListPane();
int count = widgetListPane.getComponentCount();
for (int i = 0; i < count; i++) {
Component component = widgetListPane.getComponent(i);
if (component instanceof LocalWidgetBlock) {
LocalWidgetBlock widgetBlock = (LocalWidgetBlock) component;
SharableWidgetProvider localProvider = widgetBlock.getWidget();
OnlineShareWidget remoteLatestWidget = updater.findLatestRemoteWidget(localProvider);
if (remoteLatestWidget != null) {
blockList.add(widgetBlock);
}
}
}
}
return blockList;
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Share_Local_Widget");

144
designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoUpdater.java

@ -0,0 +1,144 @@
package com.fr.design.mainframe.share.ui.local;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.form.share.Group;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.group.DefaultShareGroupManager;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.basic.version.Version;
import com.fr.stable.ProductConstants;
import com.fr.stable.StringUtils;
import javax.swing.SwingWorker;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/11/3
*/
public class LocalWidgetRepoUpdater {
private LocalWidgetRepoUpdater() {}
private static class Holder {
public static LocalWidgetRepoUpdater INSTANCE = new LocalWidgetRepoUpdater();
}
public static LocalWidgetRepoUpdater getInstance() {
return LocalWidgetRepoUpdater.Holder.INSTANCE;
}
private final Map<String, OnlineShareWidget> remoteLatestWidgetsBackup = new HashMap<>();
private final AtomicBoolean isCheckingComponentUpdates = new AtomicBoolean(false);
private SwingWorker<Boolean, Void> checkingComponentsUpdateWorker;
private Set<String> getLocalWidgetIds() {
Set<String> widgetIds = new HashSet<>();
Group[] groups = DefaultShareGroupManager.getInstance().getAllGroup();
for (Group group: groups) {
SharableWidgetProvider[] widgetProviders = group.getAllBindInfoList();
for (SharableWidgetProvider provider: widgetProviders) {
widgetIds.add(provider.getId());
}
}
return widgetIds;
}
public void clearUpdate() {
remoteLatestWidgetsBackup.clear();
}
public boolean checkUpdatable(SharableWidgetProvider provider) {
return findLatestRemoteWidget(provider) != null;
}
public OnlineShareWidget findLatestRemoteWidget(SharableWidgetProvider provider) {
OnlineShareWidget remoteLatestWidget = remoteLatestWidgetsBackup.get(provider.getId());
if (remoteLatestWidget != null && StringUtils.isNotEmpty(remoteLatestWidget.getVersion())) {
Version remoteLatestVersion = Version.create(remoteLatestWidget.getVersion());
Version localVersion = Version.create(provider.getVersion());
boolean isUpdatable = remoteLatestVersion.compareTo(localVersion) > 0;
if (isUpdatable) {
return remoteLatestWidget;
}
}
return null;
}
public List<SharableWidgetProvider> getUpdatableWidgetProviders() {
List<SharableWidgetProvider> updatableProviders = new ArrayList<>();
Group[] groups = DefaultShareGroupManager.getInstance().getAllGroup();
for (Group group: groups) {
SharableWidgetProvider[] widgetProviders = group.getAllBindInfoList();
for (SharableWidgetProvider widgetProvider: widgetProviders) {
if (checkUpdatable(widgetProvider)) {
updatableProviders.add(widgetProvider);
}
}
}
return updatableProviders;
}
public void fetchComponentUpdates(FetchComponentUpdatesListener listener) {
if (isCheckingComponentUpdates.get()) {
if (checkingComponentsUpdateWorker != null) {
checkingComponentsUpdateWorker.cancel(true);
}
}
clearUpdate();
listener.onFetchedBefore();
checkingComponentsUpdateWorker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() {
if (isCancelled()) {
return false;
}
if (isCheckingComponentUpdates.compareAndSet(false, true)) {
clearUpdate();
Set<String> widgetIds = getLocalWidgetIds();
String envVersion = ProductConstants.RELEASE_VERSION;
List<OnlineShareWidget> remoteLatestWidgetList = OnlineShopUtils.getLatestReusesByDesignerVersion(widgetIds, envVersion);
remoteLatestWidgetsBackup.clear();
for (OnlineShareWidget widget: remoteLatestWidgetList) {
remoteLatestWidgetsBackup.put(widget.getUuid(), widget);
}
return true;
}
return false;
}
@Override
public void done() {
boolean success = false;
try {
success = get();
} catch (InterruptedException | ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} finally {
listener.onFetchedAfter(success, remoteLatestWidgetsBackup);
isCheckingComponentUpdates.set(false);
}
}
};
checkingComponentsUpdateWorker.execute();
}
public interface FetchComponentUpdatesListener {
void onFetchedBefore();
void onFetchedAfter(boolean success, Map<String, OnlineShareWidget> remoteLatestWidgets);
}
}

2
designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/ManagePane.java

@ -135,7 +135,7 @@ class ManagePane extends JPanel implements ShareUIAspect {
String userInput = getFileName().replaceAll("[\\\\/:*?\"<>|]", StringUtils.EMPTY);
//新建分组,刷新显示
if (DefaultShareGroupManager.getInstance().createGroup(userInput)) {
LocalWidgetRepoPane.getInstance().refreshAllGroupPane(GroupPane.GroupCreateStrategy.CLOSURE);
LocalWidgetRepoPane.getInstance().refreshAllGroupPane(GroupPane.GroupCreateStrategy.COLLAPSED);
} else {
ShareUIUtils.showErrorMessageDialog(Toolkit.i18nText("Fine-Design_Basic_Make_Failure"));
}

8
designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/ToolbarPane.java

@ -9,6 +9,7 @@ import com.fr.design.gui.imenu.UIPopupMenu;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.ComponentShareUtil;
import com.fr.design.mainframe.share.sort.WidgetSortType;
import com.fr.design.mainframe.share.ui.base.MouseClickListener;
import com.fr.design.mainframe.share.ui.base.SortPopupMenuItem;
@ -112,10 +113,17 @@ class ToolbarPane extends JPanel {
e -> {
filterPanel.reset();
LocalWidgetRepoPane.getInstance().refreshPane();
ComponentShareUtil.recordWidgetLibHasRefreshed();
}
);
}
public void reset() {
filterPanel.reset();
searchTextField.setText(StringUtils.EMPTY);
cardLayout.show(centerPane, NORMAL);
}
private FilterPane createFilterPane() {
filterPanel = FilterPane.createLocalFilterPane();
filterPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));

11
designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/WidgetSelectedManager.java

@ -1,7 +1,9 @@
package com.fr.design.mainframe.share.ui.local;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.group.DefaultShareGroupManager;
import com.fr.form.share.Group;
import com.fr.stable.StringUtils;
import java.util.HashMap;
import java.util.List;
@ -53,7 +55,11 @@ public class WidgetSelectedManager {
*/
public synchronized boolean unInstallSelect(String groupName, String uuid) {
Group group = DefaultShareGroupManager.getInstance().getGroup(groupName);
return group != null && group.unInstallSelect(Stream.of(uuid).collect(Collectors.toList()));
boolean success = group != null && group.unInstallSelect(Stream.of(uuid).collect(Collectors.toList()));
if (success) {
DefaultShareGroupManager.getInstance().notifyComponentRemoved(groupName, uuid);
}
return success;
}
/**
@ -64,6 +70,9 @@ public class WidgetSelectedManager {
for (String groupName : selectedWidgetMap.keySet()) {
Group group = DefaultShareGroupManager.getInstance().getGroup(groupName);
result &= group != null && group.unInstallSelect(selectedWidgetMap.get(groupName));
if (result) {
DefaultShareGroupManager.getInstance().notifyComponentRemoved(groupName, StringUtils.EMPTY);
}
}
selectedWidgetMap.clear();
return result;

248
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/AbstractOnlineWidgetSelectPane.java

@ -0,0 +1,248 @@
package com.fr.design.mainframe.share.ui.online;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.AbstractWidgetSelectPane;
import com.fr.design.mainframe.share.ui.base.AbstractWidgetPopupPreviewPane;
import com.fr.design.mainframe.share.ui.base.LoadingPane;
import com.fr.design.mainframe.share.ui.base.NoMatchPane;
import com.fr.design.mainframe.share.ui.base.PagingFiledPane;
import com.fr.design.mainframe.share.ui.block.OnlineWidgetBlock;
import com.fr.design.mainframe.share.ui.block.PreviewWidgetBlock;
import com.fr.design.mainframe.share.ui.online.resource.OnlineResourceManager;
import com.fr.design.mainframe.share.ui.widgetfilter.FilterPane;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.form.share.base.DataLoad;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.constants.ShareComponentConstants;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingWorker;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.concurrent.ExecutionException;
/**
* Created by kerry on 2021/10/22
*/
public abstract class AbstractOnlineWidgetSelectPane extends AbstractWidgetSelectPane<OnlineShareWidget> {
protected static final int H_GAP = 5;
protected static final int V_GAP = 10;
protected enum PaneStatue {NORMAL, NO_MATCH, LOADING, DISCONNECTED}
private OnlineShareWidget[] sharableWidgetProviders;
private PagingFiledPane pagingFiledPane;
private JPanel contentPane;
private UIScrollPane scrollPane;
private FilterPane filterPane;
private final int widgetsPerNum;
private CardLayout cardLayout;
public AbstractOnlineWidgetSelectPane(OnlineShareWidget[] providers, FilterPane filterPane, int widgetsPerNum) {
this(providers, widgetsPerNum);
this.filterPane = filterPane;
}
public AbstractOnlineWidgetSelectPane(final DataLoad<OnlineShareWidget> dataLoad, FilterPane filterPane, final int widgetsPerNum) {
this(dataLoad, widgetsPerNum);
this.filterPane = filterPane;
}
public AbstractOnlineWidgetSelectPane(OnlineShareWidget[] providers, int widgetsPerNum) {
this.widgetsPerNum = widgetsPerNum;
sharableWidgetProviders = providers;
init();
initPagingPane();
switchPane(createComponents());
}
public AbstractOnlineWidgetSelectPane(final DataLoad<OnlineShareWidget> dataLoad, final int widgetsPerNum) {
this.widgetsPerNum = widgetsPerNum;
init();
//异步获取组件信息
new SwingWorker<OnlineWidgetSelectPane.PaneStatue, Void>() {
@Override
protected OnlineWidgetSelectPane.PaneStatue doInBackground() {
sharableWidgetProviders = dataLoad.load();
initPagingPane();
return createComponents();
}
@Override
protected void done() {
try {
switchPane(get());
fireAfterDataLoad();
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}.execute();
}
private void init() {
cardLayout = new CardLayout();
this.setLayout(cardLayout);
// 设置面板的边框 ,距离上、左、下、右 的距离
this.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
this.add(new LoadingPane(), OnlineWidgetSelectPane.PaneStatue.LOADING.name());
this.add(new NoMatchPane(), OnlineWidgetSelectPane.PaneStatue.NO_MATCH.name());
this.add(contentPane, OnlineWidgetSelectPane.PaneStatue.NORMAL.name());
switchPane(OnlineWidgetSelectPane.PaneStatue.LOADING);
}
public int getSharableWidgetNum() {
return sharableWidgetProviders == null ? 0 : sharableWidgetProviders.length;
}
public OnlineShareWidget[] getSharableWidgetProviders() {
return sharableWidgetProviders;
}
/**
* 切换需要显示的面板
*/
protected void switchPane(OnlineWidgetSelectPane.PaneStatue statue) {
if (statue == OnlineWidgetSelectPane.PaneStatue.DISCONNECTED) {
OnlineWidgetRepoPane.getInstance().switch2InternetErrorPane();
return;
}
cardLayout.show(this, statue.name());
if (statue == OnlineWidgetSelectPane.PaneStatue.NORMAL) {
//异步加载组件缩略图
OnlineResourceManager.getInstance().loadImage();
}
}
protected void fireAfterDataLoad(){
}
private void synchronizedLoadingContent() {
new SwingWorker<OnlineWidgetSelectPane.PaneStatue, Void>() {
@Override
protected OnlineWidgetSelectPane.PaneStatue doInBackground() {
return createComponents();
}
@Override
protected void done() {
try {
switchPane(get());
//加载之后设置下标记符
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}.execute();
}
private void initPagingPane() {
this.pagingFiledPane = new PagingFiledPane(sharableWidgetProviders.length, widgetsPerNum);
this.pagingFiledPane.registerChangeListener(event -> {
AbstractOnlineWidgetSelectPane.this.switchPane(OnlineWidgetSelectPane.PaneStatue.LOADING);
synchronizedLoadingContent();
OnlineWidgetRepoPane.getInstance().completeEmbedFilter();
});
pagingFiledPane.setEnable(pagePaneEnable());
}
protected OnlineWidgetSelectPane.PaneStatue createComponents() {
if (ArrayUtils.isEmpty(sharableWidgetProviders)) {
return OnlineWidgetSelectPane.PaneStatue.NO_MATCH;
}
if (!OnlineShopUtils.testConnection()) {
return OnlineWidgetSelectPane.PaneStatue.DISCONNECTED;
}
OnlineResourceManager.getInstance().cancelLoad();
contentPane.removeAll();
scrollPane = createScrollPane();
contentPane.add(scrollPane, BorderLayout.CENTER);
contentPane.add(this.pagingFiledPane, BorderLayout.SOUTH);
return OnlineWidgetSelectPane.PaneStatue.NORMAL;
}
protected UIScrollPane createScrollPane() {
OnlineShareWidget[] showWidgets = getShowWidgets();
JPanel widgetPane = createWidgetPane();
widgetPane.setLayout(new FlowLayout(FlowLayout.LEFT, H_GAP, V_GAP));
for (OnlineShareWidget provider : showWidgets) {
PreviewWidgetBlock<OnlineShareWidget> widgetButton = createWidgetBlock(provider);
widgetPane.add(widgetButton);
}
widgetPane.setPreferredSize(new Dimension(240, getPaneHeight(showWidgets.length)));
UIScrollPane scrollPane = new UIScrollPane(createContentPane(widgetPane));
setScrollPaneStyle(scrollPane);
return scrollPane;
}
protected OnlineShareWidget[] getShowWidgets(){
return this.pagingFiledPane.getShowItems(this.sharableWidgetProviders);
}
protected JPanel createWidgetPane() {
return new JPanel();
}
protected JPanel createContentPane(JPanel widgetPane) {
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane();
panel.add(widgetPane, BorderLayout.CENTER);
return panel;
}
protected boolean pagePaneEnable() {
return true;
}
protected void setScrollPaneStyle(UIScrollPane scrollPane) {
scrollPane.setBorder(null);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setWheelScrollingEnabled(filterPane == null || !filterPane.isShowPopup());
}
protected PreviewWidgetBlock<OnlineShareWidget> createWidgetBlock(OnlineShareWidget provider) {
return new OnlineWidgetBlock(provider, this);
}
protected int getPaneHeight(int count) {
return (count + 1) / 2 * (ShareComponentConstants.SHARE_BLOCK_HEIGHT + V_GAP);
}
public void setWidgetPaneScrollEnable(boolean enable) {
if (scrollPane != null) {
scrollPane.setWheelScrollingEnabled(enable);
}
}
@Override
protected AbstractWidgetPopupPreviewPane<OnlineShareWidget> createPopupPreviewPane() {
return new OnlineWidgetPopupPreviewPane();
}
protected Container getParentContainer() {
return this.getParent();
}
public void refreshShowPaneUI() {
OnlineWidgetRepoPane.getInstance().refreshShowPaneUI();
}
}

96
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/AbstractOnlineWidgetShowPane.java

@ -3,15 +3,16 @@ package com.fr.design.mainframe.share.ui.online;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.sort.OnlineWidgetSortType;
import com.fr.design.mainframe.share.ComponentShareUtil;
import com.fr.design.mainframe.share.ui.base.FlexSearchFieldPane;
import com.fr.design.mainframe.share.ui.base.LoadingPane;
import com.fr.design.mainframe.share.ui.widgetfilter.FilterPane;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.form.share.base.DataLoad;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.utils.ShareUtils;
import com.fr.design.mainframe.share.Bean.WidgetFilterInfo;
import com.fr.general.IOUtils;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
@ -39,28 +40,32 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel {
private JPanel componentSelectPane;
private JPanel searchResultShowPane;
private JPanel mainCenterPane;
private FilterPane filterPane;
protected FilterPane filterPane;
private JPanel centerPane;
private SortTabPane sortTabPane;
private JPanel toolBarPane;
private final JPanel loadingPane = new LoadingPane();
private OnlineShareWidget[] sharableWidgetProviders;
protected OnlineShareWidget[] sharableWidgetProviders;
//主面板和搜索面板的cardLayout
private CardLayout mainCardLayout;
public AbstractOnlineWidgetShowPane(OnlineShareWidget[] sharableWidgetProviders) {
this(sharableWidgetProviders, OnlineWidgetSortType.COMPOSITE);
}
public AbstractOnlineWidgetShowPane(OnlineShareWidget[] sharableWidgetProviders, OnlineWidgetSortType sortType) {
this.sharableWidgetProviders = sharableWidgetProviders;
this.setLayout(FRGUIPaneFactory.createBorderLayout());
JPanel contentPane = initContentPane();
JPanel contentPane = initContentPane(sortType);
this.add(contentPane, BorderLayout.CENTER);
}
protected JPanel initContentPane() {
protected JPanel initContentPane(OnlineWidgetSortType sortType) {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
OnlineWidgetSortType.COMPOSITE.sort(sharableWidgetProviders);
sortType.sort(sharableWidgetProviders);
componentSelectPane = createOnlineWidgetSelectPane(sharableWidgetProviders);
centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
centerPane.add(componentSelectPane, BorderLayout.CENTER);
@ -68,16 +73,17 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel {
filterPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 8));
initFilterPaneListener(filterPane);
sortTabPane = new SortTabPane();
this.sortTabPane.setIndex(sortType.ordinal());
initSortTabPane(sortTabPane);
FlexSearchFieldPane flexSearchPane = new FlexSearchFieldPane(filterPane);
initSearchTextFieldPaneListener(flexSearchPane);
JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
northPane.add(flexSearchPane, BorderLayout.CENTER);
northPane.add(sortTabPane, BorderLayout.SOUTH);
initNorthPane(jPanel, northPane);
toolBarPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
toolBarPane.add(flexSearchPane, BorderLayout.CENTER);
toolBarPane.add(sortTabPane, BorderLayout.SOUTH);
initNorthPane(jPanel, toolBarPane);
searchResultShowPane = createOnlineWidgetSelectPane(new OnlineShareWidget[]{});
this.searchResultShowPane = initSearchResultShowPane(sharableWidgetProviders);
mainCardLayout = new CardLayout();
mainCenterPane = new JPanel(mainCardLayout);
mainCenterPane.add(centerPane, MAIN_FILTER_TAB_PANE);
@ -88,12 +94,17 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel {
return jPanel;
}
protected void initNorthPane(JPanel jPanel, JPanel northPane) {
jPanel.add(northPane, BorderLayout.NORTH);
}
public void setToolBarPaneVisible(boolean flag){
this.toolBarPane.setVisible(flag);
}
protected OnlineWidgetSelectPane createOnlineWidgetSelectPane(OnlineShareWidget[] sharableWidgetProviders) {
protected AbstractOnlineWidgetSelectPane createOnlineWidgetSelectPane(OnlineShareWidget[] sharableWidgetProviders) {
return new OnlineWidgetSelectPane(sharableWidgetProviders, filterPane, 50);
}
@ -101,6 +112,17 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel {
return new OnlineWidgetSelectPane(dataLoad, filterPane, 50);
}
protected AbstractOnlineWidgetSelectPane manualCreateOnlineWidgetSelectPane(OnlineShareWidget[] sharableWidgetProviders) {
ComponentShareUtil.completeEmbedFilter();
return createOnlineWidgetSelectPane(sharableWidgetProviders);
}
protected OnlineWidgetSelectPane manualCreateOnlineWidgetSelectPane(DataLoad<OnlineShareWidget> dataLoad) {
ComponentShareUtil.completeEmbedFilter();
return createOnlineWidgetSelectPane(dataLoad);
}
protected FilterPane createFilterPane() {
return FilterPane.createOnlineFilterPane();
}
@ -114,11 +136,11 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel {
this.mainCardLayout.show(mainCenterPane, MAIN_FILTER_TAB_PANE);
return;
}
List<OnlineShareWidget> widgets = new ArrayList<>();
List<OnlineShareWidget> searchedWidgetList = new ArrayList<>();
if (StringUtils.isNotEmpty(text)) {
for (OnlineShareWidget provider : sharableWidgetProviders) {
if (provider.getName().toLowerCase().contains(text)) {
widgets.add(provider);
searchedWidgetList.add(provider);
}
}
}
@ -126,12 +148,15 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel {
if (searchResultShowPane != null) {
mainCenterPane.remove(searchResultShowPane);
}
this.searchResultShowPane = createOnlineWidgetSelectPane(widgets.toArray(new OnlineShareWidget[widgets.size()]));
searchResultShowPane = manualCreateOnlineWidgetSelectPane(searchedWidgetList.toArray(new OnlineShareWidget[]{}));
this.mainCenterPane.add(searchResultShowPane, SEARCH_RESULT_PANE);
this.mainCardLayout.show(mainCenterPane, SEARCH_RESULT_PANE);
this.validate();
this.repaint();
}
protected JPanel initSearchResultShowPane(OnlineShareWidget[] widgets) {
return new JPanel();
}
public void initFilterPaneListener(FilterPane filterPane) {
@ -139,21 +164,30 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel {
@Override
public void stateChanged(final ChangeEvent e) {
String filterStr = e.getSource().toString();
centerPane.remove(componentSelectPane);
componentSelectPane = createOnlineWidgetSelectPane(() -> {
sharableWidgetProviders = new OnlineShareWidget[0];
sharableWidgetProviders = getSharableWidgetArr(filterStr);
return sharableWidgetProviders;
});
centerPane.add(componentSelectPane, BorderLayout.CENTER);
AbstractOnlineWidgetShowPane.this.validate();
AbstractOnlineWidgetShowPane.this.repaint();
filterStateChanged(filterStr);
}
});
}
protected OnlineShareWidget[] getSharableWidgetArr( String filterStr){
return ShareUtils.getFilterWidgets(filterStr);
public void filterStateChanged(String filterStr) {
replaceSelectPane(manualCreateOnlineWidgetSelectPane(() -> {
sharableWidgetProviders = new OnlineShareWidget[0];
sharableWidgetProviders = getSharableWidgetArr(filterStr);
return sharableWidgetProviders;
}));
}
protected void replaceSelectPane(AbstractOnlineWidgetSelectPane selectPane) {
centerPane.remove(componentSelectPane);
componentSelectPane = selectPane;
centerPane.add(componentSelectPane, BorderLayout.CENTER);
AbstractOnlineWidgetShowPane.this.validate();
AbstractOnlineWidgetShowPane.this.repaint();
}
protected OnlineShareWidget[] getSharableWidgetArr(String filterStr) {
return OnlineShopUtils.getFilterWidgets(filterStr);
}
public void initSearchTextFieldPaneListener(FlexSearchFieldPane searchFieldPane) {
@ -167,6 +201,10 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel {
});
}
public void setFilterItems(List<WidgetFilterInfo> selectedFilters) {
this.filterPane.setFilter(selectedFilters);
}
public void initSortTabPane(SortTabPane sortTabPane) {
}
@ -236,7 +274,7 @@ public abstract class AbstractOnlineWidgetShowPane extends JPanel {
@Override
protected Boolean doInBackground() {
sortType.sort(sharableWidgetProviders);
componentSelectPane = createOnlineWidgetSelectPane(sharableWidgetProviders);
componentSelectPane = manualCreateOnlineWidgetSelectPane(sharableWidgetProviders);
return true;
}

74
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/CarouselStateManger.java

@ -0,0 +1,74 @@
package com.fr.design.mainframe.share.ui.online;
import com.fr.general.ComparatorUtils;
import com.fr.stable.StringUtils;
/**
* Created by kerry on 2021/10/22
*/
public class CarouselStateManger {
public static final String RIGHT_CLICK ="RIGHT_CLICK";
public static final String DOWNLOAD_COMPONENT ="DOWNLOAD_COMPONENT";
public static final String FIRST_DRAG_ANIMATE ="FIRST_DRAG_ANIMATE";
public static final String MOUSE_HOVER ="MOUSE_HOVER";
private CarouseState state;
private String suspendEvent;
public static CarouselStateManger getInstance() {
return CarouselStateManger.HOLDER.singleton;
}
private static class HOLDER {
private static CarouselStateManger singleton = new CarouselStateManger();
}
private CarouselStateManger() {
}
public void start() {
this.state = CarouseState.RUNNING;
}
public void start(String startEvent) {
if (!this.stopped() && ComparatorUtils.equals(this.suspendEvent, startEvent)){
this.state = CarouseState.RUNNING;
this.suspendEvent = StringUtils.EMPTY;
}
}
public boolean running() {
return this.state == CarouseState.RUNNING;
}
public void suspend(String externalSuspendEvent) {
if (!this.stopped()) {
this.state = CarouseState.SUSPEND;
this.suspendEvent = externalSuspendEvent;
}
}
public boolean isSuspend() {
return this.state == CarouseState.SUSPEND;
}
public void stop() {
this.state = CarouseState.STOP;
}
public boolean stopped() {
return this.state == CarouseState.STOP;
}
enum CarouseState {
RUNNING,
SUSPEND,
STOP
}
}

79
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetPopupPreviewPane.java

@ -9,6 +9,9 @@ import com.fr.design.mainframe.share.ui.constants.ColorConstants;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.plugin.basic.version.Version;
import com.fr.plugin.basic.version.VersionInterval;
import com.fr.plugin.basic.version.VersionIntervalFactory;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
@ -20,11 +23,8 @@ import javax.swing.plaf.basic.BasicLabelUI;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Toolkit;
/**
* @author Starryi
@ -32,12 +32,12 @@ import java.awt.Toolkit;
* Created by Starryi on 2021/9/14
*/
public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane<OnlineShareWidget> {
private static final int POPUP_WIDTH = 412;
public static final int POPUP_WIDTH = 412;
private static final int POPUP_TOP_HEIGHT = 28;
private static final int POPUP_BOTTOM_HEIGHT = 54;
private PreviewImagePane previewImagePane;
private UILabel versionLabel;
private UILabel compatibleEnVersionLabel;
private UILabel downloadsLabel;
private UILabel priceLabel;
@ -95,10 +95,10 @@ public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane
}
private JPanel createWidgetInfoPane() {
versionLabel = new UILabel();
versionLabel.setVerticalAlignment(SwingConstants.CENTER);
versionLabel.setFont(FRFont.getInstance(versionLabel.getFont()).deriveFont(12.0F));
versionLabel.setForeground(new Color(0x333334));
compatibleEnVersionLabel = new UILabel();
compatibleEnVersionLabel.setVerticalAlignment(SwingConstants.CENTER);
compatibleEnVersionLabel.setFont(FRFont.getInstance(compatibleEnVersionLabel.getFont()).deriveFont(12.0F));
compatibleEnVersionLabel.setForeground(new Color(0x333334));
downloadsLabel = new UILabel();
downloadsLabel.setVerticalAlignment(SwingConstants.TOP);
@ -125,7 +125,7 @@ public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 1;
container.add(versionLabel, constraints);
container.add(compatibleEnVersionLabel, constraints);
constraints.gridx = 0;
constraints.gridy = 1;
@ -167,6 +167,18 @@ public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane
@Override
public void populateBean(PreviewWidgetBlock<OnlineShareWidget> block) {
OnlineShareWidget widget = block.getWidget();
populateThemeName(widget);
populatePrice(widget);
populateCompatibleEnvVersion(widget);
downloadsLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Download_Times") + ": " + widget.getDownloadTimes());
previewImagePane.setPreviewImage(block.getPreviewImage());
int height = (suitableThemeNamePane.isVisible() ? POPUP_TOP_HEIGHT : 0) + 10 + previewImagePane.getPreferredSize().height + POPUP_BOTTOM_HEIGHT;
setPreferredSize(new Dimension(POPUP_WIDTH, height));
}
private void populateThemeName(OnlineShareWidget widget) {
String themeName = widget.getThemeName();
if (StringUtils.isNotEmpty(themeName)) {
suitableThemeNamePane.setVisible(true);
@ -174,47 +186,36 @@ public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane
} else {
suitableThemeNamePane.setVisible(false);
}
}
private void populatePrice(OnlineShareWidget widget) {
String priceText = "¥" + widget.getPrice();
if (widget.getPrice() <= 0) {
priceText = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Price_Free");
}
priceLabel.setText(priceText);
versionLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Version") + ": " + widget.getDesignerVersion());
downloadsLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Download_Times") + ": " + widget.getDownloadTimes());
previewImagePane.setPreviewImage(block.getPreviewImage());
int height = (suitableThemeNamePane.isVisible() ? POPUP_TOP_HEIGHT : 0) + 10 + previewImagePane.getPreferredSize().height + POPUP_BOTTOM_HEIGHT;
setPreferredSize(new Dimension(POPUP_WIDTH, height));
}
private static class PreviewImagePane extends JPanel {
private static final Image DEFAULT_IMAGE = IOUtils.readImage("com/fr/base/images/share/component_error.png");
private static final int PREVIEW_IMAGE_WIDTH = POPUP_WIDTH - 20;
private static final int STANDARD_DPI = 128;
private void populateCompatibleEnvVersion(OnlineShareWidget widget) {
VersionInterval versionInterval = VersionIntervalFactory.create(widget.getDesignerVersion());
private Image previewImage;
Version floorVersion = versionInterval.floor();
Version upperVersion = versionInterval.upper();
public void setPreviewImage(Image previewImage) {
this.previewImage = previewImage;
if (this.previewImage == null) {
this.previewImage = DEFAULT_IMAGE;
}
int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
int imageWidth = this.previewImage.getWidth(null);
int imageHeight = this.previewImage.getHeight(null);
String compatibleEnVersion;
boolean includingMinVersion = versionInterval.contain(Version.create("0"));
boolean includingMaxVersion = versionInterval.contain(Version.create(Integer.toString(Integer.MAX_VALUE)));
double imageAspectRatio = (double) imageWidth / imageHeight;
int width = (PREVIEW_IMAGE_WIDTH * dpi) / STANDARD_DPI;
int height = (int) (width / imageAspectRatio);
setPreferredSize(new Dimension(width, height));
if (includingMinVersion && includingMaxVersion) {
compatibleEnVersion = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Compatible_Designer_Version_Interval_All");
} else if (includingMinVersion) {
compatibleEnVersion = StringUtils.messageFormat(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Compatible_Designer_Version_Interval_Ceiling_Limit", upperVersion.getVersionStr()));
} else if (includingMaxVersion) {
compatibleEnVersion = StringUtils.messageFormat(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Compatible_Designer_Version_Interval_Floor_Limit", floorVersion.getVersionStr()));
} else {
compatibleEnVersion = floorVersion.getVersionStr() + "~" + upperVersion.getVersionStr();
}
@Override
public void paint(Graphics g) {
g.drawImage(this.previewImage, 0, 0, getWidth(), getHeight(), null);
}
compatibleEnVersionLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Compatible_Designer_Version") + ": " + compatibleEnVersion);
}
}

22
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetRepoPane.java

@ -7,8 +7,8 @@ import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.ui.base.LoadingPane;
import com.fr.design.mainframe.share.ui.base.MouseClickListener;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.utils.ShareUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
@ -48,7 +48,7 @@ public class OnlineWidgetRepoPane extends BasicPane {
return true;
}
try{
sharableWidgets = ShareUtils.getAllSharableWidgetsFromShop();
sharableWidgets = OnlineShopUtils.getAllSharableWidgetsFromShop();
return true;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
@ -222,4 +222,22 @@ public class OnlineWidgetRepoPane extends BasicPane {
return tipLabel;
}
public void refresh() {
if (componentTabPane != null) {
this.componentTabPane.refreshPane();
}
}
public void refreshShowPaneUI(){
if (componentTabPane != null) {
this.componentTabPane.refreshShowPaneUI();
}
}
public void completeEmbedFilter(){
if (componentTabPane != null) {
this.componentTabPane.completeEmbedFilter();
}
}
}

212
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetSelectPane.java

@ -1,231 +1,29 @@
package com.fr.design.mainframe.share.ui.online;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.AbstractWidgetSelectPane;
import com.fr.design.mainframe.share.ui.base.AbstractWidgetPopupPreviewPane;
import com.fr.design.mainframe.share.ui.base.LoadingPane;
import com.fr.design.mainframe.share.ui.base.NoMatchPane;
import com.fr.design.mainframe.share.ui.base.PagingFiledPane;
import com.fr.design.mainframe.share.ui.block.OnlineWidgetBlock;
import com.fr.design.mainframe.share.ui.block.PreviewWidgetBlock;
import com.fr.design.mainframe.share.ui.widgetfilter.FilterPane;
import com.fr.form.share.base.DataLoad;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.constants.ShareComponentConstants;
import com.fr.form.share.utils.ShareUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingWorker;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.concurrent.ExecutionException;
/**
* Created by kerry on 2020-10-19
*/
public class OnlineWidgetSelectPane extends AbstractWidgetSelectPane<OnlineShareWidget> {
protected static final int H_GAP = 5;
protected static final int V_GAP = 10;
enum PaneStatue {NORMAL, NO_MATCH, LOADING, DISCONNECTED}
private OnlineShareWidget[] sharableWidgetProviders;
private PagingFiledPane pagingFiledPane;
private JPanel contentPane;
private UIScrollPane scrollPane;
private FilterPane filterPane;
private final int widgetsPerNum;
private CardLayout cardLayout;
public class OnlineWidgetSelectPane extends AbstractOnlineWidgetSelectPane {
public OnlineWidgetSelectPane(OnlineShareWidget[] providers, FilterPane filterPane, int widgetsPerNum) {
this(providers, widgetsPerNum);
this.filterPane = filterPane;
super(providers, filterPane, widgetsPerNum);
}
public OnlineWidgetSelectPane(final DataLoad<OnlineShareWidget> dataLoad, FilterPane filterPane, final int widgetsPerNum) {
this(dataLoad, widgetsPerNum);
this.filterPane = filterPane;
super(dataLoad, filterPane, widgetsPerNum);
}
public OnlineWidgetSelectPane(OnlineShareWidget[] providers, int widgetsPerNum) {
this.widgetsPerNum = widgetsPerNum;
sharableWidgetProviders = providers;
init();
initPagingPane();
switchPane(createComponents());
super(providers, widgetsPerNum);
}
public OnlineWidgetSelectPane(final DataLoad<OnlineShareWidget> dataLoad, final int widgetsPerNum) {
this.widgetsPerNum = widgetsPerNum;
init();
//异步获取组件信息
new SwingWorker<PaneStatue, Void>() {
@Override
protected PaneStatue doInBackground() {
sharableWidgetProviders = dataLoad.load();
initPagingPane();
return createComponents();
}
@Override
protected void done() {
try {
switchPane(get());
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}.execute();
}
private void init() {
cardLayout = new CardLayout();
this.setLayout(cardLayout);
// 设置面板的边框 ,距离上、左、下、右 的距离
this.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
this.add(new LoadingPane(), PaneStatue.LOADING.name());
this.add(new NoMatchPane(), PaneStatue.NO_MATCH.name());
this.add(contentPane, PaneStatue.NORMAL.name());
switchPane(PaneStatue.LOADING);
}
public int getSharableWidgetNum() {
return sharableWidgetProviders == null ? 0 : sharableWidgetProviders.length;
}
public OnlineShareWidget[] getSharableWidgetProviders() {
return sharableWidgetProviders;
}
/**
* 切换需要显示的面板
*/
private void switchPane(PaneStatue statue) {
if (statue == PaneStatue.DISCONNECTED) {
OnlineWidgetRepoPane.getInstance().switch2InternetErrorPane();
return;
}
cardLayout.show(this, statue.name());
if (statue == PaneStatue.NORMAL) {
//异步加载组件缩略图
OnlineResourceManager.getInstance().loadImage();
}
}
private void synchronizedLoadingContent() {
new SwingWorker<PaneStatue, Void>() {
@Override
protected PaneStatue doInBackground() {
return createComponents();
}
@Override
protected void done() {
try {
switchPane(get());
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}.execute();
}
private void initPagingPane() {
this.pagingFiledPane = new PagingFiledPane(sharableWidgetProviders.length, widgetsPerNum);
this.pagingFiledPane.registerChangeListener(event -> {
OnlineWidgetSelectPane.this.switchPane(PaneStatue.LOADING);
synchronizedLoadingContent();
});
pagingFiledPane.setEnable(pagePaneEnable());
}
private PaneStatue createComponents() {
if (ArrayUtils.isEmpty(sharableWidgetProviders)) {
return PaneStatue.NO_MATCH;
}
if (!ShareUtils.testConnection()) {
return PaneStatue.DISCONNECTED;
}
OnlineResourceManager.getInstance().cancelLoad();
contentPane.removeAll();
scrollPane = createScrollPane();
contentPane.add(scrollPane, BorderLayout.CENTER);
contentPane.add(this.pagingFiledPane, BorderLayout.SOUTH);
return PaneStatue.NORMAL;
super(dataLoad, widgetsPerNum);
}
private UIScrollPane createScrollPane() {
OnlineShareWidget[] showWidgets = this.pagingFiledPane.getShowItems(this.sharableWidgetProviders);
JPanel widgetPane = createWidgetPane();
widgetPane.setLayout(new FlowLayout(FlowLayout.LEFT, H_GAP, V_GAP));
for (OnlineShareWidget provider : showWidgets) {
PreviewWidgetBlock<OnlineShareWidget> widgetButton = createWidgetBlock(provider);
widgetPane.add(widgetButton);
}
widgetPane.setPreferredSize(new Dimension(240, getPaneHeight(showWidgets.length)));
UIScrollPane scrollPane = new UIScrollPane(createContentPane(widgetPane));
setScrollPaneStyle(scrollPane);
return scrollPane;
}
protected JPanel createWidgetPane() {
return new JPanel();
}
protected JPanel createContentPane(JPanel widgetPane) {
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane();
panel.add(widgetPane, BorderLayout.CENTER);
return panel;
}
protected boolean pagePaneEnable() {
return true;
}
protected void setScrollPaneStyle(UIScrollPane scrollPane) {
scrollPane.setBorder(null);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setWheelScrollingEnabled(filterPane == null || !filterPane.isShowPopup());
}
protected PreviewWidgetBlock<OnlineShareWidget> createWidgetBlock(OnlineShareWidget provider) {
return new OnlineWidgetBlock(provider, this);
}
protected int getPaneHeight(int count) {
return (count + 1) / 2 * (ShareComponentConstants.SHARE_BLOCK_HEIGHT + V_GAP);
}
public void setWidgetPaneScrollEnable(boolean enable) {
if (scrollPane != null) {
scrollPane.setWheelScrollingEnabled(enable);
}
}
@Override
protected AbstractWidgetPopupPreviewPane<OnlineShareWidget> createPopupPreviewPane() {
return new OnlineWidgetPopupPreviewPane();
}
protected Container getParentContainer() {
return this.getParent();
}
}

30
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetShowPane.java

@ -4,9 +4,11 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.sort.OnlineWidgetSortType;
import com.fr.design.mainframe.share.ui.base.FlexSearchFieldPane;
import com.fr.design.mainframe.share.ui.online.embed.OnlineEmbedFilterSelectPane;
import com.fr.design.mainframe.share.ui.widgetfilter.FilterPane;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.form.share.base.DataLoad;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.utils.ShareUtils;
import com.fr.stable.StringUtils;
import javax.swing.event.ChangeEvent;
@ -31,8 +33,13 @@ public class OnlineWidgetShowPane extends AbstractOnlineWidgetShowPane {
private String lastFilter = StringUtils.EMPTY;
private int lastSortTabSelectedIndex = 0;
public OnlineWidgetShowPane(OnlineShareWidget[] sharableWidgetProviders) {
super(sharableWidgetProviders);
public OnlineWidgetShowPane(OnlineShareWidget[] sharableWidgetProviders, OnlineWidgetSortType sortType) {
super(sharableWidgetProviders, sortType);
lastSortTabSelectedIndex = sortType.ordinal();
}
public OnlineWidgetShowPane(OnlineShareWidget[] sharableWidgetProvider) {
super(sharableWidgetProvider);
}
@Override
@ -109,7 +116,7 @@ public class OnlineWidgetShowPane extends AbstractOnlineWidgetShowPane {
}
protected OnlineShareWidget[] getSharableWidgetArr( String filterStr){
OnlineShareWidget[] onlineShareWidgets = ShareUtils.getFilterWidgets(filterStr);
OnlineShareWidget[] onlineShareWidgets = OnlineShopUtils.getFilterWidgets(filterStr);
OnlineWidgetSortType.values()[lastSortTabSelectedIndex].sort(onlineShareWidgets);
return onlineShareWidgets;
}
@ -117,7 +124,6 @@ public class OnlineWidgetShowPane extends AbstractOnlineWidgetShowPane {
@Override
public void initSortTabPane(SortTabPane sortTabPane) {
super.initSortTabPane(sortTabPane);
lastSortTabSelectedIndex = sortTabPane.getIndex();
sortTabPane.registerSortTabMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
@ -149,4 +155,18 @@ public class OnlineWidgetShowPane extends AbstractOnlineWidgetShowPane {
private void collectSortType(String sortType) {
ComponentCollector.getInstance().collectSortType(sortType);
}
public OnlineEmbedFilterSelectPane animate(String filterStr) {
OnlineEmbedFilterSelectPane pane = new OnlineEmbedFilterSelectPane(new DataLoad<OnlineShareWidget>() {
@Override
public OnlineShareWidget[] load() {
sharableWidgetProviders = getSharableWidgetArr(filterStr);
return sharableWidgetProviders;
}
}, filterPane, 50);
replaceSelectPane(pane);
return pane;
}
}

27
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetTabPane.java

@ -3,6 +3,9 @@ package com.fr.design.mainframe.share.ui.online;
import com.fr.design.gui.ibutton.UITabGroup;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.sort.OnlineWidgetSortType;
import com.fr.design.mainframe.share.ComponentShareUtil;
import com.fr.design.mainframe.share.ui.online.embed.OnlineEmbedFilterShowPane;
import com.fr.design.mainframe.share.ui.online.widgetpackage.OnlineWidgetPackagesShowPane;
import com.fr.form.share.bean.OnlineShareWidget;
@ -20,10 +23,12 @@ import java.util.List;
public class OnlineWidgetTabPane extends JPanel {
private static final String COMPONENT = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share");
private static final String COMPONENT_PACKAGE = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Package");
private static final String COMPONENT_EMBED = "COMPONENT_EMBED";
private CardLayout cardLayout;
private JPanel centerPane;
private boolean packagePaneCreated = false;
private List<TabChangeListener> tabChangeListeners;
private OnlineEmbedFilterShowPane embedFilterShowPane;
public OnlineWidgetTabPane(OnlineShareWidget[] sharableWidgets, OnlineShareWidget[] sharableWidgetPackage) {
tabChangeListeners = new ArrayList<>();
@ -34,7 +39,9 @@ public class OnlineWidgetTabPane extends JPanel {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.cardLayout = new CardLayout();
this.centerPane = new JPanel(cardLayout);
this.centerPane.add(new OnlineWidgetShowPane(sharableWidgets), COMPONENT);
this.centerPane.add( embedFilterShowPane = new OnlineEmbedFilterShowPane(new OnlineWidgetShowPane(sharableWidgets, OnlineWidgetSortType.SALES)), COMPONENT_EMBED);
//延迟组件包面板的初始化,防止组件面板里组件的缩略图和组件包面板里组件的缩略图一起加载
UITabGroup headGroup = new UITabGroup(new String[]{COMPONENT, COMPONENT_PACKAGE}) {
public void tabChanged(int newSelectedIndex) {
@ -42,8 +49,9 @@ public class OnlineWidgetTabPane extends JPanel {
changeListener.tabChange(newSelectedIndex);
}
if (newSelectedIndex == 0) {
cardLayout.show(centerPane, COMPONENT);
cardLayout.show(centerPane, ComponentShareUtil.needShowEmbedFilterPane() ? COMPONENT_EMBED : COMPONENT);
} else {
ComponentShareUtil.completeEmbedFilter();
ComponentCollector.getInstance().collectCmpPktClick();
//延迟组件包面板的初始化,防止组件面板里组件和缩略图和组件包面板里组件的缩略图一起加载
if (!packagePaneCreated) {
@ -64,11 +72,27 @@ public class OnlineWidgetTabPane extends JPanel {
this.add(centerPane, BorderLayout.CENTER);
}
public void completeEmbedFilter(){
if (embedFilterShowPane!= null){
embedFilterShowPane.completeEmbedFilter();
}
}
public void addTabChangeListener(TabChangeListener listener) {
if (!tabChangeListeners.contains(listener)) {
tabChangeListeners.add(listener);
}
}
public void refreshPane() {
this.cardLayout.show(centerPane, ComponentShareUtil.needShowEmbedFilterPane() ? COMPONENT_EMBED : COMPONENT);
}
public void refreshShowPaneUI(){
if (embedFilterShowPane != null) {
this.embedFilterShowPane.refreshUI();
}
}
public void removeTabChangeListener(TabChangeListener listener) {
tabChangeListeners.remove(listener);
@ -77,4 +101,5 @@ public class OnlineWidgetTabPane extends JPanel {
public interface TabChangeListener extends EventListener {
void tabChange(int selectedIndex);
}
}

41
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/PreviewImagePane.java

@ -0,0 +1,41 @@
package com.fr.design.mainframe.share.ui.online;
import com.fr.general.IOUtils;
import javax.swing.JPanel;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
/**
* Created by kerry on 2021/11/19
*/
public class PreviewImagePane extends JPanel {
private static final Image DEFAULT_IMAGE = IOUtils.readImage("com/fr/base/images/share/component_error.png");
private static final int PREVIEW_IMAGE_WIDTH = OnlineWidgetPopupPreviewPane.POPUP_WIDTH - 20;
private static final int STANDARD_DPI = 128;
private Image previewImage;
public void setPreviewImage(Image previewImage) {
this.previewImage = previewImage;
if (this.previewImage == null) {
this.previewImage = DEFAULT_IMAGE;
}
int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
int imageWidth = this.previewImage.getWidth(null);
int imageHeight = this.previewImage.getHeight(null);
double imageAspectRatio = (double) imageWidth / imageHeight;
int width = (PREVIEW_IMAGE_WIDTH * dpi) / STANDARD_DPI;
int height = (int) (width / imageAspectRatio);
setPreferredSize(new Dimension(width, height));
}
@Override
public void paint(Graphics g) {
g.drawImage(this.previewImage, 0, 0, getWidth(), getHeight(), null);
}
}

46
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/AnimatePopupDialog.java

@ -0,0 +1,46 @@
package com.fr.design.mainframe.share.ui.online.embed;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.general.IOUtils;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
/**
* Created by kerry on 2021/10/22
*/
public class AnimatePopupDialog extends JDialog {
private static final Icon DRAG_HAND = IOUtils.readIcon("/com/fr/design/form/images/drag_hand.png");
public AnimatePopupDialog(Image image, Point initialPosition) {
super(DesignerContext.getDesignerFrame());
Container container = getContentPane();
setUndecorated(true);
JPanel jPanel = new JPanel() {
@Override
public void paint(Graphics g) {
super.paint(g);
DRAG_HAND.paintIcon(this, g, (this.getWidth() - 20) / 2, (this.getHeight() - 20) / 2);
}
};
jPanel.setLayout(FRGUIPaneFactory.createBorderLayout());
jPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
jPanel.add(new UILabel(new ImageIcon(image)), BorderLayout.CENTER);
container.add(jPanel, BorderLayout.CENTER);
setSize(123, 70);
this.setLocation(initialPosition);
this.setVisible(true);
}
}

201
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/EmbedPane.java

@ -0,0 +1,201 @@
package com.fr.design.mainframe.share.ui.online.embed;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UIButtonUI;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.share.collect.ComponentCollector;
import com.fr.design.mainframe.share.ui.widgetfilter.FilterConfigPane;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.design.ui.util.UIUtil;
import com.fr.design.mainframe.share.Bean.WidgetFilterInfo;
import com.fr.module.ModuleContext;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.UIManager;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
/**
* Created by kerry on 2021/10/21
*/
public class EmbedPane extends JPanel {
private static final String EMBED_PANE_TIMER = "EMBED_PANE_TIMER";
private static final Color BORDER_COLOR = Color.decode("#D9DADD");
private static final Color SEARCH_BUTTON_COLOR = Color.decode("#419BF9");
private static final float DELTA_ALPHA = 0.13F;
private Image image;
private float alpha = 1.0F;
public EmbedPane(OnlineEmbedFilterShowPane showPane) {
this.addMouseListener(new MouseAdapter() {
});
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
this.add(initCenterPane(showPane), BorderLayout.CENTER);
}
private JPanel initCenterPane(OnlineEmbedFilterShowPane showPane) {
JPanel jPanel = new JPanel(FRGUIPaneFactory.createBorderLayout());
jPanel.setBackground(Color.WHITE);
jPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 0));
FilterConfigPane filterConfigPane = new FilterConfigPane(OnlineShopUtils.getEmbPaneShowFilterTypeInfos(), false) {
@Override
public String assembleFilter() {
return OnlineShopUtils.assembleFilter(getFilterList());
}
};
UIButton searchBtn = initSearchBtn(filterConfigPane, showPane);
filterConfigPane.setBorder(null);
JPanel tipPane = getFilterTipPane();
tipPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
jPanel.add(tipPane, BorderLayout.NORTH);
jPanel.add(filterConfigPane, BorderLayout.CENTER);
JPanel southPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
southPane.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8));
southPane.setBackground(Color.WHITE);
southPane.add(searchBtn, BorderLayout.CENTER);
southPane.setPreferredSize(new Dimension(212, 24));
jPanel.add(southPane, BorderLayout.SOUTH);
return jPanel;
}
private JPanel getFilterTipPane() {
String remark = Toolkit.i18nText("Fine-Design_Share_Online_Embed_Filter_Tip");
UILabel label = new UILabel();
label.setSize(new Dimension(229, 30));
//用THML标签进行拼接,以实现自动换行
StringBuilder builder = new StringBuilder("<html>");
char[] chars = remark.toCharArray();
//获取字体计算大小
FontMetrics fontMetrics = label.getFontMetrics(label.getFont());
int start = 0;
int len = 0;
while (start + len < remark.length()) {
while (true) {
len++;
if (start + len > remark.length())
break;
if (fontMetrics.charsWidth(chars, start, len)
> label.getWidth()) {
break;
}
}
builder.append(chars, start, len - 1).append("<br/>");
start = start + len - 1;
len = 0;
}
//拼接剩余部分
builder.append(chars, start, remark.length() - start);
builder.append("</html>");
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
label.setText(builder.toString());
jPanel.add(label);
return jPanel;
}
private UIButton initSearchBtn(FilterConfigPane filterConfigPane, OnlineEmbedFilterShowPane showPane) {
UIButton searchBtn = new UIButton(Toolkit.i18nText("Fine-Design_Share_Online_Query_Recommend_Component"));
searchBtn.setUI(new UIButtonUI() {
@Override
protected void paintBorder(Graphics g, UIButton b) {
Color oldColor = g.getColor();
g.setColor(SEARCH_BUTTON_COLOR);
g.drawRoundRect(2, 2, b.getWidth() - 4, b.getHeight() - 4, 2, 2);
g.setColor(oldColor);
}
});
searchBtn.setForeground(SEARCH_BUTTON_COLOR);
searchBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String filterStr = filterConfigPane.assembleFilter();
if (StringUtils.isEmpty(filterStr)) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Share_Online_Embed_Filter_Warning_Tip"),
Toolkit.i18nText("Fine-Design_Basic_Message"), WARNING_MESSAGE,
UIManager.getIcon("OptionPane.warningIcon"));
ComponentCollector.getInstance().collectEmbededFilterReact(2);
return;
}
showPane.filterStateChanged(filterStr);
animateHide(showPane, filterConfigPane.getFilterList());
ComponentCollector.getInstance().collectEmbededFilterReact(1);
}
});
return searchBtn;
}
public void animateHide(OnlineEmbedFilterShowPane showPane, List<WidgetFilterInfo> selectedFilters) {
//先生成图片
image = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
this.paint(image.getGraphics());
ScheduledExecutorService service = createToastScheduleExecutorService();
this.removeAll();
service.scheduleAtFixedRate(() -> {
Dimension dimension = EmbedPane.this.getSize();
Point point = EmbedPane.this.getLocation();
if (dimension.width <= 0 || dimension.height <= 0) {
EmbedPane.this.setVisible(false);
service.shutdown();
try {
showPane.animate(selectedFilters);
} catch (InterruptedException e) {
}
}
UIUtil.invokeAndWaitIfNeeded(() -> {
Dimension newDimension = new Dimension(dimension.width - 25, dimension.height - 30);
EmbedPane.this.setSize(newDimension);
EmbedPane.this.setLocation(point.x + 25, 0);
alpha -= DELTA_ALPHA;
});
}, 0, 60, TimeUnit.MILLISECONDS);
}
@Override
public void paint(Graphics g) {
AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, Math.max(0, alpha));
((Graphics2D) g).setComposite(composite);
super.paint(g);
if (image != null) {
g.drawImage(image, 0, 0, EmbedPane.this.getWidth(), EmbedPane.this.getHeight(), null);
}
}
private ScheduledExecutorService createToastScheduleExecutorService() {
return ModuleContext.getExecutor().newSingleThreadScheduledExecutor(new NamedThreadFactory(EMBED_PANE_TIMER));
}
}

44
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/FirstDragAnimateStateManager.java

@ -0,0 +1,44 @@
package com.fr.design.mainframe.share.ui.online.embed;
/**
* Created by kerry on 2021/10/29
*/
public class FirstDragAnimateStateManager {
public static FirstDragAnimateStateManager getInstance() {
return FirstDragAnimateStateManager.HOLDER.singleton;
}
private static class HOLDER {
private static final FirstDragAnimateStateManager singleton = new FirstDragAnimateStateManager();
}
private FirstDragAnimateStateManager() {
}
private STATE state;
public void startAnimate() {
this.state = STATE.ANIMATING;
}
public boolean animating() {
return this.state == STATE.ANIMATING;
}
public void stopAnimate() {
this.state = STATE.STOP;
}
public boolean isStop() {
return this.state == STATE.STOP;
}
enum STATE {
ANIMATING,
STOP
}
}

209
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/OnlineEmbedFilterSelectPane.java

@ -0,0 +1,209 @@
package com.fr.design.mainframe.share.ui.online.embed;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.mainframe.share.ui.online.AbstractOnlineWidgetSelectPane;
import com.fr.design.mainframe.share.ui.online.CarouselStateManger;
import com.fr.design.mainframe.share.ui.widgetfilter.FilterPane;
import com.fr.form.share.base.DataLoad;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.constants.ShareComponentConstants;
import com.fr.form.share.exception.NetWorkFailedException;
import com.fr.general.http.HttpClient;
import com.fr.log.FineLoggerFactory;
import com.fr.module.ModuleContext;
import com.fr.stable.EncodeConstants;
import com.fr.third.springframework.web.util.UriUtils;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import java.awt.AWTEvent;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by kerry on 2021/10/22
*/
public class OnlineEmbedFilterSelectPane extends AbstractOnlineWidgetSelectPane {
private static final String CAROUSEL_PREVIEW = "carousel_preview";
private static final int CAROUSE_IMAGE_LOAD_TIMEOUT = 2000;
private OnlineShareWidget[] showWidgets;
private PreviewDialog previewDialog;
private JPanel widgetPane;
private final CountDownLatch countDownLatch = new CountDownLatch(1);
private final AWTEventListener awtEventListener;
public OnlineEmbedFilterSelectPane(final DataLoad<OnlineShareWidget> dataLoad, FilterPane filterPane, int widgetsPerNum) {
super(dataLoad, filterPane, widgetsPerNum);
awtEventListener = event -> {
if (event instanceof MouseEvent) {
if (((MouseEvent) event).getClickCount() > 0) {
try {
Point selectPanePoint = OnlineEmbedFilterSelectPane.this.getLocationOnScreen();
Dimension selectPaneDimension = OnlineEmbedFilterSelectPane.this.getSize();
Rectangle selectPaneRec = new Rectangle(selectPanePoint.x, selectPanePoint.y, selectPaneDimension.width, selectPaneDimension.height);
if (CarouselStateManger.getInstance().running() &&
!selectPaneRec.contains(((MouseEvent) event).getLocationOnScreen())) {
CarouselStateManger.getInstance().stop();
}
} catch (Exception e) {
//忽略
}
}
}
};
java.awt.Toolkit.getDefaultToolkit().addAWTEventListener(awtEventListener, AWTEvent.MOUSE_EVENT_MASK);
}
protected UIScrollPane createScrollPane() {
showWidgets = getShowWidgets();
widgetPane = createWidgetPane();
widgetPane.setLayout(new FlowLayout(FlowLayout.LEFT, H_GAP, V_GAP));
previewDialog = new PreviewDialog();
widgetPane.setPreferredSize(new Dimension(240, getPaneHeight(showWidgets.length)));
UIScrollPane scrollPane = new UIScrollPane(createContentPane(widgetPane));
setScrollPaneStyle(scrollPane);
return scrollPane;
}
protected void fireAfterDataLoad() {
super.fireAfterDataLoad();
countDownLatch.countDown();
}
public void animate() throws InterruptedException {
countDownLatch.await();
AtomicInteger integer = new AtomicInteger(showWidgets.length - 1);
showCurrentLoadBlock(integer, widgetPane);
this.repaint();
CarouselStateManger.getInstance().start();
previewDialog.setVisible(true);
}
private Image getPreviewImage(String url) throws NetWorkFailedException {
try {
url = UriUtils.encodePath(url, EncodeConstants.ENCODING_UTF_8);
} catch (UnsupportedEncodingException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return ShareComponentConstants.DEFAULT_COVER;
}
HttpClient httpClient = new HttpClient(url);
httpClient.setTimeout(CAROUSE_IMAGE_LOAD_TIMEOUT);
httpClient.asGet();
int responseCode = httpClient.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
throw new NetWorkFailedException();
}
try {
return ImageIO.read(httpClient.getResponseStream());
} catch (IOException e) {
throw new NetWorkFailedException();
}
}
private void showCurrentLoadBlock(AtomicInteger integer, JPanel widgetPane) {
ScheduledExecutorService service = createToastScheduleExecutorService();
OnlineShareWidget shareWidget = showWidgets[integer.get()];
widgetPane.add(createWidgetBlock(shareWidget), 0);
this.doLayout();
this.validate();
this.repaint();
try {
previewDialog.setImage(getPreviewImage(shareWidget.getPicPath()), widgetPane.getLocationOnScreen());
} catch (NetWorkFailedException e) {
this.stopCarouse(integer, false);
this.switchPane(PaneStatue.DISCONNECTED);
return;
}
//展示弹出框
service.schedule(new Runnable() {
@Override
public void run() {
if (CarouselStateManger.getInstance().stopped()) {
stopCarouse(integer);
return;
}
if (integer.get() == 0) {
CarouselStateManger.getInstance().stop();
stopCarouse(integer);
previewDialog.setVisible(false);
return;
}
integer.decrementAndGet();
if (!CarouselStateManger.getInstance().isSuspend()) {
showCurrentLoadBlock(integer, widgetPane);
} else {
previewDialog.setVisible(false);
pollingCarouselState(integer, widgetPane);
}
}
}, 500, TimeUnit.MILLISECONDS);
}
private void pollingCarouselState(AtomicInteger integer, JPanel widgetPane) {
ScheduledExecutorService service = createToastScheduleExecutorService();
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
if (CarouselStateManger.getInstance().stopped()) {
stopCarouse(integer);
return;
}
if (!CarouselStateManger.getInstance().isSuspend()) {
previewDialog.setVisible(true);
showCurrentLoadBlock(integer, widgetPane);
service.shutdown();
}
}
}, 0, 500, TimeUnit.MILLISECONDS);
}
private void stopCarouse(AtomicInteger integer) {
this.stopCarouse(integer, true);
}
private void stopCarouse(AtomicInteger integer, boolean showExtra) {
previewDialog.setVisible(false);
if (showExtra) {
loadRestShowWidgets(integer.get() - 1);
}
java.awt.Toolkit.getDefaultToolkit().removeAWTEventListener(awtEventListener);
}
private void loadRestShowWidgets(int startIndex) {
for (int i = startIndex; i >= 0; i--) {
OnlineShareWidget shareWidget = showWidgets[i];
widgetPane.add(createWidgetBlock(shareWidget));
}
this.doLayout();
this.validate();
this.repaint();
}
private ScheduledExecutorService createToastScheduleExecutorService() {
return ModuleContext.getExecutor().newSingleThreadScheduledExecutor(new NamedThreadFactory(CAROUSEL_PREVIEW));
}
}

62
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/OnlineEmbedFilterShowPane.java

@ -0,0 +1,62 @@
package com.fr.design.mainframe.share.ui.online.embed;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.ComponentShareUtil;
import com.fr.design.mainframe.share.ui.online.OnlineWidgetShowPane;
import com.fr.design.mainframe.share.Bean.WidgetFilterInfo;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.util.List;
/**
* Created by kerry on 2021/10/22
*/
public class OnlineEmbedFilterShowPane extends JPanel {
private final OnlineWidgetShowPane onlineWidgetShowPane;
private final EmbedPane embedPane;
private OnlineEmbedFilterSelectPane selectPane;
public OnlineEmbedFilterShowPane(OnlineWidgetShowPane onlineWidgetShowPane) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
embedPane = new EmbedPane(this);
embedPane.setLocation(10, 0);
embedPane.setSize(228, embedPane.getPreferredSize().height);
this.add(embedPane, BorderLayout.NORTH);
this.onlineWidgetShowPane = onlineWidgetShowPane;
this.onlineWidgetShowPane.setToolBarPaneVisible(false);
this.add(onlineWidgetShowPane, BorderLayout.CENTER);
}
public void filterStateChanged(String filterStr) {
this.removeAll();
this.add(embedPane);
this.add(onlineWidgetShowPane, BorderLayout.CENTER);
this.validate();
this.doLayout();
this.repaint();
onlineWidgetShowPane.setToolBarPaneVisible(true);
selectPane = onlineWidgetShowPane.animate(filterStr);
}
public void animate(List<WidgetFilterInfo> selectedFilters) throws InterruptedException {
onlineWidgetShowPane.setFilterItems(selectedFilters);
selectPane.animate();
}
public void refreshUI(){
if (embedPane != null) {
this.repaint();
}
}
public void completeEmbedFilter(){
if (embedPane!= null && embedPane.isShowing()){
this.remove(embedPane);
ComponentShareUtil.completeEmbedFilter();
this.doLayout();
this.repaint();
}
}
}

37
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/embed/PreviewDialog.java

@ -0,0 +1,37 @@
package com.fr.design.mainframe.share.ui.online.embed;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.share.ui.online.PreviewImagePane;
import javax.swing.JDialog;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
/**
* Created by kerry on 2021/10/22
*/
public class PreviewDialog extends JDialog {
private static final int OFFSET_Y = 9;
public PreviewDialog() {
super(DesignerContext.getDesignerFrame());
setUndecorated(true);
this.setVisible(false);
}
public void setImage(Image image, Point point) {
this.getContentPane().removeAll();
PreviewImagePane previewImagePane = new PreviewImagePane();
previewImagePane.setPreviewImage(image);
Dimension dimension = previewImagePane.getPreferredSize();
this.getContentPane().add(previewImagePane);
setSize(new Dimension(dimension.width, dimension.height));
this.setLocation(point.x - dimension.width, point.y + OFFSET_Y);
this.doLayout();
this.validate();
this.repaint();
}
}

31
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineResourceManager.java → designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/resource/OnlineResourceManager.java

@ -1,8 +1,8 @@
package com.fr.design.mainframe.share.ui.online;
package com.fr.design.mainframe.share.ui.online.resource;
import javax.swing.SwingWorker;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* Created by kerry on 2020-12-10
@ -12,34 +12,45 @@ public class OnlineResourceManager {
private static final OnlineResourceManager singleton = new OnlineResourceManager();
}
private OnlineResourceManager(){
private OnlineResourceManager() {
}
public static OnlineResourceManager getInstance() {
return HOLDER.singleton;
}
private SwingWorker<Boolean,Void> swingWorker;
private SwingWorker<Boolean, Void> swingWorker;
private final List<ResourceLoader> loaderList = new ArrayList<>();
private final BlockingQueue<ResourceLoader> loaderBlockingQueue = new ArrayBlockingQueue<ResourceLoader>(100);
public void cancelLoad() {
if (swingWorker != null) {
swingWorker.cancel(true);
}
this.loaderList.clear();
this.loaderBlockingQueue.clear();
}
public void addLoader(ResourceLoader loader) {
this.loaderList.add(loader);
try {
this.loaderBlockingQueue.put(loader);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void loadImage() {
swingWorker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() {
for (ResourceLoader loader : loaderList) {
while (!swingWorker.isCancelled()) {
ResourceLoader loader = null;
try {
loader = loaderBlockingQueue.take();
} catch (InterruptedException e) {
}
loader.load();
}
return true;

2
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/ResourceLoader.java → designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/resource/ResourceLoader.java

@ -1,4 +1,4 @@
package com.fr.design.mainframe.share.ui.online;
package com.fr.design.mainframe.share.ui.online.resource;
/**
* Created by kerry on 2020-12-10

12
designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/widgetpackage/OnlineWidgetPackagesShowPane.java

@ -9,11 +9,15 @@ import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.login.DesignerLoginHelper;
import com.fr.design.login.DesignerLoginSource;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.share.sort.OnlineWidgetSortType;
import com.fr.design.mainframe.share.ui.base.MouseClickListener;
import com.fr.design.mainframe.share.ui.online.AbstractOnlineWidgetSelectPane;
import com.fr.design.mainframe.share.ui.online.AbstractOnlineWidgetShowPane;
import com.fr.design.mainframe.share.ui.online.OnlineDownloadPackagePane;
import com.fr.design.mainframe.share.ui.online.OnlineWidgetSelectPane;
import com.fr.design.mainframe.share.ui.widgetfilter.FilterPane;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.design.mainframe.share.util.ShareUIUtils;
import com.fr.form.share.base.DataLoad;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.utils.ShareUtils;
@ -51,8 +55,8 @@ public class OnlineWidgetPackagesShowPane extends AbstractOnlineWidgetShowPane {
super(sharableWidgetProviders);
}
protected JPanel initContentPane() {
JPanel firstPane = super.initContentPane();
protected JPanel initContentPane(OnlineWidgetSortType sortType) {
JPanel firstPane = super.initContentPane(sortType);
cardLayout = new CardLayout();
centerPane = new JPanel(cardLayout);
centerPane.add(firstPane, WIDGETS_INFO);
@ -132,7 +136,7 @@ public class OnlineWidgetPackagesShowPane extends AbstractOnlineWidgetShowPane {
}
protected OnlineWidgetSelectPane createOnlineWidgetSelectPane(OnlineShareWidget[] sharableWidgetProviders) {
protected AbstractOnlineWidgetSelectPane createOnlineWidgetSelectPane(OnlineShareWidget[] sharableWidgetProviders) {
return new OnlineWidgetPackageSelectPane(filterPackageWidget(sharableWidgetProviders), 10, this);
}
@ -154,7 +158,7 @@ public class OnlineWidgetPackagesShowPane extends AbstractOnlineWidgetShowPane {
String id = widgetPackage.getId();
currentPackageId = id;
boolean containsCache = cachePanelMap.containsKey(id);
onlineWidgetSelectPane = containsCache ? cachePanelMap.get(id) : new OnlineWidgetSelectPane(() -> ShareUtils.getPackageWidgets(widgetPackage), 50);
onlineWidgetSelectPane = containsCache ? cachePanelMap.get(id) : new OnlineWidgetSelectPane(() -> OnlineShopUtils.getPackageWidgets(widgetPackage), 50);
downloadLabel.setVisible(!containsCache);
showWidgetDetailPane(onlineWidgetSelectPane);
}

285
designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/FilterConfigPane.java

@ -0,0 +1,285 @@
package com.fr.design.mainframe.share.ui.widgetfilter;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.mainframe.share.Bean.FilterTypeInfo;
import com.fr.design.mainframe.share.Bean.WidgetFilterInfo;
import com.fr.design.mainframe.share.Bean.WidgetFilterTypeInfo;
import com.fr.general.ComparatorUtils;
import com.fr.stable.StringUtils;
import com.fr.third.javax.annotation.Nullable;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
/**
* Created by kerry on 2021/11/1
*/
public abstract class FilterConfigPane extends JPanel {
private static final Color BORDER_COLOR = Color.decode("#D9DADD");
private static final String FILTER_ALL_ID = "0";
public static final int CONTENT_WIDTH = 225;
private final List<WidgetFilterInfo> filterList = new ArrayList<>();
private final List<FilterCheckBox> checkBoxList = new ArrayList<>();
private boolean reset = false;
private boolean showChildNode;
public FilterConfigPane(List<FilterTypeInfo> widgetFilterCategories, boolean showChildNode) {
this.showChildNode = showChildNode;
initPane(widgetFilterCategories);
}
public FilterConfigPane(List<FilterTypeInfo> widgetFilterCategories) {
this(widgetFilterCategories, true);
}
private void initPane(List<FilterTypeInfo> widgetFilterCategories) {
this.setBackground(Color.WHITE);
this.setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
this.setForeground(Color.decode("#FFFFFF"));
this.setLayout(new BorderLayout());
this.add(createVerticalFlowPane(widgetFilterCategories), BorderLayout.CENTER);
}
public boolean hasFilter() {
return filterList.size() > 0;
}
public List<WidgetFilterInfo> getFilterList() {
return filterList;
}
private JPanel createVerticalFlowPane(List<FilterTypeInfo> widgetFilterCategories) {
JPanel verticalFlowPane = new JPanel();
verticalFlowPane.setBackground(Color.WHITE);
VerticalFlowLayout layout = new VerticalFlowLayout(FlowLayout.LEADING, 0, 10);
layout.setAlignLeft(true);
verticalFlowPane.setLayout(layout);
verticalFlowPane.setBackground(Color.WHITE);
verticalFlowPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
for (FilterTypeInfo filterTypeInfo : widgetFilterCategories) {
verticalFlowPane.add(createCategoryPane(filterTypeInfo));
}
return verticalFlowPane;
}
private JPanel createTypeFilterPane(WidgetFilterTypeInfo widgetFilterTypeInfo) {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.setBackground(Color.WHITE);
UILabel titleLabel = new UILabel(widgetFilterTypeInfo.getTitle() + ":");
titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
titleLabel.setFont(new Font(titleLabel.getFont().getName(), Font.BOLD, titleLabel.getFont().getSize()));
jPanel.add(titleLabel, BorderLayout.NORTH);
jPanel.add(createCategoryDetailPane(widgetFilterTypeInfo), BorderLayout.CENTER);
return jPanel;
}
private JPanel createCategoryPane(FilterTypeInfo filterTypeInfo) {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.setBackground(Color.WHITE);
UILabel titleLabel = new UILabel(filterTypeInfo.getTitle());
titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
titleLabel.setPreferredSize(new Dimension(CONTENT_WIDTH - 2, 20));
titleLabel.setOpaque(true);
titleLabel.setBackground(Color.decode("#EDEDEE"));
jPanel.add(titleLabel, BorderLayout.NORTH);
jPanel.add(createCategoryDetailPane(filterTypeInfo.getFilterTypeInfos()), BorderLayout.CENTER);
return jPanel;
}
private JPanel createCategoryDetailPane(List<WidgetFilterTypeInfo> filterTypeInfoList) {
if (filterTypeInfoList.size() == 1) {
return createCategoryDetailPane(filterTypeInfoList.get(0));
}
JPanel contentPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10);
contentPane.setBackground(Color.WHITE);
for (WidgetFilterTypeInfo info : filterTypeInfoList) {
contentPane.add(createTypeFilterPane(info));
}
return contentPane;
}
private JPanel createCategoryDetailPane(WidgetFilterTypeInfo filterTypeInfo) {
JPanel contentPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(2);
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
contentPane.setBackground(Color.WHITE);
contentPane.setPreferredSize(new Dimension(CONTENT_WIDTH, calculateDetailPaneHeight(filterTypeInfo)));
for (final WidgetFilterInfo filterInfo : filterTypeInfo.getFilterItems()) {
if (ComparatorUtils.equals(FILTER_ALL_ID, filterInfo.getId())) {
continue;
}
FilterCheckBox checkBox = createCheckBox(filterInfo);
contentPane.add(checkBox);
if (showChildNode && filterInfo.hasChildFilter()) {
alignmentFilling(contentPane);
createChildPane(filterInfo.getInnerFilterInfo(), contentPane, checkBox);
alignmentFilling(contentPane);
}
}
return contentPane;
}
private void alignmentFilling(JPanel contentPane) {
if (contentPane.getComponentCount() % 2 == 1) {
contentPane.add(new UILabel(""));
}
}
private FilterCheckBox createCheckBox(WidgetFilterInfo filterInfo) {
final FilterCheckBox checkBox = new FilterCheckBox(filterInfo.getName(), filterInfo);
checkBox.setBackground(Color.WHITE);
checkBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (checkBox.isSelected() && (!checkBox.getFilterInfo().hasChildFilter() || !showChildNode)) {
filterList.add(filterInfo);
} else if (filterList.contains(filterInfo)) {
filterList.remove(filterInfo);
}
if (reset) {
return;
}
fireSelectedChanged(new ChangeEvent(assembleFilter()));
}
});
checkBoxList.add(checkBox);
return checkBox;
}
private void createChildPane(List<WidgetFilterInfo> childFilterInfo, JPanel contentPane, FilterCheckBox parentCheckBox) {
List<FilterCheckBox> childCheckboxList = new ArrayList<>();
for (WidgetFilterInfo filterInfo : childFilterInfo) {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.setBackground(Color.WHITE);
jPanel.setBorder(BorderFactory.createEmptyBorder(0, 16, 0, 0));
FilterCheckBox checkBox = createCheckBox(filterInfo);
checkBox.addItemListener(e -> {
if (this.reset) {
return;
}
this.reset = true;
parentCheckBox.setSelected(allChildSelected(childCheckboxList));
this.reset = false;
});
childCheckboxList.add(checkBox);
jPanel.add(checkBox, BorderLayout.CENTER);
contentPane.add(jPanel);
}
parentCheckBox.addItemListener(e -> {
if (this.reset) {
return;
}
this.reset = true;
for (FilterCheckBox checkBox : childCheckboxList) {
checkBox.setSelected(parentCheckBox.isSelected());
}
this.reset = false;
});
}
private boolean allChildSelected(List<FilterCheckBox> childCheckboxList) {
boolean flag = true;
for (FilterCheckBox checkBox : childCheckboxList) {
flag &= checkBox.isSelected();
}
return flag;
}
private int calculateDetailPaneHeight(WidgetFilterTypeInfo filterTypeInfo) {
int displayCount = 0;
for (final WidgetFilterInfo filterInfo : filterTypeInfo.getFilterItems()) {
if (!ComparatorUtils.equals(FILTER_ALL_ID, filterInfo.getId())) {
displayCount++;
}
if (filterInfo.getInnerFilterInfo().size() > 0 && showChildNode) {
displayCount += (1 + filterInfo.getInnerFilterInfo().size());
}
}
return ((displayCount + 1) / 2) * 27;
}
public abstract String assembleFilter();
public void setFilters(List<WidgetFilterInfo> selectedFilters) {
reset = true;
filterList.clear();
setFilterList(selectedFilters);
reset = false;
}
private void setFilterList(List<WidgetFilterInfo> selectedFilters){
for (FilterCheckBox checkBox : checkBoxList) {
String filterName = checkBox.getFilterInfo().getName();
WidgetFilterInfo selectFilterInfo = getSelectFilterInfoByName(selectedFilters, filterName);
if (selectFilterInfo == null) {
continue;
}
checkBox.setSelected(true);
if (selectFilterInfo.hasChildFilter()) {
setFilterList(selectFilterInfo.getInnerFilterInfo());
}
}
}
@Nullable
private WidgetFilterInfo getSelectFilterInfoByName(List<WidgetFilterInfo> selectedFilters, String name) {
for (WidgetFilterInfo filterInfo : selectedFilters) {
if (ComparatorUtils.equals(filterInfo.getName(), name)) {
return filterInfo;
}
}
return null;
}
public void reset() {
reset = true;
for (FilterCheckBox checkBox : checkBoxList) {
checkBox.setSelected(false);
}
filterList.clear();
fireSelectedChanged(new ChangeEvent(StringUtils.EMPTY));
reset = false;
}
protected void fireSelectedChanged(ChangeEvent changeEvent) {
}
private class FilterCheckBox extends UICheckBox {
private WidgetFilterInfo filterInfo;
public FilterCheckBox(String string, WidgetFilterInfo filterInfo) {
super(string);
this.filterInfo = filterInfo;
}
public WidgetFilterInfo getFilterInfo() {
return this.filterInfo;
}
}
}

25
designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/FilterPane.java

@ -5,8 +5,10 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.share.ui.base.MouseClickListener;
import com.fr.form.share.bean.WidgetFilterTypeInfo;
import com.fr.form.share.utils.ShareUtils;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.design.mainframe.share.Bean.FilterTypeInfo;
import com.fr.design.mainframe.share.Bean.WidgetFilterInfo;
import com.fr.design.mainframe.share.util.ShareFilterConstants;
import com.fr.general.ComparatorUtils;
import com.fr.invoke.Reflect;
@ -35,10 +37,6 @@ import java.util.List;
* Created by kerry on 2020-10-21
*/
public class FilterPane extends JPanel {
public static final String SOURCE_FILTER_KEY = "2@source";
public static final String CHART_FILTER_KEY = "3@chart";
public static final String REPORT_FILTER_KEY = "4@report";
private static final Icon FILTER_COMBO = BaseUtils.readIcon("/com/fr/base/images/share/filter_combo.png");
private static final Icon FILTER_COMBO_UP = BaseUtils.readIcon("/com/fr/base/images/share/filter_combo_up.png");
private final UILabel filterLabel;
@ -115,10 +113,9 @@ public class FilterPane extends JPanel {
public static FilterPane createOnlinePackageFilterPane() {
FilterPane pane = new FilterPane() {
@Override
protected List<WidgetFilterTypeInfo> loadFilterCategories() {
List<WidgetFilterTypeInfo> filterTypeInfos = super.loadFilterCategories();
filterTypeInfos.removeIf(info -> ComparatorUtils.equals(FilterPane.CHART_FILTER_KEY, info.getKey())
|| ComparatorUtils.equals(FilterPane.REPORT_FILTER_KEY, info.getKey()));
protected List<FilterTypeInfo> loadFilterCategories() {
List<FilterTypeInfo> filterTypeInfos = super.loadFilterCategories();
filterTypeInfos.removeIf(info -> ComparatorUtils.equals(ShareFilterConstants.WIDGET_TYPE_FILTER_KEY, info.getKey()));
return filterTypeInfos;
}
};
@ -166,8 +163,8 @@ public class FilterPane extends JPanel {
java.awt.Toolkit.getDefaultToolkit().removeAWTEventListener(awtEventListener);
}
protected List<WidgetFilterTypeInfo> loadFilterCategories() {
return ShareUtils.getWidgetFilterTypeInfos();
protected List<FilterTypeInfo> loadFilterCategories() {
return OnlineShopUtils.getShowFilterTypeInfos();
}
private boolean isCanHide(MouseEvent mv, JPanel jPanel) {
@ -208,6 +205,10 @@ public class FilterPane extends JPanel {
switchToNoFilter();
}
public void setFilter(List<WidgetFilterInfo> selectedFilters){
filterPopupPane.setFilters(selectedFilters);
}
private void switchToNoFilter() {
filterLabel.setText(Toolkit.i18nText("Fine-Design_Share_Online_No_Filter"));
filterLabel.setForeground(Color.decode("#8F8F92"));

192
designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/FilterPopupPane.java

@ -1,203 +1,33 @@
package com.fr.design.mainframe.share.ui.widgetfilter;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.form.share.bean.WidgetFilterInfo;
import com.fr.form.share.bean.WidgetFilterTypeInfo;
import com.fr.general.ComparatorUtils;
import com.fr.stable.StringUtils;
import com.fr.design.mainframe.share.Bean.FilterTypeInfo;
import com.fr.design.mainframe.share.Bean.WidgetFilterInfo;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: Yuan.Wang
* @Date: 2020/11/11
*/
public abstract class FilterPopupPane extends JPanel {
private static final Color BORDER_COLOR = Color.decode("#D9DADD");
private static final String FILTER_ALL_ID = "0";
public abstract class FilterPopupPane extends FilterConfigPane {
public static final int CONTENT_WIDTH = 225;
private final FilterPane filterPane;
FilterPane filterPane;
private List<WidgetFilterInfo> filterList = new ArrayList<>();
private final List<UICheckBox> checkBoxList = new ArrayList<>();
private boolean reset = false;
public FilterPopupPane(FilterPane filterPane, List<WidgetFilterTypeInfo> widgetFilterCategories) {
public FilterPopupPane(FilterPane filterPane, List<FilterTypeInfo> widgetFilterCategories) {
super(widgetFilterCategories);
this.filterPane = filterPane;
initPane(widgetFilterCategories);
}
private void initPane(List<WidgetFilterTypeInfo> widgetFilterCategories) {
this.setBackground(Color.WHITE);
this.setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
this.setForeground(Color.decode("#FFFFFF"));
this.setLayout(new BorderLayout());
this.add(createVerticalFlowPane(widgetFilterCategories), BorderLayout.CENTER);
}
public boolean hasFilter() {
return filterList.size() > 0;
}
protected List<WidgetFilterInfo> getFilterList() {
return filterList;
}
private JPanel createVerticalFlowPane(List<WidgetFilterTypeInfo> widgetFilterCategories) {
List<WidgetFilterTypeInfo> topWidgetTypeFilter = new ArrayList<>();
List<WidgetFilterTypeInfo> widgetTypeFilter = new ArrayList<>();
List<WidgetFilterTypeInfo> otherWidgetTypeFilter = new ArrayList<>();
for (WidgetFilterTypeInfo info : widgetFilterCategories) {
if (ComparatorUtils.equals(FilterPane.CHART_FILTER_KEY, info.getKey())
|| ComparatorUtils.equals(FilterPane.REPORT_FILTER_KEY, info.getKey())) {
widgetTypeFilter.add(info);
} else if (ComparatorUtils.equals(FilterPane.SOURCE_FILTER_KEY, info.getKey())) {
topWidgetTypeFilter.add(info);
} else {
otherWidgetTypeFilter.add(info);
}
}
JPanel verticalFlowPane = new JPanel();
verticalFlowPane.setBackground(Color.WHITE);
VerticalFlowLayout layout = new VerticalFlowLayout(FlowLayout.LEADING, 0, 10);
layout.setAlignLeft(true);
verticalFlowPane.setLayout(layout);
verticalFlowPane.setBackground(Color.WHITE);
verticalFlowPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
for (WidgetFilterTypeInfo info : topWidgetTypeFilter) {
verticalFlowPane.add(createOtherCategoryPane(info));
}
if (widgetTypeFilter.size() > 0) {
verticalFlowPane.add(createWidgetTypeFilterPane(widgetTypeFilter));
}
for (WidgetFilterTypeInfo info : otherWidgetTypeFilter) {
verticalFlowPane.add(createOtherCategoryPane(info));
}
return verticalFlowPane;
public void setFilters(List<WidgetFilterInfo> selectedFilters) {
super.setFilters(selectedFilters);
filterPane.changeFilterButtonStatus(hasFilter());
}
private JPanel createWidgetTypeFilterPane(List<WidgetFilterTypeInfo> widgetTypeFilter) {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.setBackground(Color.WHITE);
UILabel titleLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Type"));
titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
titleLabel.setPreferredSize(new Dimension(CONTENT_WIDTH - 2, 20));
titleLabel.setOpaque(true);
titleLabel.setBackground(Color.decode("#EDEDEE"));
jPanel.add(titleLabel, BorderLayout.NORTH);
JPanel contentPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 10);
contentPane.setBackground(Color.WHITE);
for (WidgetFilterTypeInfo info : widgetTypeFilter) {
contentPane.add(createTypeFilterPane(info));
}
jPanel.add(contentPane, BorderLayout.CENTER);
return jPanel;
}
private JPanel createTypeFilterPane(WidgetFilterTypeInfo widgetFilterTypeInfo) {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.setBackground(Color.WHITE);
UILabel titleLabel = new UILabel(widgetFilterTypeInfo.getTitle() + ":");
titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
titleLabel.setFont(new Font(titleLabel.getFont().getName(), Font.BOLD, titleLabel.getFont().getSize()));
jPanel.add(titleLabel, BorderLayout.NORTH);
jPanel.add(createCategoryDetailPane(widgetFilterTypeInfo), BorderLayout.CENTER);
return jPanel;
}
private JPanel createOtherCategoryPane(WidgetFilterTypeInfo filterTypeInfo) {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.setBackground(Color.WHITE);
UILabel titleLabel = new UILabel(filterTypeInfo.getTitle());
titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
titleLabel.setPreferredSize(new Dimension(CONTENT_WIDTH - 2, 20));
titleLabel.setOpaque(true);
titleLabel.setBackground(Color.decode("#EDEDEE"));
jPanel.add(titleLabel, BorderLayout.NORTH);
jPanel.add(createCategoryDetailPane(filterTypeInfo), BorderLayout.CENTER);
return jPanel;
}
private JPanel createCategoryDetailPane(WidgetFilterTypeInfo filterTypeInfo) {
JPanel contentPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(2);
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
contentPane.setBackground(Color.WHITE);
int displayCount = 0;
for (final WidgetFilterInfo filterInfo : filterTypeInfo.getFilterItems()) {
if (!ComparatorUtils.equals(FILTER_ALL_ID, filterInfo.getId())) {
displayCount++;
}
}
int contentPaneHeight = ((displayCount + 1) / 2) * 27;
contentPane.setPreferredSize(new Dimension(CONTENT_WIDTH, contentPaneHeight));
for (final WidgetFilterInfo filterInfo : filterTypeInfo.getFilterItems()) {
if (ComparatorUtils.equals(FILTER_ALL_ID, filterInfo.getId())) {
continue;
}
final UICheckBox checkBox = new UICheckBox(filterInfo.getName());
checkBox.setBackground(Color.WHITE);
checkBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (reset) {
return;
}
if (checkBox.isSelected()) {
filterList.add(filterInfo);
} else if (filterList.contains(filterInfo)) {
filterList.remove(filterInfo);
}
checkFilterButtonStatus();
filterPane.fireChangeListener(new ChangeEvent(assembleFilter()));
}
});
checkBoxList.add(checkBox);
contentPane.add(checkBox);
}
return contentPane;
}
protected abstract String assembleFilter();
private void checkFilterButtonStatus() {
protected void fireSelectedChanged(ChangeEvent changeEvent){
filterPane.changeFilterButtonStatus(hasFilter());
filterPane.fireChangeListener(changeEvent);
}
public void reset() {
reset = true;
for (UICheckBox checkBox : checkBoxList) {
checkBox.setSelected(false);
}
filterList.clear();
checkFilterButtonStatus();
filterPane.fireChangeListener(new ChangeEvent(StringUtils.EMPTY));
reset = false;
}
}

6
designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/LocalFilterPopupPane.java

@ -1,6 +1,6 @@
package com.fr.design.mainframe.share.ui.widgetfilter;
import com.fr.form.share.bean.WidgetFilterTypeInfo;
import com.fr.design.mainframe.share.Bean.FilterTypeInfo;
import com.fr.stable.StringUtils;
import java.util.ArrayList;
@ -11,12 +11,12 @@ import java.util.List;
* @Date: 2020/11/11
*/
public class LocalFilterPopupPane extends FilterPopupPane {
public LocalFilterPopupPane(FilterPane pane, List<WidgetFilterTypeInfo> loadFilterCategories) {
public LocalFilterPopupPane(FilterPane pane, List<FilterTypeInfo> loadFilterCategories) {
super(pane, loadFilterCategories);
}
@Override
protected String assembleFilter() {
public String assembleFilter() {
LocalWidgetFilter.getInstance().setFilterList(getFilterList() == null ? new ArrayList<>() : getFilterList());
return StringUtils.EMPTY;
}

2
designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/LocalWidgetFilter.java

@ -3,7 +3,7 @@ package com.fr.design.mainframe.share.ui.widgetfilter;
import com.fr.design.i18n.Toolkit;
import com.fr.form.share.DefaultSharableWidget;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.bean.WidgetFilterInfo;
import com.fr.design.mainframe.share.Bean.WidgetFilterInfo;
import com.fr.design.mainframe.share.constants.DisplayDevice;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StringUtils;

118
designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/LocalWidgetFilterCategory.java

@ -1,7 +1,10 @@
package com.fr.design.mainframe.share.ui.widgetfilter;
import com.fr.form.share.bean.WidgetFilterInfo;
import com.fr.form.share.bean.WidgetFilterTypeInfo;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.Bean.FilterTypeInfo;
import com.fr.design.mainframe.share.Bean.WidgetFilterInfo;
import com.fr.design.mainframe.share.Bean.WidgetFilterTypeInfo;
import com.fr.design.mainframe.share.util.ShareFilterConstants;
import java.util.ArrayList;
import java.util.List;
@ -12,69 +15,78 @@ import java.util.List;
*/
public class LocalWidgetFilterCategory {
public static List<WidgetFilterTypeInfo> getLocalCategory() {
List<WidgetFilterTypeInfo> category = new ArrayList<>();
public static List<FilterTypeInfo> getLocalCategory() {
List<FilterTypeInfo> category = new ArrayList<>();
WidgetFilterTypeInfo source = new WidgetFilterTypeInfo();
source.setTitle("来源");
source.setKey("2@source");
source.addFilterItem(new WidgetFilterInfo("本地", "1", "source"));
source.addFilterItem(new WidgetFilterInfo("商城", "2", "source"));
source.addFilterItem(new WidgetFilterInfo("全部", "0", "source"));
source.setTitle(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Source"));
source.setKey(ShareFilterConstants.SOURCE_TYPE_FILTER_KEY);
source.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Local"), "1", "source"));
source.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Shop"), "2", "source"));
source.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "source"));
FilterTypeInfo sourceTypeInfo = new FilterTypeInfo(source.getTitle(), source.getKey());
sourceTypeInfo.addFilterType(source);
WidgetFilterTypeInfo displayDevice = new WidgetFilterTypeInfo();
displayDevice.setTitle("展示终端");
displayDevice.setKey("1@displayDevice");
displayDevice.addFilterItem(new WidgetFilterInfo("PC端", "1", "displayDevice"));
displayDevice.addFilterItem(new WidgetFilterInfo("移动端", "2", "displayDevice"));
displayDevice.addFilterItem(new WidgetFilterInfo("全部", "0", "displayDevice"));
displayDevice.setTitle(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Show_Device"));
displayDevice.setKey(ShareFilterConstants.SHOW_TERMINAL_FILTER_KEY);
displayDevice.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_PC"), "1", "displayDevice"));
displayDevice.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Mobile"), "2", "displayDevice"));
displayDevice.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "displayDevice"));
FilterTypeInfo showDeviceTypeInfo = new FilterTypeInfo(displayDevice.getTitle(), displayDevice.getKey());
showDeviceTypeInfo.addFilterType(displayDevice);
WidgetFilterTypeInfo fee = new WidgetFilterTypeInfo();
fee.setTitle("价格");
fee.setKey("2@fee");
fee.addFilterItem(new WidgetFilterInfo("付费", "2", "fee"));
fee.addFilterItem(new WidgetFilterInfo("免费", "1", "fee"));
fee.addFilterItem(new WidgetFilterInfo("全部", "0", "fee"));
fee.setTitle(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Price"));
fee.setKey(ShareFilterConstants.FEE_FILTER_KEY);
fee.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Pay"), "2", "fee"));
fee.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Free"), "1", "fee"));
fee.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "fee"));
FilterTypeInfo feeTypeInfo = new FilterTypeInfo(fee.getTitle(), fee.getKey());
feeTypeInfo.addFilterType(fee);
WidgetFilterTypeInfo chart = new WidgetFilterTypeInfo();
chart.setTitle("基础元素");
chart.setKey("3@chart");
chart.addFilterItem(new WidgetFilterInfo("柱形图/条形图", "1", "chart"));
chart.addFilterItem(new WidgetFilterInfo("折线图", "3", "chart"));
chart.addFilterItem(new WidgetFilterInfo("组合图", "4", "chart"));
chart.addFilterItem(new WidgetFilterInfo("饼图", "2", "chart"));
chart.addFilterItem(new WidgetFilterInfo("仪表盘", "5", "chart"));
chart.addFilterItem(new WidgetFilterInfo("地图", "6", "chart"));
chart.addFilterItem(new WidgetFilterInfo("其他图表", "7", "chart"));
chart.addFilterItem(new WidgetFilterInfo("明细表", "8", "chart"));
chart.addFilterItem(new WidgetFilterInfo("基础控件", "9", "chart"));
chart.addFilterItem(new WidgetFilterInfo("全部", "0", "chart"));
chart.setTitle(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Basic_Element"));
chart.setKey(ShareFilterConstants.CHART_FILTER_KEY);
chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Bar_Chart"), "1", "chart"));
chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Line_Chart"), "3", "chart"));
chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Combination_Chart"), "4", "chart"));
chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Pie_Chart"), "2", "chart"));
chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Dashboard_Chart"), "5", "chart"));
chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Map"), "6", "chart"));
chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Other_Chart"), "7", "chart"));
chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Detail_List"), "8", "chart"));
chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Basic_Widget"), "9", "chart"));
chart.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "chart"));
WidgetFilterTypeInfo report = new WidgetFilterTypeInfo();
report.setTitle("综合应用");
report.setKey("4@report");
report.addFilterItem(new WidgetFilterInfo("指标卡", "1", "report"));
report.addFilterItem(new WidgetFilterInfo("标题头", "2", "report"));
report.addFilterItem(new WidgetFilterInfo("特殊功能卡", "4", "report"));
report.addFilterItem(new WidgetFilterInfo("多维度切换", "5", "report"));
report.addFilterItem(new WidgetFilterInfo("移动目录导航", "6", "report"));
report.addFilterItem(new WidgetFilterInfo("填报", "8", "report"));
report.addFilterItem(new WidgetFilterInfo("全部", "0", "report"));
report.setTitle(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Comprehensive_Application"));
report.setKey(ShareFilterConstants.REPORT_FILTER_KEY);
report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Indicator_Card"), "1", "report"));
report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Title_Head"), "2", "report"));
report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Special_Function_Card"), "4", "report"));
report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Multi_Dimensional_Switch"), "5", "report"));
report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Move_Directory_Navigation"), "6", "report"));
report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Write_Report"), "8", "report"));
report.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "report"));
FilterTypeInfo widgetTypeInfo = new FilterTypeInfo(Toolkit.i18nText("Fine-Design_Share_Filter_Widget_Type"), ShareFilterConstants.WIDGET_TYPE_FILTER_KEY);
widgetTypeInfo.addFilterType(chart);
widgetTypeInfo.addFilterType(report);
WidgetFilterTypeInfo style = new WidgetFilterTypeInfo();
style.setTitle("风格");
style.setKey("5@style");
style.addFilterItem(new WidgetFilterInfo("简约清新", "1", "style"));
style.addFilterItem(new WidgetFilterInfo("商务稳重", "2", "style"));
style.addFilterItem(new WidgetFilterInfo("活泼绚丽", "3", "style"));
style.addFilterItem(new WidgetFilterInfo("酷炫科技", "4", "style"));
style.addFilterItem(new WidgetFilterInfo("其他风格", "5", "style"));
style.addFilterItem(new WidgetFilterInfo("全部", "0", "style"));
category.add(displayDevice);
category.add(source);
category.add(chart);
category.add(report);
style.setTitle(Toolkit.i18nText("Fine-Design_Share_Filter_Style"));
style.setKey(ShareFilterConstants.STYLE_FILTER_KEY);
style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Simple_Fresh"), "1", "style"));
style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Business_Stable"), "2", "style"));
style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Lively_And_Bright"), "3", "style"));
style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Cool_Technology"), "4", "style"));
style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_Other_Style"), "5", "style"));
style.addFilterItem(new WidgetFilterInfo(Toolkit.i18nText("Fine-Design_Share_Local_Filter_Item_All"), "0", "style"));
FilterTypeInfo styleTypeInfo = new FilterTypeInfo(style.getTitle(), style.getKey());
styleTypeInfo.addFilterType(style);
category.add(sourceTypeInfo);
category.add(widgetTypeInfo);
category.add(showDeviceTypeInfo);
return category;
}

10
designer-form/src/main/java/com/fr/design/mainframe/share/ui/widgetfilter/OnlineFilterPopupPane.java

@ -1,7 +1,7 @@
package com.fr.design.mainframe.share.ui.widgetfilter;
import com.fr.form.share.bean.WidgetFilterTypeInfo;
import com.fr.form.share.utils.ShareUtils;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.design.mainframe.share.Bean.FilterTypeInfo;
import java.util.List;
@ -11,12 +11,12 @@ import java.util.List;
*/
public class OnlineFilterPopupPane extends FilterPopupPane {
public OnlineFilterPopupPane(FilterPane filterPane, List<WidgetFilterTypeInfo> widgetFilterCategories) {
public OnlineFilterPopupPane(FilterPane filterPane, List<FilterTypeInfo> widgetFilterCategories) {
super(filterPane, widgetFilterCategories);
}
protected String assembleFilter() {
return ShareUtils.assembleFilter(getFilterList());
public String assembleFilter() {
return OnlineShopUtils.assembleFilter(getFilterList());
}

17
designer-form/src/main/java/com/fr/design/mainframe/share/util/DownloadUtils.java

@ -6,7 +6,6 @@ import com.fr.design.extra.PluginConstants;
import com.fr.form.share.base.CancelCheck;
import com.fr.form.share.constants.ShareComponentConstants;
import com.fr.ftp.util.Base64;
import com.fr.general.CloudCenter;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
@ -39,19 +38,23 @@ import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import static com.fr.form.share.constants.ShareComponentConstants.REU_INFO_PATH;
/**
* created by Harrison on 2020/05/27
**/
public class DownloadUtils {
private static final String REUSES_URL = StableUtils.pathJoin(ShareComponentConstants.REU_INFO_PATH, "file/download");
private static final String PACKAGE_REUSES_URL = StableUtils.pathJoin(ShareComponentConstants.REU_INFO_PATH, "package/download/");
private static final String CERTIFICATE_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtsz62CPSWXZE/IYZRiAuTSZkw\n" +
"1WOwer8+JFktK0uKLAUuQoBr+UjAMFtRA8W7JgKMDwZy/2liEAiXEOSPU/hrdV8D\n" +
"tT541LnGi1X/hXiRwuttPWYN3L2GYm/d5blU+FBNwghBIrdAxXTzYBc6P4KL/oYX\n" +
"nMdTIrkz8tYkG3QoFQIDAQAB";
private static String getReusesUrl() {
return StableUtils.pathJoin(OnlineShopUtils.getReuInfoPath(), "file/download");
}
private static String getPackageReusesUrl() {
return StableUtils.pathJoin(OnlineShopUtils.getReuInfoPath(), "package/download/");
}
private static CloseableHttpClient createClient() {
@ -65,7 +68,7 @@ public class DownloadUtils {
@NotNull
public static String download(String id, String fileName, com.fr.design.extra.Process<Double> process) throws Exception {
CloseableHttpResponse fileRes = getHttpResponse(REUSES_URL, id);
CloseableHttpResponse fileRes = getHttpResponse(getReusesUrl(), id);
if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY) {
fileRes = getHttpResponse(fileRes.getHeaders("Location")[0].getValue());
}
@ -103,7 +106,7 @@ public class DownloadUtils {
public static String downloadPackage(String id, String fileName, CancelCheck cancelCheck) throws Exception {
CloseableHttpResponse fileRes = getHttpResponse(PACKAGE_REUSES_URL, id);
CloseableHttpResponse fileRes = getHttpResponse(getPackageReusesUrl(), id);
if (fileRes.getStatusLine().getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY) {
fileRes = getHttpResponse(fileRes.getHeaders("Location")[0].getValue());
}

2
designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallUtils.java

@ -117,7 +117,7 @@ public class InstallUtils {
private static boolean installReuFile(Group group, File chosenFile, long installTime) {
try {
if (!group.installModule(chosenFile)) {
if (!group.installUniqueIdModule(chosenFile)) {
return false;
}
ShareUtils.recordInstallTime(chosenFile.getName(), installTime);

349
designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java

@ -0,0 +1,349 @@
package com.fr.design.mainframe.share.util;
import com.fr.design.DesignerCloudURLManager;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.Bean.FilterTypeInfo;
import com.fr.form.share.bean.OnlineShareWidget;
import com.fr.form.share.bean.SortParameter;
import com.fr.design.mainframe.share.Bean.WidgetFilterInfo;
import com.fr.design.mainframe.share.Bean.WidgetFilterTypeInfo;
import com.fr.design.mainframe.share.config.ComponentReuseConfigManager;
import com.fr.general.ComparatorUtils;
import com.fr.general.http.HttpClient;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Created by kerry on 2021/11/3
*/
public class OnlineShopUtils {
private static final String CHART = "chart";
private static final String REPORT = "report";
private static final String CID_PREFIX = "cid";
private static final String CHART_IDS = "123457";
private OnlineShopUtils() {
}
public static String getReuInfoPath() {
return ComponentReuseConfigManager.getInstance().getMiniShopUrl();
}
private static String getWidgetReusePath() {
return StableUtils.pathJoin(getReuInfoPath(), "all/detail/");
}
private static String getPackageChildrenPath() {
return StableUtils.pathJoin(getReuInfoPath(), "children/");
}
private static String getWidgetFilterPath() {
return StableUtils.pathJoin(getReuInfoPath(), "filter");
}
private static String getGetCompositeSortParaPath() {
return StableUtils.pathJoin(getReuInfoPath(), "sort_parameter");
}
private static String getLatestReusesPath() {
return StableUtils.pathJoin(getReuInfoPath(), "prompt/update/");
}
private static String getTestConnectionUrl() {
return DesignerCloudURLManager.getInstance().acquireUrlByKind("ping");
}
public static List<FilterTypeInfo> getShowFilterTypeInfos() {
List<FilterTypeInfo> filterTypeInfos = new ArrayList<>();
List<WidgetFilterTypeInfo> widgetFilterTypeInfos = getWidgetFilterTypeInfos();
FilterTypeInfo widgetTypeInfo =
new FilterTypeInfo(Toolkit.i18nText("Fine-Design_Share_Filter_Widget_Type"), ShareFilterConstants.WIDGET_TYPE_FILTER_KEY);
for (WidgetFilterTypeInfo info : widgetFilterTypeInfos) {
if (ComparatorUtils.equals(ShareFilterConstants.CHART_FILTER_KEY, info.getKey())
|| ComparatorUtils.equals(ShareFilterConstants.REPORT_FILTER_KEY, info.getKey())) {
widgetTypeInfo.addFilterType(info);
if (!filterTypeInfos.contains(widgetTypeInfo)) {
filterTypeInfos.add(widgetTypeInfo);
}
} else {
FilterTypeInfo typeInfo = new FilterTypeInfo(info.getTitle(), info.getKey());
typeInfo.addFilterType(info);
filterTypeInfos.add(typeInfo);
}
}
filterTypeInfos.sort(Comparator.comparingInt(o -> OnlineFilterType.parse(o.getKey()).ordinal()));
return filterTypeInfos;
}
enum OnlineFilterType {
SHOW_DEVICE(ShareFilterConstants.SHOW_TERMINAL_FILTER_KEY),
STYLE(ShareFilterConstants.STYLE_FILTER_KEY),
WIDGET_TYPE(ShareFilterConstants.WIDGET_TYPE_FILTER_KEY),
FEE(ShareFilterConstants.FEE_FILTER_KEY),
VERSION(ShareFilterConstants.VERSION_FILTER_KEY);
private String flag;
private OnlineFilterType(String flag) {
this.flag = flag;
}
public static OnlineFilterType parse(String flag) {
for (OnlineFilterType filterType : values()) {
if (ComparatorUtils.equals(filterType.flag, flag)) {
return filterType;
}
}
return SHOW_DEVICE;
}
}
public static List<FilterTypeInfo> getEmbPaneShowFilterTypeInfos() {
List<FilterTypeInfo> filterTypeInfos = new ArrayList<>();
List<WidgetFilterTypeInfo> widgetFilterTypeInfos = getWidgetFilterTypeInfos();
WidgetFilterTypeInfo widgetTypeFilterInfo = new WidgetFilterTypeInfo();
widgetTypeFilterInfo.setTitle(Toolkit.i18nText("Fine-Design_Share_Filter_Widget_Type"));
FilterTypeInfo widgetType = new FilterTypeInfo(widgetTypeFilterInfo.getTitle(), ShareFilterConstants.WIDGET_TYPE_FILTER_KEY);
widgetType.addFilterType(widgetTypeFilterInfo);
WidgetFilterInfo reportCard = new WidgetFilterInfo();
reportCard.setName(Toolkit.i18nText("Fine-Design_Share_Online_Filter_Indicator_Card"));
WidgetFilterInfo chartType = new WidgetFilterInfo();
chartType.setName(Toolkit.i18nText("Fine-Design_Share_Online_Filter_Chart"));
WidgetFilterInfo otherType = new WidgetFilterInfo();
otherType.setName(Toolkit.i18nText("Fine-Design_Share_Online_Filter_Other_Type"));
widgetTypeFilterInfo.addFilterItem(reportCard);
widgetTypeFilterInfo.addFilterItem(chartType);
widgetTypeFilterInfo.addFilterItem(otherType);
for (WidgetFilterTypeInfo info : widgetFilterTypeInfos) {
if (ComparatorUtils.equals(ShareFilterConstants.SHOW_TERMINAL_FILTER_KEY, info.getKey())) {
FilterTypeInfo showTerminalInfo = new FilterTypeInfo(info.getTitle(), info.getKey());
showTerminalInfo.addFilterType(info);
filterTypeInfos.add(showTerminalInfo);
} else if (ComparatorUtils.equals(ShareFilterConstants.STYLE_FILTER_KEY, info.getKey())) {
FilterTypeInfo styleTypeInfo = new FilterTypeInfo(info.getTitle(), info.getKey());
styleTypeInfo.addFilterType(info);
filterTypeInfos.add(styleTypeInfo);
} else if (ComparatorUtils.equals(ShareFilterConstants.REPORT_FILTER_KEY, info.getKey())) {
for (WidgetFilterInfo filterInfo : info.getFilterItems()) {
if (ComparatorUtils.equals(filterInfo.getId(), "1")) {
reportCard.addChildFilterInfo(filterInfo);
} else {
otherType.addChildFilterInfo(filterInfo);
}
}
} else if (ComparatorUtils.equals(ShareFilterConstants.CHART_FILTER_KEY, info.getKey())) {
for (WidgetFilterInfo filterInfo : info.getFilterItems()) {
if (filterInfo.getId() != null && CHART_IDS.contains(filterInfo.getId())) {
chartType.addChildFilterInfo(filterInfo);
} else {
otherType.addChildFilterInfo(filterInfo);
}
}
}
}
filterTypeInfos.add(widgetType);
return filterTypeInfos;
}
public static Map<String, SortParameter> getCompositeSortPara() {
Map<String, SortParameter> para = new HashMap<>();
try {
JSONArray resultArr = getResultAttrFromUrl(getGetCompositeSortParaPath());
int size = resultArr.size();
for (int i = 0; i < size; i++) {
JSONObject jo = resultArr.getJSONObject(i);
SortParameter sortParameter = SortParameter.parseFromJSONObject(jo);
para.put(sortParameter.getParameter(), sortParameter);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return para;
}
public static String assembleFilter(List<WidgetFilterInfo> filterInfos) {
List<WidgetFilterInfo> allFilterInfos = getAllFilterInfoList(filterInfos);
List<String> cidList = new ArrayList<>();
Map<String, String> queryParaMap = new HashMap<>();
for (WidgetFilterInfo filterInfo : allFilterInfos) {
if (ComparatorUtils.equals(CHART, filterInfo.getType())
|| ComparatorUtils.equals(REPORT, filterInfo.getType())) {
cidList.add(filterInfo.getType() + "-" + filterInfo.getId());
continue;
}
String queryValue = queryParaMap.get(filterInfo.getType());
if (StringUtils.isNotEmpty(queryValue)) {
queryValue += "," + filterInfo.getId();
} else {
queryValue = filterInfo.getId();
}
queryParaMap.put(filterInfo.getType(), queryValue);
}
StringBuffer sb;
List<String> queryCondition = new ArrayList<>();
if (!cidList.isEmpty()) {
sb = new StringBuffer();
sb.append(CID_PREFIX).append("=").append(StringUtils.join(",", cidList.toArray(new String[cidList.size()])));
queryCondition.add(sb.toString());
}
Iterator<Map.Entry<String, String>> iterator = queryParaMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
sb = new StringBuffer();
sb.append(entry.getKey()).append("=").append(entry.getValue());
queryCondition.add(sb.toString());
}
return StringUtils.join("&", queryCondition.toArray(new String[queryCondition.size()]));
}
private static List<WidgetFilterInfo> getAllFilterInfoList(List<WidgetFilterInfo> filterInfos) {
List<WidgetFilterInfo> allFilterList = new ArrayList<>();
for (WidgetFilterInfo filterInfo : filterInfos) {
if (filterInfo.hasChildFilter()) {
allFilterList.addAll(filterInfo.getInnerFilterInfo());
} else {
allFilterList.add(filterInfo);
}
}
return allFilterList;
}
public static boolean testConnection() {
HttpClient httpClient = new HttpClient(getTestConnectionUrl());
httpClient.asGet();
int responseCode = httpClient.getResponseCode();
return responseCode == HttpURLConnection.HTTP_OK;
}
public static List<OnlineShareWidget>[] getAllSharableWidgetsFromShop() throws Exception {
List<OnlineShareWidget>[] sharableWidgetsArray = new List[]{new ArrayList<>(), new ArrayList<>()};
JSONArray resultArr = getResultAttrFromUrl(getWidgetReusePath());
int size = resultArr.size();
for (int i = 0; i < size; i++) {
JSONObject jo = resultArr.getJSONObject(i);
OnlineShareWidget temp = OnlineShareWidget.parseFromJSONObject(jo);
if (temp.isWidgetPackage()) {
sharableWidgetsArray[1].add(temp);
} else {
sharableWidgetsArray[0].add(temp);
}
}
return sharableWidgetsArray;
}
public static OnlineShareWidget[] getPackageWidgets(OnlineShareWidget widgetPackage) {
String plistUrl = getPackageChildrenPath() + widgetPackage.getId();
OnlineShareWidget[] widgets = getOnlineShareWidgets(plistUrl);
for (OnlineShareWidget widget : widgets) {
widget.setParentPackage(widgetPackage);
}
return widgets;
}
public static List<WidgetFilterTypeInfo> getWidgetFilterTypeInfos() {
List<WidgetFilterTypeInfo> result = new ArrayList<>();
try {
JSONArray resultArr = getResultAttrFromUrl(getWidgetFilterPath());
int size = resultArr.size();
for (int i = 0; i < size; i++) {
JSONObject jo = resultArr.getJSONObject(i);
result.add(WidgetFilterTypeInfo.parseFromJSONObject(jo));
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return result;
}
private static OnlineShareWidget[] getOnlineShareWidgets(String url) {
if (StringUtils.isNotBlank(url)) {
try {
JSONArray resultArr = getResultAttrFromUrl(url);
int size = resultArr.size();
List<OnlineShareWidget> onlineShareWidgets = new ArrayList<>();
for (int i = 0; i < size; i++) {
JSONObject jo = resultArr.getJSONObject(i);
OnlineShareWidget widget = OnlineShareWidget.parseFromJSONObject(jo);
if (!widget.isWidgetPackage()) {
onlineShareWidgets.add(widget);
}
}
return onlineShareWidgets.toArray(new OnlineShareWidget[onlineShareWidgets.size()]);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
return new OnlineShareWidget[]{};
}
public static OnlineShareWidget[] getFilterWidgets(String filterStr) {
String plistUrl = getWidgetReusePath() + "?" + filterStr;
return getOnlineShareWidgets(plistUrl);
}
public static List<OnlineShareWidget> getLatestReusesByDesignerVersion(Set<String> reuseIds, String designerVersion) {
List<OnlineShareWidget> result = new ArrayList<>();
try {
JSONObject params = JSONObject.create();
StringBuilder reuseIdsStr = new StringBuilder();
for (String id: reuseIds) {
reuseIdsStr.append(id).append(",");
}
params.put("reuseIds", reuseIdsStr.toString());
params.put("designerVersion", designerVersion);
JSONArray resultArr = postResultAttrFormUrl(getLatestReusesPath(), params);
int size = resultArr.size();
for (int i = 0; i < size; i++) {
JSONObject jo = resultArr.getJSONObject(i);
result.add(OnlineShareWidget.parseFromJSONObject(jo));
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return result;
}
private static JSONArray getResultAttrFromUrl(String url) {
HttpClient httpClient = new HttpClient(url);
httpClient.asGet();
String responseText = httpClient.getResponseText();
JSONObject resultJSONObject = new JSONObject(responseText);
return resultJSONObject.getJSONArray("result");
}
private static JSONArray postResultAttrFormUrl(String url, JSONObject params) {
JSONArray result = JSONArray.create();
try {
String responseText = HttpToolbox.post(url, params.toMap());
if (StringUtils.isNotEmpty(responseText)) {
JSONObject resultJSONObject = new JSONObject(responseText);
result = resultJSONObject.getJSONArray("result");
}
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return result;
}
}

17
designer-form/src/main/java/com/fr/design/mainframe/share/util/ShareFilterConstants.java

@ -0,0 +1,17 @@
package com.fr.design.mainframe.share.util;
/**
* Created by kerry on 2021/11/3
*/
public class ShareFilterConstants {
public static final String CHART_FILTER_KEY = "3@chart";
public static final String REPORT_FILTER_KEY = "4@report";
public static final String SHOW_TERMINAL_FILTER_KEY = "4@displayDevice";
public static final String STYLE_FILTER_KEY = "5@style";
public static final String FEE_FILTER_KEY = "2@fee";
public static final String VERSION_FILTER_KEY = "6@version";
public static final String WIDGET_TYPE_FILTER_KEY = "1@widgetType";
public static final String SOURCE_TYPE_FILTER_KEY = "2@source";
public static final String ALL_STYLE_THEME = "0";
}

3
designer-form/src/main/java/com/fr/design/widget/ui/designer/NewFormPane.java

@ -17,10 +17,10 @@ import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.form.main.Form;
import com.fr.design.DesignerCloudURLManager;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.OccupiedLayout;
import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
@ -65,6 +65,7 @@ public class NewFormPane extends BasicPane {
this.add(createModuleListPane(), BorderLayout.WEST);
this.add(createTemplateManagePane(), BorderLayout.CENTER);
initWindow();
DesignerCloudURLManager.getInstance().testConnect();
}
private void initWindow() {

BIN
designer-form/src/main/resources/com/fr/design/form/images/drag_hand.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

45
designer-form/src/test/java/com/fr/design/mainframe/ReuseTriggerPointManagerTest.java

@ -1,45 +0,0 @@
package com.fr.design.mainframe;
import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by kerry on 5/10/21
*/
public class ReuseTriggerPointManagerTest {
private static final long ONE_WEEK_TIME = 7 * 24 * 3600 * 1000L;
@Test
public void testNeedTrigger() {
ComponentReuseNotificationInfo notificationInfo = ComponentReuseNotificationInfo.getInstance();
notificationInfo.setNotifiedNumber(0);
Assert.assertTrue(ReuseTriggerPointManager.getInstance().needTrigger());
notificationInfo.setNotifiedNumber(1);
Assert.assertTrue(ReuseTriggerPointManager.getInstance().needTrigger());
notificationInfo.setNotifiedNumber(2);
Assert.assertFalse(ReuseTriggerPointManager.getInstance().needTrigger());
notificationInfo.setNotifiedNumber(0);
notificationInfo.setLastNotifyTime(System.currentTimeMillis());
Assert.assertFalse(ReuseTriggerPointManager.getInstance().needTrigger());
notificationInfo.setNotifiedNumber(1);
notificationInfo.setLastNotifyTime(System.currentTimeMillis());
Assert.assertFalse(ReuseTriggerPointManager.getInstance().needTrigger());
notificationInfo.setNotifiedNumber(1);
notificationInfo.setLastNotifyTime(System.currentTimeMillis() - ONE_WEEK_TIME - 1);
Assert.assertTrue(ReuseTriggerPointManager.getInstance().needTrigger());
notificationInfo.setNotifiedNumber(2);
notificationInfo.setLastNotifyTime(System.currentTimeMillis());
Assert.assertFalse(ReuseTriggerPointManager.getInstance().needTrigger());
}
}

4
designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/theme/DownloadComponentPackageGuide.java

@ -31,8 +31,8 @@ import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane;
import com.fr.design.mainframe.share.ui.online.OnlineWidgetTabPane;
import com.fr.design.mainframe.share.ui.online.widgetpackage.OnlineWidgetPackagesShowPane;
import com.fr.design.mainframe.share.util.DownloadUtils;
import com.fr.design.mainframe.share.util.OnlineShopUtils;
import com.fr.design.utils.ComponentUtils;
import com.fr.form.share.utils.ShareUtils;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
@ -87,7 +87,7 @@ public class DownloadComponentPackageGuide {
GuideCreateUtils.showUnLoginAlert();
GuideManager.getInstance().getCurrentGuide().terminate();
return false;
} else if (!ShareUtils.testConnection()) {
} else if (!OnlineShopUtils.testConnection()) {
GuideCreateUtils.showNoNetworkAlert();
GuideManager.getInstance().getCurrentGuide().terminate();
return false;

129
designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java

@ -7,20 +7,33 @@ import com.fr.design.EnvChangeEntrance;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.env.DesignerWorkspaceInfoContext;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.loghandler.DesignerLogger;
import com.fr.design.mainframe.share.ui.base.MouseClickListener;
import com.fr.design.mainframe.toast.DesignerToastMsgUtil;
import com.fr.design.mainframe.toast.ToastMsgDialog;
import com.fr.design.ui.util.UIUtil;
import com.fr.design.utils.BrowseUtils;
import com.fr.event.EventDispatcher;
import com.fr.general.CloudCenter;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.report.RemoteDesignConstants;
import com.fr.serialization.SerializerHelper;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.third.apache.log4j.spi.LoggingEvent;
import com.fr.third.org.apache.http.client.config.RequestConfig;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import com.fr.third.org.apache.http.client.methods.HttpGet;
import com.fr.third.org.apache.http.conn.ssl.NoopHostnameVerifier;
import com.fr.third.org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient;
import com.fr.third.org.apache.http.impl.client.HttpClients;
import com.fr.third.org.apache.http.ssl.SSLContexts;
import com.fr.web.WebSocketConfig;
import com.fr.web.socketio.WebSocketProtocol;
@ -34,8 +47,14 @@ import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import javax.net.ssl.SSLContext;
import javax.swing.BorderFactory;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@ -44,7 +63,6 @@ import java.net.URL;
import java.security.KeyStore;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
public class DesignerSocketIO {
@ -54,18 +72,21 @@ public class DesignerSocketIO {
Disconnecting
}
private static final String WEBSOCKET_HELP_DOC = CloudCenter.getInstance().acquireUrlByKind("websocketConnect", "https://help.fanruan.com/finereport/doc-view-2512.html");
private static final String HTTPS = "https";
private static final String HTTP = "http";
private static Socket socket = null;
private static Status status = Status.Disconnected;
private static Timer disConnectHintTimer = null;
private static long disConnectHintTimerDelay = 3000;
private static final int TIMEOUT = 5000;
//维护一个当前工作环境的uri列表
private static String[] uri;
//维护一个关于uri列表的计数器
private static int count;
// 当前webSocket选择的协议
private static String currentProtocol;
private static ToastMsgDialog dialog = null;
public static void close() {
@ -107,6 +128,7 @@ public class DesignerSocketIO {
} else {
//表示所有的uri都连接不成功
FineLoggerFactory.getLogger().warn("All uris failed to connect");
showSocketDisconnectToast();
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
@ -115,7 +137,6 @@ public class DesignerSocketIO {
private static IO.Options createOptions() {
IO.Options options = new IO.Options();
options.path = WebSocketConfig.getInstance().getSocketContext();
try {
if (ComparatorUtils.equals(currentProtocol, HTTPS)) {
options.sslContext = getSSLContext();
@ -224,41 +245,38 @@ public class DesignerSocketIO {
@Override
public void call(Object... objects) {
FineLoggerFactory.getLogger().info("start disConnectHintTimer");
disConnectHintTimer = new Timer();
disConnectHintTimer.schedule(new TimerTask() {
@Override
public void run() {
try {
/*
* todo 远程心跳断开不一定 socket 断开 和远程紧密相关的业务都绑定在心跳上切换成心跳断开之后进行提醒
* socket 只用推日志和通知配置变更
*/
printLog(objects, PrintEventLogImpl.ERROR, "disConnected args: {}");
if (status != Status.Disconnecting) {
showConnectionLostDialog();
}
status = Status.Disconnected;
} finally {
disConnectHintTimer.cancel();
disConnectHintTimer = null;
}
}
}, disConnectHintTimerDelay);
/*
* todo 远程心跳断开不一定 socket 断开 和远程紧密相关的业务都绑定在心跳上切换成心跳断开之后进行提醒
* socket 只用推日志和通知配置变更
*/
printLog(objects, PrintEventLogImpl.ERROR, "disConnected args: {}");
if (status != Status.Disconnecting) {
dealWithSocketDisconnect();
}
status = Status.Disconnected;
}
};
private static void showConnectionLostDialog() {
private static void dealWithSocketDisconnect() {
if (checkRPCConnect()) {
showSocketDisconnectToast();
} else {
showRPCDisconnectDialog();
}
}
private static void showSocketDisconnectToast() {
try {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
FineJOptionPane.showMessageDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Remote_Disconnected"),
UIManager.getString("OptionPane.messageDialogTitle"),
JOptionPane.ERROR_MESSAGE,
UIManager.getIcon("OptionPane.errorIcon"));
EnvChangeEntrance.getInstance().chooseEnv();
if (dialog == null) {
dialog = DesignerToastMsgUtil.createPromptDialog(createDialogContent());
}
if (!dialog.isShow()) {
dialog.setVisible(true);
}
}
});
} catch (Exception e) {
@ -266,6 +284,57 @@ public class DesignerSocketIO {
}
}
private static JPanel createDialogContent() {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
jPanel.add(new UILabel(Toolkit.i18nText("Fine-Design_WebSocket_Lost_Tip")), BorderLayout.WEST);
UILabel hyperLinkLabel = new UILabel(Toolkit.i18nText("Fine-Design_WebSocket_Lost_Tip_HyperLink_Text"));
hyperLinkLabel.addMouseListener(new MouseClickListener() {
@Override
public void mouseClicked(MouseEvent e) {
BrowseUtils.browser(WEBSOCKET_HELP_DOC);
}
});
hyperLinkLabel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
hyperLinkLabel.setForeground(Color.BLUE);
hyperLinkLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
jPanel.add(hyperLinkLabel, BorderLayout.CENTER);
return jPanel;
}
private static void showRPCDisconnectDialog() {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
FineJOptionPane.showMessageDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Remote_Disconnected"),
UIManager.getString("OptionPane.messageDialogTitle"),
JOptionPane.ERROR_MESSAGE,
UIManager.getIcon("OptionPane.errorIcon"));
EnvChangeEntrance.getInstance().chooseEnv();
}
});
}
private static boolean checkRPCConnect() {
CloseableHttpClient httpclient = HttpClients.createDefault();
WorkspaceConnectionInfo info = getConnectionInfo();
HttpGet httpGet = new HttpGet(StableUtils.pathJoin(info.getUrl(), WorkspaceConstants.CONTROLLER_PREFIX, WorkspaceConstants.VT));
RequestConfig requestConfig = RequestConfig
.custom()
.setConnectTimeout(TIMEOUT)
.setConnectionRequestTimeout(TIMEOUT)
.build();
httpGet.setConfig(requestConfig);
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
return false;
}
return true;
}
//配置变更监听器
private static final Emitter.Listener modifyConfig = new Emitter.Listener() {
@Override

32
designer-realize/src/main/java/com/fr/design/share/ui/generate/ShareGeneratePane.java

@ -26,7 +26,7 @@ import com.fr.design.share.utils.EffectItemUtils;
import com.fr.design.share.utils.ShareDialogUtils;
import com.fr.form.share.DefaultSharableWidget;
import com.fr.form.share.Group;
import com.fr.form.share.config.ComponentReuseConfigManager;
import com.fr.design.mainframe.share.config.ComponentReuseConfigManager;
import com.fr.form.share.exception.NetWorkFailedException;
import com.fr.form.share.group.DefaultShareGroup;
import com.fr.form.share.group.DefaultShareGroupManager;
@ -131,6 +131,24 @@ public class ShareGeneratePane extends BasicPane {
}
});
simplePane.getDesignerVersionField().getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
validInput();
}
@Override
public void insertUpdate(DocumentEvent e) {
validInput();
}
@Override
public void removeUpdate(DocumentEvent e) {
validInput();
}
});
uploadPane.getNameField().getDocument().addDocumentListener(new DocumentListener() {
@Override
@ -159,13 +177,13 @@ public class ShareGeneratePane extends BasicPane {
}
private void validInput() {
String userInput = getSelectMainPane().getNameField().getText().trim();
String name = getSelectMainPane().getNameField().getText().trim();
boolean isValidName = StringUtils.isNotEmpty(name);
if (StringUtils.isEmpty(userInput)) {
dialog.setButtonEnabled(false);
} else {
dialog.setButtonEnabled(true);
}
boolean isValidDesignerVersion = getSelectMainPane().getDesignerVersionField().isValidVersion();
boolean isValidInput = isValidName && isValidDesignerVersion;
dialog.setButtonEnabled(isValidInput);
}

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

Loading…
Cancel
Save