90 changed files with 1219 additions and 1187 deletions
@ -0,0 +1,90 @@ |
|||||||
|
package com.fr.van.chart.designer.type; |
||||||
|
|
||||||
|
import com.fr.chart.chartglyph.ConditionCollection; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.plugin.chart.PiePlot4VanChart; |
||||||
|
import com.fr.plugin.chart.area.VanChartAreaPlot; |
||||||
|
import com.fr.plugin.chart.attr.axis.VanChartAxis; |
||||||
|
import com.fr.plugin.chart.attr.plot.VanChartPlot; |
||||||
|
import com.fr.plugin.chart.attr.plot.VanChartRectanglePlot; |
||||||
|
import com.fr.plugin.chart.bubble.VanChartBubblePlot; |
||||||
|
import com.fr.plugin.chart.column.VanChartColumnPlot; |
||||||
|
import com.fr.plugin.chart.line.VanChartLinePlot; |
||||||
|
import com.fr.plugin.chart.scatter.VanChartScatterPlot; |
||||||
|
import com.fr.plugin.chart.type.VanChartPlotType; |
||||||
|
import com.fr.plugin.chart.vanchart.VanChart; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Bjorn |
||||||
|
* @version 10.0 |
||||||
|
* Created by Bjorn on 2020-08-24 |
||||||
|
*/ |
||||||
|
public abstract class AbstractRectanglePlotPane extends AbstractVanChartTypePane { |
||||||
|
|
||||||
|
private static Set<String> extendPlotIds = new HashSet<>(); |
||||||
|
|
||||||
|
static { |
||||||
|
extendPlotIds.add(VanChartColumnPlot.VAN_CHART_COLUMN_PLOT_ID); |
||||||
|
extendPlotIds.add(VanChartColumnPlot.VAN_CHART_BAR_PLOT_ID); |
||||||
|
extendPlotIds.add(VanChartLinePlot.VAN_CHART_LINE_PLOT); |
||||||
|
extendPlotIds.add(VanChartAreaPlot.VAN_CHART_AREA_PLOT_ID); |
||||||
|
extendPlotIds.add(VanChartScatterPlot.VAN_CHART_SCATTER_PLOT_ID); |
||||||
|
extendPlotIds.add(PiePlot4VanChart.VAN_CHART_PIE_PLOT); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected VanChartPlot cloneOldPlot2New(VanChartPlot oldPlot, VanChartPlot newPlot) { |
||||||
|
try { |
||||||
|
VanChartRectanglePlot vanChartRectanglePlot = (VanChartRectanglePlot) newPlot; |
||||||
|
VanChartRectanglePlot clonePlot = (VanChartRectanglePlot) oldPlot.clone(); |
||||||
|
clonePlot.setVanChartPlotType(vanChartRectanglePlot.getVanChartPlotType()); |
||||||
|
//自定义类型的图形要增加一个y2轴,并且增加系列中的堆积条件,反之则要去掉y2轴和条件
|
||||||
|
if (clonePlot.isCustomChart()) { |
||||||
|
List<VanChartAxis> valueAxisList = clonePlot.getValueAxisList(); |
||||||
|
valueAxisList.add(vanChartRectanglePlot.getValueAxisList().get(1)); |
||||||
|
clonePlot.setStackAndAxisCondition(vanChartRectanglePlot.getStackAndAxisCondition()); |
||||||
|
} else { |
||||||
|
List<VanChartAxis> xAxisList = clonePlot.getXAxisList(); |
||||||
|
List<VanChartAxis> yAxisList = clonePlot.getYAxisList(); |
||||||
|
List<VanChartAxis> newXAxisList = new ArrayList<>(); |
||||||
|
List<VanChartAxis> newYAxisList = new ArrayList<>(); |
||||||
|
newXAxisList.add(xAxisList.get(0)); |
||||||
|
newYAxisList.add(yAxisList.get(0)); |
||||||
|
clonePlot.setXAxisList(newXAxisList); |
||||||
|
clonePlot.setYAxisList(newYAxisList); |
||||||
|
clonePlot.setStackAndAxisCondition(new ConditionCollection()); |
||||||
|
} |
||||||
|
|
||||||
|
//百分比堆积图值轴的格式不保留
|
||||||
|
if (clonePlot.getVanChartPlotType() == VanChartPlotType.STACK_BY_PERCENT || |
||||||
|
((VanChartRectanglePlot) oldPlot).getVanChartPlotType() == VanChartPlotType.STACK_BY_PERCENT) { |
||||||
|
VanChartAxis cloneAxis = clonePlot.getValueAxisList().get(0); |
||||||
|
VanChartAxis vanChartAxis = vanChartRectanglePlot.getValueAxisList().get(0); |
||||||
|
cloneAxis.setFormat(vanChartAxis.getFormat()); |
||||||
|
cloneAxis.setPercentage(vanChartAxis.isPercentage()); |
||||||
|
cloneAxis.setCommonValueFormat(vanChartAxis.isCommonValueFormat()); |
||||||
|
cloneAxis.setHtmlLabel(vanChartAxis.getHtmlLabel()); |
||||||
|
} |
||||||
|
return clonePlot; |
||||||
|
} catch (CloneNotSupportedException ex) { |
||||||
|
FineLoggerFactory.getLogger().error("Error in change plot"); |
||||||
|
return newPlot; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//是否支持属性的继承
|
||||||
|
@Override |
||||||
|
protected boolean supportExtendAttr(VanChart chart) { |
||||||
|
if (StringUtils.equals(VanChartBubblePlot.VAN_CHART_BUBBLE_PLOT_ID, chart.getID())) { |
||||||
|
VanChartBubblePlot vanChartBubblePlot = chart.getPlot(); |
||||||
|
return !vanChartBubblePlot.isForceBubble(); |
||||||
|
} |
||||||
|
return extendPlotIds.contains(chart.getID()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,68 @@ |
|||||||
|
package com.fr.design.mainframe; |
||||||
|
|
||||||
|
import com.fr.design.designer.creator.XCreator; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.mainframe.FormDesigner; |
||||||
|
import com.fr.design.mainframe.WidgetPropertyPane; |
||||||
|
import com.fr.design.utils.ComponentUtils; |
||||||
|
import com.fr.stable.CoreGraphHelper; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.MouseEvent; |
||||||
|
import java.awt.geom.AffineTransform; |
||||||
|
import java.awt.image.BufferedImage; |
||||||
|
import java.util.ArrayList; |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author: Yuan.Wang |
||||||
|
* @Date: 2020/8/31 |
||||||
|
*/ |
||||||
|
public class TopXCreator extends JComponent { |
||||||
|
private final FormDesigner designer; |
||||||
|
private final XCreator creator; |
||||||
|
|
||||||
|
public TopXCreator(FormDesigner designer, XCreator creator) { |
||||||
|
this.designer = designer; |
||||||
|
this.creator = creator; |
||||||
|
init(); |
||||||
|
} |
||||||
|
|
||||||
|
private void init() { |
||||||
|
setOpaque(false); |
||||||
|
setBackground(null); |
||||||
|
setLayout(null); |
||||||
|
setBounds(calculateBounds()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 重新设置组件大小 |
||||||
|
* */ |
||||||
|
public void resizeTopXCreator() { |
||||||
|
setBounds(calculateBounds()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 计算显示大小 |
||||||
|
* */ |
||||||
|
private Rectangle calculateBounds() { |
||||||
|
Rectangle rect = ComponentUtils.getRelativeBounds(creator); |
||||||
|
Rectangle bounds = new Rectangle(0, 0, creator.getWidth(), creator.getHeight()); |
||||||
|
bounds.x += (rect.x - designer.getHorizontalScaleValue()); |
||||||
|
bounds.y += (rect.y - designer.getVerticalScaleValue()); |
||||||
|
return bounds; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void paint(Graphics g) { |
||||||
|
super.paint(g); |
||||||
|
ArrayList<JComponent> dbcomponents = new ArrayList<JComponent>(); |
||||||
|
// 禁止双缓冲
|
||||||
|
ComponentUtils.disableBuffer(creator, dbcomponents); |
||||||
|
creator.paint(g); |
||||||
|
// 恢复双缓冲
|
||||||
|
ComponentUtils.resetBuffer(dbcomponents); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
package com.fr.design.mainframe; |
||||||
|
|
||||||
|
import com.fr.design.designer.beans.events.DesignerEvent; |
||||||
|
import com.fr.design.designer.beans.models.SelectionModel; |
||||||
|
import com.fr.design.designer.creator.XCreator; |
||||||
|
import com.fr.design.designer.creator.XCreatorUtils; |
||||||
|
import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* 需要显示顶层的组件层 |
||||||
|
* |
||||||
|
* @Author: Yuan.Wang |
||||||
|
* @Date: 2020/8/25 |
||||||
|
*/ |
||||||
|
public class TopXCreators extends JComponent { |
||||||
|
final private FormDesigner designer; |
||||||
|
|
||||||
|
public TopXCreators(FormDesigner designer) { |
||||||
|
this.designer = designer; |
||||||
|
init(); |
||||||
|
} |
||||||
|
|
||||||
|
private void init() { |
||||||
|
setLayout(null); |
||||||
|
setVisible(false); |
||||||
|
setBackground(null); |
||||||
|
setOpaque(false); |
||||||
|
designer.addDesignerEditListener(e -> { |
||||||
|
if (e.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { |
||||||
|
refresh(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 选中的组件有变化时刷新 |
||||||
|
*/ |
||||||
|
public void refresh() { |
||||||
|
removeAll(); |
||||||
|
addXCreators(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void paint(Graphics g) { |
||||||
|
setSize(designer.getSize()); |
||||||
|
resizeTopXCreators(); |
||||||
|
super.paint(g); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加入被选择的组件 |
||||||
|
*/ |
||||||
|
private void addXCreators() { |
||||||
|
SelectionModel selectionModel = designer.getSelectionModel(); |
||||||
|
XCreator[] xCreators = selectionModel.getSelection().getSelectedCreators(); |
||||||
|
for (XCreator creator : xCreators) { |
||||||
|
if (!creator.isTopable()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
XWCardMainBorderLayout topXMainBorderLayout = XCreatorUtils.getTopXMainBorderLayout(creator); |
||||||
|
add(new TopXCreator(designer, creator)); |
||||||
|
if (topXMainBorderLayout != null) { |
||||||
|
add(new TopXCreator(designer, topXMainBorderLayout)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新顶层组件的位置和大小 |
||||||
|
*/ |
||||||
|
private void resizeTopXCreators() { |
||||||
|
for (int i = 0, count = getComponentCount(); i < count; i++) { |
||||||
|
TopXCreator topXCreator = (TopXCreator) getComponent(i); |
||||||
|
topXCreator.resizeTopXCreator(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -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.
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -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); |
|
||||||
} |
|
||||||
} |
|
@ -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(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -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."); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -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); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
Binary file not shown.
@ -0,0 +1,79 @@ |
|||||||
|
package com.fr.design.mainframe.alphafine.search.manager.impl; |
||||||
|
|
||||||
|
import com.fr.base.FRContext; |
||||||
|
import com.fr.base.extension.FileExtension; |
||||||
|
import com.fr.design.DesignerEnvManager; |
||||||
|
import com.fr.design.actions.help.alphafine.AlphaFineConfigManager; |
||||||
|
import com.fr.design.mainframe.alphafine.AlphaFineHelper; |
||||||
|
import com.fr.design.mainframe.alphafine.cell.model.AlphaCellModel; |
||||||
|
import com.fr.design.mainframe.alphafine.model.SearchResult; |
||||||
|
import com.fr.file.filetree.FileNode; |
||||||
|
import com.fr.invoke.Reflect; |
||||||
|
import com.fr.stable.project.ProjectConstants; |
||||||
|
import com.fr.web.core.SessionPoolManager; |
||||||
|
import com.fr.web.utils.WebUtils; |
||||||
|
import org.easymock.EasyMock; |
||||||
|
import org.junit.Test; |
||||||
|
import org.junit.runner.RunWith; |
||||||
|
import org.powermock.api.easymock.PowerMock; |
||||||
|
import org.powermock.core.classloader.annotations.PrepareForTest; |
||||||
|
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; |
||||||
|
import org.powermock.modules.junit4.PowerMockRunner; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import static org.junit.Assert.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yyming |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yyming on 2020/9/15 |
||||||
|
*/ |
||||||
|
@RunWith(PowerMockRunner.class) |
||||||
|
@PrepareForTest({AlphaFineHelper.class,DesignerEnvManager.class}) |
||||||
|
@SuppressStaticInitializationFor("com.fr.design.mainframe.alphafine.AlphaFineHelper") |
||||||
|
public class FileSearchManagerTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void doSearch() { |
||||||
|
String searchText = "workb"; |
||||||
|
FileSearchManager instance = FileSearchManager.getInstance(); |
||||||
|
FileNode fileNode1 = EasyMock.createMock(FileNode.class); |
||||||
|
FileNode fileNode2 = EasyMock.createMock(FileNode.class); |
||||||
|
EasyMock.expect(fileNode1.getName()).andReturn("workbook").anyTimes(); |
||||||
|
EasyMock.expect(fileNode2.getName()).andReturn("work book").anyTimes(); |
||||||
|
EasyMock.expect(fileNode1.getEnvPath()).andReturn("").anyTimes(); |
||||||
|
EasyMock.expect(fileNode2.getEnvPath()).andReturn("").anyTimes(); |
||||||
|
EasyMock.replay(fileNode1,fileNode2); |
||||||
|
FileNode[] fileNodes = { fileNode1, fileNode2 }; |
||||||
|
Reflect.on(instance).set("fileNodes",fileNodes); |
||||||
|
|
||||||
|
AlphaFineConfigManager configManager = EasyMock.createMock(AlphaFineConfigManager.class); |
||||||
|
EasyMock.expect(configManager.isContainTemplate()).andReturn(true).anyTimes(); |
||||||
|
EasyMock.replay(configManager); |
||||||
|
|
||||||
|
DesignerEnvManager manager = EasyMock.createMock(DesignerEnvManager.class); |
||||||
|
EasyMock.expect(manager.getAlphaFineConfigManager()).andReturn(configManager).anyTimes(); |
||||||
|
EasyMock.replay(manager); |
||||||
|
PowerMock.mockStatic(DesignerEnvManager.class); |
||||||
|
DesignerEnvManager.getEnvManager(); |
||||||
|
PowerMock.expectLastCall().andReturn(manager).anyTimes(); |
||||||
|
PowerMock.replay(DesignerEnvManager.class); |
||||||
|
|
||||||
|
List<AlphaCellModel> list = new ArrayList<>(); |
||||||
|
PowerMock.mockStatic(AlphaFineHelper.class); |
||||||
|
AlphaFineHelper.getFilterResult(); |
||||||
|
PowerMock.expectLastCall().andReturn(list).anyTimes(); |
||||||
|
AlphaFineHelper.findFolderName(""); |
||||||
|
PowerMock.expectLastCall().andReturn("").anyTimes(); |
||||||
|
AlphaFineHelper.checkCancel(); |
||||||
|
PowerMock.expectLastCall().andVoid().anyTimes(); |
||||||
|
PowerMock.replay(AlphaFineHelper.class); |
||||||
|
|
||||||
|
SearchResult alphaCellModels = new SearchResult(); |
||||||
|
Reflect.on(instance).set("filterModelList",alphaCellModels); |
||||||
|
Reflect.on(instance).call("doSearch",searchText); |
||||||
|
assertEquals(alphaCellModels.size(),2); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package com.fr.design.mainframe.alphafine.cell.render; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
import static org.junit.Assert.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yyming |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yyming on 2020/9/16 |
||||||
|
*/ |
||||||
|
public class ContentCellRenderTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void highLightModelName() { |
||||||
|
String searchText = "workb"; |
||||||
|
ContentCellRender contentCellRender = new ContentCellRender(searchText,new String[]{searchText}); |
||||||
|
String workbook = contentCellRender.highLightModelName("workbook", new String[]{searchText}); |
||||||
|
assertTrue(workbook.endsWith("workb</font>ook</body></HTML>")); |
||||||
|
workbook = contentCellRender.highLightModelName("work book", new String[]{searchText}); |
||||||
|
assertTrue(workbook.endsWith("work b</font>ook</body></HTML>")); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue