Browse Source

Merge branch 'feature/x' of https://code.fineres.com/scm/~harrison/design into feature/x

feature/x
Harrison 3 years ago
parent
commit
9604f98042
  1. 8
      build.gradle
  2. 3
      designer-base/src/main/java/com/fr/base/svg/IconUtils.java
  3. 6
      designer-base/src/main/java/com/fr/base/svg/SVGIcon.java
  4. 92
      designer-base/src/main/java/com/fr/base/svg/SVGLoader.java
  5. 181
      designer-base/src/main/java/com/fr/base/svg/SVGTranscoder.java
  6. 101
      designer-base/src/main/java/com/fr/base/svg/SystemScaleUtils.java
  7. 12
      designer-base/src/main/java/com/fr/common/exception/ThrowableHandler.java
  8. 13
      designer-base/src/main/java/com/fr/design/DesignModelAdapter.java
  9. 28
      designer-base/src/main/java/com/fr/design/DesignerEnvManager.java
  10. 2
      designer-base/src/main/java/com/fr/design/actions/community/BugAction.java
  11. 2
      designer-base/src/main/java/com/fr/design/actions/community/NeedAction.java
  12. 17
      designer-base/src/main/java/com/fr/design/actions/community/StudyPlanAction.java
  13. 19
      designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java
  14. 33
      designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java
  15. 180
      designer-base/src/main/java/com/fr/design/cell/CellRectangleStylePreviewPane.java
  16. 121
      designer-base/src/main/java/com/fr/design/cell/CellStylePreviewPane.java
  17. 52
      designer-base/src/main/java/com/fr/design/config/DesignerProperties.java
  18. 5
      designer-base/src/main/java/com/fr/design/constants/TableDataConstants.java
  19. 16
      designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java
  20. 7
      designer-base/src/main/java/com/fr/design/data/BasicTableDataUtils.java
  21. 119
      designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java
  22. 2
      designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java
  23. 20
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java
  24. 7
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  25. 145
      designer-base/src/main/java/com/fr/design/data/datapane/connect/AdvancePane.java
  26. 19
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java
  27. 35
      designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java
  28. 82
      designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java
  29. 19
      designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java
  30. 301
      designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java
  31. 164
      designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java
  32. 4
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java
  33. 109
      designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java
  34. 15
      designer-base/src/main/java/com/fr/design/deeplink/DeepLink.java
  35. 184
      designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java
  36. 33
      designer-base/src/main/java/com/fr/design/editor/editor/NotNegativeIntegerEditor.java
  37. 7
      designer-base/src/main/java/com/fr/design/event/ComponentChangeListener.java
  38. 6
      designer-base/src/main/java/com/fr/design/event/ComponentChangeObserver.java
  39. 29
      designer-base/src/main/java/com/fr/design/extra/PluginInstalledPane.java
  40. 12
      designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java
  41. 3
      designer-base/src/main/java/com/fr/design/extra/PluginUtils.java
  42. 23
      designer-base/src/main/java/com/fr/design/extra/WebViewDlgHelper.java
  43. 29
      designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java
  44. 4
      designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java
  45. 46
      designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java
  46. 153
      designer-base/src/main/java/com/fr/design/formula/FormulaPane.java
  47. 17
      designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java
  48. 4
      designer-base/src/main/java/com/fr/design/formula/exception/function/FormulaCheckWrongFunction.java
  49. 9
      designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedCharFunction.java
  50. 40
      designer-base/src/main/java/com/fr/design/formula/exception/function/MismatchedTokenFunction.java
  51. 96
      designer-base/src/main/java/com/fr/design/formula/exception/function/TranslateTokenUtils.java
  52. 5
      designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompleteExtraRefreshComponent.java
  53. 982
      designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompleteWithExtraRefreshPopupWindow.java
  54. 1260
      designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompletionWithExtraRefresh.java
  55. 976
      designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaAutoCompletePopupWindow.java
  56. 1241
      designer-base/src/main/java/com/fr/design/gui/autocomplete/FormulaPaneAutoCompletion.java
  57. 16
      designer-base/src/main/java/com/fr/design/gui/autocomplete/JSAutoCompletePopupWindow.java
  58. 31
      designer-base/src/main/java/com/fr/design/gui/autocomplete/JSImplPaneAutoCompletion.java
  59. 4
      designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java
  60. 11
      designer-base/src/main/java/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java
  61. 20
      designer-base/src/main/java/com/fr/design/gui/frpane/JTreeAutoBuildPane.java
  62. 14
      designer-base/src/main/java/com/fr/design/gui/frpane/TreeSettingPane.java
  63. 4
      designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java
  64. 6
      designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java
  65. 2
      designer-base/src/main/java/com/fr/design/gui/icombobox/ColorSchemeComboBox.java
  66. 4
      designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java
  67. 77
      designer-base/src/main/java/com/fr/design/gui/icombobox/SearchPreTaskTreeComboBox.java
  68. 228
      designer-base/src/main/java/com/fr/design/gui/icombobox/TableSearchTreeComboBox.java
  69. 25
      designer-base/src/main/java/com/fr/design/gui/ifilechooser/ExtensionFilter.java
  70. 109
      designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserArgs.java
  71. 44
      designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserFactory.java
  72. 13
      designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserProvider.java
  73. 33
      designer-base/src/main/java/com/fr/design/gui/ifilechooser/JavaFxNativeFileChooser.java
  74. 130
      designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingFileChooser.java
  75. 276
      designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingImageFileChooser.java
  76. 78
      designer-base/src/main/java/com/fr/design/gui/ilable/UIAutoChangeLineLabel.java
  77. 8
      designer-base/src/main/java/com/fr/design/gui/iprogressbar/ProgressDialog.java
  78. 7
      designer-base/src/main/java/com/fr/design/gui/itextfield/UIAutoCompletionField.java
  79. 113
      designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java
  80. 235
      designer-base/src/main/java/com/fr/design/gui/style/TextFormatPane.java
  81. 169
      designer-base/src/main/java/com/fr/design/javascript/JSContentPane.java
  82. 924
      designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java
  83. 95
      designer-base/src/main/java/com/fr/design/javascript/JavaScriptImplPane.java
  84. 23
      designer-base/src/main/java/com/fr/design/javascript/NewJavaScriptImplPane.java
  85. 21
      designer-base/src/main/java/com/fr/design/javascript/jsapi/CategoryTreeNodesUserObject.java
  86. 155
      designer-base/src/main/java/com/fr/design/javascript/jsapi/JSAPITreeHelper.java
  87. 9
      designer-base/src/main/java/com/fr/design/javascript/jsapi/JSAPIUserObject.java
  88. 7
      designer-base/src/main/java/com/fr/design/javascript/jsapi/JSImplPopulateAction.java
  89. 7
      designer-base/src/main/java/com/fr/design/javascript/jsapi/JSImplUpdateAction.java
  90. 122
      designer-base/src/main/java/com/fr/design/lock/LockInfoDialog.java
  91. 23
      designer-base/src/main/java/com/fr/design/lock/LockInfoUtils.java
  92. 7
      designer-base/src/main/java/com/fr/design/mainframe/BaseJForm.java
  93. 18
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java
  94. 69
      designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java
  95. 46
      designer-base/src/main/java/com/fr/design/mainframe/DesignerUIModeConfig.java
  96. 16
      designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java
  97. 190
      designer-base/src/main/java/com/fr/design/mainframe/ForbiddenPane.java
  98. 10
      designer-base/src/main/java/com/fr/design/mainframe/JDashboard.java
  99. 74
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  100. 4
      designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java
  101. Some files were not shown because too many files have changed in this diff Show More

8
build.gradle

@ -9,6 +9,7 @@ plugins {
//
ext {
frVersion = ""
cbbVersion = ""
outputPath = "build"
ignoreTestFailureSetting = true
languageLevelSetting = 1.8
@ -44,6 +45,9 @@ allprojects {
repositories {
mavenLocal()
maven {
url 'https://maven.ej-technologies.com/repository'
}
}
idea {
@ -57,6 +61,9 @@ allprojects {
}
dependencies {
implementation 'com.fr.essential:fine-essential:' + cbbVersion
implementation 'com.fr.cbb:fine-universal-skeleton:' + cbbVersion
implementation 'com.install4j:install4j-runtime:8.0.4'
implementation 'com.fr.third:jxbrowser:6.23'
implementation 'com.fr.third:jxbrowser-mac:6.23'
implementation 'com.fr.third:jxbrowser-win64:6.23'
@ -69,6 +76,7 @@ allprojects {
implementation 'org.swingexplorer:swag:1.0'
implementation 'net.java.dev.jna:jna:5.4.0'
implementation 'org.apache.tomcat:tomcat-catalina:8.5.72'
implementation 'org.apache.tomcat:tomcat-websocket:8.5.72'
implementation 'io.socket:socket.io-client:0.7.0'
implementation 'com.fr.third:fine-third:' + frVersion
implementation 'com.fr.core:fine-core:' + frDevVersion

3
designer-base/src/main/java/com/fr/base/svg/IconUtils.java

@ -6,8 +6,7 @@ import com.fr.stable.bridge.StableFactory;
import com.fr.stable.fun.ResourcePathTransformer;
import com.fr.stable.plugin.ExtraClassManagerProvider;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

6
designer-base/src/main/java/com/fr/base/svg/SVGIcon.java

@ -2,10 +2,8 @@ package com.fr.base.svg;
import com.fr.general.IOUtils;
import javax.swing.Icon;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

92
designer-base/src/main/java/com/fr/base/svg/SVGLoader.java

@ -1,92 +0,0 @@
package com.fr.base.svg;
import com.fr.general.IOUtils;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.xmlgraphics.java2d.Dimension2DDouble;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
/**
* SVG图标加载器
* @author Yvan
* @version 10.0
* Created by Yvan on 2020/12/17
*/
public class SVGLoader {
public static final int ICON_DEFAULT_SIZE = 16;
public SVGLoader() {
}
@Nullable
public static Image load(@NotNull String url) {
try {
URL resource = IOUtils.getResource(url, SVGLoader.class);
if (resource == null) {
return null;
}
return load(resource, SVGIcon.SYSTEM_SCALE);
} catch (IOException ignore) {
return null;
}
}
@Nullable
public static Image load(@NotNull URL url) throws IOException {
return load(url, SVGIcon.SYSTEM_SCALE);
}
@Nullable
public static Image load(@NotNull URL url, double scale) throws IOException {
try {
String svgUri = url.toString();
TranscoderInput input = new TranscoderInput(svgUri);
return SVGTranscoder.createImage(scale, input).getImage();
} catch (TranscoderException ignore) {
return null;
}
}
@Nullable
public static Image load(@NotNull URL url, double scale, Dimension2DDouble dimension) throws IOException {
try {
String svgUri = url.toString();
TranscoderInput input = new TranscoderInput(svgUri);
return SVGTranscoder.createImage(scale, input,
(float) (dimension.getWidth() * scale), (float) (dimension.getHeight() * scale)).getImage();
} catch (TranscoderException ignore) {
return null;
}
}
@Nullable
public static Image load(@NotNull URL url, double scale, double overriddenWidth, double overriddenHeight) throws IOException {
try {
String svgUri = url.toString();
TranscoderInput input = new TranscoderInput(svgUri);
return SVGTranscoder.createImage(scale, input, (float) (overriddenWidth * scale), (float) (overriddenHeight * scale)).getImage();
} catch (TranscoderException ignore) {
return null;
}
}
@Nullable
public static Image load(@NotNull String url, float width, float height) {
try {
URL resource = IOUtils.getResource(url, SVGLoader.class);
if (resource == null) {
return null;
}
TranscoderInput input = new TranscoderInput(resource.toString());
return SVGTranscoder.createImage(SVGIcon.SYSTEM_SCALE, input, -1, -1, width, height).getImage();
} catch (TranscoderException ignore) {
return null;
}
}
}

181
designer-base/src/main/java/com/fr/base/svg/SVGTranscoder.java

@ -1,181 +0,0 @@
package com.fr.base.svg;
import com.fr.stable.AssistUtils;
import com.fr.value.AtomicNotNullLazyValue;
import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
import org.apache.batik.anim.dom.SVGOMDocument;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.transcoder.SVGAbstractTranscoder;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.util.XMLResourceDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.StringReader;
/**
* 可以根据某个缩放倍数scale将SVG图片转化为Image对象
* @author Yvan
* @version 10.0
* Created by Yvan on 2020/12/17
*/
public class SVGTranscoder extends ImageTranscoder {
private static final float DEFAULT_VALUE = -1.0F;
public static final float ICON_DEFAULT_SIZE = 16F;
private float origDocWidth;
private float origDocHeight;
@Nullable
private BufferedImage image;
private final double scale;
@NotNull
private static AtomicNotNullLazyValue<Double> iconMaxSize = new AtomicNotNullLazyValue<Double>() {
@NotNull
@Override
protected Double compute() {
double maxSize = Double.MAX_VALUE;
if (!GraphicsEnvironment.isHeadless()) {
GraphicsDevice defaultScreenDevice = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice();
Rectangle bounds = defaultScreenDevice.getDefaultConfiguration().getBounds();
AffineTransform tx = defaultScreenDevice
.getDefaultConfiguration()
.getDefaultTransform();
maxSize = Math.max(bounds.width * tx.getScaleX(), bounds.height * tx.getScaleY());
}
return maxSize;
}
};
public SVGTranscoder(double scale) {
this.scale = scale;
this.width = ICON_DEFAULT_SIZE;
this.height = ICON_DEFAULT_SIZE;
}
public SVGTranscoder(double scale, float width, float height) {
this.scale = scale;
this.width = width;
this.height = height;
}
public final float getOrigDocWidth() {
return this.origDocWidth;
}
public final void setOrigDocWidth(float origDocWidth) {
this.origDocWidth = origDocWidth;
}
public final float getOrigDocHeight() {
return this.origDocHeight;
}
public final void setOrigDocHeight(float origDocHeight) {
this.origDocHeight = origDocHeight;
}
public static double getIconMaxSize() {
return iconMaxSize.getValue();
}
@Nullable
public final BufferedImage getImage() {
return this.image;
}
@NotNull
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input) throws TranscoderException {
return createImage(scale, input, -1, -1);
}
@NotNull
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input, float overriddenWidth, float overriddenHeight) throws TranscoderException {
return createImage(scale, input, overriddenWidth, overriddenHeight, ICON_DEFAULT_SIZE, ICON_DEFAULT_SIZE);
}
@NotNull
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input, float overriddenWidth, float overriddenHeight, float width, float height) throws TranscoderException {
SVGTranscoder transcoder = new SVGTranscoder(scale, width, height);
if (!AssistUtils.equals(overriddenWidth, DEFAULT_VALUE)) {
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, overriddenWidth);
}
if (!AssistUtils.equals(overriddenHeight, DEFAULT_VALUE)) {
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, overriddenHeight);
}
double iconMaxSize = SVGTranscoder.iconMaxSize.getValue();
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MAX_WIDTH, (float) iconMaxSize);
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MAX_HEIGHT, (float) iconMaxSize);
transcoder.transcode(input, null);
return transcoder;
}
private static SVGDocument createFallbackPlaceholder() {
try {
String fallbackIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\">\n" +
" <rect x=\"1\" y=\"1\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"red\" stroke-width=\"2\"/>\n" +
" <line x1=\"1\" y1=\"1\" x2=\"15\" y2=\"15\" stroke=\"red\" stroke-width=\"2\"/>\n" +
" <line x1=\"1\" y1=\"15\" x2=\"15\" y2=\"1\" stroke=\"red\" stroke-width=\"2\"/>\n" +
"</svg>\n";
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
return (SVGDocument) factory.createDocument(null, new StringReader(fallbackIcon));
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
@Override
protected void setImageSize(float docWidth, float docHeight) {
super.setImageSize((float) (docWidth * this.scale), (float) (docHeight * this.scale));
this.origDocWidth = docWidth;
this.origDocHeight = docHeight;
}
@Override
@NotNull
public BufferedImage createImage(int width, int height) {
return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
}
@Override
public void writeImage(@NotNull BufferedImage image, @Nullable TranscoderOutput output) {
this.image = image;
}
@Override
@NotNull
protected UserAgent createUserAgent() {
return new SVGAbstractTranscoderUserAgent() {
@Override
@NotNull
public SVGDocument getBrokenLinkDocument(@NotNull Element e, @NotNull String url, @NotNull String message) {
return createFallbackPlaceholder();
}
};
}
/**
* 开放访问权限
*/
@Override
public BridgeContext createBridgeContext(SVGOMDocument doc) {
return super.createBridgeContext(doc);
}
}

101
designer-base/src/main/java/com/fr/base/svg/SystemScaleUtils.java

@ -1,101 +0,0 @@
package com.fr.base.svg;
import com.bulenkov.iconloader.util.UIUtil;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.os.OperatingSystem;
import org.jetbrains.annotations.NotNull;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicReference;
/**
* 获取系统Scale相关的工具类
* @author Yvan
* @version 10.0
* Created by Yvan on 2020/12/17
*/
public class SystemScaleUtils {
private static final AtomicReference<Boolean> JRE_HIDPI = new AtomicReference<>();
private static final String HI_DPI = "hidpi";
/**
* 判断是否支持高清
* @return
*/
public static boolean isJreHiDPIEnabled() {
if (JRE_HIDPI.get() != null) {
return JRE_HIDPI.get();
}
if (OperatingSystem.isMacos()) {
// 如果是mac os系统,直接返回true
return true;
}
if (OperatingSystem.isWindows() && StableUtils.getMajorJavaVersion() <= 8) {
// 如果是jdk8 + Windows系统,直接返回false
return false;
}
synchronized (JRE_HIDPI) {
if (JRE_HIDPI.get() != null) {
return JRE_HIDPI.get();
}
boolean result = false;
if (getBooleanProperty(HI_DPI, true)) {
try {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Class<?> sunGraphicsEnvironmentClass = Class.forName("sun.java2d.SunGraphicsEnvironment");
if (sunGraphicsEnvironmentClass.isInstance(ge)) {
try {
Method method = sunGraphicsEnvironmentClass.getDeclaredMethod("isUIScaleEnabled");
method.setAccessible(true);
result = (Boolean)method.invoke(ge);
}
catch (NoSuchMethodException e) {
FineLoggerFactory.getLogger().error(e.getMessage());
}
}
}
catch (Throwable ignore) {
}
}
JRE_HIDPI.set(result);
return result;
}
}
public static boolean getBooleanProperty(@NotNull final String key, final boolean defaultValue) {
final String value = System.getProperty(key);
return value == null ? defaultValue : Boolean.parseBoolean(value);
}
/**
* 获取系统Scale
* @return
*/
public static float sysScale() {
// 如果检测到是retina,直接返回2
if (UIUtil.isRetina()) {
return 2.0f;
}
float scale = 1.0f;
// 先判断是否支持高清,不支持代表此时是Windows + jdk8 的设计器,返回的scale值为1.0
if (isJreHiDPIEnabled()) {
// 获取屏幕图形设备对象
GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
if (graphicsDevice != null) {
// 获取图形配置对象
GraphicsConfiguration configuration = graphicsDevice.getDefaultConfiguration();
if (configuration != null && configuration.getDevice().getType() != GraphicsDevice.TYPE_PRINTER) {
// 获取屏幕缩放率,Windows+jdk11环境下会得到用户设置的dpi值
scale = (float) configuration.getDefaultTransform().getScaleX();
}
}
}
return scale;
}
}

12
designer-base/src/main/java/com/fr/common/exception/ThrowableHandler.java

@ -0,0 +1,12 @@
package com.fr.common.exception;
/**
* @author hades
* @version 11.0
* Created by hades on 2021/12/7
*/
public interface ThrowableHandler {
boolean process(Throwable e);
}

13
designer-base/src/main/java/com/fr/design/DesignModelAdapter.java

@ -4,6 +4,7 @@ import com.fr.base.Parameter;
import com.fr.base.ParameterConfig;
import com.fr.base.TableData;
import com.fr.base.io.BaseBook;
import com.fr.base.param.ParameterSource;
import com.fr.data.TableDataSource;
import com.fr.data.operator.DataOperator;
import com.fr.design.file.HistoryTemplateListCache;
@ -19,8 +20,8 @@ import com.fr.stable.Filter;
import com.fr.stable.ParameterProvider;
import com.fr.stable.StringUtils;
import com.fr.stable.js.WidgetName;
import com.fr.util.ParameterApplyHelper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -283,9 +284,9 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
TableData tableData = this.getBook().getTableData(name);
ParameterProvider[] parameterProviders = DataOperator.getInstance().getTableDataParameters(tableData);
if (filter != null) {
ParameterApplyHelper.addPara2Map(map, parameterProviders, filter);
ParameterApplyHelper.addPara2Map(map, parameterProviders, filter, null, ParameterSource.DEFAULT_SOURCE);
} else {
ParameterApplyHelper.addPara2Map(map, parameterProviders);
ParameterApplyHelper.addPara2Map(map, parameterProviders, null, ParameterSource.TEMPLATE_SOURCE);
}
tableDataParametersMap.put(name, parameterProviders);
}
@ -353,9 +354,9 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
*/
private void updateParaMap(Map<String, ParameterProvider> map, ParameterProvider[] parameterProviders, Filter<ParameterProvider> filter) {
if (filter != null) {
ParameterApplyHelper.addPara2Map(map, parameterProviders, filter);
ParameterApplyHelper.addPara2Map(map, parameterProviders, filter, null, ParameterSource.DEFAULT_SOURCE);
} else {
ParameterApplyHelper.addPara2Map(map, parameterProviders);
ParameterApplyHelper.addPara2Map(map, parameterProviders, null, ParameterSource.DEFAULT_SOURCE);
}
}
@ -378,7 +379,7 @@ public abstract class DesignModelAdapter<T extends BaseBook, S extends JTemplate
protected void addGlobalParameters(Map<String, ParameterProvider> map) {
// 添加全局参数
Parameter[] glbParas = ParameterConfig.getInstance().getGlobalParameters();
ParameterApplyHelper.addPara2Map(map, glbParas);
ParameterApplyHelper.addPara2Map(map, glbParas, null, ParameterSource.GLOBAL_SOURCE);
}

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

@ -23,6 +23,7 @@ import com.fr.design.mainframe.ComponentReuseNotifyUtil;
import com.fr.design.mainframe.reuse.ComponentReuseNotificationInfo;
import com.fr.design.mainframe.vcs.VcsConfigManager;
import com.fr.design.notification.SnapChatConfig;
import com.fr.design.os.impl.SupportOSImpl;
import com.fr.design.port.DesignerPortContext;
import com.fr.design.style.color.ColorSelectConfigManager;
import com.fr.design.update.push.DesignerPushUpdateConfigManager;
@ -53,7 +54,8 @@ import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLTools;
import com.fr.stable.xml.XMLWriter;
import com.fr.stable.xml.XMLableReader;
import com.fr.third.apache.log4j.FileAppender;
import com.fr.third.apache.logging.log4j.core.appender.FileAppender;
import com.fr.third.apache.logging.log4j.core.layout.PatternLayout;
import com.fr.third.org.apache.commons.io.FilenameUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.WorkContextCallback;
@ -210,6 +212,8 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
private int layoutTemplateStyle = LAYOUT_TEMPLATE_SIMPLE_STYLE;
private boolean useOptimizedUPM4Adapter;
/**
* DesignerEnvManager.
*/
@ -324,18 +328,18 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
if (!new File(fileName).exists()) {
StableUtils.makesureFileExist(new File(fileName));
}
LogHandler handler = new LogHandler<FileAppender>() {
final FileAppender appender = new FileAppender(
new com.fr.third.apache.log4j.PatternLayout("%d{HH:mm:ss} %t %p [%c] %m%n"),
fileName
);
LogHandler<FileAppender> handler = new LogHandler<FileAppender>() {
final FileAppender appender = FileAppender.newBuilder().
setName(FileAppender.class.getSimpleName()).
setLayout(PatternLayout.newBuilder().withPattern("%d{HH:mm:ss} %t %p [%c] %m%n").build()).
withFileName(fileName).build();
@Override
public FileAppender getHandler() {
return appender;
}
};
handler.getHandler().start();
FineLoggerFactory.getLogger().addLogAppender(handler);
} catch (SecurityException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
@ -664,6 +668,14 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
this.showTemplateMissingPlugin = showTemplateMissingPlugin;
}
public boolean isUseOptimizedUPM4Adapter() {
return useOptimizedUPM4Adapter;
}
public void setUseOptimizedUPM4Adapter(boolean useOptimizedUPM4Adapter) {
this.useOptimizedUPM4Adapter = useOptimizedUPM4Adapter;
}
/**
* 知否自动备份
*
@ -1887,6 +1899,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
}
this.setEmbedServerLazyStartup(reader.getAttrAsBoolean("embedServerLazyStartup", false));
this.setShowTemplateMissingPlugin(reader.getAttrAsBoolean("showTemplateMissingPlugin", true));
this.setUseOptimizedUPM4Adapter(reader.getAttrAsBoolean("useOptimizedUPM4Adapter", SupportOSImpl.MACOS_12_VERSION_ADAPTER.support()));
this.setShowServerDatasetAuthTip(reader.getAttrAsBoolean("showServerDatasetAuthTip", true));
this.setLayoutTemplateStyle(reader.getAttrAsInt("layoutTemplateStyle", LAYOUT_TEMPLATE_SIMPLE_STYLE));
}
@ -2164,6 +2177,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter {
}
writer.attr("layoutTemplateStyle", this.getLayoutTemplateStyle());
writer.attr("showServerDatasetAuthTip", this.isShowServerDatasetAuthTip());
writer.attr("useOptimizedUPM4Adapter", this.isUseOptimizedUPM4Adapter());
writer.end();
}

2
designer-base/src/main/java/com/fr/design/actions/community/BugAction.java

@ -17,7 +17,7 @@ public class BugAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.bugs", "http://bbs.fanruan.com/forum-156-1.html");
return CloudCenter.getInstance().acquireUrlByKind("bbs.bugs", "https://service.fanruan.com/PF/FR/feedback?type=2");
}
public static final MenuKeySet BUG = new MenuKeySet() {

2
designer-base/src/main/java/com/fr/design/actions/community/NeedAction.java

@ -18,7 +18,7 @@ public class NeedAction extends AbstractDesignerSSO {
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.needs", "http://bbs.fanruan.com/forum-56-1.html");
return CloudCenter.getInstance().acquireUrlByKind("bbs.needs", "https://service.fanruan.com/PF/FR/feedback?type=1");
}
public static final MenuKeySet NEED = new MenuKeySet() {

17
designer-base/src/main/java/com/fr/design/actions/community/StudyPlanAction.java

@ -0,0 +1,17 @@
package com.fr.design.actions.community;
import com.fr.design.i18n.Toolkit;
import com.fr.design.login.AbstractDesignerSSO;
import com.fr.general.CloudCenter;
public class StudyPlanAction extends AbstractDesignerSSO {
public StudyPlanAction() {
this.setName(Toolkit.i18nText("Fine-Design_Study_Plan"));
this.setSmallIcon("/com/fr/design/images/bbs/studyPlan");
}
@Override
public String getJumpUrl() {
return CloudCenter.getInstance().acquireUrlByKind("bbs.studyPlan", "https://edu.fanruan.com/studypath/finereport");
}
}

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

@ -16,9 +16,10 @@ import com.fr.design.gui.ibutton.UINoThemeColorButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icombobox.UIDictionaryComboBox;
import com.fr.design.gui.ifilechooser.FileChooserArgs;
import com.fr.design.gui.ifilechooser.FileChooserFactory;
import com.fr.design.gui.ifilechooser.FileChooserProvider;
import com.fr.design.gui.ifilechooser.FileSelectionMode;
import com.fr.design.gui.ifilechooser.JavaFxNativeFileChooser;
import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.iprogressbar.UIProgressBarUI;
@ -29,7 +30,6 @@ import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.layout.VerticalFlowLayout;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.vcs.VcsConfigManager;
import com.fr.design.mainframe.vcs.common.VcsHelper;
import com.fr.design.os.impl.SupportOSImpl;
@ -45,14 +45,12 @@ import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.Constants;
import com.fr.stable.os.OperatingSystem;
import com.fr.third.apache.log4j.Level;
import com.fr.third.apache.logging.log4j.Level;
import com.fr.transaction.Configurations;
import com.fr.transaction.Worker;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.vcs.VcsOperator;
import com.fr.workspace.server.vcs.git.config.GcConfig;
import com.sun.javafx.tk.FileChooserType;
import javafx.stage.FileChooser;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
@ -110,7 +108,7 @@ public class PreferencePane extends BasicPane {
private static final int CACHING_DEFAULT = 5;
private static final int CACHING_GAP = 5;
private static final int MEMORY_TIP_LABEL_MAX_WIDTH = 230;
private static final int OFFSET_HEIGHT = 50;
private static final int OFFSET_HEIGHT = 60;
private static final String TYPE = "pressed";
private static final String DISPLAY_TYPE = "+";
@ -516,9 +514,8 @@ public class PreferencePane extends BasicPane {
@Override
public void actionPerformed(ActionEvent evt) {
FileChooserProvider fileChooserProvider =
new JavaFxNativeFileChooser.Builder().
fileSelectionMode(FileSelectionMode.DIR).
build();
FileChooserFactory.createFileChooser(FileChooserArgs.newBuilder().
setFileSelectionMode(FileSelectionMode.DIR).build());
int saveValue = fileChooserProvider.showDialog(chooseDirBtn);
if (saveValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooserProvider.getSelectedFile();
@ -731,7 +728,8 @@ public class PreferencePane extends BasicPane {
this.portEditor.setValue(new Integer(designerEnvManager.getEmbedServerPort()));
if (useOptimizedUPMCheckbox != null) {
useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM());
useOptimizedUPMCheckbox.setSelected(ServerPreferenceConfig.getInstance().isUseOptimizedUPM()
|| DesignerEnvManager.getEnvManager().isUseOptimizedUPM4Adapter());
}
if (useNewVersionLoginCheckbox != null) {
@ -811,6 +809,7 @@ public class PreferencePane extends BasicPane {
designerEnvManager.setJoinProductImprove(this.joinProductImproveCheckBox.isSelected());
designerEnvManager.setEmbedServerLazyStartup(this.embedServerLazyStartupCheckBox.isSelected());
designerEnvManager.setImageCompress(this.imageCompressPanelCheckBox.isSelected());
designerEnvManager.setUseOptimizedUPM4Adapter(this.useOptimizedUPMCheckbox != null && this.useOptimizedUPMCheckbox.isSelected());
VcsConfigManager vcsConfigManager = designerEnvManager.getVcsConfigManager();
vcsConfigManager.setSaveInterval(this.saveIntervalEditor.getValue());
vcsConfigManager.setVcsEnable(this.vcsEnableCheckBox.isSelected());

33
designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java

@ -27,11 +27,7 @@ public abstract class ClipboardFilter {
}
public static <T> T cut(T selection) {
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
providers.addAll(clipboardHandlerProviders);
for (ClipboardHandlerProvider provider : providers) {
for (ClipboardHandlerProvider provider : getClipboardHandlerProviders()) {
if (provider.support(selection)) {
selection = ((ClipboardHandlerProvider<T>) provider).cut(selection);
}
@ -40,10 +36,7 @@ public abstract class ClipboardFilter {
}
public static <T> T copy(T selection) {
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
providers.addAll(clipboardHandlerProviders);
for (ClipboardHandlerProvider provider : providers) {
for (ClipboardHandlerProvider provider : getClipboardHandlerProviders()) {
if (provider.support(selection)) {
selection = ((ClipboardHandlerProvider<T>) provider).copy(selection);
}
@ -52,15 +45,27 @@ public abstract class ClipboardFilter {
}
public static <T> T paste(T selection) {
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
providers.addAll(clipboardHandlerProviders);
for (ClipboardHandlerProvider provider : providers) {
for (ClipboardHandlerProvider provider : getClipboardHandlerProviders()) {
if (provider.support(selection)) {
selection = ((ClipboardHandlerProvider<T>) provider).paste(selection);
}
}
return selection;
}
private static Set<ClipboardHandlerProvider> getClipboardHandlerProviders() {
Set<ClipboardHandlerProvider> providers = new HashSet<>();
for (ClipboardHandlerProvider clipboardHandlerProvider : clipboardHandlerProviders) {
providers.add(clipboardHandlerProvider);
}
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> pluginProviders = manager.getArray(ClipboardHandlerProvider.XML_TAG);
for (ClipboardHandlerProvider clipboardHandlerProvider : pluginProviders) {
providers.add(clipboardHandlerProvider);
}
return providers;
}
}

180
designer-base/src/main/java/com/fr/design/cell/CellRectangleStylePreviewPane.java

@ -0,0 +1,180 @@
package com.fr.design.cell;
import com.fr.base.CellBorderSourceFlag;
import com.fr.base.CellBorderStyle;
import com.fr.base.Style;
import com.fr.design.mainframe.theme.utils.DefaultThemedTemplateCellElementCase;
import com.fr.general.IOUtils;
import com.fr.report.cell.TemplateCellElement;
import javax.swing.JPanel;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/9/3
*/
public class CellRectangleStylePreviewPane extends JPanel {
private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png");
private final float transparentBackgroundWidth;
private final float transparentBackgroundHeight;
private static final int ROW_COUNT = 2;
private static final int COLUMN_COUNT = 2;
private final TemplateCellElement[][] cellElementGrid = new TemplateCellElement[ROW_COUNT][COLUMN_COUNT];
private final int[][] borderSourceFlags = new int[ROW_COUNT][COLUMN_COUNT];
private final CellStylePreviewPane[][] cellStylePreviewPaneGrid = new CellStylePreviewPane[ROW_COUNT][COLUMN_COUNT];
public CellRectangleStylePreviewPane(boolean supportInnerBorder) {
transparentBackgroundWidth = transparentBackgroundImage.getWidth(null);
transparentBackgroundHeight = transparentBackgroundImage.getHeight(null);
setLayout(new GridLayout(2, 2));
setOpaque(false);
setBackground(null);
for (int r = 0; r < ROW_COUNT; r++) {
for (int c = 0; c < COLUMN_COUNT; c++) {
CellStylePreviewPane pane = new CellStylePreviewPane(c, r, COLUMN_COUNT, ROW_COUNT, false, false);
TemplateCellElement cellElement = DefaultThemedTemplateCellElementCase.createInstance(c, r);
int flags = CellBorderSourceFlag.INVALID_BORDER_SOURCE;
if (supportInnerBorder) {
flags = CellBorderSourceFlag.ALL_BORDER_SOURCE_OUTER;
if (r != 0) {
flags |= CellBorderSourceFlag.TOP_BORDER_SOURCE_INNER;
}
if (r != ROW_COUNT - 1) {
flags |= CellBorderSourceFlag.BOTTOM_BORDER_SOURCE_INNER;
}
if (c != 0) {
flags |= CellBorderSourceFlag.LEFT_BORDER_SOURCE_INNER;
}
if (c != COLUMN_COUNT - 1) {
flags |= CellBorderSourceFlag.RIGHT_BORDER_SOURCE_INNER;
}
}
pane.setStyle(cellElement.getStyle());
add(pane);
cellElementGrid[r][c] = cellElement;
borderSourceFlags[r][c] = flags;
cellStylePreviewPaneGrid[r][c] = pane;
}
}
}
public void setPlainText(String text) {
cellStylePreviewPaneGrid[0][1].setPaintText(text);
cellStylePreviewPaneGrid[1][1].setPaintText(text);
repaint();
}
public void setStyle(Style style, CellBorderStyle borderStyle) {
for (int i = 0; i < ROW_COUNT; i++) {
for (int j = 0; j < COLUMN_COUNT; j++) {
CellStylePreviewPane pane = cellStylePreviewPaneGrid[i][j];
TemplateCellElement cellElement = cellElementGrid[i][j];
int flag = borderSourceFlags[i][j];
cellElement.setStyle(CellBorderSourceFlag.deriveBorderedStyle(style, borderStyle, flag));
pane.setStyle(cellElement.getStyle());
}
}
repaint();
}
@Override
public void setPreferredSize(Dimension preferredSize) {
super.setPreferredSize(preferredSize);
int hw = preferredSize.width / 2;
int hh = preferredSize.height / 2;
cellStylePreviewPaneGrid[0][0].setPreferredSize(new Dimension(hw, hh));
cellStylePreviewPaneGrid[0][1].setPreferredSize(new Dimension(hw, hh));
cellStylePreviewPaneGrid[1][0].setPreferredSize(new Dimension(hw, hh));
cellStylePreviewPaneGrid[1][1].setPreferredSize(new Dimension(hw, hh));
}
@Override
public Dimension getPreferredSize() {
Dimension d00 = cellStylePreviewPaneGrid[0][0].getPreferredSize();
Dimension d01 = cellStylePreviewPaneGrid[0][1].getPreferredSize();
Dimension d10 = cellStylePreviewPaneGrid[1][0].getPreferredSize();
Dimension d11 = cellStylePreviewPaneGrid[1][1].getPreferredSize();
int width = Math.max(d00.width + d01.width, d10.width + d11.width);
int height = Math.max(d00.height + d10.height, d01.height + d11.height);
return new Dimension(width, height);
}
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.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((Graphics2D) g, cellElementGrid[0][0].getStyle());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
super.paint(g);
}
@Override
public Rectangle getBounds() {
return super.getBounds();
}
private void paintTransparentBackground(Graphics2D g2d, Style style) {
float alpha = computeTransparentBackgroundAlpha(style);
float scaleWidth = 1.0F * getWidth() / transparentBackgroundWidth;
float scaleHeight = 1.0F * getHeight() / transparentBackgroundHeight;
float maxScale = Math.max(scaleWidth, scaleHeight);
if (maxScale <= 1) {
scaleWidth = scaleHeight = 1;
} else {
scaleHeight = scaleWidth = maxScale;
}
Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
g2d.drawImage(transparentBackgroundImage, 0, 0, (int) (transparentBackgroundWidth * scaleWidth), (int) (transparentBackgroundHeight * scaleHeight), null);
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;
}
}

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

