forked from fanruan/design
Browse Source
* commit 'd8bac391fe857210adbe39c38c1df51f8562cb9d': (104 commits) REPORT-46892 切换目录有插件版本不匹配目录配置页面显示问题 REPORT-46584 【10.0.13冒烟】设计器卡死 REPORT-46892 【冒烟】切换到本地目录有插件版本不匹配时,远程配置页面会消失的比较慢 REPORT-46585 fix 单个插件监听逻辑保持与之前一致 REPORT-46585 切换工作目录时 先移除后添加插件监听 REPORT-46285 jdk11-背景图标,有一点异常的红色显示 【问题原因】这个问题是由jdk差异造成的,前景色和背景色图标都是由上面的图标+下面的取色矩形组成,下面的取色矩形的位置由整个图标的宽高决定,而在jdk11下,拿到的宽高与jdk8一样,但是最终绘制出来的取色矩形会往左边偏移一点,大概是1px,而背景色图标之前下面的取色矩形初始为红色,在偏移了之后,绘制底下取色矩形不能完全覆盖初始红色,所以漏了一点出来,表现为异常的红色。 【改动思路】与产品确认后,决定先把背景色图标取色矩形设置为透明色,这样就不会漏出一点红色,而取色矩形绘制有点偏移的问题需要去改一下UIColorButton的UI,这个在换完相关图标后再统一修改比较好 REPORT-45689 加上判空 CHART-17822 设计器界面内的图形不小心切换到其他图形且不保存,点击撤销键没法返回到切换前的图形 REPORT-46574 & REPORT-46813 & REPORT-46550 REPORT-45689 兼容空类型 无须填充面板 REPORT-46679 jdk11-设计器内图标优化-目录树图标都模糊,尤其是刷新图标 【问题原因】svg图标漏传到release分支了,所以显示的是之前的png图,比较模糊 【改动思路】补充图标 REPORT-46234 普通报表\聚合报表,点击para,上方是控件设置,但是下方是组件名称 REPORT-46585 在远程新建编辑的未保存模板切换回本地不能保存 REPORT-45689 顶部参数界面样式优化 REPORT-46713 && REPORT-46469 && REPORT-46735 删去注释代码 REPORT-46713 && REPORT-46469 && REPORT-46735 【问题原因】由REPORT-44961中的改动引起 【改动思路】引起了两个客户bug,需要在明天的中间版本发布,因此还没仔细排查原因,暂时先回退掉REPORT-44961中的改动,赶一下明天的发布,后续继续修改REPORT-44961的时候再排查原因 CHART-17805 饼图面板美化 REPORT-46683 【冒烟】数据库查询,选中表并拖动的时候,弹窗变化了 在UIConstants中添加一个EMPTY_ICON代表无图标,然后在UpdateAction的setSmallIcon方法中对传过来的资源路径进行判断,如果为"",就把null作为Icon 的Value值put到map中,与之前的逻辑一致 REPORT-46589 把单独过滤的类抽出来 以过滤器形式调用 REPORT-46683 【冒烟】数据库查询,选中表并拖动的时候,弹窗变化了 SQLEitPane的分隔符误传成CR了,改为LF重新上传 ...final/10.0
superman
4 years ago
450 changed files with 7550 additions and 2011 deletions
@ -0,0 +1,105 @@ |
|||||||
|
package com.fr.base.svg; |
||||||
|
|
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
import javax.swing.ImageIcon; |
||||||
|
|
||||||
|
/** |
||||||
|
* 主要是用来读取svgIcon的工具类 |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2020/12/23 |
||||||
|
*/ |
||||||
|
public class IconUtils { |
||||||
|
|
||||||
|
private static final String ICON_SUFFIX_SVG = ".svg"; |
||||||
|
private static final String ICON_SUFFIX_PNG = ".png"; |
||||||
|
private static final String ICON_SUFFIX_GIF = ".gif"; |
||||||
|
private static final String SUFFIX_SEPARATOR = "."; |
||||||
|
|
||||||
|
public static final String ICON_TYPE_NORMAL= "_normal.svg"; |
||||||
|
public static final String ICON_TYPE_DISABLED= "_disabled.svg"; |
||||||
|
public static final String ICON_TYPE_PRESSED= "_pressed.svg"; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 可以读取SVG图标或者普通图标,并且可以读取不带扩展名的文件 |
||||||
|
* 不带扩展名时以svg优先、其次png,最后gif |
||||||
|
* @param resource 图片路径 |
||||||
|
* @return 图标 |
||||||
|
*/ |
||||||
|
public static Icon readIcon(String resource) { |
||||||
|
// 判断是否有.XXX文件后缀
|
||||||
|
if (resource.contains(SUFFIX_SEPARATOR)) { |
||||||
|
// 判断是否以.svg结尾
|
||||||
|
if (resource.endsWith(ICON_SUFFIX_SVG)) { |
||||||
|
return SVGIcon.readSVGIcon(resource); |
||||||
|
} |
||||||
|
return IOUtils.readIcon(resource); |
||||||
|
} |
||||||
|
// 文件无后缀时
|
||||||
|
return readNoSuffixResource(resource, ICON_TYPE_NORMAL); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 尝试读取不带扩展名的图标,svg优先,其次png,最后gif,都没读到就打印错误日志,返回空白Icon |
||||||
|
* @param resource 图片路径 |
||||||
|
* @param svgIconType 针对svg来说的图标类型 |
||||||
|
* 取值为:ICON_TYPE_NORMAL、ICON_TYPE_DISABLED、ICON_TYPE_PRESSED |
||||||
|
* @return 图标 |
||||||
|
*/ |
||||||
|
private static Icon readNoSuffixResource(String resource, String svgIconType) { |
||||||
|
String svgPath = resource + svgIconType; |
||||||
|
if (IOUtils.readResource(svgPath) != null) { |
||||||
|
return SVGIcon.readSVGIcon(svgPath); |
||||||
|
} |
||||||
|
String pngPath = resource + ICON_SUFFIX_PNG; |
||||||
|
if (IOUtils.readResource(pngPath) != null) { |
||||||
|
return IOUtils.readIcon(pngPath); |
||||||
|
} |
||||||
|
String gifPath = resource + ICON_SUFFIX_GIF; |
||||||
|
if (IOUtils.readResource(gifPath) != null) { |
||||||
|
return IOUtils.readIcon(gifPath); |
||||||
|
} |
||||||
|
FineLoggerFactory.getLogger().error("File not exists:{}", resource); |
||||||
|
return new ImageIcon(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 读取指定类型的svgIcon |
||||||
|
* @param resource |
||||||
|
* @param svgIconType |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static Icon readSVGIcon(String resource, String svgIconType) { |
||||||
|
// 判断下是否有后缀
|
||||||
|
if (!resource.contains(SUFFIX_SEPARATOR)) { |
||||||
|
return readNoSuffixResource(resource, svgIconType); |
||||||
|
} |
||||||
|
// 如果是".png"后缀,就替换为传入的svgIconType,然后读取图标
|
||||||
|
if (resource.endsWith(ICON_SUFFIX_PNG)) { |
||||||
|
return readSpecifiedTypeIcon(resource, ICON_SUFFIX_PNG, svgIconType); |
||||||
|
} |
||||||
|
// 如果是"_XXXXXX.svg"后缀
|
||||||
|
if (resource.endsWith(ICON_TYPE_NORMAL)) { |
||||||
|
return readSpecifiedTypeIcon(resource, ICON_TYPE_NORMAL, svgIconType); |
||||||
|
} |
||||||
|
if (resource.endsWith(ICON_TYPE_DISABLED)) { |
||||||
|
return readSpecifiedTypeIcon(resource, ICON_TYPE_DISABLED, svgIconType); |
||||||
|
} |
||||||
|
if (resource.endsWith(ICON_TYPE_PRESSED)) { |
||||||
|
return readSpecifiedTypeIcon(resource, ICON_TYPE_PRESSED, svgIconType); |
||||||
|
} |
||||||
|
return readIcon(resource); |
||||||
|
} |
||||||
|
|
||||||
|
private static Icon readSpecifiedTypeIcon(String resource, String oldSuffix, String newSuffix) { |
||||||
|
String iconPath = resource.replace(oldSuffix, newSuffix); |
||||||
|
if (IOUtils.readResource(iconPath) != null) { |
||||||
|
return SVGIcon.readSVGIcon(iconPath); |
||||||
|
} |
||||||
|
return readIcon(resource); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
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 java.awt.image.BufferedImage; |
||||||
|
|
||||||
|
/** |
||||||
|
* SVG转化而来的Icon |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2020/12/17 |
||||||
|
*/ |
||||||
|
public class SVGIcon implements Icon { |
||||||
|
|
||||||
|
private BufferedImage image; |
||||||
|
|
||||||
|
private static final boolean HI_DPI_SURPORT = SystemScaleUtils.isJreHiDPIEnabled(); |
||||||
|
|
||||||
|
public static final float SYSTEM_SCALE = SystemScaleUtils.sysScale(); |
||||||
|
|
||||||
|
private static final String ICON_PREFIX = "/"; |
||||||
|
|
||||||
|
public SVGIcon(BufferedImage image) { |
||||||
|
this.image = image; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void paintIcon(Component c, Graphics g, int x, int y) { |
||||||
|
if (HI_DPI_SURPORT) { |
||||||
|
Graphics2D graphics = (Graphics2D) g.create(x, y, image.getWidth(null), image.getHeight(null)); |
||||||
|
float scale = SYSTEM_SCALE; |
||||||
|
graphics.scale(1 / scale, 1 / scale); |
||||||
|
graphics.drawImage(image, 0, 0, null); |
||||||
|
graphics.scale(1.0D, 1.0D); |
||||||
|
graphics.dispose(); |
||||||
|
} else { |
||||||
|
g.drawImage(image, x, y, null); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getIconWidth() { |
||||||
|
return HI_DPI_SURPORT ? (int) (image.getWidth() / SYSTEM_SCALE) : image.getWidth(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getIconHeight() { |
||||||
|
return HI_DPI_SURPORT ? (int) (image.getHeight() / SYSTEM_SCALE) : image.getHeight(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 读取高清图标 |
||||||
|
* @param url |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static Icon readSVGIcon(String url) { |
||||||
|
if (!url.startsWith(ICON_PREFIX)) { |
||||||
|
url = ICON_PREFIX + url; |
||||||
|
} |
||||||
|
BufferedImage image = (BufferedImage) SVGLoader.load(url); |
||||||
|
return image == null ? IOUtils.readIcon(url) : new SVGIcon(image); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 读取指定尺寸的图标 |
||||||
|
* @param url 资源路径 |
||||||
|
* @param width 宽度 |
||||||
|
* @param height 高度 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static Icon readSVGIcon(String url, float width, float height) { |
||||||
|
if (!url.startsWith(ICON_PREFIX)) { |
||||||
|
url = ICON_PREFIX + url; |
||||||
|
} |
||||||
|
BufferedImage image = (BufferedImage) SVGLoader.load(url, width, height); |
||||||
|
return image == null ? IOUtils.readIcon(url) : new SVGIcon(image); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,92 @@ |
|||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,181 @@ |
|||||||
|
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); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,86 @@ |
|||||||
|
package com.fr.design; |
||||||
|
|
||||||
|
import com.fr.design.constants.DesignerLaunchStatus; |
||||||
|
import com.fr.design.file.HistoryTemplateListCache; |
||||||
|
import com.fr.design.fun.HyperlinkProvider; |
||||||
|
import com.fr.design.fun.TableDataDefineProvider; |
||||||
|
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 java.util.HashSet; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/17 |
||||||
|
*/ |
||||||
|
public class PluginClassRefreshManager { |
||||||
|
|
||||||
|
|
||||||
|
private static final PluginClassRefreshManager INSTANCE = new PluginClassRefreshManager(); |
||||||
|
|
||||||
|
private final Set<String> context = new HashSet<>(); |
||||||
|
|
||||||
|
private final PluginEventListener pluginAfterRunEventListener = new PluginEventListener() { |
||||||
|
@Override |
||||||
|
public void on(PluginEvent event) { |
||||||
|
// 兼容之前版本特性
|
||||||
|
for (String tag : context) { |
||||||
|
if (event.getContext().contain(tag)) { |
||||||
|
HistoryTemplateListCache.getInstance().reloadAllEditingTemplate(); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
// 重新载入模板xml内容 到 Workbook/Form对象中
|
||||||
|
HistoryTemplateListCache.getInstance().reloadAllEditingTemplateByPlugin(event.getContext()); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private final PluginEventListener beforeAllPluginActive = new PluginEventListener() { |
||||||
|
@Override |
||||||
|
public void on(PluginEvent event) { |
||||||
|
PluginListenerRegistration.getInstance().stopListen(pluginAfterRunEventListener); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private final PluginEventListener afterAllPluginsActive = new PluginEventListener() { |
||||||
|
@Override |
||||||
|
public void on(PluginEvent event) { |
||||||
|
PluginListenerRegistration.getInstance().listen(PluginEventType.AfterRun, pluginAfterRunEventListener); |
||||||
|
if (DesignerLaunchStatus.getStatus() != DesignerLaunchStatus.WORKSPACE_INIT_COMPLETE) { |
||||||
|
HistoryTemplateListCache.getInstance().reloadAllEditingTemplate(); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
public static PluginClassRefreshManager getInstance() { |
||||||
|
return INSTANCE; |
||||||
|
} |
||||||
|
|
||||||
|
public void load() { |
||||||
|
context.add(TableDataDefineProvider.XML_TAG); |
||||||
|
context.add(HyperlinkProvider.XML_TAG); |
||||||
|
} |
||||||
|
|
||||||
|
private PluginClassRefreshManager() { |
||||||
|
PluginListenerRegistration.getInstance().listen(PluginEventType.BeforeAllActive, beforeAllPluginActive); |
||||||
|
PluginListenerRegistration.getInstance().listen(PluginEventType.AfterAllActive, afterAllPluginsActive); |
||||||
|
} |
||||||
|
|
||||||
|
public void removePluginListener() { |
||||||
|
PluginListenerRegistration.getInstance().stopListen(this.pluginAfterRunEventListener); |
||||||
|
PluginListenerRegistration.getInstance().stopListen(this.beforeAllPluginActive); |
||||||
|
PluginListenerRegistration.getInstance().stopListen(this.afterAllPluginsActive); |
||||||
|
} |
||||||
|
|
||||||
|
public void addPluginListener() { |
||||||
|
PluginListenerRegistration.getInstance().listen(PluginEventType.AfterRun, this.pluginAfterRunEventListener); |
||||||
|
PluginListenerRegistration.getInstance().listen(PluginEventType.BeforeAllActive, beforeAllPluginActive); |
||||||
|
PluginListenerRegistration.getInstance().listen(PluginEventType.AfterAllActive, afterAllPluginsActive); |
||||||
|
} |
||||||
|
|
||||||
|
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,71 @@ |
|||||||
|
package com.fr.design.file; |
||||||
|
|
||||||
|
import com.fr.common.annotations.Open; |
||||||
|
import com.fr.file.FILE; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.OutputStream; |
||||||
|
|
||||||
|
/** |
||||||
|
* 模板资源操作,可操作模板及模板目录 |
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/23 |
||||||
|
*/ |
||||||
|
@Open |
||||||
|
public interface TemplateResource { |
||||||
|
|
||||||
|
/** |
||||||
|
* 读取模板 |
||||||
|
* @param path |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
InputStream readTemplate(String path) throws Exception; |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存模板 |
||||||
|
* @param file |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
OutputStream saveTemplate(FILE file) throws Exception; |
||||||
|
|
||||||
|
/** |
||||||
|
* 删除某个目录/某个模板 |
||||||
|
* @param file |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
boolean delete(FILE file); |
||||||
|
|
||||||
|
/** |
||||||
|
* 关闭模板 |
||||||
|
* @param path |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
boolean closeTemplate(String path); |
||||||
|
|
||||||
|
/** |
||||||
|
* 重命名模板/目录 |
||||||
|
* @param from |
||||||
|
* @param to |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
boolean rename(String from, String to); |
||||||
|
|
||||||
|
/** |
||||||
|
* 模板/目录是否存在 |
||||||
|
* @param path |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
boolean exist(String path); |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建目录 |
||||||
|
* @param path |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
boolean mkdir(String path); |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
package com.fr.design.file; |
||||||
|
|
||||||
|
import com.fr.design.ExtraDesignClassManager; |
||||||
|
import com.fr.design.file.impl.DefaultTemplateResource; |
||||||
|
import com.fr.design.fun.LocalResourceProvider; |
||||||
|
import com.fr.design.mainframe.DesignerFrameFileDealerPane; |
||||||
|
import com.fr.design.ui.util.UIUtil; |
||||||
|
import com.fr.file.filetree.FileNodes; |
||||||
|
import com.fr.file.filetree.LocalFileNodes; |
||||||
|
import com.fr.plugin.injectable.PluginModule; |
||||||
|
import com.fr.plugin.manage.PluginFilter; |
||||||
|
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.workspace.WorkContext; |
||||||
|
import com.fr.workspace.engine.base.FineObjectPool; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/23 |
||||||
|
*/ |
||||||
|
public class TemplateResourceManager { |
||||||
|
|
||||||
|
private static final TemplateResource DEFAULT_OPERATION = new DefaultTemplateResource(); |
||||||
|
|
||||||
|
private static TemplateResource OPERATION = DEFAULT_OPERATION; |
||||||
|
|
||||||
|
static { |
||||||
|
PluginFilter filter = pluginContext -> pluginContext.contain(PluginModule.ExtraDesign, LocalResourceProvider.XML_TAG); |
||||||
|
|
||||||
|
PluginListenerRegistration.getInstance().listen(PluginEventType.AfterStop, new PluginEventListener() { |
||||||
|
@Override |
||||||
|
public void on(PluginEvent event) { |
||||||
|
registerOperation(new DefaultTemplateResource()); |
||||||
|
FineObjectPool.getInstance().getLocalPool().put(FileNodes.class, new LocalFileNodes()); |
||||||
|
UIUtil.invokeLaterIfNeeded(() -> DesignerFrameFileDealerPane.getInstance().refresh()); |
||||||
|
} |
||||||
|
}, filter); |
||||||
|
|
||||||
|
PluginListenerRegistration.getInstance().listen(PluginEventType.AfterRun, new PluginEventListener() { |
||||||
|
@Override |
||||||
|
public void on(PluginEvent event) { |
||||||
|
LocalResourceProvider provider = ExtraDesignClassManager.getInstance().getSingle(LocalResourceProvider.XML_TAG); |
||||||
|
if (provider != null && WorkContext.getCurrent().isLocal()) { |
||||||
|
registerOperation(provider.createResourceOperation()); |
||||||
|
FineObjectPool.getInstance().getLocalPool().put(FileNodes.class, provider.createFileNodes()); |
||||||
|
UIUtil.invokeLaterIfNeeded(() -> DesignerFrameFileDealerPane.getInstance().refresh()); |
||||||
|
} |
||||||
|
} |
||||||
|
}, filter); |
||||||
|
} |
||||||
|
|
||||||
|
private static void registerOperation(TemplateResource operation) { |
||||||
|
OPERATION = operation; |
||||||
|
} |
||||||
|
|
||||||
|
public static TemplateResource getResource() { |
||||||
|
if (OPERATION == null) { |
||||||
|
return DEFAULT_OPERATION; |
||||||
|
} |
||||||
|
return OPERATION; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.fr.design.file.filter; |
||||||
|
|
||||||
|
import com.fr.stable.Filter; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* 过滤无需遍历的jdk class
|
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/1/7 |
||||||
|
*/ |
||||||
|
public class ClassFilter implements Filter<String> { |
||||||
|
|
||||||
|
|
||||||
|
private static final Set<String> FILTER_SET = new HashSet<>(); |
||||||
|
|
||||||
|
private static final Filter<String> INSTANCE = new ClassFilter(); |
||||||
|
|
||||||
|
public static Filter<String> getInstance() { |
||||||
|
return INSTANCE; |
||||||
|
} |
||||||
|
|
||||||
|
static { |
||||||
|
FILTER_SET.add("java.awt.image.BufferedImage"); |
||||||
|
FILTER_SET.add("sun.awt.AppContext"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean accept(String s) { |
||||||
|
return FILTER_SET.contains(s); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.fr.design.file.impl; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.design.file.TemplateResource; |
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.server.lock.TplOperator; |
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.OutputStream; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/23 |
||||||
|
*/ |
||||||
|
public abstract class AbstractTemplateResource implements TemplateResource { |
||||||
|
|
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package com.fr.design.file.impl; |
||||||
|
|
||||||
|
import com.fr.file.FILE; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.server.lock.TplOperator; |
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.OutputStream; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/23 |
||||||
|
*/ |
||||||
|
public class DefaultTemplateResource extends AbstractTemplateResource { |
||||||
|
|
||||||
|
@Override |
||||||
|
public InputStream readTemplate(String path) throws Exception { |
||||||
|
return new ByteArrayInputStream(WorkContext.getCurrent().get(TplOperator.class).readAndLockFile(path)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OutputStream saveTemplate(FILE file) throws Exception { |
||||||
|
return file.asOutputStream(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean closeTemplate(String path) { |
||||||
|
return WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(path); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean delete(FILE file) { |
||||||
|
return WorkContext.getCurrent().get(TplOperator.class).delete(file.getPath()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean rename(String from, String to) { |
||||||
|
return WorkContext.getCurrent().get(TplOperator.class).rename(from, to); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean exist(String path) { |
||||||
|
return WorkContext.getWorkResource().exist(path); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean mkdir(String path) { |
||||||
|
return WorkContext.getWorkResource().createDirectory(path); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.fr.design.fun; |
||||||
|
|
||||||
|
import com.fr.design.file.TemplateResource; |
||||||
|
import com.fr.file.filetree.FileNodes; |
||||||
|
import com.fr.stable.fun.mark.Immutable; |
||||||
|
|
||||||
|
/** |
||||||
|
* 本地资源操作插件接口 |
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/22 |
||||||
|
*/ |
||||||
|
public interface LocalResourceProvider extends Immutable { |
||||||
|
|
||||||
|
String XML_TAG = "LocalResourceProvider"; |
||||||
|
|
||||||
|
int CURRENT_LEVEL = 1; |
||||||
|
|
||||||
|
/** |
||||||
|
* eg: DefaultResourceOperation |
||||||
|
* |
||||||
|
* @return 目录/模板的各种操作 |
||||||
|
*/ |
||||||
|
TemplateResource createResourceOperation(); |
||||||
|
|
||||||
|
/** |
||||||
|
* eg: LocalFileNodes |
||||||
|
* |
||||||
|
* @return 构建目录树的方式 |
||||||
|
*/ |
||||||
|
FileNodes createFileNodes(); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
package com.fr.design.fun; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.form.ui.mobile.MobileParamStyle; |
||||||
|
import com.fr.stable.fun.mark.Mutable; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/30 |
||||||
|
*/ |
||||||
|
|
||||||
|
public interface MobileParamUIProvider extends Mutable { |
||||||
|
String XML_TAG = "MobileParamUIProvider"; |
||||||
|
|
||||||
|
int CURRENT_LEVEL = 1; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 扩展项的参数面板样式 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Class<? extends MobileParamStyle> classForMobileParamStyle(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 移动端参数面板中扩展项的面板 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
Class<? extends BasicBeanPane<? extends MobileParamStyle>> classForMobileParamAppearance(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 扩展项的名称描述 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
String displayName(); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.fr.design.fun; |
||||||
|
|
||||||
|
import com.fr.stable.fun.mark.Immutable; |
||||||
|
import java.awt.event.MouseEvent; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/14 |
||||||
|
*/ |
||||||
|
public interface TemplateTreeDefineProcessor extends Immutable { |
||||||
|
|
||||||
|
String XML_TAG = "TemplateTreeDefineProcessor"; |
||||||
|
|
||||||
|
int CURRENT_LEVEL = 1; |
||||||
|
|
||||||
|
void rightClickAction(MouseEvent mouseEvent); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package com.fr.design.fun.impl; |
||||||
|
|
||||||
|
import com.fr.design.fun.LocalResourceProvider; |
||||||
|
import com.fr.stable.fun.mark.API; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/22 |
||||||
|
*/ |
||||||
|
@API(level = LocalResourceProvider.CURRENT_LEVEL) |
||||||
|
public abstract class AbstractLocalResourceProvider implements LocalResourceProvider { |
||||||
|
|
||||||
|
@Override |
||||||
|
public int currentAPILevel() { |
||||||
|
return CURRENT_LEVEL; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int layerIndex() { |
||||||
|
return DEFAULT_LAYER_INDEX; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.fr.design.fun.impl; |
||||||
|
|
||||||
|
import com.fr.design.fun.MobileParamUIProvider; |
||||||
|
import com.fr.stable.fun.impl.AbstractProvider; |
||||||
|
import com.fr.stable.fun.mark.API; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/30 |
||||||
|
*/ |
||||||
|
@API(level = MobileParamUIProvider.CURRENT_LEVEL) |
||||||
|
public abstract class AbstractMobileParamUIProvider extends AbstractProvider implements MobileParamUIProvider { |
||||||
|
|
||||||
|
@Override |
||||||
|
public int currentAPILevel() { |
||||||
|
return CURRENT_LEVEL; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String mark4Provider() { |
||||||
|
return getClass().getName(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package com.fr.design.fun.impl; |
||||||
|
|
||||||
|
import com.fr.design.fun.TemplateTreeDefineProcessor; |
||||||
|
import com.fr.stable.fun.mark.API; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2020/12/21 |
||||||
|
*/ |
||||||
|
@API(level = TemplateTreeDefineProcessor.CURRENT_LEVEL) |
||||||
|
public abstract class AbstractTemplateTreeDefineProcessor implements TemplateTreeDefineProcessor { |
||||||
|
|
||||||
|
@Override |
||||||
|
public int currentAPILevel() { |
||||||
|
return CURRENT_LEVEL; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int layerIndex() { |
||||||
|
return DEFAULT_LAYER_INDEX; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.fr.design.mainframe; |
||||||
|
|
||||||
|
import com.fr.event.Event; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by kerry on 2020-12-11 |
||||||
|
*/ |
||||||
|
public enum JTemplateEvent implements Event<JTemplate> { |
||||||
|
/** |
||||||
|
* 模板初始化之前 |
||||||
|
*/ |
||||||
|
BEFORE_TEMPLATE_INIT, |
||||||
|
|
||||||
|
/** |
||||||
|
* 模板激活之前 |
||||||
|
*/ |
||||||
|
BEFORE_TEMPLATE_ACTIVE |
||||||
|
|
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
package com.fr.design.mainframe.mobile.provider; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.fun.impl.AbstractMobileParamUIProvider; |
||||||
|
import com.fr.design.mainframe.mobile.ui.DefaultMobileParamDefinePane; |
||||||
|
import com.fr.form.ui.mobile.MobileParamStyle; |
||||||
|
import com.fr.form.ui.mobile.impl.DefaultMobileParameterStyle; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/1/4 |
||||||
|
*/ |
||||||
|
public class DefaultMobileParamUIProvider extends AbstractMobileParamUIProvider { |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends MobileParamStyle> classForMobileParamStyle() { |
||||||
|
return DefaultMobileParameterStyle.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends BasicBeanPane<MobileParamStyle>> classForMobileParamAppearance() { |
||||||
|
return DefaultMobileParamDefinePane.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String displayName() { |
||||||
|
return InterProviderFactory.getProvider().getLocText("Fine-Engine_Report_DEFAULT"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
package com.fr.design.mainframe.mobile.provider; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.fun.impl.AbstractMobileParamUIProvider; |
||||||
|
import com.fr.design.mainframe.mobile.ui.EmptyMobileParamDefinePane; |
||||||
|
import com.fr.form.ui.mobile.MobileParamStyle; |
||||||
|
import com.fr.report.fun.MobileParamStyleProvider; |
||||||
|
import com.fr.report.mobile.EmptyMobileParamStyle; |
||||||
|
|
||||||
|
/** |
||||||
|
* 作为MobileParamStyleProvider接口实现兼容转换层 |
||||||
|
* |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/1/4 |
||||||
|
*/ |
||||||
|
public class EmptyMobileParamUIProvider extends AbstractMobileParamUIProvider { |
||||||
|
|
||||||
|
private MobileParamStyleProvider styleProvider; |
||||||
|
|
||||||
|
public EmptyMobileParamUIProvider(MobileParamStyleProvider styleProvider) { |
||||||
|
this.styleProvider = styleProvider; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends MobileParamStyle> classForMobileParamStyle() { |
||||||
|
return EmptyMobileParamStyle.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends BasicBeanPane<MobileParamStyle>> classForMobileParamAppearance() { |
||||||
|
return EmptyMobileParamDefinePane.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String displayName() { |
||||||
|
return styleProvider.descriptor(); |
||||||
|
} |
||||||
|
|
||||||
|
public MobileParamStyleProvider getStyleProvider() { |
||||||
|
return styleProvider; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
package com.fr.design.mainframe.mobile.ui; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.form.ui.mobile.MobileParamStyle; |
||||||
|
import com.fr.form.ui.mobile.impl.DefaultMobileParameterStyle; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import javax.swing.JPanel; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/1/4 |
||||||
|
*/ |
||||||
|
public class DefaultMobileParamDefinePane extends BasicBeanPane<MobileParamStyle> { |
||||||
|
|
||||||
|
public DefaultMobileParamDefinePane() { |
||||||
|
initComponents(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initComponents() { |
||||||
|
this.setLayout(new BorderLayout()); |
||||||
|
JPanel centerPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Report_Set")); |
||||||
|
this.add(centerPane); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(MobileParamStyle ob) { |
||||||
|
// do nothing
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MobileParamStyle updateBean() { |
||||||
|
return new DefaultMobileParameterStyle(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package com.fr.design.mainframe.mobile.ui; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.form.ui.mobile.MobileParamStyle; |
||||||
|
import com.fr.report.fun.MobileParamStyleProvider; |
||||||
|
import com.fr.report.mobile.EmptyMobileParamStyle; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import javax.swing.JPanel; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/1/4 |
||||||
|
*/ |
||||||
|
public class EmptyMobileParamDefinePane extends BasicBeanPane<MobileParamStyle> { |
||||||
|
|
||||||
|
private final MobileParamStyleProvider styleProvider; |
||||||
|
|
||||||
|
public EmptyMobileParamDefinePane(MobileParamStyleProvider styleProvider) { |
||||||
|
this.styleProvider = styleProvider; |
||||||
|
initComponents(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initComponents() { |
||||||
|
this.setLayout(new BorderLayout()); |
||||||
|
JPanel centerPane = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Report_Set")); |
||||||
|
this.add(centerPane); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(MobileParamStyle ob) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MobileParamStyle updateBean() { |
||||||
|
return new EmptyMobileParamStyle(styleProvider); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
package com.fr.design.mainframe.mobile.ui; |
||||||
|
|
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.fun.MobileParamUIProvider; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.mainframe.mobile.provider.EmptyMobileParamUIProvider; |
||||||
|
import com.fr.form.ui.mobile.MobileParamStyle; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.invoke.Reflect; |
||||||
|
import com.fr.report.mobile.EmptyMobileParamStyle; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/1/4 |
||||||
|
*/ |
||||||
|
public class MobileParamDefinePane extends BasicBeanPane<MobileParamStyle> { |
||||||
|
|
||||||
|
private BasicBeanPane<MobileParamStyle> customBeanPane; |
||||||
|
|
||||||
|
public MobileParamDefinePane(MobileParamUIProvider provider) { |
||||||
|
if (provider == null || provider.classForMobileParamAppearance() == null || provider.classForMobileParamAppearance() == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (ComparatorUtils.equals(provider.classForMobileParamStyle(), EmptyMobileParamStyle.class)) { |
||||||
|
EmptyMobileParamUIProvider emptyMobileParamUIProvider = (EmptyMobileParamUIProvider) provider; |
||||||
|
this.customBeanPane = Reflect.on(provider.classForMobileParamAppearance()).create(emptyMobileParamUIProvider.getStyleProvider()).get(); |
||||||
|
} else { |
||||||
|
this.customBeanPane = Reflect.on(provider.classForMobileParamAppearance()).create().get(); |
||||||
|
} |
||||||
|
initComponents(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initComponents() { |
||||||
|
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
this.add(customBeanPane); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(MobileParamStyle ob) { |
||||||
|
this.customBeanPane.populateBean(ob); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public MobileParamStyle updateBean() { |
||||||
|
|
||||||
|
return this.customBeanPane.updateBean(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return "MobileParamDefinePane"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,154 @@ |
|||||||
|
package com.fr.design.mainframe.mobile.ui; |
||||||
|
|
||||||
|
import com.fr.design.ExtraDesignClassManager; |
||||||
|
import com.fr.design.beans.BasicBeanPane; |
||||||
|
import com.fr.design.dialog.BasicPane; |
||||||
|
import com.fr.design.fun.MobileParamUIProvider; |
||||||
|
import com.fr.design.layout.FRGUIPaneFactory; |
||||||
|
import com.fr.design.mainframe.mobile.provider.DefaultMobileParamUIProvider; |
||||||
|
import com.fr.design.mainframe.mobile.provider.EmptyMobileParamUIProvider; |
||||||
|
import com.fr.form.ui.container.WParameterLayout; |
||||||
|
import com.fr.form.ui.mobile.MobileParamStyle; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.report.ExtraReportClassManager; |
||||||
|
import com.fr.report.fun.MobileParamStyleProvider; |
||||||
|
import com.fr.report.mobile.EmptyMobileParamStyle; |
||||||
|
import java.awt.BorderLayout; |
||||||
|
import java.awt.CardLayout; |
||||||
|
import java.awt.Component; |
||||||
|
import java.awt.Dimension; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
import javax.swing.DefaultListCellRenderer; |
||||||
|
import javax.swing.DefaultListModel; |
||||||
|
import javax.swing.JList; |
||||||
|
import javax.swing.JPanel; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/1/4 |
||||||
|
*/ |
||||||
|
public class MobileParamSettingPane extends BasicPane { |
||||||
|
|
||||||
|
private DefaultListModel<String> listModel; |
||||||
|
private JPanel right; |
||||||
|
private CardLayout card; |
||||||
|
private JList paramStyleList; |
||||||
|
|
||||||
|
|
||||||
|
private Map<String, BasicBeanPane<MobileParamStyle>> map = new HashMap<>(); |
||||||
|
|
||||||
|
|
||||||
|
public MobileParamSettingPane() { |
||||||
|
initComponents(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void initComponents() { |
||||||
|
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||||
|
listModel = new DefaultListModel<>(); |
||||||
|
card = new CardLayout(); |
||||||
|
right = FRGUIPaneFactory.createCardLayout_S_Pane(); |
||||||
|
right.setLayout(card); |
||||||
|
MobileParamUIProvider[] mobileParamUIProviders = getMobileParamUIProviders(); |
||||||
|
for (MobileParamUIProvider provider : mobileParamUIProviders) { |
||||||
|
addShowPane(provider); |
||||||
|
} |
||||||
|
initLeftPane(); |
||||||
|
initRightPane(); |
||||||
|
} |
||||||
|
|
||||||
|
private void initLeftPane() { |
||||||
|
paramStyleList = new JList<>(listModel); |
||||||
|
paramStyleList.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 MobileParamStyle) { |
||||||
|
MobileParamStyle style = (MobileParamStyle) value; |
||||||
|
this.setText(style.toString()); |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
}); |
||||||
|
paramStyleList.addListSelectionListener(e -> { |
||||||
|
String selectedValue = (String) paramStyleList.getSelectedValue(); |
||||||
|
card.show(right, selectedValue); |
||||||
|
}); |
||||||
|
JPanel leftPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); |
||||||
|
leftPane.add(paramStyleList); |
||||||
|
leftPane.setPreferredSize(new Dimension(100, 500)); |
||||||
|
this.add(leftPane, BorderLayout.WEST); |
||||||
|
} |
||||||
|
|
||||||
|
private void initRightPane() { |
||||||
|
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); |
||||||
|
JPanel attrConfPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||||
|
centerPane.setPreferredSize(new Dimension(500, 500)); |
||||||
|
attrConfPane.add(right, BorderLayout.CENTER); |
||||||
|
centerPane.add(attrConfPane, BorderLayout.CENTER); |
||||||
|
this.add(centerPane, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void populate(MobileParamStyle mobileParamStyle) { |
||||||
|
if (mobileParamStyle != null) { |
||||||
|
MobileParamUIProvider[] mobileParamUIProviders = getMobileParamUIProviders(); |
||||||
|
for (int i = 0; i < mobileParamUIProviders.length; i++) { |
||||||
|
MobileParamUIProvider provider = mobileParamUIProviders[i]; |
||||||
|
if (ComparatorUtils.equals(mobileParamStyle.disPlayName(), provider.displayName())) { |
||||||
|
String displayName = provider.displayName(); |
||||||
|
paramStyleList.setSelectedIndex(i); |
||||||
|
// 如果是兼容空类型 无须填充面板
|
||||||
|
if (!(mobileParamStyle instanceof EmptyMobileParamStyle)) { |
||||||
|
map.get(displayName).populateBean(mobileParamStyle); |
||||||
|
} |
||||||
|
card.show(right, displayName); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
paramStyleList.setSelectedIndex(0); |
||||||
|
} |
||||||
|
|
||||||
|
private void addShowPane(MobileParamUIProvider provider) { |
||||||
|
String displayName = provider.displayName(); |
||||||
|
listModel.addElement(provider.displayName()); |
||||||
|
BasicBeanPane<MobileParamStyle> paramStyleBasicBeanPane = new MobileParamDefinePane(provider); |
||||||
|
right.add(displayName, paramStyleBasicBeanPane); |
||||||
|
map.put(displayName, paramStyleBasicBeanPane); |
||||||
|
} |
||||||
|
|
||||||
|
public MobileParamStyle update() { |
||||||
|
return map.get(paramStyleList.getSelectedValue()).updateBean(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private MobileParamUIProvider[] getMobileParamUIProviders() { |
||||||
|
Set<MobileParamUIProvider> paramUIProviders = ExtraDesignClassManager.getInstance().getArray(MobileParamUIProvider.XML_TAG); |
||||||
|
List<MobileParamUIProvider> result = new ArrayList<>(); |
||||||
|
result.add(new DefaultMobileParamUIProvider()); |
||||||
|
result.addAll(paramUIProviders); |
||||||
|
Set<String> nameSets = paramUIProviders.stream().map(MobileParamUIProvider::displayName).collect(Collectors.toSet()); |
||||||
|
// 兼容老接口
|
||||||
|
Set<MobileParamStyleProvider> paramStyleProviders = ExtraReportClassManager.getInstance().getArray(MobileParamStyleProvider.MARK_STRING); |
||||||
|
|
||||||
|
paramStyleProviders = paramStyleProviders.stream().filter(provider -> !nameSets.contains(provider.descriptor())).collect(Collectors.toSet()); |
||||||
|
|
||||||
|
for (MobileParamStyleProvider provider : paramStyleProviders) { |
||||||
|
result.add(new EmptyMobileParamUIProvider(provider)); |
||||||
|
} |
||||||
|
|
||||||
|
return result.toArray(new MobileParamUIProvider[0]); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.fr.design.mainframe.widget.wrappers; |
||||||
|
|
||||||
|
import com.fr.design.Exception.ValidationException; |
||||||
|
import com.fr.design.designer.properties.Decoder; |
||||||
|
import com.fr.design.designer.properties.Encoder; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
import org.jetbrains.annotations.Nullable; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author hades |
||||||
|
* @version 10.0 |
||||||
|
* Created by hades on 2021/1/4 |
||||||
|
*/ |
||||||
|
public class MobileParamWrapper implements Encoder, Decoder { |
||||||
|
|
||||||
|
@Nullable |
||||||
|
@Override |
||||||
|
public Object decode(String txt) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void validate(String txt) throws ValidationException { |
||||||
|
// do nothing
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String encode(Object v) { |
||||||
|
if (v == null) { |
||||||
|
return InterProviderFactory.getProvider().getLocText("Fine-Engine_Report_DEFAULT"); |
||||||
|
} |
||||||
|
return v.toString(); |
||||||
|
} |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue