* commit 'dc801317d73124a3702c71d093830bf205c5c64c': (54 commits) REPORT-44803 清除下之前关闭的pr中的已改动文件 REPORT-44803 参数面板拖动组件大小右侧不能跟随显示大小--来源【客户需求 508884】 【问题原因】之前的frm缩放的改动——REPORT-37353,把当前的像素值给设置成了组件的x、y值,这样当拖动组件改变大小的时候,x、y不变,右侧也不会变动,因为没有加上组件宽高 【改动思路】为x、y加上当前组件的宽高值 REPORT-42238 【10.0.13】JDK11设计器图标模糊问题优化 No.15: 修改打印日志语句,将中文去掉,改成英文 REPORT-42238 【10.0.13】JDK11设计器图标模糊问题优化 No.14: ①vito建议中的前三点功能其实已经实现了,只是没用一个类似Manager的方式写出来,对这种不是很熟,听vito说要配齐一大套,而这次任务已经是超时了,所以放在下次迭代任务中与缓存一起做;②将几乎所有已经改成svg的图标,传入方式统一为传入url;③补充了test REPORT-42238 【10.0.13】JDK11设计器图标模糊问题优化 No.14: 将SVGIconUtils的名字修改为IconUtils REPORT-42238 【10.0.13】JDK11设计器图标模糊问题优化 No.13: 上传下因为之前代码冲突丢失的代码 REPORT-42238 【10.0.13】JDK11设计器图标模糊问题优化 No.12: 删除误传代码 REPORT-42238 【10.0.13】JDK11设计器图标模糊问题优化 No.11: 替换了菜单栏-帮助和菜单栏-社区的图标 REPORT-45460 帆软市场国际化标签设计器适配 REPORT-44644 设计器接口开放 fix实现层级 REPORT-42238 【10.0.13】JDK11设计器图标模糊问题优化 No.10: ①根据开发评审意见,新增SVGIconUtils工具类,之后读取图标都可以用工具类中的方法;②修改UpdateAction、MenuDef、UIButton适配工具类方法;③修改之前上传的图标读取方式以及一些初始化方式;④替换了菜单栏-单元格中的所有子项的图标 REPORT-44644 fix无用import REPORT-44644 设计器接口开发 fix REPORT-44644 添加判断是否存在接口 REPORT-44644 fix调整名称 REPORT-40684 绘制表格辅助线时提前适配合并单元格,去除合并之后使用背景覆盖辅助线的方式 REPORT-44644 设计器接口开放 REPORT-44644 设计器接口开放 标记点兼容 REPORT-43744 【10.0.13】插件与jar包不匹配问题优化 ...research/11.0
@ -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,96 @@
|
||||
package com.fr.base.svg; |
||||
|
||||
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() { |
||||
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) { |
||||
// 获取屏幕缩放率,mac下固定为2,Windows+jdk11则将得到用户设置的dpi值
|
||||
scale = (float) configuration.getDefaultTransform().getScaleX(); |
||||
} |
||||
} |
||||
} |
||||
return scale; |
||||
} |
||||
} |
@ -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,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,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,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,108 @@
|
||||
package com.fr.env; |
||||
|
||||
import com.fr.design.actions.server.PluginManagerAction; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
import com.fr.general.FRFont; |
||||
import com.fr.general.GeneralContext; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.Icon; |
||||
import javax.swing.JDialog; |
||||
import javax.swing.JLabel; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JTextArea; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Dimension; |
||||
import java.awt.FlowLayout; |
||||
import java.awt.Frame; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* 插件启动失败提示窗 |
||||
*/ |
||||
public class PluginErrorRemindDialog extends JDialog implements ActionListener { |
||||
|
||||
public PluginErrorRemindDialog(Frame parent, String areaText) { |
||||
super(parent, true); |
||||
//上面的标签面板
|
||||
JPanel topPanel = FRGUIPaneFactory.createBorderLayout_L_Pane(); |
||||
JPanel imagePanel = new JPanel(); |
||||
Icon icon = IOUtils.readIcon("com/fr/design/images/warnings/warning5.png"); |
||||
|
||||
JLabel imageLabel = new JLabel(); |
||||
imageLabel.setIcon(icon); |
||||
imagePanel.add(imageLabel); |
||||
imagePanel.setPreferredSize(new Dimension(130, 100)); |
||||
|
||||
JPanel verticalPanel = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true); |
||||
|
||||
JLabel label = new JLabel(Toolkit.i18nText("Fine-Design_Plugin_Error_Remind_Title")); |
||||
label.setFont(FRFont.getInstance().applySize(18).applyStyle(1)); |
||||
label.setPreferredSize(new Dimension(650, 100)); |
||||
|
||||
verticalPanel.add(label); |
||||
|
||||
topPanel.add(imagePanel, BorderLayout.WEST); |
||||
topPanel.add(verticalPanel, BorderLayout.CENTER); |
||||
topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); |
||||
|
||||
//中间的文本域面板
|
||||
JPanel centerPanel = FRGUIPaneFactory.createBorderLayout_L_Pane(); |
||||
centerPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); |
||||
centerPanel.setPreferredSize(new Dimension(480, 320)); |
||||
|
||||
JTextArea checkArea = new JTextArea(areaText); |
||||
checkArea.setEnabled(false); |
||||
centerPanel.add(checkArea, BorderLayout.CENTER); |
||||
|
||||
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Plugin_Error_Remind_Not_Deal_With")); |
||||
UIButton okButton = new UIButton(Toolkit.i18nText("Fine-Design_Plugin_Error_Remind_Deal_With")); |
||||
|
||||
cancelButton.addActionListener(this); |
||||
okButton.addActionListener(new PluginManagerActionAdapter(this)); |
||||
|
||||
// 按钮
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); |
||||
buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); |
||||
buttonPanel.add(cancelButton); |
||||
buttonPanel.add(okButton); |
||||
|
||||
|
||||
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Tool_Tips")); |
||||
this.setResizable(false); |
||||
|
||||
this.add(topPanel, BorderLayout.NORTH); |
||||
this.add(centerPanel, BorderLayout.CENTER); |
||||
this.add(buttonPanel, BorderLayout.SOUTH); |
||||
this.setSize(new Dimension(GeneralContext.getLocale().equals(Locale.US) ? 750 : 600, 500)); |
||||
|
||||
GUICoreUtils.centerWindow(this); |
||||
} |
||||
|
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
this.dispose(); |
||||
} |
||||
|
||||
private static class PluginManagerActionAdapter extends PluginManagerAction { |
||||
|
||||
private JDialog jDialog; |
||||
|
||||
public PluginManagerActionAdapter(JDialog jDialog) { |
||||
this.jDialog = jDialog; |
||||
} |
||||
|
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
this.jDialog.dispose(); |
||||
super.actionPerformed(e); |
||||
} |
||||
} |
||||
|
||||
} |
After Width: | Height: | Size: 288 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 530 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 167 B |
After Width: | Height: | Size: 610 B |
After Width: | Height: | Size: 602 B |
After Width: | Height: | Size: 433 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 286 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 208 B |
After Width: | Height: | Size: 774 B |
After Width: | Height: | Size: 774 B |