@ -1,19 +1,27 @@
package com.fr.design.cell;
import com.fr.base.BaseUtils;
import com.fr.base.GraphHelper;
import com.fr.base.NameStyle;
import com.fr.base.ScreenResolution;
import com.fr.base.Style;
import com.fr.general.FRFont;
import com.fr.general.IOUtils;
import com.fr.stable.Constants;
import com.fr.stable.unit.PT;
import javax.swing.JPanel;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.List;
/**
* @author Starryi
@ -22,33 +30,61 @@ import java.awt.image.BufferedImage;
*/
public class CellStylePreviewPane extends JPanel {
public static final int MINIMUM_HEIGHT = 40;
private static final BufferedImage transparentBackgroundImage = IOUtils.readImage("/com/fr/design/images/transparent_background.png");
private final float transparentBackgroundWidth;
private final float transparentBackgroundHeight;
private String paintText = "Report";
private Style style = Style.DEFAULT_STYLE;
public CellStylePreviewPane() {
private final int column;
private final int row;
private final int columnSpan;
private final int rowSpan;
private final boolean autoClearCanvas;
private final boolean paintingMosaic;
public CellStylePreviewPane(int column, int row, int columnSpan, int rowSpan, boolean autoClearCanvas, boolean paintingMosaic) {
this.column = column;
this.row = row;
this.columnSpan = columnSpan;
this.rowSpan = rowSpan;
this.autoClearCanvas = autoClearCanvas;
this.paintingMosaic = paintingMosaic;
transparentBackgroundWidth = transparentBackgroundImage.getWidth(null);
transparentBackgroundHeight = transparentBackgroundImage.getHeight(null);
setPreferredSize(new Dimension(0, 0));
}
public void setPaintText(String paintText) {
this.paintText = paintText;
repaint();
}
public void setStyle(Style style) {
this.style = style;
if (style instanceof NameStyle) {
paintText = ((NameStyle) style).getName();
}
repaint();
}
public void setStyle(NameStyle style) {
paintText = style.getName();
setStyle(style.getRealStyle());
}
@Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g.clearRect(0, 0, getWidth(), getHeight());
if (autoClearCanvas) {
g2d.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);
if (paintingMosaic) {
paintTransparentBackground(g2d, style);
}
paintCellStyle(g2d, style);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
@ -107,11 +143,78 @@ public class CellStylePreviewPane extends JPanel {
Style.paintContent(g2d, paintText, style, width, height, resolution);
Style.paintBorder(g2d, style, width, height);
paintCellBorder(g2d, style);
}
protected void paintCellBorder(Graphics2D g2d, Style style) {
float adjustLeft = 0;
float adjustTop = 0;
float adjustRight = 0;
float adjustBottom = 0;
if (column == 0) {
adjustLeft = computeHalfSize4StyledBorder(style.getBorderLeft());
}
if (row == 0) {
adjustTop = computeHalfSize4StyledBorder(style.getBorderTop());
}
if (column == columnSpan - 1) {
adjustRight = -computeHalfSize4StyledBorder(style.getBorderRight());
}
if (row == rowSpan - 1) {
adjustBottom = -computeHalfSize4StyledBorder(style.getBorderBottom());
}
g2d.translate(adjustLeft, adjustTop);
Style.paintBorder(g2d, style, getWidth() - adjustLeft + adjustRight, getHeight() - adjustTop + adjustBottom);
g2d.translate(-adjustLeft, -adjustTop);
}
private float computeHalfSize4StyledBorder(int border) {
float size = GraphHelper.getLineStyleSize(border) / 2.0F;
if (border == Constants.LINE_DOUBLE) {
size += GraphHelper.getLineStyleSize(Constants.LINE_THIN) / 2.0F;
} else if (border == Constants.LINE_DOUBLE_DOT) {
size += GraphHelper.getLineStyleSize(Constants.LINE_DOT) / 2.0F;
}
return size;
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
int width = size.width;
int height = size.height;
if (height != 0) {
// 使用者设置了一个高度
return size;
} else if (width == 0) {
// 使用者未设置任何尺寸
return new Dimension(width, MINIMUM_HEIGHT);
} else {
// 使用者设置了宽度,但未设置高度
return getAutoWrapContentPreferredSize(width, height);
}
}
private Dimension getAutoWrapContentPreferredSize(int width, int height) {
int resolution = ScreenResolution.getScreenResolution();
// 计算文本区域高度
final FRFont frFont = style.getFRFont();
final Font rfont = frFont.applyResolutionNP(resolution);
final FontMetrics metrics = GraphHelper.getFontMetrics(rfont);
final int textLineHeight = metrics.getHeight();
final double textLineSpacing = PT.pt2pix(style.getLineSpacing(), resolution);
List<?> textLineList = BaseUtils.getLineTextList(paintText, style, rfont, height, width, resolution);
double textLinesHeight = textLineList.size() * textLineHeight + Math.max(0, textLineList.size() - 1) * textLineSpacing;
height = (int) Math.max(MINIMUM_HEIGHT, textLinesHeight);
return new Dimension(width, height);
}
}

52
designer-base/src/main/java/com/fr/design/config/DesignerProperties.java

@ -0,0 +1,52 @@
package com.fr.design.config;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Properties;
public class DesignerProperties {
private static DesignerProperties holder = null;
private boolean supportLoginEntry = true;
public DesignerProperties() {
String filePath = StableUtils.pathJoin(StableUtils.getInstallHome(), "/config/config.properties");
InputStream is = null;
try {
is = new BufferedInputStream(new FileInputStream(filePath));
Properties ps = new Properties();
ps.load(is);
this.initProperties(ps);
} catch (FileNotFoundException e) {
// ignore
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
} finally {
IOUtils.close(is);
}
}
public static DesignerProperties getInstance() {
if (holder == null) {
holder = new DesignerProperties();
}
return holder;
}
private void initProperties(Properties ps) {
String supportLoginEntry = ps.getProperty("supportLoginEntry");
if (StringUtils.isNotEmpty(supportLoginEntry)) {
this.supportLoginEntry = Boolean.valueOf(supportLoginEntry);
}
}
public boolean isSupportLoginEntry() {
return supportLoginEntry;
}
}

5
designer-base/src/main/java/com/fr/design/constants/TableDataConstants.java

@ -0,0 +1,5 @@
package com.fr.design.constants;
public class TableDataConstants {
public static final String SEPARATOR = "_";
}

16
designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java

@ -36,8 +36,6 @@ import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import java.util.HashSet;
import java.util.Set;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.DefaultCellEditor;
@ -55,8 +53,10 @@ import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.EventObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Coder: zack
@ -83,6 +83,7 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
protected String[] allDSNames;
protected ConnectionTableAction connectionTableAction;
protected ToolBarDef toolbarDef;
protected TableDataTreePaneListener listener = null;
private String type = "";
@ -142,6 +143,17 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
public abstract void dgEdit(final AbstractTableDataPane<?> uPanel, String originalName, boolean isUpdate);
public void showEditPane(final AbstractTableDataPane<?> tableDataPane, String originalName, TableDataTreePaneListener listener) {
this.listener = listener;
dgEdit(tableDataPane, originalName);
}
public interface TableDataTreePaneListener {
void doOk();
void doCancel();
}
protected void doPropertyChange(BasicDialog dg, BasicPane.NamePane nPanel, final String oldName) {
type = dg.getTitle();
nPanel.setShowText(StringUtils.BLANK);

7
designer-base/src/main/java/com/fr/design/data/BasicTableDataUtils.java

@ -1,6 +1,7 @@
package com.fr.design.data;
import com.fr.data.TableDataSource;
import com.fr.design.constants.TableDataConstants;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.stable.StringUtils;
@ -11,8 +12,6 @@ import com.fr.stable.StringUtils;
* Created by hades on 2020/4/27
*/
public abstract class BasicTableDataUtils {
private static final String SEPARATOR = "_";
private static final int LEN = 2;
@ -38,10 +37,10 @@ public abstract class BasicTableDataUtils {
public static String getTableDataName(boolean isCover, TableDataSource tds, String tdName, String srcName, boolean isDsNameRepeaded) {
if (isCover) {
return srcName + SEPARATOR + tdName;
return srcName + TableDataConstants.SEPARATOR + tdName;
}
if (tds.getTableData(tdName) != null || isDsNameRepeaded) {//如果有同名的就拼上来源名称
tdName = srcName + SEPARATOR + tdName;
tdName = srcName + TableDataConstants.SEPARATOR + tdName;
}
int i = 0;
while (tds.getTableData(tdName) != null) {

119
designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java

@ -1,12 +1,12 @@
package com.fr.design.data.datapane;
import com.fr.base.TableData;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.data.core.DataCoreUtils;
import com.fr.data.core.db.DBUtils;
import com.fr.data.core.db.TableProcedure;
import com.fr.data.core.db.dialect.Dialect;
import com.fr.data.core.db.dialect.DialectFactory;
import com.fr.data.impl.Connection;
import com.fr.data.impl.DBTableData;
import com.fr.data.operator.DataOperator;
import com.fr.design.DesignerEnvManager;
@ -19,7 +19,7 @@ import com.fr.design.data.datapane.preview.PreviewTablePane;
import com.fr.design.data.tabledata.Prepare4DataSourceChange;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.icombobox.FilterableComboBoxModel;
import com.fr.design.gui.icombobox.SearchPreTaskTreeComboBox;
import com.fr.design.gui.icombobox.TableSearchTreeComboBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icombobox.UIComboBoxEditor;
import com.fr.design.gui.icombobox.UIComboBoxRenderer;
@ -40,11 +40,6 @@ import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.connection.DBConnectAuth;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.util.Collections;
import java.util.concurrent.CancellationException;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
@ -58,21 +53,20 @@ import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.CancellationException;
/**
* @author zhou
@ -97,41 +91,12 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
/**
* 表名
*/
protected SearchPreTaskTreeComboBox tableNameComboBox;
private static final ExecutorService SERVICE = Executors.newSingleThreadExecutor(new NamedThreadFactory("ChoosePane"));
protected TableSearchTreeComboBox tableNameComboBox;
private SwingWorker populateWorker;
private SwingWorker<List<String>, Void> initWorker;
private PopupMenuListener popupMenuListener = new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
@Override
public Void call() throws Exception {
calculateTableDataNames();
return null;
}
});
tableNameComboBox.setPreSearchTask(task);
SERVICE.submit(task);
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// Do nothing
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// Do nothing
}
};
private PopupMenuListener listener = new PopupMenuListener() {
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
@ -181,7 +146,7 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
schemaBox = new StringUIComboBox();
schemaBox.setEditor(new ComboBoxEditor());
tableNameComboBox = new SearchPreTaskTreeComboBox(new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer, false);
tableNameComboBox = new TableSearchTreeComboBox(this, new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer);
tableNameComboBox.setEditable(true);
tableNameComboBox.setRenderer(listCellRenderer);
registerDSChangeListener();
@ -198,7 +163,6 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
});
schemaBox.addPopupMenuListener(listener);
addFocusListener();
this.tableNameComboBox.addPopupMenuListener(popupMenuListener);
}
protected void addDSBoxListener() {
@ -355,7 +319,7 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
GUICoreUtils.setSelectedItemQuietly(tableNameComboBox, -1);
}
protected com.fr.data.impl.Connection getConnection() {
public Connection getConnection() {
String selectedDSName = this.getDSName();
if (StringUtils.isEmpty(selectedDSName)) {
return null; // peter:选中了当前的零长度的节点,直接返回.
@ -455,56 +419,6 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
return "choosepane";
}
protected void calculateTableDataNames() {
JTree tree = tableNameComboBox.getTree();
if (tree == null) {
return;
}
DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot();
rootTreeNode.removeAllChildren();
String selectedDSName = this.getDSName();
com.fr.data.impl.Connection selectedDatabase = this.getConnection();
if (selectedDatabase == null) {
return;
}
try {
String schema = StringUtils.isEmpty(this.schemaBox.getSelectedItem()) ? null : this.schemaBox.getSelectedItem();
TableProcedure[] sqlTableArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace());
if (sqlTableArray.length > 0) {
ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table"));
rootTreeNode.add(tableTreeNode);
for (int i = 0; i < sqlTableArray.length; i++) {
ExpandMutableTreeNode tableChildTreeNode = new ExpandMutableTreeNode(sqlTableArray[i]);
tableTreeNode.add(tableChildTreeNode);
}
}
TableProcedure[] sqlViewArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace());
if (sqlViewArray.length > 0) {
ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View"));
rootTreeNode.add(viewTreeNode);
for (int i = 0; i < sqlViewArray.length; i++) {
ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(sqlViewArray[i]);
viewTreeNode.add(viewChildTreeNode);
}
}
((DefaultTreeModel) tree.getModel()).reload();
// daniel 展开所有tree
TreeNode root = (TreeNode) tree.getModel().getRoot();
TreePath parent = new TreePath(root);
TreeNode node = (TreeNode) parent.getLastPathComponent();
for (Enumeration e = node.children(); e.hasMoreElements(); ) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
tree.expandPath(path);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE);
}
}
/**
* 创建选中的数据集数据
*
@ -558,22 +472,23 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
return tableData;
}
protected String getDSName() {
public String getDSName() {
return this.dsNameComboBox.getSelectedItem();
}
public String getSchema() {
return this.schemaBox.getSelectedItem();
}
protected void failedToFindTable() {
// Do nothing
}
protected String getTableName() {
String tableName = "";
Object obj = this.tableNameComboBox.getSelectedItemObject();
Object obj = this.tableNameComboBox.getSelectedItem();
if (obj == null) {
obj = this.tableNameComboBox.getSelectedItem();
if (obj == null) {
obj = this.tableNameComboBox.getEditor().getItem();
}
obj = this.tableNameComboBox.getEditor().getItem();
}
if (obj instanceof TreePath) {
Object tp = ((ExpandMutableTreeNode) ((TreePath) obj).getLastPathComponent()).getUserObject();

2
designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java

@ -83,7 +83,7 @@ public class ChoosePaneSupportFormula extends ChoosePane {
*
* @return
*/
protected String getDSName() {
public String getDSName() {
String selectedDSName = null;
String item = Utils.objectToString(this.dsNameComboBox.getEditor().getItem());
// 没有选中的列表项 那么看看是不是手输值

20
designer-base/src/main/java/com/fr/design/data/datapane/TableDataPaneListPane.java

@ -17,9 +17,12 @@ import com.fr.event.EventDispatcher;
import com.fr.file.ProcedureConfig;
import com.fr.file.TableDataConfig;
import com.fr.file.TableDataOperator;
import com.fr.file.TableDataOperatorImpl;
import com.fr.general.ComparatorUtils;
import com.fr.general.NameObject;
import com.fr.log.FineLoggerFactory;
import com.fr.rpc.ExceptionHandler;
import com.fr.rpc.RPCInvokerExceptionInfo;
import com.fr.stable.ArrayUtils;
import com.fr.stable.Nameable;
import com.fr.stable.StringUtils;
@ -246,7 +249,13 @@ public class TableDataPaneListPane extends JListControlPane implements TableData
tableDataBeans.add(new TableDataBean(nameObject.getName(), oldName, (TableData) nameObject.getObject()));
}
try {
WorkContext.getCurrent().get(TableDataOperator.class).saveTableData(tableDataBeans);
WorkContext.getCurrent().get(TableDataOperator.class, new ExceptionHandler() {
@Override
public Object callHandler(RPCInvokerExceptionInfo exceptionInfo) {
// 走老的方式
return saveByOldWay(tableDataBeans);
}
}).saveTableData(new ArrayList<>(tableDataConfig.getTableDatas().keySet()), tableDataBeans);
if (!WorkContext.getCurrent().isLocal()) {
EventDispatcher.fire(RemoteConfigEvent.EDIT, TableDataConfig.getInstance().getNameSpace());
}
@ -255,6 +264,15 @@ public class TableDataPaneListPane extends JListControlPane implements TableData
}
}
private boolean saveByOldWay(List<TableDataBean> tableDataBean) {
try {
return TableDataOperatorImpl.getInstance().saveTableData(tableDataBean);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return false;
}
}
@Override
public void update(TableDataSource tds) {
tds.clearAllTableData();

7
designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java

@ -361,11 +361,18 @@ public class TableDataTreePane extends BasicTableDataTreePane {
//单独编辑数据集关闭,修改缓存配置状态,刷新下一键开启/关闭按钮
checkButtonEnabled();
if (listener != null) {
listener.doOk();
}
}
@Override
public void doCancel() {
super.doCancel();
if (listener != null) {
listener.doCancel();
}
}
});
tdNamePanel.addPropertyChangeListener(new PropertyChangeAdapter() {

145
designer-base/src/main/java/com/fr/design/data/datapane/connect/AdvancePane.java

@ -0,0 +1,145 @@
package com.fr.design.data.datapane.connect;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.pool.DBCPConnectionPoolAttr;
import com.fr.design.dialog.BasicPane;
import com.fr.design.editor.editor.IntegerEditor;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.stable.StringUtils;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
/**
* @author xiqiu
* @date 2021/11/22
* @description
*/
public class AdvancePane extends BasicPane {
private IntegerEditor DBCP_MAX_ACTIVE = new IntegerEditor();
private UIComboBox DBCP_TESTONBORROW = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")});
private IntegerEditor DBCP_MAX_WAIT = new IntegerEditor();
private SpecialUITextField DBCP_VALIDATION_QUERY = new SpecialUITextField();
public AdvancePane() {
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
DBCP_VALIDATION_QUERY.addFocusListener(new JTextFieldHintListener(DBCP_VALIDATION_QUERY));
double p = TableLayout.PREFERRED;
DBCP_VALIDATION_QUERY.setColumns(20);
double[] rowSizeDbcp = {p, p, p, p};
double[] columnDbcp = {190, p};
Component[][] comps = {
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Max_Active") + ":", SwingConstants.RIGHT), DBCP_MAX_ACTIVE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Validation_Query") + ":", SwingConstants.RIGHT), DBCP_VALIDATION_QUERY},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_On_Borrow") + ":", SwingConstants.RIGHT), DBCP_TESTONBORROW},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Max_Wait_Time") + ":", SwingConstants.RIGHT), DBCP_MAX_WAIT}
};
JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSizeDbcp, columnDbcp, 11, 11);
jPanel.add(contextPane, BorderLayout.CENTER);
this.add(jPanel);
}
public void populate(JDBCDatabaseConnection jdbcDatabase) {
DBCPConnectionPoolAttr dbcpAttr = jdbcDatabase.getDbcpAttr();
if (dbcpAttr == null) {
dbcpAttr = new DBCPConnectionPoolAttr();
jdbcDatabase.setDbcpAttr(dbcpAttr);
}
this.DBCP_MAX_ACTIVE.setValue(dbcpAttr.getMaxActive());
this.DBCP_MAX_WAIT.setValue(dbcpAttr.getMaxWait());
this.DBCP_VALIDATION_QUERY.setText(dbcpAttr.getValidationQuery());
this.DBCP_TESTONBORROW.setSelectedIndex(dbcpAttr.isTestOnBorrow() ? 1 : 0);
}
public void update(JDBCDatabaseConnection jdbcDatabase) {
DBCPConnectionPoolAttr dbcpAttr = jdbcDatabase.getDbcpAttr();
if (dbcpAttr == null) {
dbcpAttr = new DBCPConnectionPoolAttr();
jdbcDatabase.setDbcpAttr(dbcpAttr);
}
dbcpAttr.setMaxActive(this.DBCP_MAX_ACTIVE.getValue().intValue());
dbcpAttr.setMaxWait(this.DBCP_MAX_WAIT.getValue().intValue());
dbcpAttr.setValidationQuery(this.DBCP_VALIDATION_QUERY.getText());
dbcpAttr.setTestOnBorrow(this.DBCP_TESTONBORROW.getSelectedIndex() == 0 ? false : true);
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Basic_Advanced_Setup");
}
private class JTextFieldHintListener implements FocusListener {
private SpecialUITextField textField;
public JTextFieldHintListener(SpecialUITextField jTextField) {
this.textField = jTextField;
}
@Override
public void focusGained(FocusEvent e) {
//获取焦点时,清空提示内容
String temp = textField.getText();
textField.setForeground(Color.BLACK);
textField.setTextOrigin(temp);
}
@Override
public void focusLost(FocusEvent e) {
//失去焦点时,没有输入内容,显示提示内容
String temp = textField.getTextOrigin();
textField.setText(temp);
}
}
private class SpecialUITextField extends UITextField {
@Override
public String getText() {
String text = super.getText();
if (isUseless(text)) {
return StringUtils.EMPTY;
}
return text;
}
@Override
public void setText(String text) {
if (isUseless(text)) {
this.setForeground(Color.GRAY);
super.setText(Toolkit.i18nText("Fine-Design_Dbcp_Default_Query"));
} else {
this.setForeground(Color.BLACK);
super.setText(text);
}
}
public String getTextOrigin() {
return super.getText();
}
public void setTextOrigin(String text) {
super.setText(text);
}
private boolean isUseless(String text) {
return text == null || text.isEmpty() || Toolkit.i18nText("Fine-Design_Dbcp_Default_Query").equals(text);
}
}
}

19
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java

@ -16,8 +16,11 @@ import com.fr.design.i18n.Toolkit;
import com.fr.event.EventDispatcher;
import com.fr.file.ConnectionConfig;
import com.fr.file.ConnectionOperator;
import com.fr.file.ConnectionOperatorImpl;
import com.fr.general.NameObject;
import com.fr.log.FineLoggerFactory;
import com.fr.rpc.ExceptionHandler;
import com.fr.rpc.RPCInvokerExceptionInfo;
import com.fr.stable.ArrayUtils;
import com.fr.stable.Nameable;
import com.fr.stable.StringUtils;
@ -170,7 +173,12 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
connectionBeans.add(new ConnectionBean(nameObject.getName(), oldName, (Connection) nameObject.getObject()));
}
try {
WorkContext.getCurrent().get(ConnectionOperator.class).saveConnection(connectionBeans);
WorkContext.getCurrent().get(ConnectionOperator.class, new ExceptionHandler() {
@Override
public Object callHandler(RPCInvokerExceptionInfo exceptionInfo) {
return saveByOldWay(connectionBeans);
}
}).saveConnection(new ArrayList<>(connectionConfig.getConnections().keySet()), connectionBeans);
if (!WorkContext.getCurrent().isLocal()) {
EventDispatcher.fire(RemoteConfigEvent.EDIT, ConnectionConfig.getInstance().getNameSpace());
}
@ -179,6 +187,15 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
}
}
private boolean saveByOldWay(List<ConnectionBean> connectionBeans) {
try {
return ConnectionOperatorImpl.getInstance().saveConnection(connectionBeans);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
return false;
}
}
public static void showDialog(Window parent) {
final ConnectionConfig connectionConfig = ConnectionConfig.getInstance();
final ConnectionManagerPane connectionManagerPane = new ConnectionManagerPane() {

35
designer-base/src/main/java/com/fr/design/data/datapane/connect/DBCPAttrPane.java

@ -20,6 +20,7 @@ import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Window;
@ -45,13 +46,8 @@ public class DBCPAttrPane extends BasicPane {
private static final int EMPTY_FETCHSIZE = -2;
// carl:DBCP的一些属性
private IntegerEditor DBCP_INITIAL_SIZE = new IntegerEditor();
private IntegerEditor DBCP_MAX_ACTIVE = new IntegerEditor();
private IntegerEditor DBCP_MAX_IDLE = new IntegerEditor();
private IntegerEditor DBCP_MIN_IDLE = new IntegerEditor();
private IntegerEditor DBCP_MAX_WAIT = new IntegerEditor();
private UITextField DBCP_VALIDATION_QUERY = new UITextField();
private UIComboBox DBCP_TESTONBORROW = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")});
private UIComboBox DBCP_TESTONRETURN = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")});
private UIComboBox DBCP_TESTWHILEIDLE = new UIComboBox(new String[]{Toolkit.i18nText("Fine-Design_Basic_No"), Toolkit.i18nText("Fine-Design_Basic_Yes")});
@ -75,25 +71,19 @@ public class DBCPAttrPane extends BasicPane {
defaultPane = this;
// JPanel northFlowPane
northFlowPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_ConnectionPool_Attr"));
northFlowPane.setPreferredSize(new Dimension(630, 320));
northFlowPane = FRGUIPaneFactory.createTopVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_ConnectionPool_Attr"));
northFlowPane.setPreferredSize(new Dimension(630, 330));
defaultPane.add(northFlowPane, BorderLayout.NORTH);
DBCP_VALIDATION_QUERY.setColumns(15);
// ContextPane
double f = TableLayout.FILL;
// double p = TableLayout.PREFERRED;
double[] rowSize = {f, f, f, f, f, f, f, f, f, f, f, f};
double[] rowSize = {f, f, f, f, f, f, f};
double[] columnSize = {f, f};
Component[][] comps = {
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Initial_Size") + ":", SwingConstants.RIGHT), DBCP_INITIAL_SIZE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Max_Active") + ":", SwingConstants.RIGHT), DBCP_MAX_ACTIVE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Max_Idle") + ":", SwingConstants.RIGHT), DBCP_MAX_IDLE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Min_Idle") + ":", SwingConstants.RIGHT), DBCP_MIN_IDLE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Max_Wait_Time") + ":", SwingConstants.RIGHT), DBCP_MAX_WAIT},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Validation_Query") + ":", SwingConstants.RIGHT), DBCP_VALIDATION_QUERY},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_On_Borrow") + ":", SwingConstants.RIGHT), DBCP_TESTONBORROW},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_On_Return") + ":", SwingConstants.RIGHT), DBCP_TESTONRETURN},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Dbcp_Test_While_Idle") + ":", SwingConstants.RIGHT), DBCP_TESTWHILEIDLE},
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Evictionruns_millis") + ":", SwingConstants.RIGHT),
@ -102,8 +92,13 @@ public class DBCPAttrPane extends BasicPane {
{new UILabel(Toolkit.i18nText("Fine-Design_Basic_Connection_Pool_Mix_Evictable_Idle_Time_Millis") + ":", SwingConstants.RIGHT),
DBCP_MINEVICTABLEIDLETIMEMILLIS}};
JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSize, columnSize, 10, 4);
JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSize, columnSize, 10, 10);
northFlowPane.add(contextPane);
JPanel boxFlowInnerContainer = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(0, 5, 5);
UILabel uiLabel = new UILabel(Toolkit.i18nText("Fine-Design_Dbcp_Warning"));
uiLabel.setForeground(Color.RED);
boxFlowInnerContainer.add(uiLabel);
northFlowPane.add(boxFlowInnerContainer);
}
public void populate(JDBCDatabaseConnection jdbcDatabase) {
@ -113,12 +108,7 @@ public class DBCPAttrPane extends BasicPane {
jdbcDatabase.setDbcpAttr(dbcpAttr);
}
this.DBCP_INITIAL_SIZE.setValue(dbcpAttr.getInitialSize());
this.DBCP_MAX_ACTIVE.setValue(dbcpAttr.getMaxActive());
this.DBCP_MAX_IDLE.setValue(dbcpAttr.getMaxIdle());
this.DBCP_MAX_WAIT.setValue(dbcpAttr.getMaxWait());
this.DBCP_MIN_IDLE.setValue(dbcpAttr.getMinIdle());
this.DBCP_VALIDATION_QUERY.setText(dbcpAttr.getValidationQuery());
this.DBCP_TESTONBORROW.setSelectedIndex(dbcpAttr.isTestOnBorrow() ? 1 : 0);
this.DBCP_TESTONRETURN.setSelectedIndex(dbcpAttr.isTestOnReturn() ? 1 : 0);
this.DBCP_TESTWHILEIDLE.setSelectedIndex(dbcpAttr.isTestWhileIdle() ? 1 : 0);
this.DBCP_MINEVICTABLEIDLETIMEMILLIS.setValue(dbcpAttr.getMinEvictableIdleTimeMillis() / TIME_MULTIPLE);
@ -141,12 +131,7 @@ public class DBCPAttrPane extends BasicPane {
jdbcDatabase.setDbcpAttr(dbcpAttr);
}
dbcpAttr.setInitialSize(this.DBCP_INITIAL_SIZE.getValue().intValue());
dbcpAttr.setMaxActive(this.DBCP_MAX_ACTIVE.getValue().intValue());
dbcpAttr.setMaxIdle(this.DBCP_MAX_IDLE.getValue().intValue());
dbcpAttr.setMaxWait(this.DBCP_MAX_WAIT.getValue().intValue());
dbcpAttr.setMinIdle(this.DBCP_MIN_IDLE.getValue().intValue());
dbcpAttr.setValidationQuery(this.DBCP_VALIDATION_QUERY.getText());
dbcpAttr.setTestOnBorrow(this.DBCP_TESTONBORROW.getSelectedIndex() == 0 ? false : true);
dbcpAttr.setTestOnReturn(this.DBCP_TESTONRETURN.getSelectedIndex() == 0 ? false : true);
dbcpAttr.setTestWhileIdle(this.DBCP_TESTWHILEIDLE.getSelectedIndex() == 0 ? false : true);
dbcpAttr.setMinEvictableIdleTimeMillis(((Number) this.DBCP_MINEVICTABLEIDLETIMEMILLIS.getValue()).intValue() * TIME_MULTIPLE);

82
designer-base/src/main/java/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java

@ -7,6 +7,7 @@ import com.fr.data.impl.Connection;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.impl.JNDIDatabaseConnection;
import com.fr.data.operator.DataOperatorProvider;
import com.fr.data.security.ssl.impl.NormalSsl;
import com.fr.data.solution.ExceptionSolutionSelector;
import com.fr.data.solution.entity.DriverPage;
import com.fr.data.solution.processor.ClassNotFoundExceptionSolutionProcessor;
@ -14,11 +15,11 @@ import com.fr.data.solution.processor.SolutionProcessor;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.ActionLabel;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.scrollruler.ModLineBorder;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.rpc.ExceptionHandler;
@ -34,6 +35,7 @@ import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
@ -60,6 +62,8 @@ import java.util.concurrent.ExecutionException;
* Database Connection pane.
*/
public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connection> extends BasicBeanPane<com.fr.data.impl.Connection> {
private static int MAX_MAIN_PANEL_HEIGHT = 410;
private static int MAX_MAIN_PANEL_WIDTH = 675;
private UILabel message;
private UIButton okButton;
@ -305,6 +309,19 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
protected abstract E updateSubDatabaseConnectionBean();
protected JPanel getAdvancePane() {
throw new UnsupportedOperationException();
}
protected SslPane getSslPane() {
throw new UnsupportedOperationException();
}
protected SshPane getSshPane() {
throw new UnsupportedOperationException();
}
protected void initComponents() {
message = new UILabel();
uiLabel = new UILabel();
@ -318,7 +335,8 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel"));
this.setLayout(FRGUIPaneFactory.createBorderLayout());
JPanel northPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane();
this.add(northPane, BorderLayout.NORTH);
UIScrollPane uiScrollPane = new UIScrollPane(northPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
this.add(uiScrollPane, BorderLayout.CENTER);
// 按钮.
JPanel testPane = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane();
@ -330,15 +348,12 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
// Center
mainPanel = mainPanel();
northPane.add(mainPanel, BorderLayout.CENTER);
JPanel advancedPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
advancedPanel.setBorder(BorderFactory.createTitledBorder(
new ModLineBorder(ModLineBorder.TOP),
Toolkit.i18nText("Fine-Design_Basic_Advanced")
));
JPanel advancedPanel = FRGUIPaneFactory.createTopVerticalTitledBorderPane(Toolkit.i18nText("Fine-Design_Basic_Advanced"));
if (mainPanel instanceof JDBCDefPane) {
ActionLabel actionLabel = new ActionLabel(Toolkit.i18nText("Fine-Design_Basic_Advanced_Setup"));
northPane.add(mainPanel, BorderLayout.CENTER);
ActionLabel actionLabel = new ActionLabel(Toolkit.i18nText("Fine-Design_Advanced_More_Settings"));
actionLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
JDialog wDialog = createJDialog();
if (wDialog != null) {
@ -349,10 +364,25 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
JPanel actionLabelPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
actionLabelPanel.setBorder(BorderFactory.createEmptyBorder(2, 4, 4, 20));
actionLabelPanel.add(actionLabel, BorderLayout.WEST);
JPanel advancePane = getAdvancePane();
if (advancePane != null) {
advancedPanel.add(advancePane);
}
advancedPanel.add(actionLabelPanel);
northPane.add(getSshPane());
northPane.add(getSslPane());
} else {
//非jdbc配置布局保持不变
advancedPanel.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, 60));
if (mainPanel.getPreferredSize().height > MAX_MAIN_PANEL_HEIGHT || mainPanel.getPreferredSize().width > MAX_MAIN_PANEL_WIDTH) {
UIScrollPane jp = new
UIScrollPane(mainPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jp.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, MAX_MAIN_PANEL_HEIGHT));
northPane.add(jp, BorderLayout.CENTER);
} else {
mainPanel.setPreferredSize(new Dimension(MAX_MAIN_PANEL_WIDTH, MAX_MAIN_PANEL_HEIGHT));
northPane.add(mainPanel, BorderLayout.CENTER);
}
// ChartSet
String[] defaultEncode = new String[]{Toolkit.i18nText("Fine-Design_Encode_Auto")};
charSetComboBox = new UIComboBox(ArrayUtils.addAll(defaultEncode, EncodeConstants.ENCODING_ARRAY));
@ -406,6 +436,13 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
public static class JDBC extends DatabaseConnectionPane<JDBCDatabaseConnection> {
private static JDBCDefPane jdbcDefPane = new JDBCDefPane();
private static DBCPAttrPane dbcpAttrPane = new DBCPAttrPane();
private static AdvancePane advancePane = new AdvancePane();
private static SslPane sslPane = new SslPane();
private static SshPane sshPane = new SshPane();
static {
jdbcDefPane.addLinkPane(sslPane);
}
@Override
protected JPanel mainPanel() {
@ -425,15 +462,40 @@ public abstract class DatabaseConnectionPane<E extends com.fr.data.impl.Connecti
protected void populateSubDatabaseConnectionBean(JDBCDatabaseConnection ob) {
jdbcDefPane.populate(ob);
dbcpAttrPane.populate(jdbcDefPane.getJDBCDatabase());
advancePane.populate(jdbcDefPane.getJDBCDatabase());
sshPane.populate(jdbcDefPane.getJDBCDatabase());
sslPane.populate(jdbcDefPane.getJDBCDatabase());
}
@Override
protected JDBCDatabaseConnection updateSubDatabaseConnectionBean() {
JDBCDatabaseConnection jdbcDatabaseConnection = jdbcDefPane.update();
dbcpAttrPane.update(jdbcDatabaseConnection);
advancePane.update(jdbcDatabaseConnection);
sshPane.update(jdbcDatabaseConnection);
if (sslPane.isVisible()) {
sslPane.update(jdbcDatabaseConnection);
} else {
jdbcDatabaseConnection.setSsl(new NormalSsl());
}
return jdbcDatabaseConnection;
}
@Override
protected JPanel getAdvancePane() {
return advancePane;
}
@Override
protected SslPane getSslPane() {
return sslPane;
}
@Override
protected SshPane getSshPane() {
return sshPane;
}
@Override
protected String title4PopupWindow() {
return "JDBC";

19
designer-base/src/main/java/com/fr/design/data/datapane/connect/JDBCDefPane.java

@ -4,7 +4,9 @@ import com.fr.base.GraphHelper;
import com.fr.data.driver.DriverLoader;
import com.fr.data.driver.config.DriverLoaderConfig;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.solution.entity.DriverClasses;
import com.fr.design.border.UITitledBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icombobox.UIComboBoxUI;
@ -28,6 +30,7 @@ import com.fr.third.guava.collect.HashBiMap;
import com.fr.workspace.WorkContext;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
@ -67,6 +70,7 @@ public class JDBCDefPane extends JPanel {
// 编码转换.
private String originalCharSet = null;
private static Map<String, DriverURLName[]> jdbcMap = new HashMap<String, DriverURLName[]>();
private JPanel linkPanel;
static {
jdbcMap.put(OTHER_DB, new DriverURLName[]{new DriverURLName("sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:"),
@ -193,7 +197,9 @@ public class JDBCDefPane extends JPanel {
userNameTextField = new UITextField(15);
userNameTextField.setName(USER_NAME);
passwordTextField = new UIPasswordFieldWithFixedLength(15);
dbtypeButton = new UIButton(".");
dbtypeButton = new UIButton();
dbtypeButton.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT));
dbtypeButton.setPreferredSize(new Dimension(20, 20));
dbtypeButton.setToolTipText(Toolkit.i18nText("Fine-Design_Basic_Click_Get_Default_URL"));
dbtypeButton.addActionListener(dbtypeButtonActionListener);
@ -477,11 +483,16 @@ public class JDBCDefPane extends JPanel {
}
ActionListener driverListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
linkPanel.setVisible(DriverClasses.MYSQL.toString().equalsIgnoreCase((String) dbtypeComboBox.getSelectedItem())
&& driverComboBox.getSelectedItem() != null
&& ComparatorUtils.equals(DriverClasses.MYSQL.getDriverClass(), driverComboBox.getSelectedItem().toString().trim()));
odbcTipsLink.setVisible(driverComboBox.getSelectedItem() != null
&& ComparatorUtils.equals("sun.jdbc.odbc.JdbcOdbcDriver", driverComboBox.getSelectedItem().toString().trim())); // 选择的如果是ODBC就显示提示
if (driverComboBox.getSelectedItem() == null || ComparatorUtils.equals(driverComboBox.getSelectedItem(), StringUtils.EMPTY)) {
return;
}
odbcTipsLink.setVisible(ComparatorUtils.equals("sun.jdbc.odbc.JdbcOdbcDriver", driverComboBox.getSelectedItem())); // 选择的如果是ODBC就显示提示
Iterator<Entry<String, DriverURLName[]>> jdbc = jdbcMap.entrySet().iterator();
while (jdbc.hasNext()) {
Entry<String, DriverURLName[]> entry = jdbc.next();
@ -494,7 +505,6 @@ public class JDBCDefPane extends JPanel {
}
}
}
};
ActionListener dbtypeButtonActionListener = new ActionListener() {
@ -738,4 +748,7 @@ public class JDBCDefPane extends JPanel {
}
public void addLinkPane(JPanel panel) {
linkPanel = panel;
}
}

301
designer-base/src/main/java/com/fr/design/data/datapane/connect/SshPane.java

@ -0,0 +1,301 @@
package com.fr.design.data.datapane.connect;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.security.ssh.BaseSsh;
import com.fr.data.security.ssh.Ssh;
import com.fr.data.security.ssh.SshException;
import com.fr.data.security.ssh.SshType;
import com.fr.data.security.ssh.impl.KeyVerifySsh;
import com.fr.data.security.ssh.impl.NormalSsh;
import com.fr.design.border.UITitledBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.BasicPane;
import com.fr.design.editor.editor.NotNegativeIntegerEditor;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ipasswordfield.UIPasswordFieldWithFixedLength;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.file.FILE;
import com.fr.file.FILEChooserPane;
import com.fr.file.filter.ChooseFileFilter;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.third.guava.collect.HashBiMap;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.fr.design.i18n.Toolkit.i18nText;
/**
* @author xiqiu
* @date 2021/12/23
* @description
*/
public class SshPane extends BasicPane {
private static HashBiMap<String, SshType> typeMap;
static {
typeMap = HashBiMap.create();
typeMap.put(Toolkit.i18nText("Fine-Design_Basic_Password"), SshType.NORMAL);
typeMap.put(Toolkit.i18nText("Fine-Design_Basic_Ssh_Public_Key"), SshType.KEY);
}
private UICheckBox usingSsh = new UICheckBox(i18nText("Fine-Design_Basic_Ssh_Using"));
private NotNegativeIntegerEditor port = new NotNegativeIntegerEditor(20);
private UITextField ip = new UITextField(20);
private UIComboBox type = new UIComboBox();
private UITextField user = new UITextField(20);
private JPasswordField password = new UIPasswordFieldWithFixedLength(20);
private JPasswordField secret = new UIPasswordFieldWithFixedLength(20);
private KeyFileUITextField keyPath = new KeyFileUITextField(18);
private JPanel contextPane;
private Component[][] passwordComps;
private Component[][] keyComps;
private double p = TableLayout.PREFERRED;
private double f = TableLayout.FILL;
private JPanel jPanel;
private UIButton fileChooserButton = new UIButton();
private double[] columnSize = new double[]{195, p};
public SshPane() {
fileChooserButton.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT));
this.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Basic_Ssh_Settings")));
this.setLayout(FRGUIPaneFactory.createLabelFlowLayout());
typeMap.keySet().forEach(key -> type.addItem(key));
type.setSelectedItem(typeMap.inverse().get(SshType.KEY));
jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
fileChooserButton.setPreferredSize(new Dimension(20, 20));
type.setEditable(false);
type.setSelectedItem(Toolkit.i18nText("Fine-Design_Basic_Ssh_Private_Key"));
JPanel filePanel = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPath, fileChooserButton}}, new double[]{p}, new double[]{f, 20}, 0);
Component[] compIp = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Host") + ":", SwingConstants.RIGHT), ip};
Component[] compPort = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Port") + ":", SwingConstants.RIGHT), port};
Component[] compUserName = {new UILabel(Toolkit.i18nText("Fine-Design_Report_UserName") + ":", SwingConstants.RIGHT), user};
Component[] compMethod = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Verify_Method") + ":", SwingConstants.RIGHT), type};
Component[] compPassword = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Password") + ":", SwingConstants.RIGHT), password};
Component[] compKey = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Private_Key") + ":", SwingConstants.RIGHT), filePanel};
Component[] comSecret = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssh_Secret") + ":", SwingConstants.RIGHT), secret};
passwordComps = new Component[][]{
compIp,
compPort,
compUserName,
compMethod,
compPassword
};
keyComps = new Component[][]{
compIp,
compPort,
compUserName,
compMethod,
compKey,
comSecret
};
usingSsh.setSelected(true);
contextPane = TableLayoutHelper.createGapTableLayoutPane(keyComps, new double[]{p, p, p, p, p, p}, columnSize, 11, 11);
jPanel.add(usingSsh, BorderLayout.NORTH);
jPanel.add(contextPane, BorderLayout.CENTER);
this.add(jPanel);
usingSsh.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changePane();
}
});
type.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changePaneForType();
}
});
fileChooserButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(ProjectConstants.RESOURCES_NAME, new ChooseFileFilter(true));
int type = fileChooser.showOpenDialog(SshPane.this, StringUtils.EMPTY);
if (type == FILEChooserPane.OK_OPTION) {
final FILE file = fileChooser.getSelectedFILE();
if (file == null) {
keyPath.setText(StringUtils.EMPTY);
} else {
keyPath.setText(file.getPath());
}
}
fileChooser.removeAllFilter();
}
});
}
private void changePane() {
contextPane.setVisible(usingSsh.isSelected());
}
private void changePaneForType() {
contextPane.removeAll();
switch (typeMap.get(type.getSelectedItem())) {
case NORMAL:
TableLayoutHelper.addComponent2ResultPane(passwordComps, new double[]{p, p, p, p, p}, columnSize, contextPane);
break;
case KEY:
TableLayoutHelper.addComponent2ResultPane(keyComps, new double[]{p, p, p, p, p, p}, columnSize, contextPane);
break;
default:
throw new SshException("un support ssh type");
}
jPanel.revalidate();
jPanel.repaint();
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Basic_Ssh_Settings");
}
public void populate(JDBCDatabaseConnection jdbcDatabase) {
if (jdbcDatabase.getSsh() == null) {
jdbcDatabase.setSsh(new NormalSsh());
}
Ssh ssh = jdbcDatabase.getSsh();
switch (ssh.getSshType()) {
case KEY:
type.setSelectedItem(typeMap.inverse().get(ssh.getSshType()));
KeyVerifySsh keyVerifySsh = (KeyVerifySsh) ssh;
keyPath.setText(keyVerifySsh.getPrivateKeyPath());
secret.setText(keyVerifySsh.getSecret());
password.setText(StringUtils.EMPTY);
setCommonConfig(keyVerifySsh);
break;
case NORMAL:
type.setSelectedItem(typeMap.inverse().get(ssh.getSshType()));
NormalSsh normalSsh = (NormalSsh) ssh;
password.setText(normalSsh.getSecret());
keyPath.setText(StringUtils.EMPTY);
secret.setText(StringUtils.EMPTY);
setCommonConfig(normalSsh);
break;
default:
throw new SshException("un support ssh type");
}
usingSsh.setSelected(ssh.isUsingSsh());
changePane();
}
private void setCommonConfig(BaseSsh baseSsh) {
ip.setText(baseSsh.getIp());
port.setValue(baseSsh.getPort());
user.setText(baseSsh.getUser());
}
public void update(JDBCDatabaseConnection jdbcDatabase) {
Ssh ssh;
switch (typeMap.get(type.getSelectedItem())) {
case NORMAL:
NormalSsh normalSsh = new NormalSsh();
normalSsh.setSecret(new String(password.getPassword()).trim());
getCommonConfig(normalSsh);
ssh = normalSsh;
break;
case KEY:
KeyVerifySsh keyVerifySsh = new KeyVerifySsh();
keyVerifySsh.setPrivateKeyPath(keyPath.getText().trim());
keyVerifySsh.setSecret(new String(secret.getPassword()).trim());
getCommonConfig(keyVerifySsh);
ssh = keyVerifySsh;
break;
default:
throw new SshException("un support ssh type");
}
jdbcDatabase.setSsh(ssh);
}
private void getCommonConfig(BaseSsh baseSsh) {
baseSsh.setUsingSsh(usingSsh.isSelected());
baseSsh.setIp(ip.getText().trim());
baseSsh.setPort(port.getValue());
baseSsh.setUser(user.getText().trim());
}
public static class KeyFileUITextField extends UITextField {
private static final Pattern ERROR_START = Pattern.compile("^([/\\\\.]+).*");
private static final Pattern MUTI_DOT = Pattern.compile("\\.+");
private static final String PREFIX = ProjectConstants.RESOURCES_NAME + "/";
private static final String UPPER = "..";
public KeyFileUITextField(int columns) {
this();
this.setColumns(columns);
}
public KeyFileUITextField() {
super();
this.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
String text = KeyFileUITextField.this.getTextOrigin();
if (!StringUtils.isEmpty(text)) {
if (text.contains(UPPER)) {
text = MUTI_DOT.matcher(text).replaceAll(".");
KeyFileUITextField.this.setTextOrigin(text);
}
Matcher matcher = ERROR_START.matcher(text);
if (matcher.matches()) {
text = text.substring(matcher.group(1).length());
KeyFileUITextField.this.setTextOrigin(text);
}
}
}
});
}
public String getTextOrigin() {
return super.getText();
}
public void setTextOrigin(String text) {
super.setText(text);
}
@Override
public String getText() {
// 获取的时候,不为空,给他加上前缀就好了,否则还是空
if (!StringUtils.isEmpty(super.getText())) {
return PREFIX + super.getText();
}
return StringUtils.EMPTY;
}
@Override
public void setText(String text) {
// 设置的时候,不为空,说明文件指定了(文件需要是resource下),替换掉前缀
if (!StringUtils.isEmpty(text) && text.startsWith(PREFIX)) {
super.setText(text.replaceFirst(PREFIX, ""));
} else {
super.setText(text);
}
}
}
}

