Browse Source

REPORT-38632【无用代码删除】设计器启动页 动态画面相关代码

research/11.0
vito 4 years ago
parent
commit
f01534c8c6
  1. 208
      designer-realize/src/main/java/com/fr/start/fx/FastGifImage.java
  2. 208
      designer-realize/src/main/java/com/fr/start/fx/PrismImageLoader2.java
  3. 59
      designer-realize/src/main/java/com/fr/start/fx/SplashFx.java
  4. 194
      designer-realize/src/main/java/com/fr/start/fx/SplashFxWindow.java
  5. 69
      designer-realize/src/main/java/com/fr/start/jni/SplashJNI.java
  6. 100
      designer-realize/src/main/java/com/fr/start/jni/SplashMac.java
  7. BIN
      designer-realize/src/main/resources/com/fr/start/jni/splash.dylib

208
designer-realize/src/main/java/com/fr/start/fx/FastGifImage.java

@ -1,208 +0,0 @@
package com.fr.start.fx;
import com.sun.imageio.plugins.gif.GIFImageReader;
import com.sun.imageio.plugins.gif.GIFImageReaderSpi;
import com.sun.javafx.tk.ImageLoader;
import com.sun.javafx.tk.PlatformImage;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.image.WritableImage;
import javafx.util.Duration;
import javax.imageio.stream.FileImageInputStream;
import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.regex.Pattern;
/**
* 边加载边播放的gif加载器
*
* @author daniel
*/
public class FastGifImage extends WritableImage {
private String url;
private int gifCount;
public FastGifImage(String url, int w, int h) {
super(w, h);
this.url = validateUrl(url);
seekCount();
initialize();
}
/**
* 给出gif帧数加快加载速度
*
* @param url gif url
* @param gifCount gif帧数
* @param w
* @param h
*/
public FastGifImage(String url, int gifCount, int w, int h) {
super(w, h);
this.url = validateUrl(url);
this.gifCount = gifCount;
initialize();
}
private void seekCount() {
try {
GIFImageReaderSpi spi = new GIFImageReaderSpi();
GIFImageReader gifReader = (GIFImageReader) spi.createReaderInstance();
gifReader.setInput(new FileImageInputStream(new File(new URI(url))));
gifCount = gifReader.getNumImages(true);
} catch (Exception e) {
e.printStackTrace();
}
}
private static final Pattern URL_QUICKMATCH = Pattern.compile("^\\p{Alpha}[\\p{Alnum}+.-]*:.*$");
private static String validateUrl(final String url) {
if (url == null) {
throw new NullPointerException("URL must not be null");
}
if (url.trim().isEmpty()) {
throw new IllegalArgumentException("URL must not be empty");
}
try {
if (!URL_QUICKMATCH.matcher(url).matches()) {
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
URL resource;
if (url.charAt(0) == '/') {
resource = contextClassLoader.getResource(url.substring(1));
} else {
resource = contextClassLoader.getResource(url);
}
if (resource == null) {
throw new IllegalArgumentException("Invalid URL or resource not found");
}
return resource.toString();
}
// Use URL constructor for validation
return new URL(url).toString();
} catch (final IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid URL" + e.getMessage());
} catch (final MalformedURLException e) {
throw new IllegalArgumentException("Invalid URL" + e.getMessage());
}
}
private void finishImage(ImageLoader loader) {
initializeAnimatedImage(loader);
}
// Generates the animation Timeline for multiframe images.
private void initializeAnimatedImage(ImageLoader loader) {
animation = new Animation(this, loader);
animation.start();
}
// Support for animated images.
private Animation animation;
private static final class Animation {
final WeakReference<FastGifImage> imageRef;
final Timeline timeline;
private ImageLoader loader;
public Animation(final FastGifImage image, final ImageLoader loader) {
this.loader = loader;
imageRef = new WeakReference<FastGifImage>(image);
timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
final int frameCount = loader.getFrameCount();
int duration = 0;
for (int i = 0; i < frameCount; ++i) {
addKeyFrame(i, duration);
duration = duration + loader.getFrameDelay(i);
}
// Note: we need one extra frame in the timeline to define how long
// the last frame is shown, the wrap around is "instantaneous"
addKeyFrame(0, duration);
}
public void start() {
timeline.play();
}
public void stop() {
timeline.stop();
loader = null;
}
private void updateImage(final int frameIndex) {
final FastGifImage image = imageRef.get();
if (image != null) {
image.setPlatformImagePropertyImpl(
loader.getFrame(frameIndex));
} else {
timeline.stop();
}
}
private void addKeyFrame(final int index, final double duration) {
timeline.getKeyFrames().add(
new KeyFrame(Duration.millis(duration),
new EventHandler() {
@Override
public void handle(Event event) {
updateImage(index);
}
}
));
}
}
private static Method method;
static {
try {
method = FastGifImage.class.getSuperclass().getSuperclass().getDeclaredMethod("platformImagePropertyImpl");
method.setAccessible(true);
} catch (Exception e) {
}
}
private void setPlatformImagePropertyImpl(PlatformImage image) {
try {
Object o = method.invoke(this);
Method method = o.getClass().getDeclaredMethod("set", Object.class);
method.setAccessible(true);
method.invoke(o, image);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
private void initialize() {
finishImage(new PrismImageLoader2(url, gifCount, (int) getRequestedWidth(), (int) getRequestedHeight(), isPreserveRatio(), isSmooth()));
}
/**
* 销毁gif动画
*/
public void destroy() {
animation.stop();
}
}

208
designer-realize/src/main/java/com/fr/start/fx/PrismImageLoader2.java

@ -1,208 +0,0 @@
package com.fr.start.fx;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.log.FineLoggerFactory;
import com.sun.javafx.iio.ImageFrame;
import com.sun.javafx.iio.ImageLoadListener;
import com.sun.javafx.iio.ImageLoader;
import com.sun.javafx.iio.ImageMetadata;
import com.sun.javafx.iio.ImageStorageException;
import com.sun.javafx.iio.common.ImageTools;
import com.sun.javafx.iio.gif.GIFImageLoaderFactory;
import com.sun.javafx.tk.PlatformImage;
import com.sun.prism.Image;
import com.sun.prism.impl.PrismSettings;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 边加载边播放的gif加载器
*
* @author daniel
*/
class PrismImageLoader2 implements com.sun.javafx.tk.ImageLoader {
private Image[] images;
private int[] delayTimes;
private int width;
private int height;
private int gifCount = 1;
private Exception exception;
public PrismImageLoader2(final String url, int gifCount, final int width, final int height,
final boolean preserveRatio, final boolean smooth) {
this.gifCount = gifCount;
images = new Image[gifCount];
delayTimes = new int[gifCount];
this.width = width;
this.height = height;
ExecutorService es = Executors.newSingleThreadExecutor(new NamedThreadFactory("PrismImageLoader2"));
es.execute(new Runnable() {
@Override
public void run() {
InputStream inputStream = null;
try {
inputStream = ImageTools.createInputStream(url);
loadAll(inputStream, width, height, preserveRatio, smooth);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
es.shutdown();
}
@Override
public int getWidth() {
return width;
}
@Override
public int getHeight() {
return height;
}
@Override
public int getFrameCount() {
return gifCount;
}
@Override
@SuppressWarnings("squid:S2142")
public PlatformImage getFrame(int index) {
while (images[index] == null) {
synchronized (this) {
if (images[index] == null) {
try {
this.wait();
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}
}
return images[index];
}
@Override
public int getFrameDelay(int index) {
// while (images[0] == null) {
// synchronized (this) {
// if(images[0] == null) {
// try {
// this.wait();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }
// return 0;
// }
// return delayTimes[0];
// 直接使用第一帧的时间
return 40;
}
@Override
public int getLoopCount() {
return 0;
}
@Override
public Exception getException() {
return exception;
}
@SuppressWarnings("squid:S244")
private void loadAll(InputStream stream, int w, int h,
boolean preserveRatio, boolean smooth) {
ImageLoadListener listener = new PrismLoadListener();
try {
ImageLoader loader = null;
loader = GIFImageLoaderFactory.getInstance().createImageLoader(stream);
loader.addListener(listener);
for (int i = 0; i < gifCount; i++) {
ImageFrame imageFrame = loader.load(i, w, h, preserveRatio, smooth);
images[i] = convert(imageFrame);
synchronized (this) {
notifyAll();
}
}
} catch (ImageStorageException e) {
handleException(e);
} catch (Exception e) {
handleException(e);
}
}
private void handleException(final ImageStorageException isException) {
// unwrap ImageStorageException if possible
final Throwable exceptionCause = isException.getCause();
if (exceptionCause instanceof Exception) {
handleException((Exception) exceptionCause);
} else {
handleException((Exception) isException);
}
}
private void handleException(final Exception exception) {
if (PrismSettings.verbose) {
exception.printStackTrace(System.err);
}
this.exception = exception;
}
private Image convert(ImageFrame imgFrames) {
ImageFrame frame = imgFrames;
Image image = Image.convertImageFrame(frame);
ImageMetadata metadata = frame.getMetadata();
if (metadata != null) {
Integer delay = metadata.delayTime;
if (delay != null) {
delayTimes[0] = delay.intValue();
}
}
return image;
}
private class PrismLoadListener implements ImageLoadListener {
@Override
public void imageLoadWarning(ImageLoader loader, String message) {
}
@Override
public void imageLoadProgress(ImageLoader loader,
float percentageComplete) {
// progress only matters when backgroundLoading=true, but
// currently we are relying on AbstractRemoteResource for tracking
// progress of the InputStream, so there's no need to implement
// this for now; eventually though we might want to consider
// moving away from AbstractRemoteResource and instead use
// the built-in support for progress in the javafx-iio library...
}
@Override
public void imageLoadMetaData(ImageLoader loader, ImageMetadata metadata) {
// We currently have no need to listen for ImageMetadata ready.
}
}
}

59
designer-realize/src/main/java/com/fr/start/fx/SplashFx.java

@ -1,59 +0,0 @@
package com.fr.start.fx;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.start.SplashFxActionListener;
import com.fr.start.SplashStrategy;
import javafx.application.Application;
import javafx.application.Platform;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* JavaFx方式启动启动动画这种方式在mac下与
* swing一起启动会会出现线程死锁jvm等问题
* 所以这个方式仅用于windows上
*
* @author vito
* @date 2018/6/4
* @see com.fr.start.jni.SplashMac
*/
public class SplashFx implements SplashStrategy {
private SplashFxWindow fxWindow;
private static final ExecutorService SERVICE = Executors.newSingleThreadExecutor(new NamedThreadFactory("SplashFx"));
@Override
public void show() {
Platform.setImplicitExit(false);
SERVICE.execute(new Runnable() {
@Override
public void run() {
Application.launch(SplashFxWindow.class);
}
});
fxWindow = SplashFxWindow.waitForStartUpTest();
fxWindow.addSplashActionListener(new SplashFxActionListener() {
@Override
public void splashClose() {
DesignerContext.getDesignerFrame().setVisible(true);
}
});
}
@Override
public void hide() {
fxWindow.close();
}
@Override
public void updateModuleLog(final String text) {
fxWindow.updateModuleInfo(text);
}
@Override
public void updateThanksLog(final String text) {
fxWindow.updateThanks(text);
}
}

194
designer-realize/src/main/java/com/fr/start/fx/SplashFxWindow.java

@ -1,194 +0,0 @@
package com.fr.start.fx;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.OperatingSystem;
import com.fr.start.SplashContext;
import com.fr.start.SplashFxActionListener;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* JavaFx启动动画窗口
*
* @author vito
*/
public class SplashFxWindow extends Application {
private static final String ARIAL_FONT_NAME = "Arial";
private static final String PF_FONT_NAME = "PingFang";
private static final String YAHEI_FONT_NAME = "Microsoft YaHei";
private static final int MODULE_INFO_LEFT_MARGIN = 36;
private static final int MODULE_INFO_BOTTOM_MARGIN = 28;
private static final int THINKS_BOTTOM_RIGHT = 35;
private static final int THINKS_BOTTOM_MARGIN = 27;
private static final int WINDOW_WIDTH = 640;
private static final int WINDOW_HEIGHT = 360;
private static final int FONT = 12;
private static final int FRAME_COUNT = 315;
private static final String THINKS_COLOR = "#82b1ce";
private static final CountDownLatch LATCH = new CountDownLatch(1);
private static SplashFxWindow app = null;
private Text moduleInfo;
private Text thanks;
private FastGifImage image;
private List<SplashFxActionListener> listeners = new ArrayList<SplashFxActionListener>();
/**
* 获取当前运行实例黑科技
*
* @return 运行实例
*/
@SuppressWarnings("squid:S2142")
public static SplashFxWindow waitForStartUpTest() {
try {
LATCH.await();
} catch (InterruptedException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return app;
}
private static void setApp(SplashFxWindow window) {
app = window;
LATCH.countDown();
}
public SplashFxWindow() {
setApp(this);
}
@Override
public void start(Stage primaryStage) {
AnchorPane root = new AnchorPane();
primaryStage.initStyle(StageStyle.TRANSPARENT);
image = new FastGifImage(SplashContext.SPLASH_PATH, FRAME_COUNT, WINDOW_WIDTH, WINDOW_HEIGHT);
ImageView gif = new ImageView(image);
AnchorPane.setBottomAnchor(gif, 0d);
AnchorPane.setTopAnchor(gif, 0d);
AnchorPane.setLeftAnchor(gif, 0d);
AnchorPane.setRightAnchor(gif, 0d);
Font font;
if (OperatingSystem.isWindows()) {
font = new Font(YAHEI_FONT_NAME, FONT);
} else if (OperatingSystem.isMacOS()) {
font = new Font(PF_FONT_NAME, FONT);
} else {
font = new Font(ARIAL_FONT_NAME, FONT);
}
moduleInfo = new Text();
moduleInfo.setFont(font);
moduleInfo.setFill(Color.WHITE);
AnchorPane.setLeftAnchor(moduleInfo,(double) MODULE_INFO_LEFT_MARGIN);
AnchorPane.setBottomAnchor(moduleInfo,(double) MODULE_INFO_BOTTOM_MARGIN);
thanks = new Text();
thanks.setFont(font);
thanks.setFill(Color.valueOf(THINKS_COLOR));
AnchorPane.setRightAnchor(thanks, (double) THINKS_BOTTOM_RIGHT);
AnchorPane.setBottomAnchor(thanks, (double) THINKS_BOTTOM_MARGIN);
root.getChildren().add(gif);
root.getChildren().add(moduleInfo);
root.getChildren().add(thanks);
primaryStage.setWidth(WINDOW_WIDTH);
primaryStage.setHeight(WINDOW_HEIGHT);
primaryStage.setScene(new Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT, null));
setWindowCenter(primaryStage);
primaryStage.show();
}
public void close() {
Platform.runLater(new Runnable() {
@Override
public void run() {
try {
((Stage) moduleInfo.getScene().getWindow()).close();
image.destroy();
fireSplashClose();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
});
}
/**
* 设置窗口居中
*
* @param stage 窗口
*/
private void setWindowCenter(Stage stage) {
Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
stage.setX(primaryScreenBounds.getMinX() + (primaryScreenBounds.getWidth() - stage.getWidth()) / 2.0);
stage.setY(primaryScreenBounds.getMinY() + (primaryScreenBounds.getHeight() - stage.getHeight()) / 2.0);
}
/**
* 更新模块信息
*
* @param s 文字
*/
public void updateModuleInfo(final String s) {
Platform.runLater(new Runnable() {
@Override
public void run() {
if (moduleInfo != null) {
moduleInfo.setText(s);
}
}
});
}
/**
* 更新欢迎信息
*
* @param s 文字
*/
public void updateThanks(final String s) {
Platform.runLater(new Runnable() {
@Override
public void run() {
if (thanks != null) {
thanks.setText(s);
}
}
});
}
/**
* 添加一个动画状态监听
*
* @param listener
*/
public void addSplashActionListener(SplashFxActionListener listener) {
listeners.add(listener);
}
public void fireSplashClose() {
for (SplashFxActionListener listener : listeners) {
listener.splashClose();
}
}
}

69
designer-realize/src/main/java/com/fr/start/jni/SplashJNI.java

@ -1,69 +0,0 @@
package com.fr.start.jni;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
/**
* Splash JNI调用jni类改名或者移包之后
* 必须重新编译动态库
*
* @author vito
* @date 2018/6/4
*/
public class SplashJNI {
static {
try {
System.setProperty("java.library.path", ".");
System.loadLibrary("splash");
} catch (UnsatisfiedLinkError e) {
loadLibraryFromJar("/com/fr/start/jni/splash.dylib");
}
}
/**
* 显示启动动画窗口
*/
public native void show(String path);
/**
* 隐藏启动动画窗口
*/
public native void hide();
/**
* 设置模块加载信息
*/
public native void updateModuleLog(String text);
/**
* 设置感谢文字
*/
public native void updateThanksLog(String text);
/**
* 从jar中加载动态库
*
* @param path 路径/com/a/b
* @throws UnsatisfiedLinkError 没有找到合适的动态库
*/
private static void loadLibraryFromJar(String path) throws UnsatisfiedLinkError {
try (InputStream inputStream = SplashJNI.class.getResourceAsStream(path)) {
File tempLib = File.createTempFile(path, "");
byte[] buffer = new byte[1024];
int read = -1;
try (FileOutputStream fileOutputStream = new FileOutputStream(tempLib)) {
while ((read = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
}
}
System.load(tempLib.getAbsolutePath());
} catch (Exception e) {
throw new UnsatisfiedLinkError("Unable to open " + path + " from jar file.");
}
}
}

100
designer-realize/src/main/java/com/fr/start/jni/SplashMac.java

@ -1,100 +0,0 @@
package com.fr.start.jni;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.start.SplashContext;
import com.fr.start.SplashStrategy;
import javax.swing.JFrame;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* mac上使用jni方式绘制gif不使用javafx有两个原因
* 1.mac上javafx和swing同时启动会导致卡死
* 2.platform.exit会导致设计器崩溃
*
* @author vito
* @see com.fr.start.fx.SplashFx
*/
public class SplashMac implements SplashStrategy {
private SplashJNI jni;
private static final int EXILE = 10000;
public SplashMac() {
jni = new SplashJNI();
}
/**
* 将jar中的资源拷贝到缓存文件夹
*
* @return 路径
*/
private static String loadResFromJar() {
File tempLib = null;
try (InputStream inputStream = SplashContext.class.getResourceAsStream(SplashContext.SPLASH_PATH)) {
if (inputStream == null) {
FineLoggerFactory.getLogger().error("Unable to copy " + SplashContext.SPLASH_PATH + " from jar file.");
return StringUtils.EMPTY;
}
tempLib = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), SplashContext.SPLASH_CACHE_NAME));
byte[] buffer = new byte[1024];
int read = -1;
try (FileOutputStream fileOutputStream = new FileOutputStream(tempLib)) {
while ((read = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
}
}
return tempLib.getAbsolutePath();
} catch (IOException e) {
if (tempLib != null) {
tempLib.deleteOnExit();
}
// 直接抛异常
throw new RuntimeException("Unable to copy " + SplashContext.SPLASH_PATH + " from jar file.");
}
}
@Override
public void show() {
if (jni != null) {
// mac下安装版模糊的hack
JFrame jFrame = new JFrame();
jFrame.setLocation(EXILE, EXILE);
jFrame.setVisible(true);
jFrame.setVisible(false);
File splash = new File(StableUtils.pathJoin(ProductConstants.getEnvHome(), SplashContext.SPLASH_CACHE_NAME));
String path = splash.exists() ? splash.getAbsolutePath() : loadResFromJar();
jni.show(path);
}
}
@Override
public void hide() {
if (jni != null) {
jni.hide();
jni = null;
}
}
@Override
public void updateModuleLog(String text) {
if (jni != null) {
jni.updateModuleLog(text);
}
}
@Override
public void updateThanksLog(String text) {
if (jni != null) {
jni.updateThanksLog(text);
}
}
}

BIN
designer-realize/src/main/resources/com/fr/start/jni/splash.dylib

Binary file not shown.
Loading…
Cancel
Save