164
designer-base/src/main/java/com/fr/design/data/datapane/connect/SslPane.java

@ -0,0 +1,164 @@
package com.fr.design.data.datapane.connect;
import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.security.ssl.Ssl;
import com.fr.data.security.ssl.SslException;
import com.fr.data.security.ssl.SslType;
import com.fr.data.security.ssl.impl.NormalSsl;
import com.fr.design.border.UITitledBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.data.datapane.connect.SshPane.KeyFileUITextField;
import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.file.FILE;
import com.fr.file.FILEChooserPane;
import com.fr.file.filter.ChooseFileFilter;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import static com.fr.design.i18n.Toolkit.i18nText;
/**
* @author xiqiu
* @date 2022/1/4
* @description
*/
public class SslPane extends BasicPane {
UICheckBox usingSsl = new UICheckBox(i18nText("Fine-Design_Basic_Ssl_Using"));
private KeyFileUITextField keyPathCa = new KeyFileUITextField(18);
private UIButton fileChooserButtonCa = new UIButton();
private KeyFileUITextField keyPathClientCert = new KeyFileUITextField(18);
private UIButton fileChooserButtonClientCert = new UIButton();
private KeyFileUITextField keyPathClientKey = new KeyFileUITextField(18);
private UIButton fileChooserButtonClientKey = new UIButton();
private UICheckBox verifyCa = new UICheckBox(i18nText("Fine-Design_Basic_Ssl_Verify_Ca"));
// private UITextField cipher = new UITextField(20);
private JPanel jPanel;
private Component[][] usingComps;
private double p = TableLayout.PREFERRED;
private double f = TableLayout.FILL;
private JPanel contextPane;
private double[] columnSize = new double[]{195, p};
public SslPane() {
fileChooserButtonCa.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT));
fileChooserButtonClientCert.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT));
fileChooserButtonClientKey.setIcon(new ImageIcon(UIConstants.ACCESSIBLE_EDITOR_DOT));
this.setBorder(UITitledBorder.createBorderWithTitle(Toolkit.i18nText("Fine-Design_Basic_Ssl_Settings")));
this.setLayout(FRGUIPaneFactory.createLabelFlowLayout());
jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
Dimension dimension = new Dimension(20, 20);
fileChooserButtonCa.setPreferredSize(dimension);
fileChooserButtonClientCert.setPreferredSize(dimension);
fileChooserButtonClientKey.setPreferredSize(dimension);
JPanel filePanelCa = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPathCa, fileChooserButtonCa}}, new double[]{p}, new double[]{f, 20}, 0);
Component[] compCa = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Ca") + ":", SwingConstants.RIGHT), filePanelCa};
Component[] compVerifyCa = {null, verifyCa};
JPanel filePanelClientCert = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPathClientCert, fileChooserButtonClientCert}}, new double[]{p}, new double[]{f, 20}, 0);
Component[] compClientCert = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Client_Cert") + ":", SwingConstants.RIGHT), filePanelClientCert};
JPanel filePanelClientKey = TableLayoutHelper.createCommonTableLayoutPane(new Component[][]{{keyPathClientKey, fileChooserButtonClientKey}}, new double[]{p}, new double[]{f, 20}, 0);
Component[] compClientKey = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Client_Key") + ":", SwingConstants.RIGHT), filePanelClientKey};
// Component[] comCipher = {new UILabel(Toolkit.i18nText("Fine-Design_Basic_Ssl_Cipher") + ":", SwingConstants.RIGHT), cipher};
usingComps = new Component[][]{
compCa,
compVerifyCa,
compClientCert,
compClientKey,
// comCipher
};
usingSsl.setSelected(true);
contextPane = TableLayoutHelper.createGapTableLayoutPane(usingComps, new double[]{p, p, p, p}, columnSize, 11, 11);
jPanel.add(usingSsl, BorderLayout.NORTH);
jPanel.add(contextPane, BorderLayout.CENTER);
this.add(jPanel);
usingSsl.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changePane();
}
});
fileChooserButtonCa.addActionListener(new TextFieldActionListener(keyPathCa));
fileChooserButtonClientCert.addActionListener(new TextFieldActionListener(keyPathClientCert));
fileChooserButtonClientKey.addActionListener(new TextFieldActionListener(keyPathClientKey));
}
private void changePane() {
contextPane.setVisible(usingSsl.isSelected());
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Basic_Ssl_Settings");
}
public void populate(JDBCDatabaseConnection jdbcDatabase) {
Ssl ssl = jdbcDatabase.getSsl();
if (ssl == null) {
ssl = new NormalSsl();
jdbcDatabase.setSsl(ssl);
}
if (ssl.getSslType() == SslType.NORMAL) {
NormalSsl normalSsl = (NormalSsl) ssl;
keyPathCa.setText(normalSsl.getCaCertificate());
keyPathClientCert.setText(normalSsl.getClientCertificate());
keyPathClientKey.setText(normalSsl.getClientPrivateKey());
verifyCa.setSelected(normalSsl.isVerifyCa());
// cipher.setText(normalSsl.getCipher());
} else {
throw new SslException("un support ssl type");
}
usingSsl.setSelected(ssl.isUsingSsl());
changePane();
}
public void update(JDBCDatabaseConnection jdbcDatabase) {
NormalSsl normalSsl = new NormalSsl();
// normalSsl.setCipher(cipher.getText().trim());
normalSsl.setVerifyCa(verifyCa.isSelected());
normalSsl.setCaCertificate(keyPathCa.getText().trim());
normalSsl.setClientCertificate(keyPathClientCert.getText().trim());
normalSsl.setClientPrivateKey(keyPathClientKey.getText().trim());
normalSsl.setUsingSsl(usingSsl.isSelected());
jdbcDatabase.setSsl(normalSsl);
}
private class TextFieldActionListener implements ActionListener {
private UITextField textField;
public TextFieldActionListener(UITextField textField) {
this.textField = textField;
}
@Override
public void actionPerformed(ActionEvent e) {
FILEChooserPane fileChooser = FILEChooserPane.getInstanceWithDesignatePath(ProjectConstants.RESOURCES_NAME, new ChooseFileFilter(true));
int type = fileChooser.showOpenDialog(SslPane.this, StringUtils.EMPTY);
if (type == FILEChooserPane.OK_OPTION) {
final FILE file = fileChooser.getSelectedFILE();
if (file == null) {
textField.setText(StringUtils.EMPTY);
} else {
textField.setText(file.getPath());
}
}
fileChooser.removeAllFilter();
}
}
}

4
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java

@ -715,8 +715,8 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
if (useGlobal(getTableData(), strategyConfig)) {
//使用全局配置
strategyConfig = StrategyConfigHelper.createStrategyConfig(true);
} else if (getTableData().isShare()) {
//使用共享数据集兼容配置
} else if (strategyConfig == null && getTableData().isShare()) {
//没有配置时,使用共享数据集兼容配置
strategyConfig = StrategyConfigHelper.createStrategyConfig(true, false, true);
}
}

109
designer-base/src/main/java/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java

@ -63,26 +63,27 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
public StoreProcedureDataWrapper(Component component, StoreProcedure storeProcedure, String storeprocedureName, String dsName) {
this(component, storeProcedure, storeprocedureName, dsName, true);
}
/**
* @param: component loadingBar的父弹框如果不设置父弹框的话可能出现loadingBar隐藏在一个弹框后的情况
* @param: storeProcedure 存储过程
* @param: storeprocedureName 存储过程的名字(某些情况下可以为空)
* @param: dsName 存储过程一个返回数据集的名字
* @param: needLoad 是否要加载
* @param component loadingBar的父弹框如果不设置父弹框的话可能出现loadingBar隐藏在一个弹框后的情况
* @param storeProcedure 存储过程
* @param storeprocedureName 存储过程的名字(某些情况下可以为空)
* @param dsName 存储过程一个返回数据集的名字
* @param needLoad 是否要加载
**/
public StoreProcedureDataWrapper(Component component, StoreProcedure storeProcedure, String storeprocedureName, String dsName, boolean needLoad) {
this.dsName = dsName;
this.storeProcedure = storeProcedure;
this.storeProcedure.setCalculating(false);
this.storeprocedureName = storeprocedureName;
if (needLoad) {
setWorker();
}
if (component == null) {
component = new JFrame();
}
if (needLoad) {
setWorker(component);
}
loadingBar = new AutoProgressBar(component, Toolkit.i18nText("Fine-Design_Basic_Loading_Data"), "", 0, 100) {
@Override
public void doMonitorCanceled() {
getWorker().cancel(true);
}
@ -93,16 +94,17 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
* 数据集执行结果返回的所有字段
*
* @return 数据集执行结果返回的所有字段
*
*
* @date 2014-12-3-下午7:43:17
*
*/
* @date 2014-12-3-下午7:43:17
*/
@Override
public List<String> calculateColumnNameList() {
if (columnNameList != null) {
return columnNameList;
}
if (!createStore(false)) {
try {
createStore(false);
} catch (Exception e) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Toolkit.i18nText("Fine-Design_Basic_Engine_No_TableData"));
return new ArrayList<String>();
}
@ -114,11 +116,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
* 生成子节点
*
* @return 节点数组
*
*
* @date 2014-12-3-下午7:06:47
*
*/
* @date 2014-12-3-下午7:06:47
*/
@Override
public ExpandMutableTreeNode[] load() {
List<String> namelist;
if (storeProcedure.isCalculating()) {
@ -134,23 +134,16 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
return res;
}
private boolean createStore(boolean needLoadingBar) {
try {
dataModels = DesignTableDataManager.createLazyDataModel(storeProcedure, needLoadingBar);
if (dataModels == null || dataModels.length == 0) {
return false;
}
for (int i = 0; i < dataModels.length; i++) {
if (ComparatorUtils.equals(this.dsName, storeprocedureName + "_" + dataModels[i].getName())) {
procedureDataModel = dataModels[i];
private void createStore(boolean needLoadingBar) throws Exception {
dataModels = DesignTableDataManager.createLazyDataModel(storeProcedure, needLoadingBar);
if (dataModels != null && dataModels.length != 0) {
for (ProcedureDataModel dataModel : dataModels) {
if (ComparatorUtils.equals(this.dsName, storeprocedureName + "_" + dataModel.getName())) {
procedureDataModel = dataModel;
break;
}
}
return true;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
@Override
@ -159,17 +152,15 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
}
/**
* 预览数据
*
* @param previewModel 预览模式, 全部还是一个
*
*
* @date 2014-12-3-下午7:05:50
*
*/
* 预览数据
*
* @param previewModel 预览模式, 全部还是一个
* @date 2014-12-3-下午7:05:50
*/
public void previewData(final int previewModel) {
this.previewModel = previewModel;
connectionBar = new AutoProgressBar(new JFrame(), Toolkit.i18nText("Fine-Design_Basic_Utils_Now_Create_Connection"), "", 0, 100) {
@Override
public void doMonitorCanceled() {
connectionBar.close();
worker.cancel(true);
@ -178,8 +169,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
worker.execute();
}
private void setWorker() {
private void setWorker(final Component parent) {
worker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
loadingBar.close();
PreviewTablePane.resetPreviewTable();
@ -195,6 +187,7 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
return null;
}
@Override
public void done() {
try {
get();
@ -206,13 +199,15 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
case StoreProcedureDataWrapper.PREVIEW_ONE:
previewData();
break;
default:
break;
}
} catch (Exception e) {
loadingBar.close();
if (!(e instanceof CancellationException)) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage());
FineJOptionPane.showMessageDialog(parent, e.getMessage());
}
loadingBar.close();
}
}
};
@ -227,10 +222,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
/**
* 预览返回的一个数据集
*
*
* @date 2014-12-3-下午7:42:53
*
*/
* @date 2014-12-3-下午7:42:53
*/
@Override
public void previewData() {
previewData(-1, -1);
}
@ -240,13 +234,11 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
/**
* 预览返回的一个数据集带有显示值和实际值的标记结果
*
* @param keyIndex 实际值
* @param valueIndex 显示值
*
*
* @date 2014-12-3-下午7:42:27
*
*/
* @param keyIndex 实际值
* @param valueIndex 显示值
* @date 2014-12-3-下午7:42:27
*/
@Override
public void previewData(final int keyIndex, final int valueIndex) {
PreviewTablePane.previewStoreData(procedureDataModel, keyIndex, valueIndex);
}
@ -257,7 +249,9 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
*/
public void previewAllTable() {
if (procedureDataModel == null) {
if (!createStore(true)) {
try {
createStore(true);
} catch (Exception e) {
return;
}
}
@ -269,6 +263,7 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
return dsName;
}
@Override
public TableData getTableData() {
return storeProcedure;
}
@ -282,10 +277,12 @@ public final class StoreProcedureDataWrapper implements TableDataWrapper {
*
* @return 是否异常
*/
@Override
public boolean isUnusual() {
return false;
}
@Override
public boolean equals(Object obj) {
return obj instanceof StoreProcedureDataWrapper
&& ComparatorUtils.equals(this.dsName, ((StoreProcedureDataWrapper) obj).getTableDataName())

15
designer-base/src/main/java/com/fr/design/deeplink/DeepLink.java

@ -0,0 +1,15 @@
package com.fr.design.deeplink;
import java.util.Map;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/6
*/
public abstract class DeepLink {
public abstract boolean accept(String url, String host, String path, Map<String, Object> params);
public abstract void run(String url, String host, String path, Map<String, Object> params);
}

184
designer-base/src/main/java/com/fr/design/deeplink/DeepLinkCore.java

@ -0,0 +1,184 @@
package com.fr.design.deeplink;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.design.startup.FineStartupNotificationFactory;
import com.fr.design.startup.FineStartupNotificationProvider;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.event.Null;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.stable.os.OperatingSystem;
import com.fr.third.org.apache.http.NameValuePair;
import com.fr.web.URLUtils;
import javax.swing.SwingUtilities;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/1/6
*/
public class DeepLinkCore {
protected DeepLinkCore(){}
private static final DeepLinkCore instance = new DeepLinkCore();
public static DeepLinkCore getInstance(){
return instance;
}
private String pendingURL;
private final List<DeepLink> deepLinkList = new ArrayList<>();
private boolean isDesignerStartupCompleted = false;
public void register(DeepLink deepLink) {
if (deepLink != null) {
deepLinkList.add(deepLink);
}
}
public void start(String[] args) {
if (OperatingSystem.isWindows()) {
if (args.length > 0) {
receiveDeeplink(args[0]);
}
}
if (OperatingSystem.isWindows() && args.length > 0) {
receiveDeeplink(args[0]);
}
FineStartupNotificationFactory.getNotification()
.registerStartupListener(new FineStartupNotificationProvider.Listener() {
@Override
public void startupPerformed(String parameters) {
receiveDeeplink(parameters);
}
});
EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener<Null>() {
@Override
public void on(Event event, Null param) {
EventDispatcher.stopListen(this);
isDesignerStartupCompleted = true;
if (canConsumePendingURL()) {
consumePendingURL();
}
}
});
}
public void receiveDeeplink(String url) {
if (canAcceptNewURL()) {
acceptNewURL(url);
if (canConsumePendingURL()) {
consumePendingURL();
}
}
}
public void receiveDeeplink2(String url) {
if (canAcceptNewURL()) {
acceptNewURL(url);
if (canConsumePendingURL()) {
consumePendingURL();
} else {
Frame frame = new Frame("can not ConsumePendingURL");
frame.setSize(400, 400);
frame.setBackground(Color.BLACK);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
frame.dispose();
}
});
frame.setVisible(true);
}
} else {
Frame frame = new Frame("can not AcceptNewURL");
frame.setSize(400, 400);
frame.setBackground(Color.BLACK);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
frame.dispose();
}
});
frame.setVisible(true);
}
}
private boolean canAcceptNewURL() {
return StringUtils.isEmpty(this.pendingURL);
}
private void acceptNewURL(String url) {
this.pendingURL = url;
}
private boolean canConsumePendingURL() {
return StringUtils.isNotEmpty(this.pendingURL) && isDesignerStartupCompleted;
}
private void consumePendingURL() {
String host = null;
String path = null;
Map<String, Object> params = new HashMap<>();
URL url = null;
try {
url = new URL(null, this.pendingURL, new URLStreamHandler() {
@Override
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
});
} catch (MalformedURLException ignored) {}
if (url != null) {
host = url.getHost();
path = url.getPath();
List<NameValuePair> pairs = URLUtils.parse(url.getQuery());
for (NameValuePair pair: pairs) {
params.put(pair.getName(), pair.getValue());
}
}
FineLoggerFactory.getLogger().info("consume deep link: " + this.pendingURL);
performDeepLinks(this.pendingURL, host, path, params);
markPendingURLConsumed();
}
private void performDeepLinks(String url, String host, String path, Map<String, Object> params) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
for (DeepLink deepLink: deepLinkList) {
if (deepLink.accept(url, host, path, params)) {
deepLink.run(url, host, path, params);
}
}
}
});
}
private void markPendingURLConsumed() {
this.pendingURL = null;
}
}

33
designer-base/src/main/java/com/fr/design/editor/editor/NotNegativeIntegerEditor.java

@ -0,0 +1,33 @@
package com.fr.design.editor.editor;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
/**
* @author xiqiu
* @date 2022/1/10
* @description 一个简单的非负整数框
*/
public class NotNegativeIntegerEditor extends IntegerEditor {
private static final String NEG = "-";
public NotNegativeIntegerEditor(int columns) {
this();
this.setColumns(columns);
}
public NotNegativeIntegerEditor() {
super();
this.numberField.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent evt) {
char keyChar = evt.getKeyChar();
if (NEG.equals(keyChar + "")) {
numberField.setText(numberField.getTextValue().replace(NEG, ""));
}
}
});
}
}

7
designer-base/src/main/java/com/fr/design/event/ComponentChangeListener.java

@ -0,0 +1,7 @@
package com.fr.design.event;
import java.awt.*;
public interface ComponentChangeListener {
void initListener(Container changedComponent);
}

6
designer-base/src/main/java/com/fr/design/event/ComponentChangeObserver.java

@ -0,0 +1,6 @@
package com.fr.design.event;
public interface ComponentChangeObserver {
void registerChangeListener(ComponentChangeListener uiChangeableListener);
}

29
designer-base/src/main/java/com/fr/design/extra/PluginInstalledPane.java

@ -60,11 +60,14 @@ public class PluginInstalledPane extends PluginAbstractViewPane {
public void actionPerformed(ActionEvent e) {
PluginView plugin = controlPane.getSelectedPlugin();
if (plugin != null) {
boolean isActive = plugin.isActive();
PluginMarker pluginMarker = PluginMarker.create(plugin.getID(), plugin.getVersion());
final String modifyMessage = isActive ? com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Has_Been_Actived") : com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Has_Been_Disabled");
if (isActive) {
PluginManager.getController().forbid(pluginMarker, new PluginTaskCallback() {
PluginContext pluginContext = getPluginContextByView(plugin);
if (pluginContext == null) {
return;
}
boolean running = pluginContext.isRunning();
final String modifyMessage = running ? com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Has_Been_Actived") : com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Has_Been_Disabled");
if (running) {
PluginManager.getController().forbidPersistently(pluginContext.getMarker(), new PluginTaskCallback() {
@Override
public void done(PluginTaskResult result) {
if (result.isSuccess()) {
@ -75,7 +78,7 @@ public class PluginInstalledPane extends PluginAbstractViewPane {
}
});
} else {
PluginManager.getController().enable(pluginMarker, new PluginTaskCallback() {
PluginManager.getController().enablePersistently(pluginContext.getMarker(), new PluginTaskCallback() {
@Override
public void done(PluginTaskResult result) {
if (result.isSuccess()) {
@ -145,13 +148,25 @@ public class PluginInstalledPane extends PluginAbstractViewPane {
}
private void changeTextForButton(PluginView plugin) {
if (plugin.isActive()) {
PluginContext pluginContext = getPluginContextByView(plugin);
if (pluginContext == null) {
return;
}
if (pluginContext.isRunning()) {
disableButton.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Disable"));
} else {
disableButton.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Plugin_Active"));
}
}
private PluginContext getPluginContextByView(PluginView pluginView) {
if (pluginView != null) {
PluginMarker pluginMarker = PluginMarker.create(pluginView.getID(), pluginView.getVersion());
return PluginManager.getContext(pluginMarker);
}
return null;
}
@Override
protected String title4PopupWindow() {
return "Installed";

12
designer-base/src/main/java/com/fr/design/extra/PluginOperateUtils.java

@ -99,9 +99,9 @@ public class PluginOperateUtils {
public void run() {
PluginMarker pluginMarker = PluginUtils.createPluginMarker(pluginInfo);
PluginContext plugin = PluginManager.getContext(pluginMarker);
boolean active = plugin.isActive();
PluginTaskCallback modifyStatusCallback = new ModifyStatusCallback(active, jsCallback);
if (active) {
boolean isRunning = plugin.isRunning();
PluginTaskCallback modifyStatusCallback = new ModifyStatusCallback(isRunning, jsCallback);
if (isRunning) {
PluginXmlElement forbidReminder = plugin.getXml().getElement(PluginElementName.ForbidReminder);
if (forbidReminder != null && forbidReminder.getContent() != null) {
// 禁用前提示
@ -113,14 +113,14 @@ public class PluginOperateUtils {
JOptionPane.WARNING_MESSAGE
);
if (rv == JOptionPane.OK_OPTION) {
PluginManager.getController().forbid(pluginMarker, modifyStatusCallback);
PluginManager.getController().forbidPersistently(pluginMarker, modifyStatusCallback);
}
} else {
// 正常禁用
PluginManager.getController().forbid(pluginMarker, modifyStatusCallback);
PluginManager.getController().forbidPersistently(pluginMarker, modifyStatusCallback);
}
} else {
PluginManager.getController().enable(pluginMarker, modifyStatusCallback);
PluginManager.getController().enablePersistently(pluginMarker, modifyStatusCallback);
}
}
});

3
designer-base/src/main/java/com/fr/design/extra/PluginUtils.java

@ -269,7 +269,8 @@ public class PluginUtils {
jo.put("vendor", pluginContext.getVendor());
jo.put("price", pluginContext.getPrice());
jo.put("requiredJarTime", pluginContext.getRequiredJarTime());
jo.put("active", pluginContext.isActive());
// 前端需求的active实际上是插件的运行状态,通过isRunning()获取
jo.put("active", pluginContext.isRunning());
jo.put("hidden", pluginContext.isHidden());
jo.put("free", pluginContext.isFree());
jo.put("licDamaged", pluginContext.isLicDamaged());

23
designer-base/src/main/java/com/fr/design/extra/WebViewDlgHelper.java

@ -1,6 +1,6 @@
package com.fr.design.extra;
import com.fr.base.FRContext;
import com.fr.decision.webservice.v10.plugin.helper.category.impl.PluginResourceLoader;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.dialog.UIDialog;
@ -15,12 +15,12 @@ import com.fr.general.IOUtils;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.PluginStoreConfig;
import com.fr.plugin.PluginStoreConstants;
import com.fr.stable.CommonUtils;
import com.fr.stable.EnvChangedListener;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
@ -44,15 +44,15 @@ public class WebViewDlgHelper {
private static final String LATEST = "latest";
private static final String SHOP_SCRIPTS = "shop_scripts";
private static final int VERSION_8 = 8;
private static String installHome = FRContext.getCommonOperator().getWebRootPath();
private static String installHome = PluginStoreConstants.getLocalInstallHome();
private static final String MAIN_JS_PATH = "/scripts/plugin.html";
private static final String ENV_VERSION = "ENV_VERSION";
static {
GeneralContext.addEnvChangedListener(new EnvChangedListener() {
@Override
public void envChanged() {
installHome = FRContext.getCommonOperator().getWebRootPath();
installHome = PluginStoreConstants.getLocalInstallHome();
PluginResourceLoader.INSTANCE.checkOldShopFile();
}
});
}
@ -74,8 +74,11 @@ public class WebViewDlgHelper {
}
return;
}
String jar_version = PluginStoreConstants.getProps(ENV_VERSION, StringUtils.EMPTY);
if (ComparatorUtils.equals(jar_version, ProductConstants.VERSION)) {
// 检测更新前先刷新一下版本号
PluginStoreConstants.refreshProps();
String jarVersion = PluginStoreConfig.getInstance().getEnvVersion();
if (ComparatorUtils.equals(jarVersion, ProductConstants.VERSION)) {
updateShopScripts(SHOP_SCRIPTS);
showPluginDlg();
} else {
@ -133,7 +136,7 @@ public class WebViewDlgHelper {
*
* @param filePath 待删除文件路径
*/
private static void deleteExtraFile(String filePath){
private static void deleteExtraFile(String filePath) {
CommonIOUtils.deleteFile(new File(filePath));
}
@ -259,7 +262,7 @@ public class WebViewDlgHelper {
try {
if (get()) {
File scriptZip = new File(StableUtils.pathJoin(PluginConstants.DOWNLOAD_PATH, PluginConstants.TEMP_FILE));
if(scriptZip.exists()){
if (scriptZip.exists()) {
IOUtils.unzip(scriptZip, installHome);
CommonUtils.deleteFile(scriptZip);
}
@ -283,7 +286,7 @@ public class WebViewDlgHelper {
protected Void doInBackground() throws Exception {
String url = CloudCenter.getInstance().acquireUrlByKind("shop.plugin.update");
if (url != null) {
String text = HttpToolbox.get(url + "?" + PluginUtils.FR_VERSION + "=" + ProductConstants.VERSION + "&version=" + PluginStoreConstants.getProps("VERSION"));
String text = HttpToolbox.get(url + "?" + PluginUtils.FR_VERSION + "=" + ProductConstants.VERSION + "&version=" + PluginStoreConfig.getInstance().getVersion());
JSONObject resultJSONObject = new JSONObject(text);
String isLatest = resultJSONObject.optString("result");
if (!ComparatorUtils.equals(isLatest, LATEST)) {

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

@ -15,7 +15,6 @@ import com.fr.design.mainframe.JVirtualTemplate;
import com.fr.design.ui.util.UIUtil;
import com.fr.file.FILE;
import com.fr.file.FileNodeFILE;
import com.fr.file.StashedFILE;
import com.fr.general.ComparatorUtils;
import com.fr.invoke.ClassHelper;
import com.fr.log.FineLoggerFactory;
@ -25,7 +24,7 @@ import com.fr.stable.CoreConstants;
import com.fr.stable.StringUtils;
import com.fr.third.org.apache.commons.io.FilenameUtils;
import java.io.ByteArrayOutputStream;
import javax.swing.SwingWorker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -33,7 +32,6 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import javax.swing.SwingWorker;
/**
* 历史模板缓存
@ -253,7 +251,11 @@ public class HistoryTemplateListCache implements CallbackEvent {
for (int i = 0; i < vCount; i++) {
JTemplate overTemplate = historyList.get(i);
if (overTemplate.getEditingFILE().exists() && overTemplate.isALLSaved() && overTemplate != editingTemplate) {
boolean replaceWithJVirtualTemplate = overTemplate.getEditingFILE().exists()
&& overTemplate.isALLSaved()
&& overTemplate != editingTemplate
&& overTemplate.checkEnable();
if (replaceWithJVirtualTemplate) {
closeVirtualSelectedReport(overTemplate);
historyList.set(i, new JVirtualTemplate(overTemplate.getEditingFILE()));
}
@ -360,7 +362,7 @@ public class HistoryTemplateListCache implements CallbackEvent {
int size = historyList.size();
for (int i = 0; i < size; i++) {
JTemplate<?, ?> template = historyList.get(i);
FILE file = templateToStashFile(template);
FILE file = template.templateToStashFile();
if (file != null) {
stashFILEMap.put(i, file);
}
@ -368,21 +370,6 @@ public class HistoryTemplateListCache implements CallbackEvent {
FineLoggerFactory.getLogger().info("Env Change Template Stashed.");
}
private FILE templateToStashFile(JTemplate<?, ?> template) {
FILE file = template.getEditingFILE();
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BaseBook target = template.getTarget();
if (target != null) {
target.export(outputStream);
return new StashedFILE(file, outputStream.toByteArray(), template.suffix());
}
// 如果 target == null 那么这个模板是被模板内存优化功能处理过的,不用处理
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
private boolean checkStash() {
try {
@ -465,7 +452,7 @@ public class HistoryTemplateListCache implements CallbackEvent {
FILE file = template.getEditingFILE();
boolean needReload = context == null || needReloadTemplate(context, template);
if (needReload) {
FILE stashFile = templateToStashFile(template);
FILE stashFile = template.templateToStashFile();
if (stashFile != null) {
FineLoggerFactory.getLogger().info("{} is being reloaded", file.getName());
template.refreshResource(stashFile);

4
designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java

@ -4,7 +4,6 @@ package com.fr.design.file;
import com.fr.base.BaseUtils;
import com.fr.base.GraphHelper;
import com.fr.base.vcs.DesignerMode;
import com.fr.design.base.mode.DesignModeContext;
import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.imenu.UIMenuItem;
@ -17,6 +16,7 @@ import com.fr.design.utils.DesignUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.design.utils.gui.GUIPaintUtils;
import com.fr.design.worker.WorkerManager;
import com.fr.design.utils.TemplateUtils;
import com.fr.design.worker.save.CallbackSaveWorker;
import com.fr.file.FILE;
import com.fr.general.ComparatorUtils;
@ -269,7 +269,7 @@ public class MutilTempalteTabPane extends JComponent {
private String tempalteShowName(JTemplate<?, ?> template) {
String name = template.getTemplateName();
String name = TemplateUtils.createLockeTemplatedName(template, template.getTemplateName());
if (!template.isSaved() && !name.endsWith(" *")) {
name += " *";
}

46
designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java

@ -12,7 +12,11 @@ import com.fr.design.gui.itree.filetree.TemplateFileTree;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.lock.LockInfoUtils;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrameFileDealerPane;
import com.fr.design.lock.LockInfoDialog;
import com.fr.design.mainframe.JTemplate;
import com.fr.file.FILE;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
@ -21,12 +25,15 @@ import com.fr.form.fit.web.editpreview.FileLockStateObservable;
import com.fr.general.ComparatorUtils;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.workspace.base.UserInfo;
import com.fr.stable.ArrayUtils;
import com.fr.stable.CoreConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.WorkContext;
import com.fr.report.lock.LockInfoOperator;
import java.util.UUID;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
@ -50,6 +57,8 @@ import java.util.Enumeration;
import java.util.Objects;
import java.util.Observable;
import java.util.Observer;
import org.jetbrains.annotations.Nullable;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
import static javax.swing.JOptionPane.YES_NO_OPTION;
@ -113,6 +122,7 @@ public class TemplateTreePane extends JPanel implements FileOperations {
if (toolBarStateChangeListener != null) {
toolBarStateChangeListener.stateChange();
}
DesignerFrameFileDealerPane.getInstance().refreshRightToolBarBy(reportletsTree.getSelectedFileNode());
}
};
// lx: add mouse listener
@ -216,15 +226,44 @@ public class TemplateTreePane extends JPanel implements FileOperations {
if (node == null) {
return;
}
String reportPath = reportletsTree.getSelectedTemplatePath();
final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, reportPath);
String lock = node.getLock();
if (lock != null && !lock.equals(node.getUserID())) {
boolean showLockInfo = LockInfoUtils.isCompatibleOperator()
|| LockInfoUtils.unableGetLockInfo()
|| WorkContext.getCurrent().get(LockInfoOperator.class).isTplUnLocked(selectedFilePath)
? (lock != null && !lock.equals(node.getUserID()))
: WorkContext.getCurrent().get(LockInfoOperator.class).isTplLocked(selectedFilePath);
if (showLockInfo) {
UserInfo userInfo = WorkContext.getCurrent().get(LockInfoOperator.class).getUserInfo(selectedFilePath);
node.setLock(UUID.randomUUID().toString());
// 对于开发者预览占位锁定 定位到tab中
checkDevelopForBiddenTemplate(selectedFilePath);
LockInfoDialog.show(userInfo);
return;
} else {
node.setLock(null);
}
String reportPath = reportletsTree.getSelectedTemplatePath();
final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, reportPath);
DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(selectedFilePath, false)));
}
private void checkDevelopForBiddenTemplate(String selectedFilePath) {
JTemplate<?, ?> template = getOpenedTemplate(selectedFilePath);
if (template != null && template.isForbidden()) {
DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(selectedFilePath, false)));
}
}
@Nullable
private JTemplate<?, ?> getOpenedTemplate(String path) {
for (JTemplate<?, ?> template : HistoryTemplateListCache.getInstance().getHistoryList()) {
if (ComparatorUtils.equals(template.getEditingFILE().getPath(), path)) {
return template;
}
}
return null;
}
/**
* 打开文件夹
*/
@ -248,6 +287,7 @@ public class TemplateTreePane extends JPanel implements FileOperations {
// 刷新远程文件夹权限
NodeAuthProcessor.getInstance().refresh();
reportletsTree.refresh();
DesignerFrameFileDealerPane.getInstance().refreshRightToolBarBy(null);
FineLoggerFactory.getLogger().info(Toolkit.i18nText("Fine-Design_Basic_Template_File_Tree_Refresh_Successfully") + "!");
}

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

@ -16,6 +16,7 @@ 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.AutoCompleteExtraRefreshComponent;
import com.fr.design.gui.autocomplete.CompletionCellRenderer;
import com.fr.design.gui.autocomplete.CompletionProvider;
import com.fr.design.gui.autocomplete.DefaultCompletionProvider;
@ -290,6 +291,11 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
initTextPane();
initTipsPane();
initVariableTreeAndDescriptionArea();
refocusInWindow();
}
public void refocusInWindow() {
SwingUtilities.invokeLater(() -> formulaTextArea.requestFocusInWindow());
}
private void initVariableTreeAndDescriptionArea() {
@ -342,11 +348,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
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);
installAutoCompletion();
}
}
@ -410,6 +412,14 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
}
}
private void installAutoCompletion() {
CompletionProvider provider = createCompletionProvider();
autoCompletion = new FormulaPaneAutoCompletion(provider);
autoCompletion.setListCellRenderer(new CompletionCellRenderer());
autoCompletion.install(formulaTextArea);
autoCompletion.installExtraRefreshComponent(variableTreeAndDescriptionArea);
}
protected void extendCheckBoxPane(JPanel checkBoxPane) {
@ -546,6 +556,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
private void fixFunctionNameList(String functionName) {
int signOfContinue = 1;
int indexOfFunction = 0;
boolean found = false;
for (int i = 0; i < functionTypeListModel.size(); i++) {
int signOfType = 0;
FunctionGroup functionType = (FunctionGroup) functionTypeListModel.getElementAt(i);
@ -559,6 +570,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
signOfType = 1;
signOfContinue = 0;
indexOfFunction = k;
found = true;
}
}
@ -568,8 +580,12 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
}
}
}
functionNameList.setSelectedIndex(indexOfFunction);
functionNameList.ensureIndexIsVisible(indexOfFunction);
if (found) {
functionNameList.setSelectedIndex(indexOfFunction);
functionNameList.ensureIndexIsVisible(indexOfFunction);
} else {
functionTypeList.setSelectedIndex(0);
}
}
private int getBeginPosition() {
@ -795,67 +811,77 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
}
};
private void calculateFormula() {
String formulaText = formulaTextArea.getText().trim();
String unSupportFormula = containsUnsupportedSimulationFormulas(formulaText);
if (unSupportFormula != null) {
showMessageDialog(Toolkit.i18nText("Fine-Design_Basic_Formula_Unsupported_Formulas") + ":" + unSupportFormula, false, true);
return;
}
private final ActionListener calculateActionListener = new ActionListener() {
boolean calException = false;
String messageTips;
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);
calculator.pushNameSpace(parameterMapNameSpace);
JTemplate<?, ?> currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (currentEditingTemplate != null) {
IOFile file = (IOFile) currentEditingTemplate.getTarget();
calculator.setAttribute(TableDataSource.KEY, file);
calculator.pushNameSpace(TableDataNameSpace.getInstance());
calculator.pushNameSpace(SimpleCellValueNameSpace.getInstance());
}
@Override
public void actionPerformed(ActionEvent e) {
String formulaText = formulaTextArea.getText().trim();
String unSupportFormula = containsUnsupportedSimulationFormulas(formulaText);
if (unSupportFormula != null) {
showMessageDialog(Toolkit.i18nText("Fine-Design_Basic_Formula_Unsupported_Formulas") + ":" + unSupportFormula, false);
return;
BaseFormula baseFormula = BaseFormula.createFormulaBuilder().build(formulaText);
Object calResult;
try {
calResult = calculator.evalValue(baseFormula);
String objectToString = EssentialUtils.objectToString(calResult);
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;
} catch (Exception ce) {
//模拟计算如果出现错误,则抛出错误
calResult = ce.getMessage();
calException = true;
FineLoggerFactory.getLogger().error(ce.getMessage(), ce);
messageTips = messageTips + Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Error") + ":" + calResult;
}
FineLoggerFactory.getLogger().info("value:{}", calResult);
} else {
messageTips = checkResult.getTips();
}
if (checkResult.isValid()) {
showMessageDialog(messageTips, checkResult.isValid(), calException);
} else {
confirmCheckResult(checkResult, messageTips);
}
}
String messageTips;
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);
calculator.pushNameSpace(parameterMapNameSpace);
JTemplate<?, ?> currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (currentEditingTemplate != null) {
IOFile file = (IOFile) currentEditingTemplate.getTarget();
calculator.setAttribute(TableDataSource.KEY, file);
calculator.pushNameSpace(TableDataNameSpace.getInstance());
calculator.pushNameSpace(SimpleCellValueNameSpace.getInstance());
}
BaseFormula baseFormula = BaseFormula.createFormulaBuilder().build(formulaText);
Object calResult;
try {
calResult = calculator.evalValue(baseFormula);
String objectToString = EssentialUtils.objectToString(calResult);
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;
} catch (Exception ce) {
//模拟计算如果出现错误,则抛出错误
calResult = ce.getMessage();
FineLoggerFactory.getLogger().error(ce.getMessage(), ce);
messageTips = messageTips + Toolkit.i18nText("Fine-Design_Basic_Formula_Cal_Error") + ":" + calResult;
}
FineLoggerFactory.getLogger().info("value:{}", calResult);
} else {
messageTips = checkResult.getTips();
}
if (checkResult.isValid()) {
showMessageDialog(messageTips, checkResult.isValid());
} else {
confirmCheckResult(checkResult, messageTips);
}
private final ActionListener calculateActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
calculateFormula();
}
};
private boolean confirmCheckResult(FormulaCheckResult checkResult, String messageTips) {
if (checkResult.isValid()) {
showMessageDialog(checkResult.getTips(), checkResult.isValid());
showMessageDialog(checkResult.getTips(), checkResult.isValid(), false);
} else {
String position = Toolkit.i18nText("Fine-Design_Basic_Formula_The") + (checkResult.getFormulaCoordinates().getColumns())
+ Toolkit.i18nText("Fine-Design_Basic_Formula_Error_Position") + " ";
int columns = checkResult.getFormulaCoordinates().getColumns();
String position = StringUtils.EMPTY;
if (columns >= 0) {
position = Toolkit.i18nText("Fine-Design_Basic_Formula_The") + columns
+ Toolkit.i18nText("Fine-Design_Basic_Formula_Error_Position") + " ";
}
int confirmDialog = FineJOptionPane.showConfirmDialog(
FormulaPane.this,
position + messageTips,
@ -866,7 +892,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
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.setCaretPosition(Math.max(columns, 0));
formulaTextArea.requestFocus();
return false;
}
@ -874,8 +900,8 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
return true;
}
private void showMessageDialog(String message, boolean formulaValid) {
if (formulaValid) {
private void showMessageDialog(String message, boolean formulaValid, boolean calException) {
if (formulaValid && !calException) {
FineJOptionPane.showMessageDialog(
FormulaPane.this,
message);
@ -1019,7 +1045,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
}
}
public class VariableTreeAndDescriptionArea extends JPanel {
public class VariableTreeAndDescriptionArea extends JPanel implements AutoCompleteExtraRefreshComponent {
private JTree variablesTree;
private UITextArea descriptionTextArea;
@ -1260,6 +1286,11 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula {
functionTypeList.setSelectedIndex(0);
}
@Override
public void refresh(String replacementText) {
refreshText(replacementText);
}
/*
* 查看函数的详细信息
*/

17
designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java

@ -36,6 +36,7 @@ import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@ -46,6 +47,7 @@ public final class FunctionConstants {
public static NameAndFunctionList COMMON = getCommonFunctionList();
public static NameAndTypeAndFunctionList[] EMBFUNCTIONS = getEmbededFunctionListArray();
public static FunctionGroup ALL = getAllFunctionGroup();
public static List<String> abandonFormulas = Arrays.asList("CIRCULAR", "CROSSLAYERTOTAL", "HIERARCHY", "LAYERTOTAL");
static {
loadEmbededFunctions();
@ -54,7 +56,8 @@ public final class FunctionConstants {
/**
* Don't let anyone instantiate this class.
*/
private FunctionConstants() {}
private FunctionConstants() {
}
private static void loadEmbededFunctions() {
String pkgName = "com.fr.function";
@ -88,7 +91,10 @@ public final class FunctionConstants {
Class<?> cls = Class.forName(pkgName + "." + fileName.substring(0, fileName.length() - 6));
if (StableUtils.classInstanceOf(cls, iface)) {
Function inst;
inst = (Function)cls.newInstance();
inst = (Function) cls.newInstance();
if (abandonFormulas.contains(inst.getClass().getSimpleName())) {
continue;
}
for (NameAndTypeAndFunctionList EMBFUNCTION : EMBFUNCTIONS) {
if (EMBFUNCTION.test(inst)) {
break;
@ -300,11 +306,12 @@ public final class FunctionConstants {
Collections.addAll(all, CUSTOM.getDescriptions());
//hugh:自定义函数分组
Set<Mutable> containers = ExtraClassManager.getInstance().getArray(FunctionDefContainer.MARK_STRING);
if(!containers.isEmpty()){
for(Mutable container : containers){
Collections.addAll(all,createFunctionGroup(((FunctionDefContainer)container)).getDescriptions());
if (!containers.isEmpty()) {
for (Mutable container : containers) {
Collections.addAll(all, createFunctionGroup(((FunctionDefContainer) container)).getDescriptions());
}
}
all = all.stream().filter(n -> !abandonFormulas.contains(n.getName())).collect(Collectors.toList());
Collections.sort(all, new Comparator<NameAndDescription>() {
@Override

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

@ -73,6 +73,8 @@ public class FormulaCheckWrongFunction implements Function<Exception, FormulaChe
if (invalidFormula.contains(",")) {
invalidFormula = invalidFormula.substring(0, invalidFormula.indexOf(","));
}
return formulaText.indexOf(invalidFormula);
int index = formulaText.indexOf(invalidFormula);
return index;
}
}

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

@ -35,10 +35,6 @@ public class MismatchedCharFunction implements Function<Exception, FormulaCheckR
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") + ": ")
@ -58,8 +54,6 @@ public class MismatchedCharFunction implements Function<Exception, FormulaCheckR
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:
@ -71,9 +65,6 @@ public class MismatchedCharFunction implements Function<Exception, FormulaCheckR
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"));

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

@ -40,11 +40,7 @@ public class MismatchedTokenFunction implements Function<Exception, FormulaCheck
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("'");
.append(tokenName(exception.expecting, exception));
break;
case 2:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting_Anything") + ": ")
@ -59,9 +55,7 @@ public class MismatchedTokenFunction implements Function<Exception, FormulaCheck
.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("'");
.append(tokenName(exception.upper, exception));
break;
case 4:
sb.append(Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Expecting") + ": ")
@ -71,12 +65,7 @@ public class MismatchedTokenFunction implements Function<Exception, FormulaCheck
.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("'");
.append(tokenName(exception.upper, exception));
break;
case 5:
case 6:
@ -90,11 +79,6 @@ public class MismatchedTokenFunction implements Function<Exception, FormulaCheck
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"));
@ -106,26 +90,14 @@ public class MismatchedTokenFunction implements Function<Exception, FormulaCheck
private String tokenName(int tokenType, MismatchedTokenException exception) {
if (tokenType == 0) {
return "<Set of tokens>";
} else if (tokenType == 33 || tokenType == 26 || tokenType == 31) {
return Toolkit.i18nText("Fine-Design_Basic_Formula_Right_Closing_Symbol");
} else {
String[] tokenNames = (String[]) getFieldValue(exception, "tokenNames");
return tokenType >= 0 && tokenType < tokenNames.length ? translateToken(tokenNames[tokenType]) : "<" + tokenType + ">";
return tokenType >= 0 && tokenType < tokenNames.length ? TranslateTokenUtils.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 {

96
designer-base/src/main/java/com/fr/design/formula/exception/function/TranslateTokenUtils.java

@ -0,0 +1,96 @@
package com.fr.design.formula.exception.function;
import com.fr.design.i18n.Toolkit;
/**
* @author Hoky
* @date 2021/11/30
*/
public class TranslateTokenUtils {
public static String translateToken(String token) {
switch (token) {
case ("RPAREN"):
return ")";
case ("LPAREN"):
return "(";
case ("COMMA"):
return ",";
case ("COLON"):
return ":";
case ("EOF"):
return Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Mismatched_EOF");
case ("DOT"):
return ".";
case ("FLOT_NUM"):
return Toolkit.i18nText("Fine-Design_Basic_Formula_Float_Number");
case ("LOR"):
return "||";
case ("LAND"):
return "&&";
case ("EQUAL"):
return "=";
case ("EQUAL2"):
return "=";
case ("NOT_EQUAL"):
return "!=";
case ("NOT_EQUAL2"):
return "!=";
case ("GE"):
return ">=";
case ("LE"):
return "<=";
case ("LT"):
return "<";
case ("PLUS"):
return "+";
case ("MINUS"):
return "-";
case ("STAR"):
return "*";
case ("DIV"):
return "/";
case ("MOD"):
return "%";
case ("POWER"):
return "^";
case ("LNOT"):
return "!";
case ("WAVE"):
return "~";
case ("LBRACK"):
return "[";
case ("SEMI"):
return ";";
case ("RBRACK"):
return "]";
case ("LCURLY"):
return "{";
case ("RCURLY"):
return "}";
case ("DCOLON"):
return ";";
case ("INT_NUM"):
return Toolkit.i18nText("Fine-Design_Basic_Formula_Integer");
case ("CR_ADRESS"):
return "\n";
case ("SHARP"):
return "#";
case ("AT"):
return "@";
case ("QUESTION"):
return "?";
case ("BOR"):
return "||";
case ("BAND"):
return "&&";
case ("Char"):
return Toolkit.i18nText("Fine-Design_Basic_Formula_Character");
case ("DIGIT"):
return Toolkit.i18nText("Fine-Design_Basic_Formula_Digital");
case ("XDIGIT"):
return Toolkit.i18nText("Fine-Design_Basic_Formula_Hexadecimal_Digital");
default:
return token;
}
}
}

5
designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompleteExtraRefreshComponent.java

@ -0,0 +1,5 @@
package com.fr.design.gui.autocomplete;
public interface AutoCompleteExtraRefreshComponent {
void refresh(String replacementText);
}

982
designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompleteWithExtraRefreshPopupWindow.java

@ -0,0 +1,982 @@
package com.fr.design.gui.autocomplete;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.PopupWindowDecorator;
import com.fr.log.FineLoggerFactory;
import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JWindow;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.ListUI;
import javax.swing.text.Caret;
import javax.swing.text.JTextComponent;
public abstract class AutoCompleteWithExtraRefreshPopupWindow extends JWindow implements CaretListener,
ListSelectionListener, MouseListener {
private final static int DIS = 5;
/**
* The parent AutoCompletion instance.
*/
private AutoCompletion ac;
/**
* The list of completion choices.
*/
private JList list;
/**
* The contents of {@link #list()}.
*/
private CompletionListModel model;
/**
* A hack to work around the fact that we clear our completion model (and
* our selection) when hiding the completion window. This allows us to
* still know what the user selected after the popup is hidden.
*/
private Completion lastSelection;
/**
* Optional popup window containing a description of the currently
* selected completion.
*/
private AutoCompleteDescWindow descWindow;
/**
* The preferred size of the optional description window. This field
* only exists because the user may (and usually will) set the size of
* the description window before it exists (it must be parented to a
* Window).
*/
private Dimension preferredDescWindowSize;
/**
* Whether the completion window and the optional description window
* should be displayed above the current caret position (as opposed to
* underneath it, which is preferred unless there is not enough space).
*/
private boolean aboveCaret;
private int lastLine;
private KeyActionPair escapeKap;
private KeyActionPair upKap;
private KeyActionPair downKap;
private KeyActionPair leftKap;
private KeyActionPair rightKap;
private KeyActionPair enterKap;
private KeyActionPair tabKap;
private KeyActionPair homeKap;
private KeyActionPair endKap;
private KeyActionPair pageUpKap;
private KeyActionPair pageDownKap;
private KeyActionPair ctrlCKap;
private KeyActionPair oldEscape, oldUp, oldDown, oldLeft, oldRight,
oldEnter, oldTab, oldHome, oldEnd, oldPageUp, oldPageDown,
oldCtrlC;
/**
* The space between the caret and the completion popup.
*/
private static final int VERTICAL_SPACE = 1;
/**
* The class name of the Substance List UI.
*/
private static final String SUBSTANCE_LIST_UI =
"org.pushingpixels.substance.internal.ui.SubstanceListUI";
protected AutoCompleteExtraRefreshComponent component;
/**
* Constructor.
*
* @param parent The parent window (hosting the text component).
* @param ac The auto-completion instance.
*/
public AutoCompleteWithExtraRefreshPopupWindow(Window parent, final AutoCompletion ac) {
super(parent);
ComponentOrientation o = ac.getTextComponentOrientation();
this.ac = ac;
model = new CompletionListModel();
list = new PopupList(model);
list.setCellRenderer(new DelegatingCellRenderer());
list.addListSelectionListener(this);
list.addMouseListener(this);
JPanel contentPane = new JPanel(new BorderLayout());
JScrollPane sp = new JScrollPane(list,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
// In 1.4, JScrollPane.setCorner() has a bug where it won't accept
// JScrollPane.LOWER_TRAILING_CORNER, even though that constant is
// defined. So we have to put the logic added in 1.5 to handle it
// here.
JPanel corner = new SizeGrip();
//sp.setCorner(JScrollPane.LOWER_TRAILING_CORNER, corner);
boolean isLeftToRight = o.isLeftToRight();
String str = isLeftToRight ? JScrollPane.LOWER_RIGHT_CORNER :
JScrollPane.LOWER_LEFT_CORNER;
sp.setCorner(str, corner);
contentPane.add(sp);
setContentPane(contentPane);
applyComponentOrientation(o);
// Give apps a chance to decorate us with drop shadows, etc.
if (Util.getShouldAllowDecoratingMainAutoCompleteWindows()) {
PopupWindowDecorator decorator = PopupWindowDecorator.get();
if (decorator != null) {
decorator.decorate(this);
}
}
pack();
setFocusableWindowState(false);
lastLine = -1;
}
public void caretUpdate(CaretEvent e) {
if (isVisible()) { // Should always be true
int line = ac.getLineOfCaret();
if (line != lastLine) {
lastLine = -1;
setVisible(false);
} else {
doAutocomplete();
}
} else if (AutoCompletion.isDebug()) {
Thread.dumpStack();
}
}
/**
* Creates the description window.
*
* @return The description window.
*/
private AutoCompleteDescWindow createDescriptionWindow() {
AutoCompleteDescWindow dw = new AutoCompleteDescWindow(this, ac);
dw.applyComponentOrientation(ac.getTextComponentOrientation());
Dimension size = preferredDescWindowSize;
if (size == null) {
size = getSize();
}
dw.setSize(size);
return dw;
}
/**
* Creates the mappings from keys to Actions we'll be putting into the
* text component's ActionMap and InputMap.
*/
private void createKeyActionPairs() {
// Actions we'll install.
EnterAction enterAction = new EnterAction();
escapeKap = new KeyActionPair("Escape", new EscapeAction());
upKap = new KeyActionPair("Up", new UpAction());
downKap = new KeyActionPair("Down", new DownAction());
leftKap = new KeyActionPair("Left", new LeftAction());
rightKap = new KeyActionPair("Right", new RightAction());
enterKap = new KeyActionPair("Enter", enterAction);
tabKap = new KeyActionPair("Tab", enterAction);
homeKap = new KeyActionPair("Home", new HomeAction());
endKap = new KeyActionPair("End", new EndAction());
pageUpKap = new KeyActionPair("PageUp", new PageUpAction());
pageDownKap = new KeyActionPair("PageDown", new PageDownAction());
ctrlCKap = new KeyActionPair("CtrlC", new CopyAction());
// Buffers for the actions we replace.
oldEscape = new KeyActionPair();
oldUp = new KeyActionPair();
oldDown = new KeyActionPair();
oldLeft = new KeyActionPair();
oldRight = new KeyActionPair();
oldEnter = new KeyActionPair();
oldTab = new KeyActionPair();
oldHome = new KeyActionPair();
oldEnd = new KeyActionPair();
oldPageUp = new KeyActionPair();
oldPageDown = new KeyActionPair();
oldCtrlC = new KeyActionPair();
}
protected void doAutocomplete() {
lastLine = ac.refreshPopupWindow();
}
/**
* Returns the copy keystroke to use for this platform.
*
* @return The copy keystroke.
*/
private static final KeyStroke getCopyKeyStroke() {
int key = KeyEvent.VK_C;
int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
return KeyStroke.getKeyStroke(key, mask);
}
/**
* Returns the default list cell renderer used when a completion provider
* does not supply its own.
*
* @return The default list cell renderer.
* @see #setListCellRenderer(ListCellRenderer)
*/
public ListCellRenderer getListCellRenderer() {
DelegatingCellRenderer dcr = (DelegatingCellRenderer) list.
getCellRenderer();
return dcr.getFallbackCellRenderer();
}
/**
* Returns the selected value, or <code>null</code> if nothing is selected.
*
* @return The selected value.
*/
public Completion getSelection() {
return isShowing() ? (Completion) list.getSelectedValue() : lastSelection;
}
/**
* Inserts the currently selected completion.
*
* @see #getSelection()
*/
private void insertSelectedCompletion() {
Completion comp = getSelection();
ac.insertCompletion(comp);
}
public void installComp(AutoCompleteExtraRefreshComponent component){
this.component = component;
}
public void refreshInstallComp() {
component.refresh(getSelection().getReplacementText());
}
/**
* Registers keyboard actions to listen for in the text component and
* intercept.
*
* @see #uninstallKeyBindings()
*/
private void installKeyBindings() {
if (AutoCompletion.isDebug()) {
FineLoggerFactory.getLogger().debug("PopupWindow: Installing keybindings");
}
if (escapeKap == null) { // Lazily create actions.
createKeyActionPairs();
}
JTextComponent comp = ac.getTextComponent();
InputMap im = comp.getInputMap();
ActionMap am = comp.getActionMap();
replaceAction(im, am, KeyEvent.VK_ESCAPE, escapeKap, oldEscape);
if (AutoCompletion.isDebug() && oldEscape.action == escapeKap.action) {
Thread.dumpStack();
}
replaceAction(im, am, KeyEvent.VK_UP, upKap, oldUp);
replaceAction(im, am, KeyEvent.VK_LEFT, leftKap, oldLeft);
replaceAction(im, am, KeyEvent.VK_DOWN, downKap, oldDown);
replaceAction(im, am, KeyEvent.VK_RIGHT, rightKap, oldRight);
replaceAction(im, am, KeyEvent.VK_ENTER, enterKap, oldEnter);
replaceAction(im, am, KeyEvent.VK_TAB, tabKap, oldTab);
replaceAction(im, am, KeyEvent.VK_HOME, homeKap, oldHome);
replaceAction(im, am, KeyEvent.VK_END, endKap, oldEnd);
replaceAction(im, am, KeyEvent.VK_PAGE_UP, pageUpKap, oldPageUp);
replaceAction(im, am, KeyEvent.VK_PAGE_DOWN, pageDownKap, oldPageDown);
// Make Ctrl+C copy from description window. This isn't done
// automagically because the desc. window is not focusable, and copying
// from text components can only be done from focused components.
KeyStroke ks = getCopyKeyStroke();
oldCtrlC.key = im.get(ks);
im.put(ks, ctrlCKap.key);
oldCtrlC.action = am.get(ctrlCKap.key);
am.put(ctrlCKap.key, ctrlCKap.action);
comp.addCaretListener(this);
}
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2 && e.getButton() == 1) {
insertSelectedCompletion();
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
refreshInstallComp();
}
public void mouseReleased(MouseEvent e) {
}
/**
* Positions the description window relative to the completion choices
* window. We assume there is room on one side of the other for this
* entire window to fit.
*/
private void positionDescWindow() {
boolean showDescWindow = descWindow != null && ac.isShowDescWindow();
if (!showDescWindow) {
return;
}
// Don't use getLocationOnScreen() as this throws an exception if
// window isn't visible yet, but getLocation() doesn't, and is in
// screen coordinates!
Point p = getLocation();
Rectangle screenBounds = Util.getScreenBoundsForPoint(p.x, p.y);
//Dimension screenSize = getToolkit().getScreenSize();
//int totalH = Math.max(getHeight(), descWindow.getHeight());
// Try to position to the right first (LTR)
int x;
if (ac.getTextComponentOrientation().isLeftToRight()) {
x = getX() + getWidth() + DIS;
if (x + descWindow.getWidth() > screenBounds.x + screenBounds.width) { // doesn't fit
x = getX() - DIS - descWindow.getWidth();
}
} else { // RTL
x = getX() - DIS - descWindow.getWidth();
if (x < screenBounds.x) { // Doesn't fit
x = getX() + getWidth() + DIS;
}
}
int y = getY();
if (aboveCaret) {
y = y + getHeight() - descWindow.getHeight();
}
if (x != descWindow.getX() || y != descWindow.getY()) {
descWindow.setLocation(x, y);
}
}
/**
* "Puts back" the original key/Action pair for a keystroke. This is used
* when this popup is hidden.
*
* @param im The input map.
* @param am The action map.
* @param key The keystroke whose key/Action pair to change.
* @param kap The (original) key/Action pair.
* @see #replaceAction(InputMap, ActionMap, int, KeyActionPair, KeyActionPair)
*/
private void putBackAction(InputMap im, ActionMap am, int key,
KeyActionPair kap) {
KeyStroke ks = KeyStroke.getKeyStroke(key, 0);
am.put(im.get(ks), kap.action); // Original action for the "new" key
im.put(ks, kap.key); // Original key for the keystroke.
}
/**
* Replaces a key/Action pair in an InputMap and ActionMap with a new
* pair.
*
* @param im The input map.
* @param am The action map.
* @param key The keystroke whose information to replace.
* @param kap The new key/Action pair for <code>key</code>.
* @param old A buffer in which to place the old key/Action pair.
* @see #putBackAction(InputMap, ActionMap, int, KeyActionPair)
*/
private void replaceAction(InputMap im, ActionMap am, int key,
KeyActionPair kap, KeyActionPair old) {
KeyStroke ks = KeyStroke.getKeyStroke(key, 0);
old.key = im.get(ks);
im.put(ks, kap.key);
old.action = am.get(kap.key);
am.put(kap.key, kap.action);
}
/**
* Selects the first item in the completion list.
*
* @see #selectLastItem()
*/
private void selectFirstItem() {
if (model.getSize() > 0) {
list.setSelectedIndex(0);
list.ensureIndexIsVisible(0);
}
}
/**
* Selects the last item in the completion list.
*
* @see #selectFirstItem()
*/
private void selectLastItem() {
int index = model.getSize() - 1;
if (index > -1) {
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
}
/**
* Selects the next item in the completion list.
*
* @see #selectPreviousItem()
*/
private void selectNextItem() {
int index = list.getSelectedIndex();
if (index > -1) {
index = (index + 1) % model.getSize();
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
}
/**
* Selects the completion item one "page down" from the currently selected
* one.
*
* @see #selectPageUpItem()
*/
private void selectPageDownItem() {
int visibleRowCount = list.getVisibleRowCount();
int i = Math.min(list.getModel().getSize() - 1,
list.getSelectedIndex() + visibleRowCount);
list.setSelectedIndex(i);
list.ensureIndexIsVisible(i);
}
/**
* Selects the completion item one "page up" from the currently selected
* one.
*
* @see #selectPageDownItem()
*/
private void selectPageUpItem() {
int visibleRowCount = list.getVisibleRowCount();
int i = Math.max(0, list.getSelectedIndex() - visibleRowCount);
list.setSelectedIndex(i);
list.ensureIndexIsVisible(i);
}
/**
* Selects the previous item in the completion list.
*
* @see #selectNextItem()
*/
private void selectPreviousItem() {
int index = list.getSelectedIndex();
switch (index) {
case 0:
index = list.getModel().getSize() - 1;
break;
case -1: // Check for an empty list (would be an error)
index = list.getModel().getSize() - 1;
if (index == -1) {
return;
}
break;
default:
index = index - 1;
break;
}
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
/**
* Sets the completions to display in the choices list. The first
* completion is selected.
*
* @param completions The completions to display.
*/
public void setCompletions(List<Completion> completions) {
model.setContents(completions);
selectFirstItem();
}
/**
* Sets the size of the description window.
*
* @param size The new size. This cannot be <code>null</code>.
*/
public void setDescriptionWindowSize(Dimension size) {
if (descWindow != null) {
descWindow.setSize(size);
} else {
preferredDescWindowSize = size;
}
}
/**
* Sets the default list cell renderer to use when a completion provider
* does not supply its own.
*
* @param renderer The renderer to use. If this is <code>null</code>,
* a default renderer is used.
* @see #getListCellRenderer()
*/
public void setListCellRenderer(ListCellRenderer renderer) {
DelegatingCellRenderer dcr = (DelegatingCellRenderer) list.
getCellRenderer();
dcr.setFallbackCellRenderer(renderer);
}
/**
* Sets the location of this window to be "good" relative to the specified
* rectangle. That rectangle should be the location of the text
* component's caret, in screen coordinates.
*
* @param r The text component's caret position, in screen coordinates.
*/
public void setLocationRelativeTo(Rectangle r) {
// Multi-monitor support - make sure the completion window (and
// description window, if applicable) both fit in the same window in
// a multi-monitor environment. To do this, we decide which monitor
// the rectangle "r" is in, and use that one (just pick top-left corner
// as the defining point).
Rectangle screenBounds = Util.getScreenBoundsForPoint(r.x, r.y);
//Dimension screenSize = getToolkit().getScreenSize();
boolean showDescWindow = descWindow != null && ac.isShowDescWindow();
int totalH = getHeight();
if (showDescWindow) {
totalH = Math.max(totalH, descWindow.getHeight());
}
// Try putting our stuff "below" the caret first. We assume that the
// entire height of our stuff fits on the screen one way or the other.
aboveCaret = false;
int y = r.y + r.height + VERTICAL_SPACE;
if (y + totalH > screenBounds.height) {
y = r.y - VERTICAL_SPACE - getHeight();
aboveCaret = true;
}
// Get x-coordinate of completions. Try to align left edge with the
// caret first.
int x = r.x;
if (!ac.getTextComponentOrientation().isLeftToRight()) {
x -= getWidth(); // RTL => align right edge
}
if (x < screenBounds.x) {
x = screenBounds.x;
} else if (x + getWidth() > screenBounds.x + screenBounds.width) { // completions don't fit
x = screenBounds.x + screenBounds.width - getWidth();
}
setLocation(x, y);
// Position the description window, if necessary.
if (showDescWindow) {
positionDescWindow();
}
}
/**
* Toggles the visibility of this popup window.
*
* @param visible Whether this window should be visible.
*/
@Override
public void setVisible(boolean visible) {
if (visible != isVisible()) {
if (visible) {
installKeyBindings();
lastLine = ac.getLineOfCaret();
selectFirstItem();
if (descWindow == null && ac.isShowDescWindow()) {
descWindow = createDescriptionWindow();
positionDescWindow();
}
// descWindow needs a kick-start the first time it's displayed.
// Also, the newly-selected item in the choices list is
// probably different from the previous one anyway.
if (descWindow != null) {
Completion c = (Completion) list.getSelectedValue();
if (c != null) {
descWindow.setDescriptionFor(c);
}
}
} else {
uninstallKeyBindings();
}
super.setVisible(visible);
// Some languages, such as Java, can use quite a lot of memory
// when displaying hundreds of completion choices. We pro-actively
// clear our list model here to make them available for GC.
// Otherwise, they stick around, and consider the following: a
// user starts code-completion for Java 5 SDK classes, then hides
// the dialog, then changes the "class path" to use a Java 6 SDK
// instead. On pressing Ctrl+space, a new array of Completions is
// created. If this window holds on to the previous Completions,
// you're getting roughly 2x the necessary Completions in memory
// until the Completions are actually passed to this window.
if (!visible) { // Do after super.setVisible(false)
lastSelection = (Completion) list.getSelectedValue();
model.clear();
}
// Must set descWindow's visibility one way or the other each time,
// because of the way child JWindows' visibility is handled - in
// some ways it's dependent on the parent, in other ways it's not.
if (descWindow != null) {
descWindow.setVisible(visible && ac.isShowDescWindow());
}
}
}
/**
* Stops intercepting certain keystrokes from the text component.
*
* @see #installKeyBindings()
*/
private void uninstallKeyBindings() {
if (AutoCompletion.isDebug()) {
FineLoggerFactory.getLogger().debug("PopupWindow: Removing keybindings");
}
JTextComponent comp = ac.getTextComponent();
InputMap im = comp.getInputMap();
ActionMap am = comp.getActionMap();
putBackAction(im, am, KeyEvent.VK_ESCAPE, oldEscape);
putBackAction(im, am, KeyEvent.VK_UP, oldUp);
putBackAction(im, am, KeyEvent.VK_DOWN, oldDown);
putBackAction(im, am, KeyEvent.VK_LEFT, oldLeft);
putBackAction(im, am, KeyEvent.VK_RIGHT, oldRight);
putBackAction(im, am, KeyEvent.VK_ENTER, oldEnter);
putBackAction(im, am, KeyEvent.VK_TAB, oldTab);
putBackAction(im, am, KeyEvent.VK_HOME, oldHome);
putBackAction(im, am, KeyEvent.VK_END, oldEnd);
putBackAction(im, am, KeyEvent.VK_PAGE_UP, oldPageUp);
putBackAction(im, am, KeyEvent.VK_PAGE_DOWN, oldPageDown);
// Ctrl+C
KeyStroke ks = getCopyKeyStroke();
am.put(im.get(ks), oldCtrlC.action); // Original action
im.put(ks, oldCtrlC.key); // Original key
comp.removeCaretListener(this);
}
/**
* Updates the <tt>LookAndFeel</tt> of this window and the description
* window.
*/
public void updateUI() {
SwingUtilities.updateComponentTreeUI(this);
if (descWindow != null) {
descWindow.updateUI();
}
}
/**
* Called when a new item is selected in the popup list.
*
* @param e The event.
*/
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
Object value = list.getSelectedValue();
if (value != null && descWindow != null) {
descWindow.setDescriptionFor((Completion) value);
positionDescWindow();
}
}
}
class CopyAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
boolean doNormalCopy = false;
if (descWindow != null && descWindow.isVisible()) {
doNormalCopy = !descWindow.copy();
}
if (doNormalCopy) {
ac.getTextComponent().copy();
}
}
}
class DownAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectNextItem();
refreshInstallComp();
}
}
}
class EndAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectLastItem();
}
}
}
class EnterAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
insertSelectedCompletion();
refreshInstallComp();
}
}
}
class EscapeAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
setVisible(false);
}
}
}
class HomeAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectFirstItem();
}
}
}
/**
* A mapping from a key (an Object) to an Action.
*/
private static class KeyActionPair {
public Object key;
public Action action;
public KeyActionPair() {
}
public KeyActionPair(Object key, Action a) {
this.key = key;
this.action = a;
}
}
class LeftAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
JTextComponent comp = ac.getTextComponent();
Caret c = comp.getCaret();
int dot = c.getDot();
if (dot > 0) {
c.setDot(--dot);
// Ensure moving left hasn't moved us up a line, thus
// hiding the popup window.
if (comp.isVisible()) {
if (lastLine != -1) {
doAutocomplete();
}
}
}
}
}
}
class PageDownAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectPageDownItem();
}
}
}
class PageUpAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectPageUpItem();
}
}
}
/**
* The actual list of completion choices in this popup window.
*/
private class PopupList extends JList {
public PopupList(CompletionListModel model) {
super(model);
}
@Override
public void setUI(ListUI ui) {
if (Util.getUseSubstanceRenderers() &&
SUBSTANCE_LIST_UI.equals(ui.getClass().getName())) {
// Substance requires its special ListUI be installed for
// its renderers to actually render (!), but long completion
// lists (e.g. PHPCompletionProvider in RSTALanguageSupport)
// will simply populate too slowly on initial display (when
// calculating preferred size of all items), so in this case
// we give a prototype cell value.
CompletionProvider p = ac.getCompletionProvider();
BasicCompletion bc = new BasicCompletion(p, "Hello world");
setPrototypeCellValue(bc);
} else {
// Our custom UI that is faster for long HTML completion lists.
ui = new FastListUI();
setPrototypeCellValue(null);
}
super.setUI(ui);
}
}
class RightAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
JTextComponent comp = ac.getTextComponent();
Caret c = comp.getCaret();
int dot = c.getDot();
if (dot < comp.getDocument().getLength()) {
c.setDot(++dot);
// Ensure moving right hasn't moved us up a line, thus
// hiding the popup window.
if (comp.isVisible()) {
if (lastLine != -1) {
doAutocomplete();
}
}
}
}
}
}
class UpAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectPreviousItem();
refreshInstallComp();
}
}
}
}

1260
designer-base/src/main/java/com/fr/design/gui/autocomplete/AutoCompletionWithExtraRefresh.java

File diff suppressed because it is too large Load Diff

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

@ -9,41 +9,7 @@
*/
package com.fr.design.gui.autocomplete;
import com.fr.design.formula.FormulaPane;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.PopupWindowDecorator;
import com.fr.log.FineLoggerFactory;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JWindow;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.ListUI;
import javax.swing.text.Caret;
import javax.swing.text.JTextComponent;
import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
/**
* The actual popup window of choices. When visible, this window intercepts
@ -55,949 +21,11 @@ import java.util.List;
* @author Robert Futrell
* @version 1.0
*/
class FormulaAutoCompletePopupWindow extends JWindow implements CaretListener,
ListSelectionListener, MouseListener {
private final static int DIS = 5;
/**
* The parent AutoCompletion instance.
*/
private FormulaPaneAutoCompletion ac;
/**
* The list of completion choices.
*/
private JList list;
/**
* The contents of {@link #list()}.
*/
private CompletionListModel model;
/**
* A hack to work around the fact that we clear our completion model (and
* our selection) when hiding the completion window. This allows us to
* still know what the user selected after the popup is hidden.
*/
private Completion lastSelection;
/**
* Optional popup window containing a description of the currently
* selected completion.
*/
private AutoCompleteDescWindow descWindow;
/**
* The preferred size of the optional description window. This field
* only exists because the user may (and usually will) set the size of
* the description window before it exists (it must be parented to a
* Window).
*/
private Dimension preferredDescWindowSize;
private FormulaPane.VariableTreeAndDescriptionArea component;
/**
* Whether the completion window and the optional description window
* should be displayed above the current caret position (as opposed to
* underneath it, which is preferred unless there is not enough space).
*/
private boolean aboveCaret;
private int lastLine;
private KeyActionPair escapeKap;
private KeyActionPair upKap;
private KeyActionPair downKap;
private KeyActionPair leftKap;
private KeyActionPair rightKap;
private KeyActionPair enterKap;
private KeyActionPair tabKap;
private KeyActionPair homeKap;
private KeyActionPair endKap;
private KeyActionPair pageUpKap;
private KeyActionPair pageDownKap;
private KeyActionPair ctrlCKap;
private KeyActionPair oldEscape, oldUp, oldDown, oldLeft, oldRight,
oldEnter, oldTab, oldHome, oldEnd, oldPageUp, oldPageDown,
oldCtrlC;
/**
* The space between the caret and the completion popup.
*/
private static final int VERTICAL_SPACE = 1;
/**
* The class name of the Substance List UI.
*/
private static final String SUBSTANCE_LIST_UI =
"org.pushingpixels.substance.internal.ui.SubstanceListUI";
class FormulaAutoCompletePopupWindow extends AutoCompleteWithExtraRefreshPopupWindow {
/**
* Constructor.
*
* @param parent The parent window (hosting the text component).
* @param ac The auto-completion instance.
*/
public FormulaAutoCompletePopupWindow(Window parent, final FormulaPaneAutoCompletion ac) {
super(parent);
ComponentOrientation o = ac.getTextComponentOrientation();
this.ac = ac;
model = new CompletionListModel();
list = new PopupList(model);
list.setCellRenderer(new DelegatingCellRenderer());
list.addListSelectionListener(this);
list.addMouseListener(this);
JPanel contentPane = new JPanel(new BorderLayout());
JScrollPane sp = new JScrollPane(list,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
// In 1.4, JScrollPane.setCorner() has a bug where it won't accept
// JScrollPane.LOWER_TRAILING_CORNER, even though that constant is
// defined. So we have to put the logic added in 1.5 to handle it
// here.
JPanel corner = new SizeGrip();
//sp.setCorner(JScrollPane.LOWER_TRAILING_CORNER, corner);
boolean isLeftToRight = o.isLeftToRight();
String str = isLeftToRight ? JScrollPane.LOWER_RIGHT_CORNER :
JScrollPane.LOWER_LEFT_CORNER;
sp.setCorner(str, corner);
contentPane.add(sp);
setContentPane(contentPane);
applyComponentOrientation(o);
// Give apps a chance to decorate us with drop shadows, etc.
if (Util.getShouldAllowDecoratingMainAutoCompleteWindows()) {
PopupWindowDecorator decorator = PopupWindowDecorator.get();
if (decorator != null) {
decorator.decorate(this);
}
}
pack();
setFocusableWindowState(false);
lastLine = -1;
}
public void caretUpdate(CaretEvent e) {
if (isVisible()) { // Should always be true
int line = ac.getLineOfCaret();
if (line != lastLine) {
lastLine = -1;
setVisible(false);
} else {
doAutocomplete();
}
} else if (AutoCompletion.isDebug()) {
Thread.dumpStack();
}
}
/**
* Creates the description window.
*
* @return The description window.
*/
private AutoCompleteDescWindow createDescriptionWindow() {
AutoCompleteDescWindow dw = new AutoCompleteDescWindow(this, ac);
dw.applyComponentOrientation(ac.getTextComponentOrientation());
Dimension size = preferredDescWindowSize;
if (size == null) {
size = getSize();
}
dw.setSize(size);
return dw;
}
/**
* Creates the mappings from keys to Actions we'll be putting into the
* text component's ActionMap and InputMap.
*/
private void createKeyActionPairs() {
// Actions we'll install.
EnterAction enterAction = new EnterAction();
escapeKap = new KeyActionPair("Escape", new EscapeAction());
upKap = new KeyActionPair("Up", new UpAction());
downKap = new KeyActionPair("Down", new DownAction());
leftKap = new KeyActionPair("Left", new LeftAction());
rightKap = new KeyActionPair("Right", new RightAction());
enterKap = new KeyActionPair("Enter", enterAction);
tabKap = new KeyActionPair("Tab", enterAction);
homeKap = new KeyActionPair("Home", new HomeAction());
endKap = new KeyActionPair("End", new EndAction());
pageUpKap = new KeyActionPair("PageUp", new PageUpAction());
pageDownKap = new KeyActionPair("PageDown", new PageDownAction());
ctrlCKap = new KeyActionPair("CtrlC", new CopyAction());
// Buffers for the actions we replace.
oldEscape = new KeyActionPair();
oldUp = new KeyActionPair();
oldDown = new KeyActionPair();
oldLeft = new KeyActionPair();
oldRight = new KeyActionPair();
oldEnter = new KeyActionPair();
oldTab = new KeyActionPair();
oldHome = new KeyActionPair();
oldEnd = new KeyActionPair();
oldPageUp = new KeyActionPair();
oldPageDown = new KeyActionPair();
oldCtrlC = new KeyActionPair();
}
protected void doAutocomplete() {
lastLine = ac.refreshPopupWindow();
}
/**
* Returns the copy keystroke to use for this platform.
*
* @return The copy keystroke.
*/
private static final KeyStroke getCopyKeyStroke() {
int key = KeyEvent.VK_C;
int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
return KeyStroke.getKeyStroke(key, mask);
}
/**
* Returns the default list cell renderer used when a completion provider
* does not supply its own.
*
* @return The default list cell renderer.
* @see #setListCellRenderer(ListCellRenderer)
*/
public ListCellRenderer getListCellRenderer() {
DelegatingCellRenderer dcr = (DelegatingCellRenderer) list.
getCellRenderer();
return dcr.getFallbackCellRenderer();
}
/**
* Returns the selected value, or <code>null</code> if nothing is selected.
*
* @return The selected value.
*/
public Completion getSelection() {
return isShowing() ? (Completion) list.getSelectedValue() : lastSelection;
}
/**
* Inserts the currently selected completion.
*
* @see #getSelection()
*/
private void insertSelectedCompletion() {
Completion comp = getSelection();
ac.insertCompletion(comp);
}
public void installComp(FormulaPane.VariableTreeAndDescriptionArea component) {
this.component = component;
}
private void refreshInstallComp() {
component.refreshText(getSelection().getReplacementText());
}
/**
* Registers keyboard actions to listen for in the text component and
* intercept.
*
* @see #uninstallKeyBindings()
*/
private void installKeyBindings() {
if (AutoCompletion.isDebug()) {
FineLoggerFactory.getLogger().debug("PopupWindow: Installing keybindings");
}
if (escapeKap == null) { // Lazily create actions.
createKeyActionPairs();
}
JTextComponent comp = ac.getTextComponent();
InputMap im = comp.getInputMap();
ActionMap am = comp.getActionMap();
replaceAction(im, am, KeyEvent.VK_ESCAPE, escapeKap, oldEscape);
if (AutoCompletion.isDebug() && oldEscape.action == escapeKap.action) {
Thread.dumpStack();
}
replaceAction(im, am, KeyEvent.VK_UP, upKap, oldUp);
replaceAction(im, am, KeyEvent.VK_LEFT, leftKap, oldLeft);
replaceAction(im, am, KeyEvent.VK_DOWN, downKap, oldDown);
replaceAction(im, am, KeyEvent.VK_RIGHT, rightKap, oldRight);
replaceAction(im, am, KeyEvent.VK_ENTER, enterKap, oldEnter);
replaceAction(im, am, KeyEvent.VK_TAB, tabKap, oldTab);
replaceAction(im, am, KeyEvent.VK_HOME, homeKap, oldHome);
replaceAction(im, am, KeyEvent.VK_END, endKap, oldEnd);
replaceAction(im, am, KeyEvent.VK_PAGE_UP, pageUpKap, oldPageUp);
replaceAction(im, am, KeyEvent.VK_PAGE_DOWN, pageDownKap, oldPageDown);
// Make Ctrl+C copy from description window. This isn't done
// automagically because the desc. window is not focusable, and copying
// from text components can only be done from focused components.
KeyStroke ks = getCopyKeyStroke();
oldCtrlC.key = im.get(ks);
im.put(ks, ctrlCKap.key);
oldCtrlC.action = am.get(ctrlCKap.key);
am.put(ctrlCKap.key, ctrlCKap.action);
comp.addCaretListener(this);
}
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2 && e.getButton() == 1) {
insertSelectedCompletion();
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
refreshInstallComp();
}
public void mouseReleased(MouseEvent e) {
}
/**
* Positions the description window relative to the completion choices
* window. We assume there is room on one side of the other for this
* entire window to fit.
*/
private void positionDescWindow() {
boolean showDescWindow = descWindow != null && ac.isShowDescWindow();
if (!showDescWindow) {
return;
}
// Don't use getLocationOnScreen() as this throws an exception if
// window isn't visible yet, but getLocation() doesn't, and is in
// screen coordinates!
Point p = getLocation();
Rectangle screenBounds = Util.getScreenBoundsForPoint(p.x, p.y);
//Dimension screenSize = getToolkit().getScreenSize();
//int totalH = Math.max(getHeight(), descWindow.getHeight());
// Try to position to the right first (LTR)
int x;
if (ac.getTextComponentOrientation().isLeftToRight()) {
x = getX() + getWidth() + DIS;
if (x + descWindow.getWidth() > screenBounds.x + screenBounds.width) { // doesn't fit
x = getX() - DIS - descWindow.getWidth();
}
} else { // RTL
x = getX() - DIS - descWindow.getWidth();
if (x < screenBounds.x) { // Doesn't fit
x = getX() + getWidth() + DIS;
}
}
int y = getY();
if (aboveCaret) {
y = y + getHeight() - descWindow.getHeight();
}
if (x != descWindow.getX() || y != descWindow.getY()) {
descWindow.setLocation(x, y);
}
}
/**
* "Puts back" the original key/Action pair for a keystroke. This is used
* when this popup is hidden.
*
* @param im The input map.
* @param am The action map.
* @param key The keystroke whose key/Action pair to change.
* @param kap The (original) key/Action pair.
* @see #replaceAction(InputMap, ActionMap, int, KeyActionPair, KeyActionPair)
*/
private void putBackAction(InputMap im, ActionMap am, int key,
KeyActionPair kap) {
KeyStroke ks = KeyStroke.getKeyStroke(key, 0);
am.put(im.get(ks), kap.action); // Original action for the "new" key
im.put(ks, kap.key); // Original key for the keystroke.
}
/**
* Replaces a key/Action pair in an InputMap and ActionMap with a new
* pair.
*
* @param im The input map.
* @param am The action map.
* @param key The keystroke whose information to replace.
* @param kap The new key/Action pair for <code>key</code>.
* @param old A buffer in which to place the old key/Action pair.
* @see #putBackAction(InputMap, ActionMap, int, KeyActionPair)
*/
private void replaceAction(InputMap im, ActionMap am, int key,
KeyActionPair kap, KeyActionPair old) {
KeyStroke ks = KeyStroke.getKeyStroke(key, 0);
old.key = im.get(ks);
im.put(ks, kap.key);
old.action = am.get(kap.key);
am.put(kap.key, kap.action);
}
/**
* Selects the first item in the completion list.
*
* @see #selectLastItem()
*/
private void selectFirstItem() {
if (model.getSize() > 0) {
list.setSelectedIndex(0);
list.ensureIndexIsVisible(0);
}
}
/**
* Selects the last item in the completion list.
*
* @see #selectFirstItem()
*/
private void selectLastItem() {
int index = model.getSize() - 1;
if (index > -1) {
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
}
/**
* Selects the next item in the completion list.
*
* @see #selectPreviousItem()
*/
private void selectNextItem() {
int index = list.getSelectedIndex();
if (index > -1) {
index = (index + 1) % model.getSize();
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
}
/**
* Selects the completion item one "page down" from the currently selected
* one.
*
* @see #selectPageUpItem()
*/
private void selectPageDownItem() {
int visibleRowCount = list.getVisibleRowCount();
int i = Math.min(list.getModel().getSize() - 1,
list.getSelectedIndex() + visibleRowCount);
list.setSelectedIndex(i);
list.ensureIndexIsVisible(i);
}
/**
* Selects the completion item one "page up" from the currently selected
* one.
*
* @see #selectPageDownItem()
*/
private void selectPageUpItem() {
int visibleRowCount = list.getVisibleRowCount();
int i = Math.max(0, list.getSelectedIndex() - visibleRowCount);
list.setSelectedIndex(i);
list.ensureIndexIsVisible(i);
}
/**
* Selects the previous item in the completion list.
*
* @see #selectNextItem()
*/
private void selectPreviousItem() {
int index = list.getSelectedIndex();
switch (index) {
case 0:
index = list.getModel().getSize() - 1;
break;
case -1: // Check for an empty list (would be an error)
index = list.getModel().getSize() - 1;
if (index == -1) {
return;
}
break;
default:
index = index - 1;
break;
}
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
/**
* Sets the completions to display in the choices list. The first
* completion is selected.
*
* @param completions The completions to display.
*/
public void setCompletions(List<Completion> completions) {
model.setContents(completions);
selectFirstItem();
}
/**
* Sets the size of the description window.
*
* @param size The new size. This cannot be <code>null</code>.
*/
public void setDescriptionWindowSize(Dimension size) {
if (descWindow != null) {
descWindow.setSize(size);
} else {
preferredDescWindowSize = size;
}
}
/**
* Sets the default list cell renderer to use when a completion provider
* does not supply its own.
*
* @param renderer The renderer to use. If this is <code>null</code>,
* a default renderer is used.
* @see #getListCellRenderer()
*/
public void setListCellRenderer(ListCellRenderer renderer) {
DelegatingCellRenderer dcr = (DelegatingCellRenderer) list.
getCellRenderer();
dcr.setFallbackCellRenderer(renderer);
}
/**
* Sets the location of this window to be "good" relative to the specified
* rectangle. That rectangle should be the location of the text
* component's caret, in screen coordinates.
*
* @param r The text component's caret position, in screen coordinates.
*/
public void setLocationRelativeTo(Rectangle r) {
// Multi-monitor support - make sure the completion window (and
// description window, if applicable) both fit in the same window in
// a multi-monitor environment. To do this, we decide which monitor
// the rectangle "r" is in, and use that one (just pick top-left corner
// as the defining point).
Rectangle screenBounds = Util.getScreenBoundsForPoint(r.x, r.y);
//Dimension screenSize = getToolkit().getScreenSize();
boolean showDescWindow = descWindow != null && ac.isShowDescWindow();
int totalH = getHeight();
if (showDescWindow) {
totalH = Math.max(totalH, descWindow.getHeight());
}
// Try putting our stuff "below" the caret first. We assume that the
// entire height of our stuff fits on the screen one way or the other.
aboveCaret = false;
int y = r.y + r.height + VERTICAL_SPACE;
if (y + totalH > screenBounds.height) {
y = r.y - VERTICAL_SPACE - getHeight();
aboveCaret = true;
}
// Get x-coordinate of completions. Try to align left edge with the
// caret first.
int x = r.x;
if (!ac.getTextComponentOrientation().isLeftToRight()) {
x -= getWidth(); // RTL => align right edge
}
if (x < screenBounds.x) {
x = screenBounds.x;
} else if (x + getWidth() > screenBounds.x + screenBounds.width) { // completions don't fit
x = screenBounds.x + screenBounds.width - getWidth();
}
setLocation(x, y);
// Position the description window, if necessary.
if (showDescWindow) {
positionDescWindow();
}
}
/**
* Toggles the visibility of this popup window.
*
* @param visible Whether this window should be visible.
*/
@Override
public void setVisible(boolean visible) {
if (visible != isVisible()) {
if (visible) {
installKeyBindings();
lastLine = ac.getLineOfCaret();
selectFirstItem();
if (descWindow == null && ac.isShowDescWindow()) {
descWindow = createDescriptionWindow();
positionDescWindow();
}
// descWindow needs a kick-start the first time it's displayed.
// Also, the newly-selected item in the choices list is
// probably different from the previous one anyway.
if (descWindow != null) {
Completion c = (Completion) list.getSelectedValue();
if (c != null) {
descWindow.setDescriptionFor(c);
}
}
} else {
uninstallKeyBindings();
}
super.setVisible(visible);
// Some languages, such as Java, can use quite a lot of memory
// when displaying hundreds of completion choices. We pro-actively
// clear our list model here to make them available for GC.
// Otherwise, they stick around, and consider the following: a
// user starts code-completion for Java 5 SDK classes, then hides
// the dialog, then changes the "class path" to use a Java 6 SDK
// instead. On pressing Ctrl+space, a new array of Completions is
// created. If this window holds on to the previous Completions,
// you're getting roughly 2x the necessary Completions in memory
// until the Completions are actually passed to this window.
if (!visible) { // Do after super.setVisible(false)
lastSelection = (Completion) list.getSelectedValue();
model.clear();
}
// Must set descWindow's visibility one way or the other each time,
// because of the way child JWindows' visibility is handled - in
// some ways it's dependent on the parent, in other ways it's not.
if (descWindow != null) {
descWindow.setVisible(visible && ac.isShowDescWindow());
}
}
}
/**
* Stops intercepting certain keystrokes from the text component.
*
* @see #installKeyBindings()
*/
private void uninstallKeyBindings() {
if (AutoCompletion.isDebug()) {
FineLoggerFactory.getLogger().debug("PopupWindow: Removing keybindings");
}
JTextComponent comp = ac.getTextComponent();
InputMap im = comp.getInputMap();
ActionMap am = comp.getActionMap();
putBackAction(im, am, KeyEvent.VK_ESCAPE, oldEscape);
putBackAction(im, am, KeyEvent.VK_UP, oldUp);
putBackAction(im, am, KeyEvent.VK_DOWN, oldDown);
putBackAction(im, am, KeyEvent.VK_LEFT, oldLeft);
putBackAction(im, am, KeyEvent.VK_RIGHT, oldRight);
putBackAction(im, am, KeyEvent.VK_ENTER, oldEnter);
putBackAction(im, am, KeyEvent.VK_TAB, oldTab);
putBackAction(im, am, KeyEvent.VK_HOME, oldHome);
putBackAction(im, am, KeyEvent.VK_END, oldEnd);
putBackAction(im, am, KeyEvent.VK_PAGE_UP, oldPageUp);
putBackAction(im, am, KeyEvent.VK_PAGE_DOWN, oldPageDown);
// Ctrl+C
KeyStroke ks = getCopyKeyStroke();
am.put(im.get(ks), oldCtrlC.action); // Original action
im.put(ks, oldCtrlC.key); // Original key
comp.removeCaretListener(this);
}
/**
* Updates the <tt>LookAndFeel</tt> of this window and the description
* window.
*/
public void updateUI() {
SwingUtilities.updateComponentTreeUI(this);
if (descWindow != null) {
descWindow.updateUI();
}
}
/**
* Called when a new item is selected in the popup list.
*
* @param e The event.
*/
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
Object value = list.getSelectedValue();
if (value != null && descWindow != null) {
descWindow.setDescriptionFor((Completion) value);
positionDescWindow();
}
}
}
class CopyAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
boolean doNormalCopy = false;
if (descWindow != null && descWindow.isVisible()) {
doNormalCopy = !descWindow.copy();
}
if (doNormalCopy) {
ac.getTextComponent().copy();
}
}
}
class DownAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectNextItem();
refreshInstallComp();
}
}
}
class EndAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectLastItem();
}
}
}
class EnterAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
insertSelectedCompletion();
refreshInstallComp();
}
}
super(parent,ac);
}
class EscapeAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
setVisible(false);
}
}
}
class HomeAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectFirstItem();
}
}
}
/**
* A mapping from a key (an Object) to an Action.
*/
private static class KeyActionPair {
public Object key;
public Action action;
public KeyActionPair() {
}
public KeyActionPair(Object key, Action a) {
this.key = key;
this.action = a;
}
}
class LeftAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
JTextComponent comp = ac.getTextComponent();
Caret c = comp.getCaret();
int dot = c.getDot();
if (dot > 0) {
c.setDot(--dot);
// Ensure moving left hasn't moved us up a line, thus
// hiding the popup window.
if (comp.isVisible()) {
if (lastLine != -1) {
doAutocomplete();
}
}
}
}
}
}
class PageDownAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectPageDownItem();
}
}
}
class PageUpAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectPageUpItem();
}
}
}
/**
* The actual list of completion choices in this popup window.
*/
private class PopupList extends JList {
public PopupList(CompletionListModel model) {
super(model);
}
@Override
public void setUI(ListUI ui) {
if (Util.getUseSubstanceRenderers() &&
SUBSTANCE_LIST_UI.equals(ui.getClass().getName())) {
// Substance requires its special ListUI be installed for
// its renderers to actually render (!), but long completion
// lists (e.g. PHPCompletionProvider in RSTALanguageSupport)
// will simply populate too slowly on initial display (when
// calculating preferred size of all items), so in this case
// we give a prototype cell value.
CompletionProvider p = ac.getCompletionProvider();
BasicCompletion bc = new BasicCompletion(p, "Hello world");
setPrototypeCellValue(bc);
} else {
// Our custom UI that is faster for long HTML completion lists.
ui = new FastListUI();
setPrototypeCellValue(null);
}
super.setUI(ui);
}
}
class RightAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
JTextComponent comp = ac.getTextComponent();
Caret c = comp.getCaret();
int dot = c.getDot();
if (dot < comp.getDocument().getLength()) {
c.setDot(++dot);
// Ensure moving right hasn't moved us up a line, thus
// hiding the popup window.
if (comp.isVisible()) {
if (lastLine != -1) {
doAutocomplete();
}
}
}
}
}
}
class UpAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
if (isVisible()) {
selectPreviousItem();
refreshInstallComp();
}
}
}
}

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

File diff suppressed because it is too large Load Diff

16
designer-base/src/main/java/com/fr/design/gui/autocomplete/JSAutoCompletePopupWindow.java

@ -0,0 +1,16 @@
package com.fr.design.gui.autocomplete;
import java.awt.Window;
public class JSAutoCompletePopupWindow extends AutoCompleteWithExtraRefreshPopupWindow {
/**
* Constructor.
*
* @param parent The parent window (hosting the text component).
* @param ac The auto-completion instance.
*/
public JSAutoCompletePopupWindow(Window parent, AutoCompletion ac) {
super(parent, ac);
}
}

31
designer-base/src/main/java/com/fr/design/gui/autocomplete/JSImplPaneAutoCompletion.java

@ -0,0 +1,31 @@
package com.fr.design.gui.autocomplete;
public class JSImplPaneAutoCompletion extends AutoCompletionWithExtraRefresh{
/**
* Constructor.
*
* @param provider The completion provider. This cannot be
* <code>null</code>.
*/
public JSImplPaneAutoCompletion(CompletionProvider provider) {
super(provider);
}
@Override
protected AutoCompleteWithExtraRefreshPopupWindow createAutoCompletePopupWindow() {
JSAutoCompletePopupWindow popupWindow = new JSAutoCompletePopupWindow(getParentWindow(),this);
popupWindow.applyComponentOrientation(
getTextComponentOrientation());
if (getCellRender() != null) {
popupWindow.setListCellRenderer(getCellRender());
}
if (getPreferredChoicesWindowSize() != null) {
popupWindow.setSize(getPreferredChoicesWindowSize());
}
if (getPreferredDescWindowSize() != null) {
popupWindow.setDescriptionWindowSize(
getPreferredDescWindowSize());
}
return popupWindow;
}
}

4
designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java

@ -125,7 +125,9 @@ public abstract class UIListGroupControlPane extends UIControlPane implements Li
for (int i = 0, size = widget.getListenerSize(); i < size; i++) {
Listener listener = widget.getListener(i);
if (!listener.isDefault()) {
nameObjectList.add(i, new NameObject(switchLang(listener.getEventName()) + (i + 1), listener));
String eventName = switchLang(listener.getEventName()) + (nameObjectList.size() + 1);
NameObject nameObject = new NameObject(eventName, listener);
nameObjectList.add(nameObject);
}
}
populate(getHelper().processCatalog(nameObjectList));

11
designer-base/src/main/java/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java

@ -3,6 +3,8 @@ package com.fr.design.gui.frpane;
import com.fr.design.dialog.BasicPane;
import com.fr.design.event.GlobalNameListener;
import com.fr.design.event.GlobalNameObserver;
import com.fr.design.event.ComponentChangeListener;
import com.fr.design.event.ComponentChangeObserver;
import com.fr.design.event.UIObserver;
import com.fr.design.event.UIObserverListener;
import com.fr.stable.StringUtils;
@ -103,6 +105,15 @@ public abstract class AbstractAttrNoScrollPane extends BasicPane {
}
});
}
if(tmpComp instanceof ComponentChangeObserver){
ComponentChangeObserver uiChangeableObserver = ((ComponentChangeObserver)tmpComp);
uiChangeableObserver.registerChangeListener(new ComponentChangeListener() {
@Override
public void initListener(Container changedComponent) {
AbstractAttrNoScrollPane.this.initListener(changedComponent);
}
});
}
}
}

20
designer-base/src/main/java/com/fr/design/gui/frpane/JTreeAutoBuildPane.java

@ -242,12 +242,22 @@ public class JTreeAutoBuildPane extends BasicPane implements PreviewLabel.Previe
rtd = treeTableDataComboBox.getSelcetedTableData();
name = treeTableDataComboBox.getSelectedItem().getTableDataName();
}
final String tableDataName = name;
AbstractTableDataWrapper atdw = new TemplateTableDataWrapper(rtd, "");
tdtp.dgEdit(atdw.creatTableDataPane(), name);
treeTableDataComboBox.refresh();
treeTableDataComboBox.setSelectedTableDataByName(name);
textPane.populate(1);
valuePane.populate(1);
tdtp.showEditPane(atdw.creatTableDataPane(), name, new BasicTableDataTreePane.TableDataTreePaneListener() {
@Override
public void doOk() {
// 去除缓存列,后面刷新会重新选中
DesignTableDataManager.removeSelectedColumnNames(tableDataName);
treeTableDataComboBox.refresh();
treeTableDataComboBox.setSelectedTableDataByName(tableDataName);
}
@Override
public void doCancel() {
}
});
}
}

14
designer-base/src/main/java/com/fr/design/gui/frpane/TreeSettingPane.java

@ -127,7 +127,7 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI {
buildBox.setSelectedIndex(1);
TableDataDictionary dictionary = treeEditor.getDictionary();
autoBuildPane.populate(dictionary);
} else if (treeEditor.isLayerBuild()) {
} else if (treeEditor.isFastLayerBuild()) {
buildBox.setSelectedIndex(0);
java.util.List<LayerConfig> layerConfigList = treeEditor.getLayerConfigs();
LayerConfig[] layerConfigs = new LayerConfig[layerConfigList.size()];
@ -156,12 +156,12 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI {
if (buildBox.getSelectedIndex() == 1) {
TableDataDictionary dictionary = this.autoBuildPane.update();
te.setAutoBuild(true);
te.setLayerBuild(false);
te.setFastLayerBuild(false);
te.setDictionary(dictionary);
te.setNodeOrDict(dictionary);
} else if (buildBox.getSelectedIndex() == 2) {
te.setAutoBuild(false);
te.setLayerBuild(false);
te.setFastLayerBuild(false);
NameObject no = this.controlPane.update();
if (no != null) {
TreeEditor editor = (TreeEditor) no.getObject();
@ -181,7 +181,7 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI {
} else {
LayerConfig[] configs = (LayerConfig[]) layerDataControlPane.update().getObject();
te.setAutoBuild(false);
te.setLayerBuild(true);
te.setFastLayerBuild(true);
te.setLayerConfigs(Arrays.asList(configs));
}
return te;
@ -215,12 +215,12 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI {
if (buildBox.getSelectedIndex() == 1) {
TableDataDictionary dictionary = this.autoBuildPane.update();
tcb.setAutoBuild(true);
tcb.setLayerBuild(false);
tcb.setFastLayerBuild(false);
tcb.setDictionary(dictionary);
tcb.setNodeOrDict(dictionary);
} else if (buildBox.getSelectedIndex() == 2) {
tcb.setAutoBuild(false);
tcb.setLayerBuild(false);
tcb.setFastLayerBuild(false);
NameObject no = this.controlPane.update();
if (no != null) {
if (no.getObject() instanceof TreeComboBoxEditor) {
@ -244,7 +244,7 @@ public class TreeSettingPane extends BasicPane implements DataCreatorUI {
}else {
LayerConfig[] configs = (LayerConfig[]) layerDataControlPane.update().getObject();
tcb.setAutoBuild(false);
tcb.setLayerBuild(true);
tcb.setFastLayerBuild(true);
tcb.setLayerConfigs(Arrays.asList(configs));
}
return tcb;

4
designer-base/src/main/java/com/fr/design/gui/ibutton/UIButtonGroup.java

@ -389,9 +389,9 @@ public class UIButtonGroup<T> extends JPanel implements GlobalNameObserver, UIOb
* @param l
*/
public void addChangeListener(ChangeListener l) {
listenerList.add(ChangeListener.class, l);
for (int i = 0; i < labelButtonList.size(); i++) {
labelButtonList.get(i).addChangeListener(l);
listenerList.add(ChangeListener.class, l);
}
}
@ -399,9 +399,9 @@ public class UIButtonGroup<T> extends JPanel implements GlobalNameObserver, UIOb
* @param l
*/
public void removeChangeListener(ChangeListener l) {
listenerList.remove(ChangeListener.class, l);
for (int i = 0; i < labelButtonList.size(); i++) {
labelButtonList.get(i).removeChangeListener(l);
listenerList.remove(ChangeListener.class, l);
}
}

6
designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java

@ -58,7 +58,7 @@ public class UICheckBox extends JCheckBox implements UIObserver, GlobalNameObser
super(locText, b);
setUI(new UICheckBoxUI());
initListener();
this.markMnemonic=markMnemonic;
this.markMnemonic = markMnemonic;
}
public UICheckBox(String text, Icon icon) {
@ -100,6 +100,10 @@ public class UICheckBox extends JCheckBox implements UIObserver, GlobalNameObser
}
public void removeChangeListener() {
uiObserverListener = null;
}
@Override
public void setGlobalName(String name) {
checkboxName = name;

2
designer-base/src/main/java/com/fr/design/gui/icombobox/ColorSchemeComboBox.java

@ -153,7 +153,7 @@ public class ColorSchemeComboBox extends UIComboBox {
if (selectedIndex == itemCount - 2) {
return SelectType.COMBINATION_COLOR;
}
if (selectedIndex == 0) {
if (selectedIndex == 0 && ChartEditContext.supportTheme()) {
return SelectType.DEFAULT;
}
return SelectType.NORMAL;

4
designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java

@ -248,7 +248,7 @@ public class FRTreeComboBox extends UIComboBox {
private static TreePopup treePopup;
private static class FRTreeComboBoxUI extends BasicComboBoxUI implements MouseListener{
protected static class FRTreeComboBoxUI extends BasicComboBoxUI implements MouseListener{
private boolean isRollover = false;
public FRTreeComboBoxUI() {
@ -535,7 +535,7 @@ public class FRTreeComboBox extends UIComboBox {
public class FrTreeSearchComboBoxEditor extends UIComboBoxEditor implements DocumentListener {
private volatile boolean setting = false;
private FRTreeComboBox comboBox;
private Object item;
protected Object item;
public FrTreeSearchComboBoxEditor(FRTreeComboBox comboBox) {
super();

77
designer-base/src/main/java/com/fr/design/gui/icombobox/SearchPreTaskTreeComboBox.java

@ -1,77 +0,0 @@
package com.fr.design.gui.icombobox;
import com.fr.log.FineLoggerFactory;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.tree.TreeCellRenderer;
import java.util.concurrent.FutureTask;
/**
* 模糊搜索前需执行完前置任务的TreeComboBox
* @author Lucian.Chen
* @version 10.0
* Created by Lucian.Chen on 2021/4/14
*/
public class SearchPreTaskTreeComboBox extends FRTreeComboBox {
/**
* 模糊搜索前任务
*/
private FutureTask<Void> preSearchTask;
public SearchPreTaskTreeComboBox(JTree tree, TreeCellRenderer renderer, boolean editable) {
super(tree, renderer, editable);
}
public FutureTask<Void> getPreSearchTask() {
return preSearchTask;
}
public void setPreSearchTask(FutureTask<Void> preSearchTask) {
this.preSearchTask = preSearchTask;
}
protected UIComboBoxEditor createEditor() {
return new SearchPreTaskComboBoxEditor(this);
}
private class SearchPreTaskComboBoxEditor extends FrTreeSearchComboBoxEditor {
public SearchPreTaskComboBoxEditor(FRTreeComboBox comboBox) {
super(comboBox);
}
protected void changeHandler() {
if (isSetting()) {
return;
}
setPopupVisible(true);
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() {
FutureTask<Void> task = getPreSearchTask();
try {
// 确保模糊搜索前任务执行完成后,再进行模糊搜索
if (task != null) {
task.get();
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
if (task != null) {
// 任务执行后置空,否则会被别的操作重复触发
setPreSearchTask(null);
}
return null;
}
@Override
protected void done() {
// 模糊搜索
search();
}
}.execute();
}
}
}

228
designer-base/src/main/java/com/fr/design/gui/icombobox/TableSearchTreeComboBox.java

@ -0,0 +1,228 @@
package com.fr.design.gui.icombobox;
import com.fr.data.core.DataCoreUtils;
import com.fr.data.core.db.TableProcedure;
import com.fr.data.impl.Connection;
import com.fr.design.DesignerEnvManager;
import com.fr.design.data.datapane.ChoosePane;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.mainframe.DesignerContext;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.Filter;
import com.fr.stable.StringUtils;
import javax.swing.JOptionPane;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.util.Enumeration;
/**
* 实现模糊搜索表名的FRTreeComboBox
* FRTreeComboBox搜索后滚动到首个匹配节点
* SearchFRTreeComboBox显示所有匹配的节点
*
* @author Lucian.Chen
* @version 10.0
* Created by Lucian.Chen on 2021/4/14
*/
public class TableSearchTreeComboBox extends FRTreeComboBox {
// 持有父容器,需要实时获取其他组件值
private final ChoosePane parent;
public TableSearchTreeComboBox(ChoosePane parent, JTree tree, TreeCellRenderer renderer) {
super(tree, renderer);
this.parent = parent;
initPopupListener();
}
protected UIComboBoxEditor createEditor() {
return new TableSearchComboBoxEditor(this);
}
@Override
protected String pathToString(TreePath path) {
Object obj = ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject();
if (obj instanceof TableProcedure) {
return ((TableProcedure) obj).getName();
}
return super.pathToString(path);
}
@Override
public void setSelectedItemString(String _name) {
super.setSelectedItemString(_name);
// 会因为连续两次选中的值一致,导致未触发编辑框联动
this.getEditor().setItem(_name);
}
/**
* 执行模糊搜索
*/
private void searchExecute() {
UIComboBoxEditor searchEditor = (UIComboBoxEditor) this.getEditor();
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() {
processTableDataNames(
parent.getDSName(),
parent.getConnection(),
parent.getSchema(),
createFilter((String) searchEditor.getItem()));
return null;
}
@Override
protected void done() {
expandTree();
// 输入框获取焦点
searchEditor.getEditorComponent().requestFocus();
}
}.execute();
}
private TableNameFilter createFilter(String text) {
return StringUtils.isEmpty(text) ? EMPTY_FILTER : new TableNameFilter(text);
}
/**
* 查询数据库表并构建节点目录
*
* @param databaseName 数据库名
* @param connection 数据连接
* @param schema 模式
* @param filter 模糊搜索过滤器
*/
private void processTableDataNames(String databaseName, Connection connection, String schema, TableNameFilter filter) {
if (tree == null) {
return;
}
DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot();
rootTreeNode.removeAllChildren();
if (connection == null) {
return;
}
try {
schema = StringUtils.isEmpty(schema) ? null : schema;
TableProcedure[] sqlTableArray = DataCoreUtils.getTables(connection, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace());
if (ArrayUtils.isNotEmpty(sqlTableArray)) {
ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table"));
rootTreeNode.add(tableTreeNode);
addArrayNode(tableTreeNode, sqlTableArray, filter);
}
TableProcedure[] sqlViewArray = DataCoreUtils.getTables(connection, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace());
if (ArrayUtils.isNotEmpty(sqlViewArray)) {
ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View"));
rootTreeNode.add(viewTreeNode);
addArrayNode(viewTreeNode, sqlViewArray, filter);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE);
}
}
private void addArrayNode(ExpandMutableTreeNode rootNode, TableProcedure[] sqlArray, TableNameFilter filter) {
if (sqlArray != null) {
for (TableProcedure procedure : sqlArray) {
if (filter.accept(procedure)) {
ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(procedure);
rootNode.add(viewChildTreeNode);
}
}
}
}
/**
* 展开节点
*/
private void expandTree() {
((DefaultTreeModel) tree.getModel()).reload();
// daniel 展开所有tree
TreeNode root = (TreeNode) tree.getModel().getRoot();
TreePath parent = new TreePath(root);
TreeNode node = (TreeNode) parent.getLastPathComponent();
for (Enumeration e = node.children(); e.hasMoreElements(); ) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
tree.expandPath(path);
}
}
/**
* 表名模糊搜索实现
*/
private static class TableNameFilter implements Filter<TableProcedure> {
private String searchFilter;
public TableNameFilter() {
}
public TableNameFilter(String searchFilter) {
this.searchFilter = searchFilter.toLowerCase().trim();
}
// 表名匹配
@Override
public boolean accept(TableProcedure procedure) {
return procedure.getName().toLowerCase().contains(searchFilter);
}
}
private static final TableNameFilter EMPTY_FILTER = new TableNameFilter() {
public boolean accept(TableProcedure procedure) {
return true;
}
};
private void initPopupListener() {
// 点击下拉时触发模糊搜索
this.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
searchExecute();
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
}
/**
* 重写输入框编辑器实现输入框模糊搜索逻辑
*/
private class TableSearchComboBoxEditor extends FrTreeSearchComboBoxEditor {
public TableSearchComboBoxEditor(FRTreeComboBox comboBox) {
super(comboBox);
}
@Override
protected void changeHandler() {
if (isSetting()) {
return;
}
setPopupVisible(true);
this.item = textField.getText();
searchExecute();
}
}
}

25
designer-base/src/main/java/com/fr/design/gui/ifilechooser/ExtensionFilter.java

@ -0,0 +1,25 @@
package com.fr.design.gui.ifilechooser;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/12/29
*/
public class ExtensionFilter {
private final String des;
private final String[] extensions;
public ExtensionFilter(String des, String... extensions) {
this.des = des;
this.extensions = extensions;
}
public String getDes() {
return des;
}
public String[] getExtensions() {
return extensions;
}
}

109
designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserArgs.java

@ -0,0 +1,109 @@
package com.fr.design.gui.ifilechooser;
/**
* 文件选择器可设置的参数集合
*
* @author hades
* @version 10.0
* Created by hades on 2021/12/21
*/
public class FileChooserArgs {
private final FileSelectionMode fileSelectionMode;
private final String filterDes;
private final String[] extensions;
private final String selectedPath;
private final ExtensionFilter[] filters;
private final String tipText;
private final boolean multiSelectionEnabled;
public static Builder newBuilder() {
return new Builder();
}
private FileChooserArgs(Builder builder) {
this.fileSelectionMode = builder.fileSelectionMode;
this.filterDes = builder.filterDes;
this.extensions = builder.extensions;
this.selectedPath = builder.selectedPath;
this.filters = builder.filters;
this.tipText = builder.tipText;
this.multiSelectionEnabled = builder.multiSelectionEnabled;
}
public FileSelectionMode getFileSelectionMode() {
return fileSelectionMode;
}
public String getFilterDes() {
return filterDes;
}
public String[] getExtensions() {
return extensions;
}
public String getSelectedPath() {
return selectedPath;
}
public ExtensionFilter[] getFilters() {
return filters;
}
public String getTipText() {
return tipText;
}
public boolean isMultiSelectionEnabled() {
return multiSelectionEnabled;
}
public static class Builder {
private FileSelectionMode fileSelectionMode;
private String filterDes;
private String[] extensions;
private String selectedPath;
private ExtensionFilter[] filters = new ExtensionFilter[0];
private String tipText;
private boolean multiSelectionEnabled;
public Builder setFileSelectionMode(FileSelectionMode fileSelectionMode) {
this.fileSelectionMode = fileSelectionMode;
return this;
}
public Builder setFilter(String filterDes, String... extensions) {
this.filterDes = filterDes;
this.extensions = extensions;
return this;
}
public Builder setSelectedPath(String selectedPath) {
this.selectedPath = selectedPath;
return this;
}
public Builder setFilters(ExtensionFilter[] filters) {
this.filters = filters;
return this;
}
public Builder setTipText(String tipText) {
this.tipText = tipText;
return this;
}
public Builder setMultiSelectionEnabled(boolean multiSelectionEnabled) {
this.multiSelectionEnabled = multiSelectionEnabled;
return this;
}
public FileChooserArgs build() {
return new FileChooserArgs(this);
}
}
}

44
designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserFactory.java

@ -0,0 +1,44 @@
package com.fr.design.gui.ifilechooser;
import com.fr.design.i18n.Toolkit;
import com.fr.design.os.impl.SupportOSImpl;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/12/21
*/
public class FileChooserFactory {
public static FileChooserProvider createFileChooser(FileChooserArgs fileChooserArgs) {
if (SupportOSImpl.OLD_STYLE_CHOOSER.support()) {
return new SwingFileChooser.Builder().
setFileSelectionMode(fileChooserArgs.getFileSelectionMode()).
setFileFilter(fileChooserArgs.getFilterDes(), fileChooserArgs.getExtensions()).
setSelectedFile(fileChooserArgs.getSelectedPath()).
setMultiSelectionEnabled(fileChooserArgs.isMultiSelectionEnabled()).
setTipText(fileChooserArgs.getTipText()).
setFileFilter(fileChooserArgs.getFilters()).build();
} else {
return new JavaFxNativeFileChooser.Builder().
fileSelectionMode(fileChooserArgs.getFileSelectionMode()).
filter(fileChooserArgs.getFilterDes(), fileChooserArgs.getExtensions()).
currentDirectory(fileChooserArgs.getSelectedPath()).
title(fileChooserArgs.getTipText()).
filters(fileChooserArgs.getFilters()).build();
}
}
public static FileChooserProvider createImageFileChooser() {
if (SupportOSImpl.OLD_STYLE_CHOOSER.support()) {
return new SwingImageFileChooser();
} else {
return new JavaFxNativeFileChooser.Builder().
fileSelectionMode(FileSelectionMode.FILE).
title(Toolkit.i18nText("Fine-Design_Basic_Open")).
filter(Toolkit.i18nText("Fine-Design_Basic_Image_Image_Files"), "*.jpg", "*.gif", "*.png", "*.bmp").
build();
}
}
}

13
designer-base/src/main/java/com/fr/design/gui/ifilechooser/FileChooserProvider.java

@ -9,4 +9,17 @@ public interface FileChooserProvider {
File getSelectedFile();
int showDialog(Component parent);
default int showOpenDialog(Component parent, String approveButtonText) {
return -1;
}
default void setMultiSelectionEnabled(boolean multiple) {
}
default void setCurrentDirectory(File file) {
}
}

33
designer-base/src/main/java/com/fr/design/gui/ifilechooser/JavaFxNativeFileChooser.java

@ -4,6 +4,8 @@ package com.fr.design.gui.ifilechooser;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StringUtils;
import com.sun.javafx.application.PlatformImpl;
import javafx.application.Platform;
import javafx.scene.Scene;
@ -173,10 +175,20 @@ public class JavaFxNativeFileChooser implements FileChooserProvider {
this.fileSelectionMode = fileSelectionMode;
}
@Override
public void setCurrentDirectory(File currentDirectory) {
this.currentDirectory = currentDirectory;
}
@Override
public void setMultiSelectionEnabled(boolean multiple) {
this.setSelectionMode(multiple ? FileSelectionMode.MULTIPLE_FILE : FileSelectionMode.FILE);
}
@Override
public int showOpenDialog(Component parent, String approveButtonText) {
return this.showDialog(parent);
}
public static class Builder {
private FileSelectionMode fileSelectionMode = FileSelectionMode.FILE;
@ -185,17 +197,32 @@ public class JavaFxNativeFileChooser implements FileChooserProvider {
private File currentDirectory;
public Builder fileSelectionMode(FileSelectionMode fileSelectionMode) {
this.fileSelectionMode = fileSelectionMode;
if (fileSelectionMode != null) {
this.fileSelectionMode = fileSelectionMode;
}
return this;
}
public Builder title(String title) {
this.title = title;
if (StringUtils.isNotEmpty(title)) {
this.title = title;
}
return this;
}
public Builder filters(FileChooser.ExtensionFilter[] filters) {
this.filters = filters;
if (filters != null) {
this.filters = filters;
}
return this;
}
public Builder filters(ExtensionFilter[] filters) {
if (filters != null) {
for (ExtensionFilter filter : filters) {
this.filters = ArrayUtils.add(this.filters, new FileChooser.ExtensionFilter(filter.getDes(), filter.getExtensions()));
}
}
return this;
}

130
designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingFileChooser.java

@ -0,0 +1,130 @@
package com.fr.design.gui.ifilechooser;
import com.fr.common.annotations.Negative;
import com.fr.design.upm.UpmUtils;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StringUtils;
import java.awt.Component;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/12/21
*/
@Negative(until = "2022-6-1")
class SwingFileChooser implements FileChooserProvider {
private final JFileChooser fileChooser;
private final Builder builder;
private SwingFileChooser(Builder builder) {
fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(builder.fileSelectionMode);
fileChooser.setFileFilter(builder.fileFilter);
fileChooser.setSelectedFile(builder.selectedFile);
fileChooser.setMultiSelectionEnabled(builder.multiSelectionEnabled);
this.builder = builder;
}
@Override
public File[] getSelectedFiles() {
return fileChooser.getSelectedFiles();
}
@Override
public File getSelectedFile() {
return fileChooser.getSelectedFile();
}
@Override
public int showDialog(Component parent) {
if (StringUtils.isEmpty(builder.tipText)) {
return fileChooser.showOpenDialog(parent);
} else {
return fileChooser.showDialog(parent, builder.tipText);
}
}
@Override
public int showOpenDialog(Component parent, String approveButtonText) {
return fileChooser.showDialog(parent, approveButtonText);
}
@Override
public void setCurrentDirectory(File file) {
fileChooser.setCurrentDirectory(file);
}
@Override
public void setMultiSelectionEnabled(boolean multiple) {
fileChooser.setMultiSelectionEnabled(multiple);
}
/**
* 和一般builder不同的是 setXXX还做参数转换逻辑
*/
public static class Builder {
private int fileSelectionMode = JFileChooser.FILES_ONLY;
private FileFilter fileFilter;
private File selectedFile;
private boolean multiSelectionEnabled;
private String tipText;
public Builder setFileSelectionMode(FileSelectionMode fileSelectionMode) {
if (FileSelectionMode.DIR.equals(fileSelectionMode)) {
this.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY;
} else if (FileSelectionMode.FILE.equals(fileSelectionMode)) {
this.fileSelectionMode = JFileChooser.FILES_ONLY;
} else if (FileSelectionMode.MULTIPLE_FILE.equals(fileSelectionMode)) {
this.fileSelectionMode = JFileChooser.FILES_AND_DIRECTORIES;
}
return this;
}
public Builder setFileFilter(String des, String... extension) {
if (StringUtils.isNotEmpty(des) && ArrayUtils.isNotEmpty(extension)) {
this.fileFilter = new FileNameExtensionFilter(des, UpmUtils.findMatchedExtension(extension));
}
return this;
}
public Builder setFileFilter(ExtensionFilter[] extensionFilters) {
StringBuilder desBuilder = new StringBuilder();
String[] extensions = new String[0];
for (ExtensionFilter extensionFilter : extensionFilters) {
desBuilder.append(extensionFilter.getDes()).append(" ");
extensions = ArrayUtils.addAll(extensions, UpmUtils.findMatchedExtension(extensionFilter.getExtensions()));
}
if (ArrayUtils.isNotEmpty(extensionFilters)) {
this.fileFilter = new FileNameExtensionFilter(desBuilder.toString().trim(), extensions);
}
return this;
}
public Builder setSelectedFile(String selectedPath) {
if (StringUtils.isNotEmpty(selectedPath)) {
this.selectedFile = new File(selectedPath);
}
return this;
}
public Builder setMultiSelectionEnabled(boolean multiSelectionEnabled) {
this.multiSelectionEnabled = multiSelectionEnabled;
return this;
}
public Builder setTipText(String tipText) {
this.tipText = tipText;
return this;
}
public SwingFileChooser build() {
return new SwingFileChooser(this);
}
}
}

276
designer-base/src/main/java/com/fr/design/gui/ifilechooser/SwingImageFileChooser.java

@ -0,0 +1,276 @@
package com.fr.design.gui.ifilechooser;
import com.fr.base.BaseUtils;
import com.fr.common.annotations.Negative;
import com.fr.design.DesignerEnvManager;
import com.fr.design.style.ChooseFileView;
import com.fr.design.style.background.image.ExpandFileChooser;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.filechooser.FileFilter;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/12/30
*/
@Negative(until = "2022-6-1")
class SwingImageFileChooser extends ExpandFileChooser implements FileChooserProvider {
public SwingImageFileChooser() {
super(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Image_Compress"),com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Open"));
ExampleFileFilter bothFilter = new ExampleFileFilter(
new String[]{"jpg", "gif", "png", "bmp"},
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Image_Image_Files"));
bothFilter.setExtensionListInDescription(true);
this.addChoosableFileFilter(bothFilter);
this.setAcceptAllFileFilterUsed(false);
// Create Custom FileView
ChooseFileView fileView = new ChooseFileView();
fileView.putIcon("jpg", BaseUtils.readIcon("/com/fr/base/images/dialog/file/jpgFile.gif"));
fileView.putIcon("gif", BaseUtils.readIcon("/com/fr/base/images/dialog/file/gifFile.gif"));
fileView.putIcon("png", BaseUtils.readIcon("/com/fr/base/images/dialog/file/pngFile.png"));
fileView.putIcon("bmp", BaseUtils.readIcon("/com/fr/base/images/dialog/file/bmpFile.gif"));
this.setFileView(fileView);
}
@Override
public int showDialog(Component parent, String approveButtonText) {
return super.showDialog(parent, approveButtonText);
}
@Override
public ActionListener checkAction() {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DesignerEnvManager.getEnvManager().setImageCompress(isCheckSelected());
DesignerEnvManager.getEnvManager().saveXMLFile();
}
};
}
@Override
public int showDialog(Component parent) {
return showOpenDialog(parent);
}
/**
* A convenience implementation of FileFilter that filters out
* all files except for those type extensions that it knows about.
* <p/>D:\finereport\develop\code\test\TestCase\WEB-INF\reportlets\TestCase\01903.cpt
* <p>
* Extensions are of the type ".foo", which is typically found on
* Windows and Unix boxes, but not on Macinthosh. Case is ignored.
* <p/>
* Example - create a new filter that filerts out all files
* but gif and jpg image files:
* <p/>
* JFileChooser chooser = new JFileChooser();
* ExampleFileFilter filter = new ExampleFileFilter(
* new String{"gif", "jpg"}, "JPEG & GIF Images")
* chooser.addChoosableFileFilter(filter);
* chooser.showOpenDialog(this);
*
* @author Jeff Dinkins
* @version 1.12 12/03/01
*/
class ExampleFileFilter extends FileFilter {
private Hashtable filters = null;
private String description = null;
private String fullDescription = null;
private boolean useExtensionsInDescription = true;
/**
* Creates a file filter. If no filters are added, then all
* files are accepted.
*
* @see #addExtension
*/
public ExampleFileFilter() {
this.filters = new Hashtable();
}
/**
* Creates a file filter that accepts files with the given extension.
* Example: new ExampleFileFilter("jpg");
*
* @see #addExtension
*/
public ExampleFileFilter(String extension) {
this(extension, null);
}
/**
* Creates a file filter that accepts the given file type.
* Example: new ExampleFileFilter("jpg", "JPEG Image Images");
* <p/>
* Note that the "." before the extension is not needed. If
* provided, it will be ignored.
*
* @see #addExtension
*/
public ExampleFileFilter(String extension, String description) {
this();
if (extension != null) addExtension(extension);
if (description != null) setDescription(description);
}
/**
* Creates a file filter from the given string array.
* Example: new ExampleFileFilter(String {"gif", "jpg"});
* <p/>
* Note that the "." before the extension is not needed adn
* will be ignored.
*
* @see #addExtension
*/
public ExampleFileFilter(String[] filters) {
this(filters, null);
}
/**
* Creates a file filter from the given string array and description.
* Example: new ExampleFileFilter(String {"gif", "jpg"}, "Gif and JPG Images");
* <p/>
* Note that the "." before the extension is not needed and will be ignored.
*
* @see #addExtension
*/
public ExampleFileFilter(String[] filters, String description) {
this();
for (int i = 0; i < filters.length; i++) {
// add filters one by one
addExtension(filters[i]);
}
if (description != null) setDescription(description);
}
/**
* Return true if this file should be shown in the directory pane,
* false if it shouldn't.
* <p/>
* Files that begin with "." are ignored.
*
* @see #getExtension
*/
@Override
public boolean accept(File f) {
if (f != null) {
if (f.isDirectory()) {
return true;
}
String extension = getExtension(f);
if (extension != null && filters.get(getExtension(f)) != null) {
return true;
}
}
return false;
}
/**
* Return the extension portion of the file's name .
*
* @see #getExtension
* @see FileFilter#accept
*/
public String getExtension(File f) {
if (f != null) {
String filename = f.getName();
int i = filename.lastIndexOf('.');
if (i > 0 && i < filename.length() - 1) {
return filename.substring(i + 1).toLowerCase();
}
}
return null;
}
/**
* Adds a filetype "dot" extension to filter against.
* <p/>
* For example: the following code will create a filter that filters
* out all files except those that end in ".jpg" and ".tif":
* <p/>
* ExampleFileFilter filter = new ExampleFileFilter();
* filter.addExtension("jpg");
* filter.addExtension("tif");
* <p/>
* Note that the "." before the extension is not needed and will be ignored.
*/
public void addExtension(String extension) {
if (filters == null) {
filters = new Hashtable(5);
}
filters.put(extension.toLowerCase(), this);
fullDescription = null;
}
/**
* Returns the human readable description of this filter. For
* example: "JPEG and GIF Image Files (*.jpg, *.gif)"
*
* @see FileFilter#getDescription
*/
@Override
public String getDescription() {
if (fullDescription == null) {
if (description == null || isExtensionListInDescription()) {
fullDescription = description == null ? "(" : description + " (";
// build the description from the extension list
Enumeration extensions = filters.keys();
if (extensions != null) {
fullDescription += "." + extensions.nextElement();
while (extensions.hasMoreElements()) {
fullDescription += ", ." + extensions.nextElement();
}
}
fullDescription += ")";
} else {
fullDescription = description;
}
}
return fullDescription;
}
/**
* Sets the human readable description of this filter. For
* example: filter.setDescription("Gif and JPG Images");
*/
public void setDescription(String description) {
this.description = description;
fullDescription = null;
}
/**
* Determines whether the extension list (.jpg, .gif, etc) should
* show up in the human readable description.
* <p/>
* Only relevent if a description was provided in the constructor
* or using setDescription();
*/
public void setExtensionListInDescription(boolean b) {
useExtensionsInDescription = b;
fullDescription = null;
}
/**
* Returns whether the extension list (.jpg, .gif, etc) should
* show up in the human readable description.
* <p/>
* Only relevent if a description was provided in the constructor
* or using setDescription();
*/
public boolean isExtensionListInDescription() {
return useExtensionsInDescription;
}
}
}

78
designer-base/src/main/java/com/fr/design/gui/ilable/UIAutoChangeLineLabel.java

@ -0,0 +1,78 @@
package com.fr.design.gui.ilable;
import javax.swing.JLabel;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.util.ArrayList;
import java.util.List;
public class UIAutoChangeLineLabel extends JLabel {
private final String text;
private final int width;
public UIAutoChangeLineLabel(String text, int width) {
super(text);
this.text = text;
this.width = width;
}
@Override
public void doLayout() {
super.doLayout();
this.setText(wrapperHtmlText());
}
private String wrapperHtmlText() {
List<String> stringList = autoChangeLine(this.getWidth());
StringBuilder builder = new StringBuilder("<html>");
for (String s : stringList) {
//用THML标签进行拼接,以实现自动换行
builder.append(s).append("<br/>");
}
builder.append("</html>");
return builder.toString();
}
private List<String> autoChangeLine(int width) {
List<String> result = new ArrayList<>();
if (width <= 0) {
result.add(this.text);
} else {
char[] chars = this.text.toCharArray();
//获取字体计算大小
FontMetrics fontMetrics = this.getFontMetrics(this.getFont());
int start = 0;
int len = 0;
while (start + len < this.text.length()) {
while (true) {
len++;
if (start + len > this.text.length())
break;
if (fontMetrics.charsWidth(chars, start, len)
> width) {
break;
}
}
result.add(String.copyValueOf(chars, start, len - 1));
start = start + len - 1;
len = 0;
}
if (this.text.length() - start > 0) {
result.add(String.copyValueOf(chars, start, this.text.length() - start));
}
}
return result;
}
@Override
public Dimension getPreferredSize() {
Dimension preferredSize = super.getPreferredSize();
List<String> stringList = autoChangeLine(width);
FontMetrics fontMetrics = this.getFontMetrics(this.getFont());
return new Dimension(preferredSize.width, fontMetrics.getHeight() * stringList.size());
}
}

8
designer-base/src/main/java/com/fr/design/gui/iprogressbar/ProgressDialog.java

@ -31,22 +31,22 @@ public class ProgressDialog extends UIDialog {
super(parent);
setUndecorated(true);
setSize(parent.getSize());
setLocationRelativeTo(null);
setLocation(parent.getLocation());
OSSupportCenter.buildAction(new OSBasedAction() {
@Override
public void execute(Object... objects) {
setOpacity(0.5f);
}
}, SupportOSImpl.OPACITY);
initComponent();
initComponent(parent);
}
private void initComponent() {
private void initComponent(Frame parent) {
centerDialog = new JDialog(this);
centerDialog.setSize(new Dimension(482, 124));
centerDialog.setUndecorated(true);
GUICoreUtils.centerWindow(centerDialog);
centerDialog.setLocationRelativeTo(parent);
JPanel panel = new JPanel();
panel.setBorder(new UIProgressBorder(3, UIConstants.DEFAULT_BG_RULER, 14, 46, 47, 37, 47));
panel.setLayout(new BorderLayout(4, 15));

7
designer-base/src/main/java/com/fr/design/gui/itextfield/UIAutoCompletionField.java

@ -256,10 +256,9 @@ public class UIAutoCompletionField extends UITextField implements DocumentListen
*
*/
public void setText(String t) {
if (this.isOpen == true) {
if (!UIAutoCompletionField.this.isShowing()) {
return;
}
boolean unavailable = !this.isEnabled() && !this.isEditable();
if (unavailable) {
return;
}
try {
Document doc = getDocument();

113
designer-base/src/main/java/com/fr/design/gui/style/BorderPane.java

@ -4,7 +4,6 @@ package com.fr.design.gui.style;
* Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
*/
import com.fr.base.BaseUtils;
import com.fr.base.CellBorderStyle;
import com.fr.base.Style;
import com.fr.design.constants.LayoutConstants;
@ -17,14 +16,21 @@ import com.fr.design.gui.ilable.UILabel;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.design.style.color.NewColorSelectBox;
import com.fr.design.utils.gui.AdjustWorkBookDefaultStyleUtils;
import com.fr.general.IOUtils;
import com.fr.stable.Constants;
import com.fr.stable.CoreConstants;
import javax.swing.*;
import javax.swing.Icon;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@ -38,7 +44,6 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse
private static final String[] BORDERARRAY = {"currentLineCombo", "currentLineColorPane", "outerToggleButton", "topToggleButton",
"leftToggleButton", "bottomToggleButton", "rightToggleButton", "innerToggleButton", "horizontalToggleButton", "verticalToggleButton"};
private static final Set<String> BORDER_SET = new HashSet<>(Arrays.asList(BORDERARRAY));
private boolean insideMode = false;
private UIToggleButton topToggleButton;
private UIToggleButton horizontalToggleButton;
@ -50,11 +55,8 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse
private UIToggleButton innerToggleButton;
private UIToggleButton outerToggleButton;
private LineComboBox currentLineCombo;
private NewColorSelectBox currentLineColorPane;
private JPanel panel;
private JPanel borderPanel;
private JPanel backgroundPanel;
protected LineComboBox currentLineCombo;
protected NewColorSelectBox currentLineColorPane;
private BackgroundPane backgroundPane;
private GlobalNameListener globalNameListener = null;
@ -81,18 +83,18 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse
new Component[]{null, null},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Color") + " ", SwingConstants.LEFT), currentLineColorPane},
new Component[]{null, null},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Out_Border") + " ", SwingConstants.LEFT), outerToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("com/fr/design/images/m_format/out.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/out_white.png")}, false)},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Out_Border") + " ", SwingConstants.LEFT), outerToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("com/fr/design/images/m_format/out.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/out_white.png")}, false)},
new Component[]{null, externalPane},
new Component[]{null, null},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_In_Border") + " ", SwingConstants.LEFT), innerToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("com/fr/design/images/m_format/in.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/in_white.png")}, false)},
new Component[]{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_In_Border") + " ", SwingConstants.LEFT), innerToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("com/fr/design/images/m_format/in.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/in_white.png")}, false)},
new Component[]{null, insidePane},
new Component[]{null, null}
};
double[] rowSize = {p, p, p, p, p, p, p, p, p, p, p};
double[] columnSize = {p, f};
int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}};
panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_SMALL, LayoutConstants.VGAP_MEDIUM);
borderPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Border"), 280, 24, panel);
JPanel panel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_SMALL, LayoutConstants.VGAP_MEDIUM);
JPanel borderPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Border"), 280, 24, panel);
this.add(borderPanel, BorderLayout.NORTH);
UILabel backgroundFillLabel = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Background_Fill"));
@ -102,7 +104,7 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse
JPanel backgroundContainPane = TableLayoutHelper.createGapTableLayoutPane(new Component[][]{new Component[]{backgroundFillLabel, backgroundPane}},
TableLayoutHelper.FILL_LASTCOLUMN, LayoutConstants.VGAP_SMALL, LayoutConstants.VGAP_MEDIUM);
backgroundPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background"), 280, 24, backgroundContainPane);
JPanel backgroundPanel = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Background"), 280, 24, backgroundContainPane);
this.add(backgroundPanel, BorderLayout.CENTER);
initAllNames();
outerToggleButton.addChangeListener(outerToggleButtonChangeListener);
@ -130,12 +132,12 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse
};
private void initButtonsWithIcon() {
topToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/top.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/top_white.png")}, false);
leftToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/left.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/left_white.png")}, false);
bottomToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/bottom.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bottom_white.png")}, false);
rightToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/right.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/right_white.png")}, false);
horizontalToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/horizontal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/horizontal_white.png")}, false);
verticalToggleButton = new UIToggleButton(new Icon[]{BaseUtils.readIcon("/com/fr/base/images/dialog/border/vertical.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/vertical_white.png")}, false);
topToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/top.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/top_white.png")}, false);
leftToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/left.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/left_white.png")}, false);
bottomToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/bottom.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bottom_white.png")}, false);
rightToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/right.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/right_white.png")}, false);
horizontalToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/horizontal.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/horizontal_white.png")}, false);
verticalToggleButton = new UIToggleButton(new Icon[]{IOUtils.readIcon("/com/fr/base/images/dialog/border/vertical.png"), IOUtils.readIcon("/com/fr/design/images/m_format/cellstyle/vertical_white.png")}, false);
this.currentLineCombo = new LineComboBox(CoreConstants.UNDERLINE_STYLE_ARRAY);
this.currentLineColorPane = new NewColorSelectBox(100);
}
@ -174,15 +176,15 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse
cellBorderStyle.setRightStyle(style.getBorderRight());
cellBorderStyle.setRightColor(style.getBorderRightColor());
this.backgroundPane.populateBean(style.getBackground());
this.populateBean(cellBorderStyle, false, style.getBorderTop(), style.getBorderTopColor());
this.populateBean(cellBorderStyle, false);
}
public void populateBean(CellBorderStyle cellBorderStyle, boolean insideMode, int currentStyle, Color currentColor) {
this.insideMode = insideMode;
public void populateBean(CellBorderStyle cellBorderStyle, boolean insideMode) {
populateBean(cellBorderStyle, insideMode, true);
}
this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getTopStyle() == Constants.LINE_NONE ? Constants.LINE_THIN : cellBorderStyle.getTopStyle());
this.currentLineColorPane.setSelectObject(cellBorderStyle.getTopColor());
public void populateBean(CellBorderStyle cellBorderStyle, boolean insideMode, boolean onlyInspectTop) {
this.topToggleButton.setSelected(cellBorderStyle.getTopStyle() != Constants.LINE_NONE);
this.bottomToggleButton.setSelected(cellBorderStyle.getBottomStyle() != Constants.LINE_NONE);
@ -195,16 +197,53 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse
this.innerToggleButton.setSelected(cellBorderStyle.getInnerBorder() != Constants.LINE_NONE);
this.outerToggleButton.setSelected(cellBorderStyle.getOuterBorderStyle() != Constants.LINE_NONE);
this.innerToggleButton.setEnabled(this.insideMode);
this.horizontalToggleButton.setEnabled(this.insideMode);
this.verticalToggleButton.setEnabled(this.insideMode);
this.innerToggleButton.setEnabled(insideMode);
this.horizontalToggleButton.setEnabled(insideMode);
this.verticalToggleButton.setEnabled(insideMode);
populateLineStyleAndColor(cellBorderStyle, onlyInspectTop);
}
public void populateLineStyleAndColor(CellBorderStyle cellBorderStyle, boolean onlyInspectTop) {
resetLineStyleAndColorSetting();
if (cellBorderStyle.getTopStyle() != Constants.LINE_NONE) {
this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getTopStyle());
this.currentLineColorPane.setSelectObject(cellBorderStyle.getTopColor());
} else if (!onlyInspectTop) {
if (cellBorderStyle.getBottomStyle() != Constants.LINE_NONE) {
this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getBottomStyle());
this.currentLineColorPane.setSelectObject(cellBorderStyle.getBottomColor());
} else if (cellBorderStyle.getLeftStyle() != Constants.LINE_NONE) {
this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getLeftStyle());
this.currentLineColorPane.setSelectObject(cellBorderStyle.getLeftColor());
} else if (cellBorderStyle.getRightStyle() != Constants.LINE_NONE) {
this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getRightStyle());
this.currentLineColorPane.setSelectObject(cellBorderStyle.getRightColor());
} else if (cellBorderStyle.getVerticalStyle() != Constants.LINE_NONE) {
this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getVerticalStyle());
this.currentLineColorPane.setSelectObject(cellBorderStyle.getVerticalColor());
} else if (cellBorderStyle.getHorizontalStyle() != Constants.LINE_NONE) {
this.currentLineCombo.setSelectedLineStyle(cellBorderStyle.getHorizontalStyle());
this.currentLineColorPane.setSelectObject(cellBorderStyle.getHorizontalColor());
}
}
if (this.currentLineCombo.getSelectedLineStyle() == Constants.LINE_NONE) {
this.currentLineCombo.setSelectedLineStyle(Constants.LINE_THIN);
}
}
private void resetLineStyleAndColorSetting() {
this.currentLineCombo.setSelectedLineStyle(Constants.LINE_NONE);
this.currentLineColorPane.setSelectObject(null);
}
@Override
public Style update(Style style) {
if (style == null) {
style = Style.DEFAULT_STYLE;
style = AdjustWorkBookDefaultStyleUtils.adjustCellElement(Style.DEFAULT_STYLE);
}
if (backgroundPane.currentPane.isBackgroundChange()) {
@ -213,7 +252,7 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse
if (BORDER_SET.contains(globalNameListener.getGlobalName())) {
CellBorderStyle cellBorderStyle = this.update();
style = style.deriveBorder(cellBorderStyle.getTopStyle(), cellBorderStyle.getTopColor(), cellBorderStyle.getBottomStyle(), cellBorderStyle.getBottomColor(),
cellBorderStyle.getLeftStyle(), cellBorderStyle.getLeftColor(), cellBorderStyle.getRightStyle(), cellBorderStyle.getRightColor());
cellBorderStyle.getLeftStyle(), cellBorderStyle.getLeftColor(), cellBorderStyle.getRightStyle(), cellBorderStyle.getRightColor());
}
return style;
@ -253,16 +292,8 @@ public class BorderPane extends AbstractBasicStylePane implements GlobalNameObse
}
cellBorderStyle.setHorizontalStyle(horizontalToggleButton.isSelected() ? lineStyle : Constants.LINE_NONE);
if (leftToggleButton.isSelected() && bottomToggleButton.isSelected() && rightToggleButton.isSelected() && topToggleButton.isSelected()) {
outerToggleButton.setSelected(true);
} else {
outerToggleButton.setSelected(false);
}
if (verticalToggleButton.isSelected() && horizontalToggleButton.isSelected()) {
innerToggleButton.setSelected(true);
} else {
innerToggleButton.setSelected(false);
}
outerToggleButton.setSelected(leftToggleButton.isSelected() && bottomToggleButton.isSelected() && rightToggleButton.isSelected() && topToggleButton.isSelected());
innerToggleButton.setSelected(verticalToggleButton.isSelected() && horizontalToggleButton.isSelected());
return cellBorderStyle;
}

235
designer-base/src/main/java/com/fr/design/gui/style/TextFormatPane.java

@ -7,7 +7,6 @@ import com.fr.base.TextFormat;
import com.fr.data.core.FormatField;
import com.fr.data.core.FormatField.FormatContents;
import com.fr.design.border.UIRoundedBorder;
import com.fr.design.constants.LayoutConstants;
import com.fr.design.constants.UIConstants;
import com.fr.design.event.GlobalNameListener;
import com.fr.design.event.GlobalNameObserver;
@ -18,21 +17,18 @@ import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icombobox.UIComboBoxRenderer;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
import com.fr.general.ComparatorUtils;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
@ -43,7 +39,6 @@ import java.awt.event.ItemListener;
import java.math.RoundingMode;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Arrays;
/**
* @author Starryi
@ -68,69 +63,45 @@ public class TextFormatPane extends AbstractBasicStylePane implements GlobalName
private static final Integer[] DATE_TYPES = new Integer[]{FormatContents.NULL, FormatContents.DATE, FormatContents.TIME};
private Format format;
private UIComboBox typeComboBox;
private TextFontComboBox textField;
private UILabel sampleLabel;
private JPanel contentPane;
private JPanel txtCenterPane;
private JPanel centerPane;
private JPanel optionPane;
private UICheckBox roundingBox;
private JPanel formatFontPane;
protected UIComboBox typeComboBox;
protected TextFontComboBox<String> textField;
protected UICheckBox roundingBox;
protected UILabel previewLabel;
private boolean isRightFormat;
private boolean isDate = false;
private GlobalNameListener globalNameListener = null;
/**
* Constructor.
*/
public TextFormatPane() {
this.initComponents(TYPES);
}
protected UIComboBox getTypeComboBox() {
return typeComboBox;
initFormatTypesComboBox();
initTextFontComboBox4GeneralFormats();
initRoundingCheckBox4PercentFormat();
initPreviewLabel4GeneralFormat();
initLayout();
setTextFieldVisible(false);
setRoundingBoxVisible(false);
setPreviewLabelVisible(false);
}
protected void initComponents(Integer[] types) {
this.setLayout(new BorderLayout(0, 4));
initSampleLabel();
contentPane = new JPanel(new BorderLayout(0, 4)) {
@Override
public Dimension getPreferredSize() {
return new Dimension(super.getPreferredSize().width, 65);
}
};
typeComboBox = new UIComboBox(types);
UIComboBoxRenderer render = createComBoxRender();
typeComboBox.setRenderer(render);
private void initFormatTypesComboBox() {
typeComboBox = new UIComboBox(TextFormatPane.TYPES);
typeComboBox.setRenderer(createComBoxRender());
typeComboBox.addItemListener(itemListener);
typeComboBox.setGlobalName("typeComboBox");
contentPane.add(sampleLabel, BorderLayout.NORTH);
typeComboBox.setPreferredSize(new Dimension(155,20));
}
txtCenterPane = new JPanel(new BorderLayout());
textField = new TextFontComboBox();
private void initTextFontComboBox4GeneralFormats() {
textField = new TextFontComboBox<>();
textField.addItemListener(textFieldItemListener);
textField.setEditable(true);
textField.setGlobalName("textField");
txtCenterPane.add(textField, BorderLayout.NORTH);
contentPane.add(txtCenterPane, BorderLayout.CENTER);
centerPane = new JPanel(new CardLayout());
centerPane.add(new JPanel(), "hide");
centerPane.setPreferredSize(new Dimension(0, 0));
centerPane.add(contentPane, "show");
typeComboBox.setPreferredSize(new Dimension(155,20));
JPanel typePane = new JPanel(new BorderLayout());
typePane.add(typeComboBox, BorderLayout.CENTER);
typePane.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 0));
}
JPanel option = new JPanel(new BorderLayout());
option.add(new UILabel(Toolkit.i18nText("Fine-Design_Report_Base_Option"), SwingConstants.LEFT), BorderLayout.WEST);
private void initRoundingCheckBox4PercentFormat() {
roundingBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Report_Base_Option_Half_Up"));
roundingBox.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0));
roundingBox.addItemListener(new ItemListener() {
@ -139,54 +110,13 @@ public class TextFormatPane extends AbstractBasicStylePane implements GlobalName
}
});
roundingBox.setGlobalName("roundingBox");
option.add(roundingBox, BorderLayout.CENTER);
optionPane = new JPanel(new CardLayout());
optionPane.add(new JPanel(), "hide");
optionPane.setPreferredSize(new Dimension(0, 0));
optionPane.add(option, "show");
Component[][] components = getComponent(centerPane, typePane);
this.add(createContentPane(components), BorderLayout.CENTER);
}
protected JPanel createContentPane (Component[][] components) {
double f = TableLayout.FILL;
double p = TableLayout.PREFERRED;
double[] rowSize = new double[components.length];
Arrays.fill(rowSize, p);
double[] columnSize = {p, f};
int[][] rowCount = new int[components.length][2];
Arrays.fill(rowCount, new int[] {1, 1});
return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_LARGE, LayoutConstants.VGAP_MEDIUM);
}
protected Component[][] getComponent (JPanel centerPane, JPanel typePane) {
return new Component[][]{
new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Report_Base_Format"), SwingConstants.LEFT), typePane},
new Component[]{centerPane, null},
new Component[]{optionPane, null},
};
}
protected UIComboBoxRenderer createComBoxRender() {
return new UIComboBoxRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Integer) {
label.setText(" " + FormatField.getInstance().getName((Integer) value));
}
return label;
}
};
}
private void initSampleLabel() {
private void initPreviewLabel4GeneralFormat() {
Border interBorder = new UIRoundedBorder(UIConstants.LINE_COLOR, 1, 4);
String title = Toolkit.i18nText("Fine-Design_Report_Base_StyleFormat_Sample");
Border border = BorderFactory.createTitledBorder(interBorder, title, TitledBorder.LEFT, 0, null, UIConstants.LINE_COLOR);
sampleLabel = new UILabel(FormatField.getInstance().getFormatValue()) {
previewLabel = new UILabel(FormatField.getInstance().getFormatValue()) {
@Override
public void paint(Graphics g) {
@ -198,12 +128,65 @@ public class TextFormatPane extends AbstractBasicStylePane implements GlobalName
g.setColor(UIConstants.LINE_COLOR);
FontMetrics cellFM = g.getFontMetrics();
int textWidth = cellFM.stringWidth(getText());
GraphHelper.drawString(g, getText(), (width - textWidth) / 2, 26);
GraphHelper.drawString(g, getText(), (width - textWidth) / 2F, 26);
g.setColor(original);
}
};
sampleLabel.setHorizontalAlignment(UILabel.CENTER);
sampleLabel.setBorder(border);
previewLabel.setHorizontalAlignment(UILabel.CENTER);
previewLabel.setBorder(border);
}
protected void initLayout() {
JPanel labeledFormatTypeComboBoxPane = new JPanel(new BorderLayout(20, 0));
labeledFormatTypeComboBoxPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Report_Base_Format")), BorderLayout.WEST);
labeledFormatTypeComboBoxPane.add(typeComboBox, BorderLayout.CENTER);
JPanel labeledRoundingCheckboxPane = new JPanel(new BorderLayout(0, 0));
labeledRoundingCheckboxPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Report_Base_Option")), BorderLayout.WEST);
labeledRoundingCheckboxPane.add(roundingBox, BorderLayout.CENTER);
addComponents(4, new JComponent[] { labeledFormatTypeComboBoxPane, textField, labeledRoundingCheckboxPane, previewLabel});
}
protected void setTextFieldVisible(boolean visible) {
textField.setVisible(visible);
}
protected void setRoundingBoxVisible(boolean visible) {
roundingBox.getParent().setVisible(visible);
}
protected void setPreviewLabelVisible(boolean visible) {
previewLabel.setVisible(visible);
}
protected void addComponents(int gap, JComponent[] components) {
JPanel container = this;
container.setLayout(new BorderLayout(0, gap));
for (JComponent component: components) {
if (component != null) {
container.add(component, BorderLayout.NORTH);
JPanel nextContainer = new JPanel(new BorderLayout(0, gap));
container.add(nextContainer, BorderLayout.CENTER);
container = nextContainer;
}
}
if (container.getComponentCount() == 0) {
container.getParent().remove(container);
}
}
protected UIComboBoxRenderer createComBoxRender() {
return new UIComboBoxRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Integer) {
label.setText(" " + FormatField.getInstance().getName((Integer) value));
}
return label;
}
};
}
@ -231,8 +214,6 @@ public class TextFormatPane extends AbstractBasicStylePane implements GlobalName
* Populate
*/
public void populateBean(Format format) {
this.format = format;
if (format == null) {
this.typeComboBox.setSelectedIndex(FormatContents.NULL);
} else {
@ -325,17 +306,17 @@ public class TextFormatPane extends AbstractBasicStylePane implements GlobalName
* Refresh preview label.
*/
private void refreshPreviewLabel() {
this.sampleLabel.setText(FormatField.getInstance().getFormatValue());
this.sampleLabel.setForeground(UIManager.getColor("Label.foreground"));
this.previewLabel.setText(FormatField.getInstance().getFormatValue());
this.previewLabel.setForeground(UIManager.getColor("Label.foreground"));
try {
isRightFormat = true;
if (StringUtils.isEmpty(String.valueOf(textField.getSelectedItem()))) {
return;
}
this.sampleLabel.setText(FormatField.getInstance().getFormatValue(getFormatContents(), String.valueOf(textField.getSelectedItem())));
this.previewLabel.setText(FormatField.getInstance().getFormatValue(getFormatContents(), String.valueOf(textField.getSelectedItem())));
} catch (Exception e) {
this.sampleLabel.setForeground(Color.red);
this.sampleLabel.setText(e.getMessage());
this.previewLabel.setForeground(Color.red);
this.previewLabel.setText(e.getMessage());
isRightFormat = false;
}
}
@ -354,28 +335,16 @@ public class TextFormatPane extends AbstractBasicStylePane implements GlobalName
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
int contents = getFormatContents();
String[] items = FormatField.getInstance().getFormatArray(contents, false);
CardLayout cardLayout = (CardLayout) centerPane.getLayout();
if (isTextOrNull()) {
centerPane.setPreferredSize(new Dimension(0, 0));
cardLayout.show(centerPane, "hide");
} else {
if (!isTextOrNull()) {
textField.removeAllItems();
String[] items = FormatField.getInstance().getFormatArray(contents, false);
textField.setItemArray(items);
textField.setSelectedIndex(0);
centerPane.setPreferredSize(new Dimension(270, 65));
cardLayout.show(centerPane, "show");
}
CardLayout optionLayout = ((CardLayout) optionPane.getLayout());
if (getFormatContents() == FormatContents.PERCENT) {
optionPane.setPreferredSize(new Dimension(100, 20));
optionLayout.show(optionPane, "show");
} else {
optionPane.setPreferredSize(new Dimension(0, 0));
optionLayout.show(optionPane, "hide");
roundingBox.setSelected(false);
}
setTextFieldVisible(!isTextOrNull());
setPreviewLabelVisible(!isTextOrNull());
setRoundingBoxVisible(getFormatContents() == FormatContents.PERCENT);
}
}
@ -403,10 +372,20 @@ public class TextFormatPane extends AbstractBasicStylePane implements GlobalName
* update
*/
public Style update(Style style) {
if (ComparatorUtils.equals(globalNameListener.getGlobalName(), "textField")
|| ComparatorUtils.equals(globalNameListener.getGlobalName(), "typeComboBox")
|| ComparatorUtils.equals(globalNameListener.getGlobalName(), "roundingBox")) {
return style.deriveFormat(this.update());
return updateByGlobalNamedSetting(style);
}
private Style updateByGlobalNamedSetting(Style style) {
if (globalNameListener != null) {
String[] alterSettingNames = new String[] {"typeComboBox", "textField", "roundingBox"};
String globalSettingName = globalNameListener.getGlobalName();
if (StringUtils.isNotEmpty(globalSettingName)) {
for (String alterSettingName : alterSettingNames) {
if (ComparatorUtils.equals(alterSettingName, globalSettingName)) {
return style.deriveFormat(this.update());
}
}
}
}
return style;
}

169
designer-base/src/main/java/com/fr/design/javascript/JSContentPane.java

@ -1,10 +1,13 @@
package com.fr.design.javascript;
import com.fr.base.svg.IconUtils;
import com.fr.design.DesignerEnvManager;
import com.fr.design.border.UIRoundedBorder;
import com.fr.design.constants.KeyWords;
import com.fr.design.constants.UIConstants;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.gui.autocomplete.AutoCompletion;
import com.fr.design.gui.autocomplete.BasicCompletion;
import com.fr.design.gui.autocomplete.CompletionProvider;
@ -14,32 +17,147 @@ import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants;
import com.fr.design.i18n.Toolkit;
import com.fr.design.javascript.beautify.JavaScriptFormatHelper;
import com.fr.design.javascript.jsapi.JSImplPopulateAction;
import com.fr.design.javascript.jsapi.JSImplUpdateAction;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.general.IOUtils;
import com.fr.js.JavaScriptImpl;
import javax.swing.*;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
public class JSContentPane extends BasicPane {
private RSyntaxTextArea contentTextArea;
private UILabel funNameLabel;
protected RSyntaxTextArea contentTextArea;
private UILabel funNameLabel = new UILabel();
private AutoCompletion ac;
private static final Dimension FUNCTION_NAME_LABEL_SIZE = new Dimension(300, 80);
private String[] defaultArgs;
private int titleWidth = 180;
private JPanel labelPane = new JPanel(new BorderLayout(6, 4));;
private NewJavaScriptImplPane newJavaScriptImplPane = null;
private JavaScriptImpl javaScript;
private JSImplUpdateAction jsImplUpdateAction;
private JSImplPopulateAction jsImplPopulateAction;
private boolean modal;
BasicDialog advancedEditorDialog ;
public JSContentPane(){}
public JSContentPane(String[] args) {
defaultArgs = args;
this.setLayout(FRGUIPaneFactory.createBorderLayout());
funNameLabel = new UILabel();
this.setFunctionTitle(args);
initFunctionTitle(args);
JPanel jsParaPane = createJSParaPane();
addNewPaneLabel();
this.add(jsParaPane, BorderLayout.NORTH);
UIScrollPane sp = createContentTextAreaPanel();
initContentTextAreaListener();
this.add(sp, BorderLayout.CENTER);
UILabel funNameLabel2 = new UILabel();
funNameLabel2.setText("}");
this.add(funNameLabel2, BorderLayout.SOUTH);
}
public JSContentPane(String[] args,boolean modal) {
this(args);
this.modal = modal;
}
public void setJsImplUpdateAction(JSImplUpdateAction jsImplUpdateAction){
this.jsImplUpdateAction = jsImplUpdateAction;
}
public void setJsImplPopulateAction(JSImplPopulateAction jsImplPopulateAction){
this.jsImplPopulateAction = jsImplPopulateAction;
}
public void updateJSImpl(JavaScriptImpl javaScript){
this.javaScript = javaScript;
}
private void addNewPaneLabel(){
UILabel advancedEditorLabel = new UILabel(Toolkit.i18nText("Fine-Design_Advanced_Editor"), IconUtils.readIcon("com/fr/design/images/edit/advancedEditor.svg"), SwingConstants.LEFT);
advancedEditorLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
advancedEditorLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if(newJavaScriptImplPane == null){
newJavaScriptImplPane = new NewJavaScriptImplPane(defaultArgs);
}
jsImplUpdateAction.update(javaScript);
newJavaScriptImplPane.populate(javaScript);
if(advancedEditorDialog == null || !advancedEditorDialog.isVisible()) {
advancedEditorDialog = newJavaScriptImplPane.showWindowWithCustomSize(DesignerContext.getDesignerFrame(), new DialogActionAdapter() {
@Override
public void doOk() {
if (javaScript != null) {
newJavaScriptImplPane.updateBean(javaScript);
jsImplPopulateAction.populate(javaScript);
}
}
@Override
public void doCancel() {
super.doCancel();
}
},new Dimension(900,800));
advancedEditorDialog.setModal(modal);
advancedEditorDialog.setResizable(true);
advancedEditorDialog.pack();
advancedEditorDialog.setVisible(true);
}
advancedEditorDialog.requestFocus();
}
});
labelPane.add(advancedEditorLabel,BorderLayout.EAST);
}
protected UIScrollPane createContentTextAreaPanel(){
contentTextArea = new RSyntaxTextArea();
contentTextArea.setCloseCurlyBraces(true);
contentTextArea.setLineWrap(true);
contentTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
contentTextArea.setCodeFoldingEnabled(true);
contentTextArea.setAntiAliasingEnabled(true);
return new UIScrollPane(contentTextArea);
}
private void initContentTextAreaListener(){
contentTextArea.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// 获得焦点时 安装
installAutoCompletion();
}
@Override
public void focusLost(FocusEvent e) {
// 失去焦点时 卸载
uninstallAutoCompletion();
}
});
}
protected JPanel createJSParaPane(){
UILabel label = new UILabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Format_JavaScript"), IOUtils.readIcon("com/fr/design/images/edit/format.png"), SwingConstants.LEFT);
label.setCursor(new Cursor(Cursor.HAND_CURSOR));
label.setToolTipText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Format_JavaScript"));
@ -65,43 +183,20 @@ public class JSContentPane extends BasicPane {
}
});
//REPORT-10533 用户参数多达25个,导致JS没地方写,增加滚动条显示
labelPane.add(label,BorderLayout.CENTER);
JPanel jsParaPane = new JPanel(new BorderLayout(4, 4));
jsParaPane.setPreferredSize(new Dimension(300, 80));
UIScrollPane scrollPane = new UIScrollPane(funNameLabel);
scrollPane.setPreferredSize(FUNCTION_NAME_LABEL_SIZE);
scrollPane.setBorder(new UIRoundedBorder(UIConstants.TITLED_BORDER_COLOR, 1, UIConstants.ARC));
jsParaPane.add(scrollPane, BorderLayout.WEST);
jsParaPane.add(label, BorderLayout.EAST);
this.add(jsParaPane, BorderLayout.NORTH);
contentTextArea = new RSyntaxTextArea();
contentTextArea.setCloseCurlyBraces(true);
contentTextArea.setLineWrap(true);
contentTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
contentTextArea.setCodeFoldingEnabled(true);
contentTextArea.setAntiAliasingEnabled(true);
UIScrollPane sp = new UIScrollPane(contentTextArea);
this.add(sp, BorderLayout.CENTER);
contentTextArea.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
// 获得焦点时 安装
installAutoCompletion();
}
@Override
public void focusLost(FocusEvent e) {
// 失去焦点时 卸载
uninstallAutoCompletion();
}
});
jsParaPane.add(labelPane, BorderLayout.EAST);
return jsParaPane;
}
UILabel funNameLabel2 = new UILabel();
funNameLabel2.setText("}");
this.add(funNameLabel2, BorderLayout.SOUTH);
protected void initFunctionTitle(String[] args){
funNameLabel = new UILabel();
this.setFunctionTitle(args);
}
private KeyStroke convert2KeyStroke(String ks) {

924
designer-base/src/main/java/com/fr/design/javascript/JSContentWithDescriptionPane.java

@ -0,0 +1,924 @@
package com.fr.design.javascript;
import com.fr.base.svg.IconUtils;
import com.fr.design.border.UIRoundedBorder;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.autocomplete.AutoCompleteExtraRefreshComponent;
import com.fr.design.gui.autocomplete.BasicCompletion;
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.JSImplPaneAutoCompletion;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextarea.UITextArea;
import com.fr.design.gui.itextfield.PlaceholderTextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.javascript.jsapi.JSAPITreeHelper;
import com.fr.design.javascript.jsapi.JSAPIUserObject;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.general.CloudCenter;
import com.fr.general.ComparatorUtils;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONArray;
import com.fr.json.JSONException;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class JSContentWithDescriptionPane extends JSContentPane implements KeyListener {
//搜索关键词输入框
private PlaceholderTextField keyWordTextField = new PlaceholderTextField(16);
//搜索出的提示列表
private JList tipsList;
private DefaultListModel tipsListModel = new DefaultListModel();
private JList interfaceNameList;
private DefaultListModel interfaceNameModel;
private JTree moduleTree;
private DefaultCompletionProvider completionProvider;
private JSImplPaneAutoCompletion autoCompletion;
//函数说明文本框
private UITextArea descriptionTextArea;
private JPopupMenu popupMenu;
private InterfaceAndDescriptionPanel interfaceAndDescriptionPanel;
private JList helpDOCList;
private int ifHasBeenWriten = 0;
private int currentPosition = 0;
private int beginPosition = 0;
private int insertPosition = 0;
private static final String SEPARATOR = "_";
private static final int KEY_10 = 10;
//上下左右
private static final int KEY_37 = 37;
private static final int KEY_38 = 38;
private static final int KEY_39 = 39;
private static final int KEY_40 = 40;
private static final String URL_FOR_TEST_NETWORK = "https://www.baidu.com";
private static final String DOCUMENT_SEARCH_URL = "https://help.fanruan.com/finereport/api-helpdoc-title-";
private String currentValue;
private static CardLayout card;
private static final String RELOAD_CARD = "reloadCard";
private static final String DOC_LIST_CARD = "docListCard";
public JSContentWithDescriptionPane(String[] args) {
this.setLayout(new BorderLayout());
//===============================
this.initFunctionTitle(args);
JPanel jsParaAndSearchPane = new JPanel(new BorderLayout());
//js函数声明面板
JPanel jsParaPane = createJSParaPane();
jsParaPane.setPreferredSize(new Dimension(650, 80));
//右上角的搜索提示面板
JPanel tipsPane = createTipsPane();
jsParaAndSearchPane.add(jsParaPane, BorderLayout.CENTER);
jsParaAndSearchPane.add(tipsPane, BorderLayout.EAST);
initPopTips();
//js文本编辑面板
UIScrollPane contentTextAreaPanel = createContentTextAreaPanel();
initContextAreaListener();
contentTextAreaPanel.setPreferredSize(new Dimension(850, 250));
//js函数结束标签
UILabel endBracketsLabel = new UILabel();
endBracketsLabel.setText("}");
//结尾括号和复用函数按钮面板
JPanel endBracketsPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
endBracketsPanel.add(endBracketsLabel, BorderLayout.WEST);
JPanel northPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
northPanel.add(jsParaAndSearchPane, BorderLayout.NORTH);
northPanel.add(contentTextAreaPanel, BorderLayout.CENTER);
northPanel.add(endBracketsPanel, BorderLayout.SOUTH);
//主编辑框,也就是面板的正中间部分
this.add(northPanel, BorderLayout.CENTER);
//函数分类和函数说明面板==================================
JPanel functionNameAndDescriptionPanel = createInterfaceAndDescriptionPanel();
functionNameAndDescriptionPanel.setPreferredSize(new Dimension(880, 220));
this.add(functionNameAndDescriptionPanel, BorderLayout.SOUTH);
}
public void populate(String js) {
contentTextArea.setText(js);
ifHasBeenWriten = 1;
currentPosition = contentTextArea.getCaretPosition();
beginPosition = getBeginPosition();
insertPosition = beginPosition;
}
private void initContextAreaListener() {
contentTextArea.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
if ((e.getKeyChar() >= 'A' && e.getKeyChar() <= 'z') || e.getKeyChar() == '_') {
if (autoCompletion != null) {
autoCompletion.doCompletion();
}
}
}
@Override
public void keyReleased(KeyEvent e) {
contentTextArea.setForeground(Color.black);
}
});
contentTextArea.addKeyListener(this);
contentTextArea.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
if (autoCompletion == null) {
installAutoCompletion();
}
}
@Override
public void focusLost(FocusEvent e) {
uninstallAutoCompletion();
}
});
contentTextArea.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
insertPosition = contentTextArea.getCaretPosition();
if (ifHasBeenWriten == 0) {
contentTextArea.setText(StringUtils.EMPTY);
ifHasBeenWriten = 1;
contentTextArea.setForeground(Color.black);
insertPosition = 0;
}
}
@Override
public void mouseReleased(MouseEvent e) {
currentPosition = contentTextArea.getCaretPosition();
if (currentPosition == insertPosition) {
beginPosition = getBeginPosition();
insertPosition = beginPosition;
}
}
});
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (ifHasBeenWriten == 0) {
this.contentTextArea.setText(StringUtils.EMPTY);
}
}
@Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KEY_38 || key == KEY_40 || key == KEY_37 || key == KEY_39 || key == KEY_10) //如果是删除符号 ,为了可读性 没有和其他按键的程序相融合
{
currentPosition = contentTextArea.getCaretPosition();
insertPosition = currentPosition;
beginPosition = getBeginPosition();
} else {
if (contentTextArea.getText().trim().length() == 0) {
insertPosition = 0;
} else {
contentTextArea.setForeground(Color.black);
currentPosition = contentTextArea.getCaretPosition();
beginPosition = getBeginPosition();
insertPosition = beginPosition;
ifHasBeenWriten = 1;
}
}
}
private int getBeginPosition() {
int i = currentPosition;
String textArea = contentTextArea.getText();
for (; i > 0; i--) {
String tested = textArea.substring(i - 1, i).toUpperCase();
char[] testedChar = tested.toCharArray();
if (isChar(testedChar[0]) || isNum(testedChar[0])) {
continue;
} else {
break;
}
}
return i;
}
private static boolean isNum(char tested) {
return tested >= '0' && tested <= '9';
}
private boolean isChar(char tested) {
return tested >= 'A' && tested <= 'Z' || tested >= 'a' && tested < 'z';
}
public class InterfaceAndDescriptionPanel extends JPanel implements AutoCompleteExtraRefreshComponent {
@Override
public void refresh(String replacementText) {
fixInterfaceNameList(replacementText);
}
}
private void fixInterfaceNameList(String interfaceName) {
DefaultTreeModel defaultTreeModel = (DefaultTreeModel) moduleTree.getModel();
TreeNode root = (TreeNode) defaultTreeModel.getRoot();
String directCategory = JSAPITreeHelper.getDirectCategory(interfaceName);
if (directCategory == null) {
return;
}
setModuleTreeSelection(root, directCategory, defaultTreeModel);
interfaceNameModel = (DefaultListModel) interfaceNameList.getModel();
interfaceNameModel.clear();
List<String> interfaceNames = JSAPITreeHelper.getNames(directCategory);
int index = 0;
for (int i = 0; i < interfaceNames.size(); i++) {
interfaceNameModel.addElement(interfaceNames.get(i));
if (StringUtils.equals(interfaceNames.get(i), interfaceName)) {
index = i;
}
}
interfaceNameList.setSelectedIndex(index);
interfaceNameList.ensureIndexIsVisible(index);
}
private boolean setModuleTreeSelection(TreeNode node, String directCategory, DefaultTreeModel treeModel) {
DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode) node;
Object userObject = defaultMutableTreeNode.getUserObject();
if (userObject instanceof JSAPIUserObject) {
String value = ((JSAPIUserObject) userObject).getValue();
if (StringUtils.equals(value, directCategory)) {
moduleTree.setSelectionPath(new TreePath(treeModel.getPathToRoot(node)));
moduleTree.scrollPathToVisible(moduleTree.getSelectionPath());
return true;
}
}
for (int i = 0; i < node.getChildCount(); i++) {
if (setModuleTreeSelection(node.getChildAt(i), directCategory, treeModel)) {
return true;
}
}
return false;
}
private JPanel createInterfaceAndDescriptionPanel() {
interfaceAndDescriptionPanel = new InterfaceAndDescriptionPanel();
interfaceAndDescriptionPanel.setLayout(new BorderLayout(4, 4));
JPanel interfacePanel = new JPanel(new BorderLayout(4, 4));
interfaceAndDescriptionPanel.add(interfacePanel, BorderLayout.WEST);
JPanel descriptionAndDocumentPanel = new JPanel(new BorderLayout(4, 4));
//函数说明和帮助文档框
initDescriptionArea(descriptionAndDocumentPanel);
//模块和接口面板
initInterfaceModuleTree(interfacePanel);
initInterfaceNameList(interfacePanel);
initHelpDocumentPane(descriptionAndDocumentPanel);
interfaceAndDescriptionPanel.add(descriptionAndDocumentPanel, BorderLayout.CENTER);
return interfaceAndDescriptionPanel;
}
private void doHelpDocumentSearch() {
Object value = interfaceNameList.getSelectedValue();
if (value != null) {
String url = CloudCenter.getInstance().acquireUrlByKind("af.doc_search", DOCUMENT_SEARCH_URL) + value.toString();
try {
String result = HttpToolbox.get(url);
JSONObject jsonObject = new JSONObject(result);
JSONArray jsonArray = jsonObject.optJSONArray("list");
if (jsonArray != null) {
DefaultListModel helpDOCModel = (DefaultListModel) helpDOCList.getModel();
helpDOCModel.clear();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject resultJSONObject = jsonArray.optJSONObject(i);
String docURL = resultJSONObject.optString("url");
String name = resultJSONObject.optString("title").trim();
HelpDocument helpDocument = new HelpDocument(docURL, name);
helpDOCModel.addElement(helpDocument);
}
}
} catch (JSONException e) {
FineLoggerFactory.getLogger().debug(e.getMessage(), e);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}
private void initHelpDocumentPane(JPanel descriptionAndDocumentPanel) {
card = new CardLayout();
JPanel mainPane = new JPanel(card);
initHelpDocumentList();
UIScrollPane helpDOCScrollPane = new UIScrollPane(helpDOCList);
helpDOCScrollPane.setPreferredSize(new Dimension(200, 200));
helpDOCScrollPane.setBorder(null);
mainPane.add(helpDOCScrollPane, DOC_LIST_CARD);
UILabel imageLabel = new UILabel();
imageLabel.setIcon(IconUtils.readIcon("com/fr/design/javascript/jsapi/images/connectFailed.svg"));
imageLabel.setPreferredSize(new Dimension(180, 65));
JPanel imagePane = FRGUIPaneFactory.createBorderLayout_S_Pane();
imagePane.setBorder(BorderFactory.createEmptyBorder(0, 42, 0, 0));
imagePane.add(imageLabel);
imagePane.setBackground(Color.WHITE);
UILabel failedLabel = new UILabel(Toolkit.i18nText("Fine-Design_Net_Connect_Failed"), 0);
failedLabel.setPreferredSize(new Dimension(180, 20));
UILabel reloadLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Reload"), 0);
reloadLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
reloadLabel.setPreferredSize(new Dimension(180, 20));
reloadLabel.setForeground(Color.blue);
JPanel labelPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, 0, 0, 0);
labelPane.setBorder(BorderFactory.createEmptyBorder(35, 45, 0, 0));
labelPane.setBackground(Color.WHITE);
labelPane.add(imagePane);
labelPane.add(failedLabel);
labelPane.add(reloadLabel);
JPanel containerPanel = FRGUIPaneFactory.createBorderLayout_S_Pane();
containerPanel.add(labelPane, BorderLayout.CENTER);
reloadLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (isNetworkOk()) {
doHelpDocumentSearch();
card.show(mainPane, DOC_LIST_CARD);
}
}
});
mainPane.add(containerPanel, RELOAD_CARD);
if (isNetworkOk()) {
doHelpDocumentSearch();
card.show(mainPane, DOC_LIST_CARD);
} else {
card.show(mainPane, RELOAD_CARD);
}
descriptionAndDocumentPanel.add(this.createNamePane(Toolkit.i18nText("Fine-Design_Relevant_Cases"), mainPane), BorderLayout.EAST);
}
private void initHelpDocumentList() {
helpDOCList = new JList(new DefaultListModel());
initHelpDOCListRender();
initHelpDOCListListener();
}
private void initHelpDOCListListener() {
helpDOCList.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
Object value = helpDOCList.getSelectedValue();
if (value instanceof HelpDocument) {
String url = ((HelpDocument) value).getDocumentUrl();
browse(url);
}
}
}
});
}
private void browse(String url){
try {
Desktop.getDesktop().browse(new URI(url));
} catch (IOException | URISyntaxException ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
}
private void initHelpDOCListRender() {
helpDOCList.setCellRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof HelpDocument) {
this.setText(((HelpDocument) value).getName());
this.setForeground(Color.BLUE);
}
return this;
}
});
}
private static boolean isNetworkOk() {
try {
HttpToolbox.get(URL_FOR_TEST_NETWORK);
return true;
} catch (Exception ignore) {
// 网络异常
return false;
}
}
private static class HelpDocument {
private String documentUrl;
private String name;
public HelpDocument(String documentUrl, String name) {
this.documentUrl = documentUrl;
this.name = name;
}
public String getDocumentUrl() {
return documentUrl;
}
public String getName() {
return name;
}
}
private void initDescriptionArea(JPanel descriptionPanel) {
descriptionTextArea = new UITextArea();
UIScrollPane descriptionScrollPane = new UIScrollPane(descriptionTextArea);
descriptionScrollPane.setPreferredSize(new Dimension(300, 200));
descriptionPanel.add(this.createNamePane(Toolkit.i18nText("Fine-Design_Interface_Description"), descriptionScrollPane), BorderLayout.CENTER);
descriptionTextArea.setBackground(Color.white);
descriptionTextArea.setLineWrap(true);
descriptionTextArea.setWrapStyleWord(true);
descriptionTextArea.setEditable(false);
}
private void installAutoCompletion() {
CompletionProvider provider = createCompletionProvider();
autoCompletion = new JSImplPaneAutoCompletion(provider);
autoCompletion.setListCellRenderer(new CompletionCellRenderer());
autoCompletion.install(contentTextArea);
autoCompletion.installExtraRefreshComponent(interfaceAndDescriptionPanel);
}
private void uninstallAutoCompletion() {
if (autoCompletion != null) {
autoCompletion.uninstall();
autoCompletion = null;
}
}
private CompletionProvider createCompletionProvider() {
if (completionProvider == null) {
completionProvider = new DefaultCompletionProvider();
for (String name : JSAPITreeHelper.getAllNames()) {
completionProvider.addCompletion(new BasicCompletion(completionProvider, name));
}
}
return completionProvider;
}
private void initInterfaceModuleTree(JPanel interfacePanel) {
moduleTree = new JTree();
UIScrollPane moduleTreePane = new UIScrollPane(moduleTree);
moduleTreePane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
interfacePanel.add(this.createNamePane(Toolkit.i18nText("Fine-Design_Module"), moduleTreePane), BorderLayout.WEST);
moduleTreePane.setPreferredSize(new Dimension(180, 200));
moduleTree.setRootVisible(false);
moduleTree.setShowsRootHandles(true);
moduleTree.setCellRenderer(moduleTreeCellRender);
DefaultTreeModel moduleTreeModel = (DefaultTreeModel) moduleTree.getModel();
DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) moduleTreeModel.getRoot();
rootNode.removeAllChildren();
JSAPITreeHelper.createJSAPITree(rootNode);
moduleTreeModel.reload();
initModuleTreeSelectionListener();
}
private void initModuleTreeSelectionListener() {
moduleTree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode selectedTreeNode = (DefaultMutableTreeNode) moduleTree.getLastSelectedPathComponent();
Object selectedValue = selectedTreeNode.getUserObject();
if (null == selectedValue) {
return;
}
if (selectedValue instanceof JSAPIUserObject) {
interfaceNameModel = (DefaultListModel) interfaceNameList.getModel();
interfaceNameModel.clear();
String text = ((JSAPIUserObject) selectedValue).getValue();
List<String> allInterfaceNames = JSAPITreeHelper.getNames(text);
for (String interfaceName : allInterfaceNames) {
interfaceNameModel.addElement(interfaceName);
}
if (interfaceNameModel.size() > 0) {
interfaceNameList.setSelectedIndex(0);
setDescription(interfaceNameList.getSelectedValue().toString());
interfaceNameList.ensureIndexIsVisible(0);
}
}
}
});
}
private DefaultTreeCellRenderer moduleTreeCellRender = new DefaultTreeCellRenderer() {
public Component getTreeCellRendererComponent(JTree tree,
Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, selected,
expanded, leaf, row, hasFocus);
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
Object userObj = treeNode.getUserObject();
if (userObj instanceof JSAPIUserObject) {
this.setText(((JSAPIUserObject) userObj).getDisplayText());
this.setIcon(null);
}
return this;
}
};
private void initInterfaceNameList(JPanel interfacePanel) {
interfaceNameList = new JList(new DefaultListModel());
UIScrollPane interfaceNamePanelScrollPane = new UIScrollPane(interfaceNameList);
interfaceNamePanelScrollPane.setPreferredSize(new Dimension(180, 200));
interfacePanel.add(
this.createNamePane(Toolkit.i18nText("Fine-Design_Interface") + ":", interfaceNamePanelScrollPane),
BorderLayout.CENTER);
interfaceNamePanelScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
initInterfaceNameModule();
initInterfaceNameListSelectionListener();
initInterfaceNameListMouseListener();
}
private void initInterfaceNameModule() {
DefaultTreeModel defaultTreeModel = (DefaultTreeModel) moduleTree.getModel();
TreeNode root = (TreeNode) defaultTreeModel.getRoot();
while (root.getChildCount() > 0){
root = root.getChildAt(0);
}
moduleTree.setSelectionPath(new TreePath(defaultTreeModel.getPathToRoot(root)));
}
private void setDescription(String interfaceName) {
StringBuilder il8Key = new StringBuilder();
moduleTree.getSelectionPath().getPath();
Object obj = moduleTree.getSelectionPath().getPath()[moduleTree.getSelectionPath().getPath().length - 1];
Object userObject = ((DefaultMutableTreeNode) obj).getUserObject();
if (userObject instanceof JSAPIUserObject) {
il8Key.append(JSAPITreeHelper.getDirectCategory(interfaceName));
}
interfaceName = interfaceName.toUpperCase();
if (!interfaceName.startsWith(SEPARATOR)) {
interfaceName = SEPARATOR + interfaceName;
}
il8Key.append(interfaceName);
descriptionTextArea.setText(Toolkit.i18nText(il8Key.toString()));
descriptionTextArea.moveCaretPosition(0);
}
private void initInterfaceNameListSelectionListener() {
interfaceNameList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent evt) {
Object selectedValue = interfaceNameList.getSelectedValue();
if (selectedValue == null) {
return;
}
String interfaceName = selectedValue.toString();
if (!StringUtils.equals(interfaceName, currentValue)) {
setDescription(interfaceName);
doHelpDocumentSearch();
currentValue = interfaceName;
}
}
});
}
private void initInterfaceNameListMouseListener() {
interfaceNameList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() >= 2) {
Object selectedValue = interfaceNameList.getSelectedValue();
String interfaceName = selectedValue.toString();
applyText(interfaceName);
}
}
});
}
private void applyText(String text) {
if (text == null || text.length() <= 0) {
return;
}
if (ifHasBeenWriten == 0) {
contentTextArea.setForeground(Color.black);
contentTextArea.setText(StringUtils.EMPTY);
ifHasBeenWriten = 1;
insertPosition = 0;
}
String textAll = contentTextArea.getText();
currentPosition = contentTextArea.getCaretPosition();
int insert = 0;
int current = 0;
if (insertPosition <= currentPosition) {
insert = insertPosition;
current = currentPosition;
} else {
insert = currentPosition;
current = insertPosition;
}
String beforeIndexOfInsertString = textAll.substring(0, insert);
String afterIndexofInsertString = textAll.substring(current);
contentTextArea.setText(beforeIndexOfInsertString + text + afterIndexofInsertString);
contentTextArea.getText();
contentTextArea.requestFocus();
insertPosition = contentTextArea.getCaretPosition();
}
private JPanel createNamePane(String name, JComponent comp) {
JPanel namePane = new JPanel(new BorderLayout(4, 4));
namePane.add(new UILabel(name), BorderLayout.NORTH);
namePane.add(comp, BorderLayout.CENTER);
return namePane;
}
private JPanel createTipsPane() {
JPanel tipsPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
tipsPane.setLayout(new BorderLayout(4, 4));
tipsPane.setBorder(BorderFactory.createEmptyBorder(30, 2, 0, 0));
JPanel searchPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
searchPane.setLayout(new BorderLayout(4, 4));
keyWordTextField.setPlaceholder(Toolkit.i18nText("Fine-Design_Search_Interface"));
searchPane.add(keyWordTextField, BorderLayout.CENTER);
//搜索按钮
UIButton searchButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Search"));
searchButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String toFind = keyWordTextField.getText();
search(toFind);
popTips();
tipsList.requestFocusInWindow();
}
});
keyWordTextField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_ENTER) {
e.consume();
String toFind = keyWordTextField.getText();
search(toFind);
popTips();
tipsList.requestFocusInWindow();
}
}
});
searchPane.add(searchButton, BorderLayout.EAST);
tipsPane.add(searchPane, BorderLayout.NORTH);
tipsList = new JList(tipsListModel);
tipsList.addMouseListener(tipsListMouseListener);
tipsList.addListSelectionListener(tipsListSelectionListener);
tipsList.addKeyListener(tipListKeyListener);
return tipsPane;
}
private void search(String key) {
tipsListModel.removeAllElements();
tipsListModel.clear();
key = key.replaceAll(StringUtils.BLANK, StringUtils.EMPTY);
ArrayList<String> list = new ArrayList<>();
if (!StringUtils.isEmpty(key)) {
List<String> allNames = JSAPITreeHelper.getAllNames();
for (String name : allNames) {
if (searchResult(key, name)) {
list.add(name);
}
}
String finalKey = key;
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int result;
boolean o1StartWidth = o1.toLowerCase().startsWith(finalKey.toLowerCase());
boolean o2StartWidth = o2.toLowerCase().startsWith(finalKey.toLowerCase());
if (o1StartWidth) {
result = o2StartWidth ? o1.compareTo(o2) : -1;
} else {
result = o2StartWidth ? 1 : o1.compareTo(o2);
}
return result;
}
});
for (String name : list) {
tipsListModel.addElement(name);
}
if (!tipsListModel.isEmpty()) {
tipsList.setSelectedIndex(0);
}
}
}
private boolean searchResult(String key, String interfaceName) {
if (StringUtils.isBlank(key) || StringUtils.isBlank(interfaceName)) {
return false;
}
int length = key.length();
String temp = interfaceName.toUpperCase();
for (int i = 0; i < length; i++) {
String check = key.substring(i, i + 1);
int index = temp.indexOf(check.toUpperCase());
if (index == -1) {
return false;
} else {
temp = temp.substring(index + 1);
}
}
return true;
}
private void initPopTips() {
popupMenu = new JPopupMenu();
JScrollPane tipsScrollPane = new JScrollPane(tipsList);
popupMenu.add(tipsScrollPane);
tipsScrollPane.setPreferredSize(new Dimension(220, 146));
tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
}
private void popTips() {
popupMenu.show(keyWordTextField, 0, 23);
}
private ListSelectionListener tipsListSelectionListener = new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
Object selectValue = tipsList.getSelectedValue();
if (selectValue == null) {
return;
}
String interfaceName = selectValue.toString();
fixInterfaceNameList(interfaceName);
}
};
private KeyListener tipListKeyListener = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_ENTER) {
Object selectValue = tipsList.getSelectedValue();
if (selectValue == null) {
return;
}
tipListValueSelectAction(selectValue.toString());
if (popupMenu != null) {
popupMenu.setVisible(false);
}
contentTextArea.requestFocusInWindow();
}
}
};
private void tipListValueSelectAction(String value) {
if (ifHasBeenWriten == 0) {
contentTextArea.setForeground(Color.black);
contentTextArea.setText(StringUtils.EMPTY);
}
contentTextArea.setForeground(Color.black);
currentPosition = contentTextArea.getCaretPosition();
String output = value;
String textAll = contentTextArea.getText();
String textReplaced;
int position = 0;
if (insertPosition <= currentPosition) {
textReplaced = textAll.substring(0, insertPosition) + output + textAll.substring(currentPosition);
position = insertPosition + output.length();
} else {
textReplaced = textAll.substring(0, currentPosition) + output + textAll.substring(insertPosition);
position = currentPosition + output.length();
}
contentTextArea.setText(textReplaced);
contentTextArea.setCaretPosition(position);
insertPosition = position;
ifHasBeenWriten = 1;
tipsListModel.removeAllElements();
}
private MouseListener tipsListMouseListener = new MouseAdapter() {
String singlePressContent;
String doublePressContent;
@Override
public void mousePressed(MouseEvent e) {
int index = tipsList.getSelectedIndex();
if (index != -1) {
if (e.getClickCount() == 1) {
singlePressContent = (String) tipsListModel.getElementAt(index);
} else if (e.getClickCount() == 2) {
doublePressContent = (String) tipsListModel.getElementAt(index);
}
}
}
@Override
public void mouseReleased(MouseEvent e) {
int index = tipsList.getSelectedIndex();
if (index != -1) {
if (e.getClickCount() == 1) {
if (ComparatorUtils.equals((String) tipsListModel.getElementAt(index), singlePressContent)) {
singleClickActuator(singlePressContent);
}
} else if (e.getClickCount() == 2) {
if (ComparatorUtils.equals((String) tipsListModel.getElementAt(index), doublePressContent)) {
doubleClickActuator(doublePressContent);
}
if (popupMenu != null) {
popupMenu.setVisible(false);
}
}
}
}
private void singleClickActuator(String currentLineContent) {
setDescription(currentLineContent);
fixInterfaceNameList(currentLineContent);
}
private void doubleClickActuator(String currentLineContent) {
tipListValueSelectAction(currentLineContent);
}
};
}

95
designer-base/src/main/java/com/fr/design/javascript/JavaScriptImplPane.java

@ -9,6 +9,8 @@ import com.fr.design.gui.itableeditorpane.UITableEditAction;
import com.fr.design.gui.itableeditorpane.UITableEditorPane;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.hyperlink.AbstractHyperLinkPane;
import com.fr.design.javascript.jsapi.JSImplPopulateAction;
import com.fr.design.javascript.jsapi.JSImplUpdateAction;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.scrollruler.ModLineBorder;
import com.fr.design.utils.gui.GUICoreUtils;
@ -17,10 +19,16 @@ import com.fr.js.JavaScriptImpl;
import com.fr.stable.ParameterProvider;
import com.fr.stable.StringUtils;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import java.awt.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -28,11 +36,11 @@ import java.util.List;
public class JavaScriptImplPane extends AbstractHyperLinkPane<JavaScriptImpl> {
private static final int BOTTOM_BORDER = 12;
private UITextField itemNameTextField;
private JSContentPane jsPane;
protected JSContentPane jsPane;
private UITableEditorPane<String> importedJsPane;
private ReportletParameterViewPane parameterPane;
private String[] defaultArgs;
private boolean modal;
public JavaScriptImplPane() {
this(new String[0]);
@ -50,8 +58,57 @@ public class JavaScriptImplPane extends AbstractHyperLinkPane<JavaScriptImpl> {
initComponents();
}
public JavaScriptImplPane(String[] args, boolean modal) {
this.modal = modal;
this.defaultArgs = args;
initComponents();
}
protected void initComponents() {
parameterPane = new ReportletParameterViewPane(getChartParaType(), getValueEditorPane(), getValueEditorPane());
parameterPane = createParameterViewPane();
importedJsPane = createImportedJsPane();
importedJsPane.setPreferredSize(new Dimension(265, 150));
jsPane = createJSContentPane(defaultArgs);
jsPane.setBorder(BorderFactory.createTitledBorder(new ModLineBorder(ModLineBorder.TOP), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_JavaScript")));
parameterPane.setPreferredSize(new Dimension(265, 150));
JPanel topPane = new JPanel(new GridLayout(1,2));
topPane.add(importedJsPane);
topPane.add(parameterPane);
topPane.setBorder(BorderFactory.createEmptyBorder(0, 0, BOTTOM_BORDER, 0));
this.setLayout(new BorderLayout());
this.add(topPane, BorderLayout.NORTH);
this.add(jsPane, BorderLayout.CENTER);
this.reLayoutForChart();
}
protected JSContentPane createJSContentPane(String[] defaultArgs){
JSContentPane jsContentPane= new JSContentPane(defaultArgs,modal);
jsContentPane.setJsImplUpdateAction(new JSImplUpdateAction() {
@Override
public void update(JavaScriptImpl javaScript) {
if(javaScript != null){
updateBean(javaScript);
}
}
});
jsContentPane.setJsImplPopulateAction(new JSImplPopulateAction() {
@Override
public void populate(JavaScriptImpl javaScript) {
if(javaScript != null){
populateBean(javaScript);
}
}
});
return jsContentPane;
}
protected ReportletParameterViewPane createParameterViewPane(){
ReportletParameterViewPane parameterPane = new ReportletParameterViewPane(getChartParaType(), getValueEditorPane(), getValueEditorPane());
parameterPane.setBorder(BorderFactory.createTitledBorder(new ModLineBorder(ModLineBorder.TOP), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Parameter")));
parameterPane.addTableEditorListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
@ -72,7 +129,10 @@ public class JavaScriptImplPane extends AbstractHyperLinkPane<JavaScriptImpl> {
parameterChanger(list);
}
});
return parameterPane;
}
protected UITableEditorPane<String> createImportedJsPane(){
OneListTableModel<String> model = new OneListTableModel<String>(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_ReportServerP_Import_JavaScript"), this) {
public UITableEditAction[] createAction() {
@ -84,26 +144,12 @@ public class JavaScriptImplPane extends AbstractHyperLinkPane<JavaScriptImpl> {
return new AddJsAction();
}
};
importedJsPane = new UITableEditorPane<String>(model);
UITableEditorPane<String> importedJsPane = new UITableEditorPane<String>(model);
importedJsPane.setBorder(BorderFactory.createTitledBorder(new ModLineBorder(ModLineBorder.TOP), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_ReportServerP_Import_JavaScript")));
importedJsPane.setPreferredSize(new Dimension(265, 150));
jsPane = new JSContentPane(defaultArgs);
jsPane.setBorder(BorderFactory.createTitledBorder(new ModLineBorder(ModLineBorder.TOP), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_JavaScript")));
return importedJsPane;
}
parameterPane.setPreferredSize(new Dimension(265, 150));
JPanel topPane = GUICoreUtils.createBorderLayoutPane(
importedJsPane, BorderLayout.CENTER,
parameterPane, BorderLayout.EAST
);
topPane.setPreferredSize(new Dimension(300, 150));
topPane.setBorder(BorderFactory.createEmptyBorder(0, 0, BOTTOM_BORDER, 0));
this.setLayout(new BorderLayout());
this.add(topPane, BorderLayout.NORTH);
this.add(jsPane, BorderLayout.CENTER);
this.reLayoutForChart();
}
/**
* 参数改变
@ -140,10 +186,10 @@ public class JavaScriptImplPane extends AbstractHyperLinkPane<JavaScriptImpl> {
if (javaScriptImpl == null) {
javaScriptImpl = new JavaScriptImpl();
jsPane.reset();
}else{
} else {
jsPane.populate(javaScriptImpl.getContent());
}
jsPane.updateJSImpl(javaScriptImpl);
int rowCount = javaScriptImpl.getJSImportSize();
String[] value = new String[rowCount];
for (int i = 0; i < rowCount; i++) {
@ -160,6 +206,7 @@ public class JavaScriptImplPane extends AbstractHyperLinkPane<JavaScriptImpl> {
public JavaScriptImpl updateBean() {
JavaScriptImpl javaScript = new JavaScriptImpl();
updateBean(javaScript);
jsPane.updateJSImpl(javaScript);
return javaScript;
}

23
designer-base/src/main/java/com/fr/design/javascript/NewJavaScriptImplPane.java

@ -0,0 +1,23 @@
package com.fr.design.javascript;
import com.fr.js.JavaScriptImpl;
public class NewJavaScriptImplPane extends JavaScriptImplPane {
public NewJavaScriptImplPane(String[] args) {
super(args);
}
protected JSContentPane createJSContentPane(String[] defaultArgs){
return new JSContentWithDescriptionPane(defaultArgs);
}
public void populate(JavaScriptImpl javaScript) {
if (javaScript != null) {
populateBean(javaScript);
} else {
jsPane.reset();
}
}
}

21
designer-base/src/main/java/com/fr/design/javascript/jsapi/CategoryTreeNodesUserObject.java

@ -0,0 +1,21 @@
package com.fr.design.javascript.jsapi;
import com.fr.design.i18n.Toolkit;
public class CategoryTreeNodesUserObject implements JSAPIUserObject {
private String value;
public CategoryTreeNodesUserObject(String value) {
this.value = value;
}
@Override
public String getValue() {
return value;
}
@Override
public String getDisplayText() {
return Toolkit.i18nText(value);
}
}

155
designer-base/src/main/java/com/fr/design/javascript/jsapi/JSAPITreeHelper.java

@ -0,0 +1,155 @@
package com.fr.design.javascript.jsapi;
import com.fr.general.IOUtils;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode;
public class JSAPITreeHelper {
private static final String JSAPI_PATH = "com/fr/design/javascript/jsapi/jsapi.json";
private static final String CATEGORY_PATH = "com/fr/design/javascript/jsapi/category.json";
private static JSONObject categoryJSON ;
private static JSONObject jsapiJSON ;
static {
jsapiJSON = createJSON(JSAPI_PATH);
categoryJSON = createJSON(CATEGORY_PATH);
}
private static JSONObject createJSON(String path) {
StringBuilder jsonString = new StringBuilder(StringUtils.EMPTY);
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(IOUtils.readResource(path)))) {
String s;
while ((s = bufferedReader.readLine()) != null) {
jsonString.append(s);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return new JSONObject(jsonString.toString());
}
public static void createJSAPITree(DefaultMutableTreeNode rootNode) {
createJSAPITree(categoryJSON, rootNode);
}
public static String getDirectCategory(String name) {
if (jsapiJSON != null) {
Iterator<String> it = jsapiJSON.keys();
while (it.hasNext()) {
String key = it.next();
JSONArray nameArray = jsapiJSON.optJSONArray(key);
for (int i = 0; i < nameArray.length(); i++) {
if (StringUtils.equals(nameArray.getString(i), name)) {
return key;
}
}
}
}
return null;
}
private static void createJSAPITree(JSONObject jsonObject, DefaultMutableTreeNode rootNode) {
if (jsonObject != null && rootNode != null) {
Iterator<String> it = jsonObject.keys();
while (it.hasNext()) {
String key = it.next();
JSONObject subNode = jsonObject.optJSONObject(key);
if (subNode.size() == 0) {
rootNode.add(new DefaultMutableTreeNode(new CategoryTreeNodesUserObject(key)));
} else {
DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(new CategoryTreeNodesUserObject(key));
rootNode.add(treeNode);
createJSAPITree(subNode, treeNode);
}
}
}
}
private static List<String> getAllSubNodes(String name) {
return getAllSubNodes(name, categoryJSON);
}
public static List<String> getAllNames() {
ArrayList<String> result = new ArrayList<>();
if (jsapiJSON != null) {
Iterator<String> it = jsapiJSON.keys();
while (it.hasNext()) {
String key = it.next();
JSONArray nameArray = jsapiJSON.optJSONArray(key);
for (int i = 0; i < nameArray.length(); i++) {
result.add(nameArray.getString(i));
}
}
}
return result;
}
public static List<String> getNames(String category) {
ArrayList<String> result = new ArrayList<>();
List<String> subCategories = getAllSubNodes(category);
if (jsapiJSON != null) {
for (String subCategory : subCategories) {
if (jsapiJSON.containsKey(subCategory)) {
JSONArray nameArray = jsapiJSON.optJSONArray(subCategory);
for (int i = 0; i < nameArray.length(); i++) {
result.add(nameArray.getString(i));
}
}
}
}
return result;
}
private static List<String> getAllSubNodes(String name, JSONObject jsonObject) {
ArrayList<String> result = new ArrayList<>();
if (jsonObject != null) {
Iterator<String> it = jsonObject.keys();
while (it.hasNext()) {
String key = it.next();
JSONObject subNode = jsonObject.optJSONObject(key);
if (subNode.size() == 0) {
if (StringUtils.equals(key, name)) {
result.add(key);
return result;
}
} else {
if (StringUtils.equals(key, name)) {
result.add(key);
result.addAll(getAllSubNodes(subNode));
return result;
} else {
result.addAll(getAllSubNodes(name, subNode));
}
}
}
}
return result;
}
private static List<String> getAllSubNodes(JSONObject jsonObject) {
ArrayList<String> result = new ArrayList<>();
if (jsonObject != null) {
Iterator<String> it = jsonObject.keys();
while (it.hasNext()) {
String key = it.next();
JSONObject subNode = jsonObject.optJSONObject(key);
if (subNode.size() == 0) {
result.add(key);
} else {
result.add(key);
result.addAll(getAllSubNodes(subNode));
}
}
}
return result;
}
}

9
designer-base/src/main/java/com/fr/design/javascript/jsapi/JSAPIUserObject.java

@ -0,0 +1,9 @@
package com.fr.design.javascript.jsapi;
public interface JSAPIUserObject {
String getValue();
String getDisplayText();
}

7
designer-base/src/main/java/com/fr/design/javascript/jsapi/JSImplPopulateAction.java

@ -0,0 +1,7 @@
package com.fr.design.javascript.jsapi;
import com.fr.js.JavaScriptImpl;
public interface JSImplPopulateAction {
void populate(JavaScriptImpl javaScript);
}

7
designer-base/src/main/java/com/fr/design/javascript/jsapi/JSImplUpdateAction.java

@ -0,0 +1,7 @@
package com.fr.design.javascript.jsapi;
import com.fr.js.JavaScriptImpl;
public interface JSImplUpdateAction {
void update(JavaScriptImpl javaScript);
}

122
designer-base/src/main/java/com/fr/design/lock/LockInfoDialog.java

@ -0,0 +1,122 @@
package com.fr.design.lock;
import com.fr.design.file.TemplateTreePane;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.DesignSizeI18nManager;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrameFileDealerPane;
import com.fr.design.utils.TemplateUtils;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
import com.fr.general.IOUtils;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.workspace.base.UserInfo;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JPanel;
/**
* @author hades
* @version 11.0
* Created by hades on 2021/12/2
*/
public class LockInfoDialog extends JDialog {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
public LockInfoDialog(UserInfo userInfo) {
super(DesignerContext.getDesignerFrame());
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
panel.add(createContentPane(userInfo), BorderLayout.CENTER);
panel.add(createControlPane(), BorderLayout.SOUTH);
this.getContentPane().add(panel);
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Title_Hint"));
this.setSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.lock.LockInfoDialog"));
this.setResizable(false);
this.setModal(true);
GUICoreUtils.centerWindow(this);
this.setVisible(true);
}
private JPanel createContentPane(UserInfo userInfo) {
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
JPanel messagePane = new JPanel(new BorderLayout(13, 0));
UILabel iconLabel = new UILabel(IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png"));
iconLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
messagePane.add(iconLabel, BorderLayout.WEST);
UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine-Design_Template_Lock_And_SaveAs_Tip"));
tipLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
messagePane.add(tipLabel, BorderLayout.CENTER);
contentPanel.add(messagePane, BorderLayout.NORTH);
JPanel detailInfoPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane();
detailInfoPane.setBorder(BorderFactory.createEmptyBorder(0, 45, 0,0));
if (userInfo != null && StringUtils.isNotEmpty(userInfo.getUserName())) {
UILabel label = createLabel(Toolkit.i18nText("Fine-Design_Template_Lock_Holder", userInfo.getUserName()));
label .setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
detailInfoPane.add(label);
}
if (userInfo != null && StringUtils.isNotEmpty(userInfo.getIp())) {
detailInfoPane.add(createLabel(Toolkit.i18nText("Fine-Design_Template_Lock_Holder_Ip", userInfo.getIp()) ));
}
detailInfoPane.add(createLabel(Toolkit.i18nText("Fine-Design_Template_Lock_Get_Time", FORMATTER.format(LocalDateTime.now()))));
contentPanel.add(detailInfoPane, BorderLayout.CENTER);
return contentPanel;
}
private UILabel createLabel(String text) {
UILabel label = new UILabel(text);
label.setForeground(Color.GRAY);
label.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));
return label;
}
private JPanel createControlPane() {
JPanel controlPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 5));
controlPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0,5));
UIButton saveAsButton = new UIButton(Toolkit.i18nText("Fine_Design_Template_Lock_Save_As"));
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Button_Cancel"));
saveAsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
FileNode node = TemplateTreePane.getInstance().getFileNode();
if (node == null) {
return;
}
final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, TemplateTreePane.getInstance().getFilePath());
TemplateUtils.createAndOpenTemplate(Toolkit.i18nText("Fine_Design_Template_Lock_Copy"), new FileNodeFILE(new FileNode(selectedFilePath, false)), true);
}
});
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
controlPane.add(saveAsButton);
controlPane.add(cancelButton);
return controlPane;
}
public static void show(UserInfo userInfo) {
DesignerFrameFileDealerPane.getInstance().refreshRightToolBarBy(TemplateTreePane.getInstance().getFileNode());
new LockInfoDialog(userInfo);
}
}

23
designer-base/src/main/java/com/fr/design/lock/LockInfoUtils.java

@ -0,0 +1,23 @@
package com.fr.design.lock;
import com.fr.report.lock.DefaultLockInfoOperator;
import com.fr.report.lock.LockInfoOperator;
import com.fr.start.server.FineEmbedServer;
import com.fr.workspace.WorkContext;
/**
* @author hades
* @version 11.0
* Created by hades on 2021/12/8
*/
public class LockInfoUtils {
public static boolean isCompatibleOperator() {
LockInfoOperator lockInfoOperator = WorkContext.getCurrent().get(LockInfoOperator.class);
return lockInfoOperator instanceof DefaultLockInfoOperator;
}
public static boolean unableGetLockInfo() {
return WorkContext.getCurrent().isLocal() && !FineEmbedServer.isRunning();
}
}

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

@ -10,7 +10,7 @@ import javax.swing.JComponent;
* Date: 13-7-15
* Time: 上午10:28
*/
public interface BaseJForm<T> extends JTemplateProvider<T> {
public interface BaseJForm<T> extends JTemplateProvider<T>, JDashboard {
String XML_TAG = "JForm";
int FORM_TAB = 0;
@ -58,4 +58,9 @@ public interface BaseJForm<T> extends JTemplateProvider<T> {
* @param ecContainer ElementCase所在container
*/
void tabChanged(int index, FormElementCaseContainerProvider ecContainer);
@Override
default void switchToDashBoardEditor() {
tabChanged(FORM_TAB);
}
}

18
designer-base/src/main/java/com/fr/design/mainframe/DesignerFrame.java

@ -28,6 +28,8 @@ import com.fr.design.fun.impl.AbstractTemplateTreeShortCutProvider;
import com.fr.design.gui.iprogressbar.ProgressDialog;
import com.fr.design.gui.iscrollbar.UIScrollBar;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.share.mini.MiniShopDisposingChecker;
import com.fr.design.mainframe.share.mini.MiniShopNativeTaskManager;
import com.fr.design.mainframe.toolbar.ToolBarMenuDock;
import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
import com.fr.design.mainframe.vcs.common.VcsHelper;
@ -35,8 +37,11 @@ import com.fr.design.menu.ShortCut;
import com.fr.design.os.impl.MacOsAddListenerAction;
import com.fr.design.os.impl.SupportOSImpl;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.design.utils.TemplateUtils;
import com.fr.design.lock.LockInfoDialog;
import com.fr.event.EventDispatcher;
import com.fr.exception.DecryptTemplateException;
import com.fr.exception.TplLockedException;
import com.fr.exit.DesignerExiter;
import com.fr.file.FILE;
import com.fr.file.FILEFactory;
@ -57,6 +62,7 @@ import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import com.fr.workspace.connect.WorkspaceConnectionInfo;
import java.util.UUID;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JFrame;
@ -153,6 +159,11 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
@Override
public void windowClosing(WindowEvent e) {
// 检查mini商城是否存在未结束的后台任务
if (!MiniShopDisposingChecker.check()) {
return;
}
// 关闭前check
if (!TemplateSavingChecker.check()) {
return;
@ -678,7 +689,7 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
if (!editingTemplate.getEditingFILE().exists()) {
path = FILEFactory.MEM_PREFIX + path;
} else if (path.startsWith(ProjectConstants.REPORTLETS_NAME)) {
path = workspace.getPath() + File.separator + path;
path = workspace.getPath() + File.separator + TemplateUtils.createLockeTemplatedName(editingTemplate, path);
}
defaultTitleSB.append(" ").append(path);
}
@ -962,6 +973,11 @@ public class DesignerFrame extends JFrame implements JTemplateActionListener, Ta
}
} catch (Throwable t) {
FineLoggerFactory.getLogger().error(t.getMessage(), t);
if (t.getCause() instanceof TplLockedException) {
TemplateTreePane.getInstance().getFileNode().setLock(UUID.randomUUID().toString());
LockInfoDialog.show(null);
return;
}
addAndActivateJTemplate();
}

69
designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java

@ -43,6 +43,7 @@ import com.fr.file.FileNodeFILE;
import com.fr.file.filetree.FileNode;
import com.fr.general.ComparatorUtils;
import com.fr.general.GeneralContext;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.injectable.PluginModule;
@ -56,6 +57,7 @@ import com.fr.stable.project.ProjectConstants;
import com.fr.third.org.apache.commons.io.FilenameUtils;
import com.fr.workspace.WorkContext;
import com.fr.report.lock.LockInfoOperator;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
@ -127,6 +129,8 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
private UIToolbar toolBar;
private UIToolbar rightToolBar;
private NewFolderAction newFolderAction = new NewFolderAction();
private RefreshTreeAction refreshTreeAction = new RefreshTreeAction();
@ -148,7 +152,7 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
toolBar.setBorderPainted(true);
JPanel tooBarPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
JPanel parent = new JPanel(new BorderLayout());
parent.add(toolBar, BorderLayout.CENTER);
parent.add(createUpToolBarPane(), BorderLayout.CENTER);
parent.setBorder(BorderFactory.createEmptyBorder(3, 0, 4, 0));
tooBarPane.add(parent, BorderLayout.CENTER);
tooBarPane.add(new UIMenuHighLight(), BorderLayout.SOUTH);
@ -186,6 +190,56 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
selectedOperation.refresh();
}
private JPanel createUpToolBarPane() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(toolBar, BorderLayout.CENTER);
if (WorkContext.getCurrent().isRoot()) {
rightToolBar = new UIToolbar(FlowLayout.RIGHT);
rightToolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.TOOLBAR_BORDER_COLOR));
rightToolBar.setBorderPainted(true);
UILabel tipLabel = new UILabel(Toolkit.i18nText("Fine_Design_Template_Lock_Status"));
tipLabel.setForeground(Color.GRAY);
rightToolBar.add(tipLabel);
UIButton button = new UIButton(IOUtils.readIcon("/com/fr/design/images/toolbarbtn/lock.png"));
button.setRolloverIcon(IOUtils.readIcon("/com/fr/design/images/toolbarbtn/unlock.png"));
button.setBorderPainted(false);
button.setContentAreaFilled(false);
button.set4ToolbarButton();
button.setToolTipText(Toolkit.i18nText("Fine_Design_Template_Unlock_Tip"));
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int option = FineJOptionPane.showOptionDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine_Design_Template_UnLock_Tip"),
Toolkit.i18nText("Fine-Design_Basic_Alert"),
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE,
IOUtils.readIcon("/com/fr/design/images/warnings/warning32.png"),
new Object[] {Toolkit.i18nText("Fine_Design_Template_UnLock_I_Known"), Toolkit.i18nText("Fine-Design_Basic_Button_Cancel")}, null);
if (option == JOptionPane.YES_OPTION) {
String path = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, TemplateTreePane.getInstance().getTemplateFileTree().getSelectedTemplatePath());
boolean success = WorkContext.getCurrent().get(LockInfoOperator.class).unLockTpl(path);
if (success) {
FileNode fileNode = TemplateTreePane.getInstance().getFileNode();
refreshRightToolBarBy(fileNode);
} else {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Template_Unlock_Failed"),
Toolkit.i18nText("Fine-Design_Basic_Alert"),
JOptionPane.WARNING_MESSAGE);
FineLoggerFactory.getLogger().error("Unlock {} failed", path);
}
TemplateTreePane.getInstance().refresh();
}
}
});
rightToolBar.add(button);
refreshRightToolBarBy(TemplateTreePane.getInstance().getFileNode());
panel.add(rightToolBar, BorderLayout.EAST);
}
return panel;
}
public final void setCurrentEditingTemplate(JTemplate<?, ?> jt) {
DesignModelAdapter.setCurrentModelAdapter(jt.getModel());
@ -545,6 +599,19 @@ public class DesignerFrameFileDealerPane extends JPanel implements FileToolbarSt
}
}
public void refreshRightToolBarBy(FileNode fileNode) {
if (rightToolBar != null) {
boolean locked = fileNode != null
&& StringUtils.isNotEmpty(fileNode.getLock())
&& !ComparatorUtils.equals(fileNode.getLock(), fileNode.getUserID());
boolean visible = locked
&& WorkContext.getCurrent().isRoot()
&& WorkContext.getCurrent().get(LockInfoOperator.class).isUnLockable()
&& !WorkContext.getCurrent().get(LockInfoOperator.class).isTplUnLocked(fileNode.getEnvPath());
rightToolBar.setVisible(visible);
}
}
/**
* 重命名对话框
* 支持快捷键EnterESC

46
designer-form/src/main/java/com/fr/design/fit/DesignerUIModeConfig.java → designer-base/src/main/java/com/fr/design/mainframe/DesignerUIModeConfig.java

@ -1,19 +1,16 @@
package com.fr.design.fit;
package com.fr.design.mainframe;
import com.fr.base.ScreenResolution;
import com.fr.design.fun.ReportLengthUNITProvider;
import com.fr.design.unit.UnitConvertUtil;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRScreen;
import com.fr.stable.Constants;
import java.awt.Dimension;
/**
* Created by kerry on 2020-06-05
*/
public class DesignerUIModeConfig {
private DesignerUIMode mode = DesignerUIMode.NEW_UI_MODE;
private DesignerUIMode mode = DesignerUIMode.ABSOLUTE_MEASURE_UI_MODE;
private static class DesignerUIModeConfigHolder {
private static final DesignerUIModeConfig designerUIModeConfig = new DesignerUIModeConfig();
@ -33,22 +30,22 @@ public class DesignerUIModeConfig {
*
* @return boolean
*/
public boolean newUIMode() {
return ComparatorUtils.equals(DesignerUIMode.NEW_UI_MODE, mode);
public boolean simulateWebUIMode() {
return ComparatorUtils.equals(DesignerUIMode.SIMULATE_WEB_UI_MODE, mode);
}
/**
* 设置新ui模式
*/
public void setNewUIMode() {
this.mode = DesignerUIMode.NEW_UI_MODE;
public void setSimulateWebUIMode() {
this.mode = DesignerUIMode.SIMULATE_WEB_UI_MODE;
}
/**
* 设置老ui模式
*/
public void setOldUIMode() {
this.mode = DesignerUIMode.OLD_UI_MODE;
public void setAbsoluteMeasureUIMode() {
this.mode = DesignerUIMode.ABSOLUTE_MEASURE_UI_MODE;
}
/**
@ -70,55 +67,38 @@ public class DesignerUIModeConfig {
return mode.getScreenResolution();
}
/**
* 根据屏幕尺寸获取设计时的FRScreen
*
* @param screen 屏幕尺寸
* @return FRScreen
*/
public FRScreen getDesignScreenByDimension(Dimension screen) {
return mode.getDesignScreenByDimension(screen);
}
private enum DesignerUIMode {
OLD_UI_MODE {
ABSOLUTE_MEASURE_UI_MODE {
@Override
protected ReportLengthUNITProvider parseLengthUNIT(int unitType) {
return UnitConvertUtil.parseLengthUNIT(unitType);
}
@Override
protected FRScreen getDesignScreenByDimension(Dimension screen) {
return FRScreen.getDesignScreenByDimension(screen);
}
@Override
protected int getScreenResolution() {
return ScreenResolution.getScreenResolution();
}
},
NEW_UI_MODE {
SIMULATE_WEB_UI_MODE {
@Override
protected ReportLengthUNITProvider parseLengthUNIT(int unitType) {
return new PXReportLengthUNIT();
}
@Override
protected FRScreen getDesignScreenByDimension(Dimension screen) {
return FRScreen.p1440;
}
@Override
protected int getScreenResolution() {
return Constants.DEFAULT_WEBWRITE_AND_SCREEN_RESOLUTION;
}
};
protected abstract ReportLengthUNITProvider parseLengthUNIT(int unitType);
protected abstract FRScreen getDesignScreenByDimension(Dimension screen);
protected abstract int getScreenResolution();
}
}

16
designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java

@ -11,9 +11,11 @@ import com.fr.design.dialog.BasicPane;
import com.fr.design.event.TargetModifiedEvent;
import com.fr.design.event.TargetModifiedListener;
import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.utils.LoadingUtils;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.util.HashMap;
@ -30,12 +32,14 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener
private static final int TRANSPARENT_LAYER = 1;
private static final int LOADING_LAYER = 2;
private static final int FAILED_LAYER = 3;
private static final int FORBIDDEN_LAYER = 4;
private static final long serialVersionUID = 1L;
private JTemplate<?, ?> component;
private TransparentPane transparentPane = new TransparentPane();
private OpenLoadingPane loadingPane = new OpenLoadingPane();
private JPanel loadingPane = LoadingUtils.createLoadingPane();
private OpenFailedPane failedPane = new OpenFailedPane();
private ForbiddenPane forbiddenPane = new ForbiddenPane();
Map<Component, Boolean> backUpToolbarComponentState = new HashMap<>();
@ -52,6 +56,7 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener
setLayout(new BorderLayout());
layeredPane.add(transparentPane, TRANSPARENT_LAYER);
layeredPane.add(failedPane, FAILED_LAYER);
layeredPane.add(forbiddenPane, FORBIDDEN_LAYER);
add(layeredPane, BorderLayout.CENTER);
}
@ -93,6 +98,8 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener
showOpenStatus();
} else if (jt.isOpenFailed()) {
showOpenFailedCover(jt.getTemplateOpenFailedTip());
} else if (jt.isForbidden()) {
showForbiddenStatus();
} else {
hideCover();
}
@ -138,6 +145,13 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener
}
}
public void showForbiddenStatus() {
component.setVisible(false);
layeredPane.moveToFront(forbiddenPane);
forbidToolBar();
EastRegionContainerPane.getInstance().updateAllPropertyPane();
}
public void hideCover() {
recoverToolBar();
transparentPane.stop();

190
designer-base/src/main/java/com/fr/design/mainframe/ForbiddenPane.java

@ -0,0 +1,190 @@
package com.fr.design.mainframe;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.DesignSizeI18nManager;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.guide.base.GuideView;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.workspace.WorkContext;
import com.fr.report.lock.LockInfoOperator;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
/**
* @author hades
* @version 11.0
* Created by hades on 2021/12/6
*/
public class ForbiddenPane extends JPanel {
private static final ImageIcon LOCK_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/mainframe/lock_template.png"));
private static final Color TIP_COLOR = new Color(108, 174, 235);
private static final Color BUTTON_COLOR = new Color(63, 155, 249);
private static final int Y_GAP = 10;
private static final int X_GAP = 10;
private static final int ARC = 4;
private final UILabel lockLabel;
private final UILabel tipLabel;
private final JButton refreshButton;
public ForbiddenPane() {
setLayout(new LayoutManager() {
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return parent.getPreferredSize();
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return null;
}
@Override
public void layoutContainer(Container parent) {
int width = parent.getParent().getWidth();
int height = parent.getParent().getHeight();
int lockLabelWidth = lockLabel.getPreferredSize().width;
int lockLabelHeight = lockLabel.getPreferredSize().height;
int lockLabelX = (width - lockLabelWidth) / 2;
int lockLabelY = (height - lockLabelHeight) / 2;
int tipLabelWidth = tipLabel.getPreferredSize().width;
int tipLabelHeight = tipLabel.getPreferredSize().height;
int tipLabelX = (width - tipLabelWidth) / 2 + X_GAP;
int tipLabelY = lockLabelY + lockLabelHeight;
int refreshButtonWidth = refreshButton.getPreferredSize().width;
int refreshButtonHeight = refreshButton.getPreferredSize().height;
int refreshButtonX = (width - refreshButtonWidth) / 2 + X_GAP;
int refreshButtonY = tipLabelY + refreshButtonHeight + Y_GAP;
lockLabel.setBounds(lockLabelX, lockLabelY, lockLabelWidth, lockLabelHeight);
tipLabel.setBounds(tipLabelX, tipLabelY, tipLabelWidth, tipLabelHeight);
refreshButton.setBounds(refreshButtonX, refreshButtonY, refreshButtonWidth, refreshButtonHeight);
}
@Override
public void addLayoutComponent(String name, Component comp) {
}
});
setBackground(Color.WHITE);
lockLabel = new UILabel(LOCK_ICON);
tipLabel = new UILabel(Toolkit.i18nText("Fine_Design_Template_Has_Been_Locked_Tip"));
Font labelFont = tipLabel.getFont();
tipLabel.setFont(new Font(labelFont.getName(), labelFont.getStyle(), 14));
tipLabel.setForeground(TIP_COLOR);
refreshButton = new JButton(Toolkit.i18nText("Fine-Design_Basic_Refresh")) {
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(BUTTON_COLOR);
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), ARC, ARC);
super.paintComponent(g2d);
}
};
refreshButton.setPreferredSize(DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.mainframe.ForbiddenPane.refreshButton"));
refreshButton.setForeground(Color.WHITE);
refreshButton.setBorderPainted(false);
refreshButton.setContentAreaFilled(false);
refreshButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
if (template == null) {
return;
}
// 展示下画面
LoadingDialog loadingDialog = new LoadingDialog();
loadingDialog.showDialog();
new SwingWorker<Boolean, Void>(){
@Override
protected Boolean doInBackground() throws Exception {
return WorkContext.getCurrent().get(LockInfoOperator.class).isTplLocked(template.getEditingFILE().getPath());
}
@Override
protected void done() {
boolean unLocked;
loadingDialog.hideDialog();
try {
unLocked = !get();
if (unLocked) {
template.whenClose();
JTemplate<?, ?> newTemplate = JTemplateFactory.createJTemplate(template.getEditingFILE());
HistoryTemplateListCache.getInstance().replaceCurrentEditingTemplate(newTemplate);
DesignerContext.getDesignerFrame().addAndActivateJTemplate(newTemplate);
}
} catch (Exception e) {
loadingDialog.hideDialog();
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}.execute();
}
});
add(lockLabel);
add(tipLabel);
add(refreshButton);
}
}
class LoadingDialog extends JDialog {
private static final ImageIcon LOADING_ICON = new ImageIcon(IOUtils.readImage("/com/fr/design/images/mainframe/refreh_icon.png"));
private GuideView guideView;
public LoadingDialog() {
super(DesignerContext.getDesignerFrame());
setLayout(new BorderLayout());
this.getContentPane().setBackground(Color.WHITE);
this.setResizable(false);
this.setUndecorated(true);
this.setAlwaysOnTop(true);
this.setModal(false);
this.setSize(new Dimension(400, 100));
this.add(new UILabel(LOADING_ICON, UILabel.CENTER), BorderLayout.NORTH);
this.add(new UILabel(Toolkit.i18nText(Toolkit.i18nText("Fine_Design_Template_Refresh")), UILabel.CENTER), BorderLayout.CENTER);
GUICoreUtils.centerWindow(this);
}
public void showDialog() {
DesignerContext.getDesignerFrame().setExtendedState(JFrame.MAXIMIZED_BOTH);
guideView = new GuideView(DesignerContext.getDesignerFrame());
GUICoreUtils.centerWindow(DesignerContext.getDesignerFrame(), guideView);
guideView.setBounds(DesignerContext.getDesignerFrame().getBounds());
guideView.setVisible(true);
this.setVisible(true);
}
public void hideDialog() {
this.dispose();
guideView.dismissGuide();
}
}

10
designer-base/src/main/java/com/fr/design/mainframe/JDashboard.java

@ -0,0 +1,10 @@
package com.fr.design.mainframe;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2022/3/1
*/
public interface JDashboard {
void switchToDashBoardEditor();
}

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

@ -2,6 +2,7 @@ package com.fr.design.mainframe;
import com.fr.base.BaseUtils;
import com.fr.base.Parameter;
import com.fr.base.TRL;
import com.fr.base.extension.FileExtension;
import com.fr.base.io.BaseBook;
import com.fr.base.iofile.attr.DesignBanCopyAttrMark;
@ -58,12 +59,14 @@ import com.fr.design.ui.util.UIUtil;
import com.fr.design.utils.DesignUtils;
import com.fr.design.worker.save.CallbackSaveWorker;
import com.fr.design.worker.save.EmptyCallBackSaveWorker;
import com.fr.design.worker.save.SaveFailureHandler;
import com.fr.design.write.submit.DBManipulationInWidgetEventPane;
import com.fr.design.write.submit.DBManipulationPane;
import com.fr.event.EventDispatcher;
import com.fr.file.FILE;
import com.fr.file.FILEChooserPane;
import com.fr.file.MemFILE;
import com.fr.file.StashedFILE;
import com.fr.form.ui.NoneWidget;
import com.fr.form.ui.Widget;
import com.fr.general.ComparatorUtils;
@ -83,8 +86,11 @@ import com.fr.plugin.observer.PluginEvent;
import com.fr.plugin.observer.PluginEventListener;
import com.fr.plugin.observer.PluginEventType;
import com.fr.plugin.observer.PluginListenerRegistration;
import com.fr.report.InconsistentLockException;
import com.fr.report.UnLockedException;
import com.fr.report.cell.Elem;
import com.fr.report.cell.cellattr.CellImage;
import com.fr.report.lock.LockInfoOperator;
import com.fr.stable.ArrayUtils;
import com.fr.stable.Filter;
import com.fr.stable.ProductConstants;
@ -102,6 +108,7 @@ import javax.swing.undo.UndoManager;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.io.ByteArrayOutputStream;
import java.util.Set;
import java.util.concurrent.Callable;
@ -124,6 +131,8 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
protected U authorityUndoState = null;
protected T template; // 当前模板
private boolean isNewCreateTpl = false; //当前模板是否为新建模板
private volatile boolean forbidden;
/**
* 模板过程的相关信息
*
@ -432,6 +441,22 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
stopListenThemeConfig();
}
public FILE templateToStashFile() {
FILE file = this.getEditingFILE();
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BaseBook target = this.getTarget();
if (target != null) {
target.export(outputStream);
return new StashedFILE(file, outputStream.toByteArray(), template.suffix());
}
// 如果 target == null 那么这个模板是被模板内存优化功能处理过的,不用处理
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
/**
* 刷新内部资源
@ -640,6 +665,8 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
*/
public void redo() {
this.getUndoManager().redo();
// 重做前模版使用主题可能已经被删除或修改,需要重置模版样式
checkAndResetTheme();
fireSuperTargetModified();
}
@ -959,10 +986,11 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
return false;
}
try {
checkBeforeSave();
export();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage(), "Save Error", JOptionPane.ERROR_MESSAGE);
SaveFailureHandler.getInstance().process(e);
return false;
}
this.editingFILE = editingFILE;
@ -973,10 +1001,21 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
return true;
}
public boolean isNewCreateTpl(){
public boolean isNewCreateTpl() {
return isNewCreateTpl;
}
protected void checkBeforeSave() throws Exception {
// 保存前校验下未解锁
if (WorkContext.getCurrent().get(LockInfoOperator.class).isTplUnLocked(getEditingFILE().getPath())) {
throw new UnLockedException();
}
// 校验锁定信息是否一致
if (getEditingFILE().exists() && !WorkContext.getCurrent().get(LockInfoOperator.class).isConsistentLock(getEditingFILE().getPath())) {
throw new InconsistentLockException();
}
}
protected boolean export() throws Exception {
return this.getTarget().export(TemplateResourceManager.getResource().saveTemplate(getEditingFILE()));
@ -1505,7 +1544,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
/**
* 设置新引擎后有不支持的功能时设计器中模板的标题需要加上兼容模式或者不支持分页引擎来提示用户
* */
*/
private String compatibilityTip() {
if (!CptAndCptxCompatibilityUtil.isEngineXEnable(this.getTarget(), getEditingFILE().getPath())) {
return StringUtils.EMPTY;
@ -1618,6 +1657,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
if (editingFILE == null || editingFILE instanceof MemFILE) {
return false;
}
checkBeforeSave();
export();
this.editingFILE = editingFILE;
return true;
@ -1806,8 +1846,16 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
this.openFailed = openFailed;
}
public boolean isForbidden() {
return forbidden;
}
public void setForbidden(boolean forbidden) {
this.forbidden = forbidden;
}
public boolean checkEnable() {
return !isSaving() && !isOpening() && !isOpenFailed();
return !isSaving() && !isOpening() && !isOpenFailed() && !isForbidden();
}
public String getRuntimeId() {
@ -1840,4 +1888,22 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
templateThemeButton.setText(name);
templateThemeButton.setToolTipText(name);
}
/**
* 定位
*
* @param trl
*/
public void navigate(TRL trl) {
}
public void generateForBiddenTemplate() {
}
public void setDesignerUIMode(){
DesignerUIModeConfig.getInstance().setAbsoluteMeasureUIMode();
}
}

4
designer-base/src/main/java/com/fr/design/mainframe/NorthRegionContainerPane.java

@ -151,7 +151,7 @@ public class NorthRegionContainerPane extends JPanel {
public void execute(Object... objects) {
bbsLoginPane[0] = ad.createBBSLoginPane();
}
}, SupportOSImpl.USERINFOPANE);
}, SupportOSImpl. BBS_USER_LOGIN_PANE);
processor.hold(northEastPane, LogMessageBar.getInstance(), bbsLoginPane[0]);
}
northEastPane.add(ad.createAlphaFinePane());
@ -166,7 +166,7 @@ public class NorthRegionContainerPane extends JPanel {
public void execute(Object... objects) {
northEastPane.add(ad.createBBSLoginPane());
}
}, SupportOSImpl.USERINFOPANE);
}, SupportOSImpl.BBS_USER_LOGIN_PANE);
}

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

Loading…
Cancel
Save