|
|
|
@ -14,9 +14,13 @@ import javax.swing.JComponent;
|
|
|
|
|
import javax.swing.JPanel; |
|
|
|
|
import javax.swing.SwingUtilities; |
|
|
|
|
import java.awt.AWTException; |
|
|
|
|
import java.awt.AlphaComposite; |
|
|
|
|
import java.awt.Color; |
|
|
|
|
import java.awt.Component; |
|
|
|
|
import java.awt.Composite; |
|
|
|
|
import java.awt.Dimension; |
|
|
|
|
import java.awt.Graphics; |
|
|
|
|
import java.awt.Graphics2D; |
|
|
|
|
import java.awt.Point; |
|
|
|
|
import java.awt.Rectangle; |
|
|
|
|
import java.awt.Window; |
|
|
|
@ -27,6 +31,9 @@ import java.util.ArrayList;
|
|
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
|
|
public abstract class AbstractGuideScene extends JPanel implements GuideScene { |
|
|
|
|
private static final int DEFAULT_ARROW_HEIGHT = 12; |
|
|
|
|
private static final int DEFAULT_ARROW_WIDTH = 18; |
|
|
|
|
|
|
|
|
|
private GuideScene nextScene; |
|
|
|
|
private SceneFilter sceneFilter; |
|
|
|
|
private GuideSceneLifecycle lifecycle; |
|
|
|
@ -34,12 +41,15 @@ public abstract class AbstractGuideScene extends JPanel implements GuideScene {
|
|
|
|
|
private List<Component> targetList; |
|
|
|
|
private List<Component> highlightList; |
|
|
|
|
private Component nextButton; |
|
|
|
|
private List<Point[]> pointsList; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public AbstractGuideScene() { |
|
|
|
|
this.setLayout(null); |
|
|
|
|
this.setOpaque(false); |
|
|
|
|
targetList = new ArrayList<>(); |
|
|
|
|
highlightList = new ArrayList<>(); |
|
|
|
|
pointsList = new ArrayList<>(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -62,26 +72,16 @@ public abstract class AbstractGuideScene extends JPanel implements GuideScene {
|
|
|
|
|
if (component instanceof JComponent) { |
|
|
|
|
JComponent jComponent = (JComponent) component; |
|
|
|
|
image = ScreenImage.createImage(jComponent); |
|
|
|
|
} else if (component instanceof Window){ |
|
|
|
|
Window window = (Window) component; |
|
|
|
|
window.toFront(); |
|
|
|
|
window.requestFocus(); |
|
|
|
|
image = ScreenImage.createImage(component); |
|
|
|
|
SwingUtilities.invokeLater(new Runnable() { |
|
|
|
|
@Override |
|
|
|
|
public void run() { |
|
|
|
|
container.toFront(); |
|
|
|
|
container.requestFocus(); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
|
image = captureImage(component); |
|
|
|
|
showContainer(); |
|
|
|
|
} |
|
|
|
|
targetList.add(component); |
|
|
|
|
highlightList.add(getTargetComponentWithImage(image, rectangle)); |
|
|
|
|
return true; |
|
|
|
|
} catch (AWTException e) { |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
GuideManager.getInstance().getCurrentGuide().terminate(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -94,12 +94,12 @@ public abstract class AbstractGuideScene extends JPanel implements GuideScene {
|
|
|
|
|
public boolean addTarget(Rectangle rectangle) { |
|
|
|
|
try { |
|
|
|
|
targetList.add(null); |
|
|
|
|
container.setVisible(false); |
|
|
|
|
BufferedImage image = captureImage(rectangle); |
|
|
|
|
highlightList.add(getTargetComponentWithImage(image, rectangle)); |
|
|
|
|
return true; |
|
|
|
|
} catch (AWTException e) { |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
GuideManager.getInstance().getCurrentGuide().terminate(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -116,6 +116,8 @@ public abstract class AbstractGuideScene extends JPanel implements GuideScene {
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
Point point = SwingUtilities.convertPoint(component,0,0, container.getRootPane()); |
|
|
|
|
|
|
|
|
|
origin = origin.intersection(new Rectangle(0,0,component.getWidth(), component.getHeight())); |
|
|
|
|
Rectangle rectangle = new Rectangle(point.x + origin.x, point.y + origin.y, origin.width, origin.height); |
|
|
|
|
|
|
|
|
|
BufferedImage image; |
|
|
|
@ -131,6 +133,7 @@ public abstract class AbstractGuideScene extends JPanel implements GuideScene {
|
|
|
|
|
return true; |
|
|
|
|
} catch (AWTException e) { |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
GuideManager.getInstance().getCurrentGuide().terminate(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -184,6 +187,7 @@ public abstract class AbstractGuideScene extends JPanel implements GuideScene {
|
|
|
|
|
showContainer(); |
|
|
|
|
return image; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void showContainer() { |
|
|
|
|
SwingUtilities.invokeLater(new Runnable() { |
|
|
|
|
@Override |
|
|
|
@ -249,6 +253,10 @@ public abstract class AbstractGuideScene extends JPanel implements GuideScene {
|
|
|
|
|
this.add(tip.getTip()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void addLineArrow(Point... points) { |
|
|
|
|
pointsList.add(points); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setContainer(GuideView container) { |
|
|
|
|
this.container = container; |
|
|
|
|
} |
|
|
|
@ -271,6 +279,7 @@ public abstract class AbstractGuideScene extends JPanel implements GuideScene {
|
|
|
|
|
@Override |
|
|
|
|
public void start() { |
|
|
|
|
clear(); |
|
|
|
|
showContainer(); |
|
|
|
|
if (lifecycle != null && !lifecycle.prepared()) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -310,26 +319,26 @@ public abstract class AbstractGuideScene extends JPanel implements GuideScene {
|
|
|
|
|
public void complete() { |
|
|
|
|
container.getLayeredPane().remove(this); |
|
|
|
|
container.repaint(); |
|
|
|
|
|
|
|
|
|
if (lifecycle != null) { |
|
|
|
|
lifecycle.onComplete(); |
|
|
|
|
} |
|
|
|
|
if (sceneFilter != null) { |
|
|
|
|
nextScene = sceneFilter.getFilterScene(); |
|
|
|
|
} |
|
|
|
|
if (nextScene != null) { |
|
|
|
|
if (nextScene instanceof AbstractGuideScene) { |
|
|
|
|
((AbstractGuideScene) nextScene).setContainer(container); |
|
|
|
|
} |
|
|
|
|
SwingUtilities.invokeLater(new Runnable() { |
|
|
|
|
@Override |
|
|
|
|
public void run() { |
|
|
|
|
SwingUtilities.invokeLater(new Runnable() { |
|
|
|
|
@Override |
|
|
|
|
public void run() { |
|
|
|
|
if (lifecycle != null) { |
|
|
|
|
lifecycle.onComplete(); |
|
|
|
|
} |
|
|
|
|
if (sceneFilter != null) { |
|
|
|
|
nextScene = sceneFilter.getFilterScene(); |
|
|
|
|
} |
|
|
|
|
if (nextScene != null) { |
|
|
|
|
if (nextScene instanceof AbstractGuideScene) { |
|
|
|
|
((AbstractGuideScene) nextScene).setContainer(container); |
|
|
|
|
} |
|
|
|
|
nextScene.start(); |
|
|
|
|
} else { |
|
|
|
|
GuideManager.getInstance().getCurrentGuide().complete(); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
|
GuideManager.getInstance().getCurrentGuide().complete(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@ -383,4 +392,87 @@ public abstract class AbstractGuideScene extends JPanel implements GuideScene {
|
|
|
|
|
invalidate(); |
|
|
|
|
repaint(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void paint(Graphics g) { |
|
|
|
|
super.paint(g); |
|
|
|
|
if (pointsList.isEmpty()) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
Graphics2D g2d = (Graphics2D) g; |
|
|
|
|
Composite oldComposite = g2d.getComposite(); |
|
|
|
|
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); |
|
|
|
|
g2d.setColor(Color.WHITE); |
|
|
|
|
for (Point[] points : pointsList) { |
|
|
|
|
if (points.length <= 1) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
Point startPoint = points[0]; |
|
|
|
|
Point endPoint = startPoint; |
|
|
|
|
for (int index = 1; index < points.length; index++) { |
|
|
|
|
startPoint = endPoint; |
|
|
|
|
endPoint = points[index]; |
|
|
|
|
g2d.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
drawArrow(g2d, startPoint, endPoint); |
|
|
|
|
} |
|
|
|
|
g2d.setComposite(oldComposite); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 根据最后两点坐标计算出三角箭头的三个点坐标,绘制箭头 |
|
|
|
|
* 这里实现以终点坐标为坐标轴圆点计算 |
|
|
|
|
* @param start 起始点坐标 |
|
|
|
|
* @param end 重点坐标 |
|
|
|
|
*/ |
|
|
|
|
private void drawArrow(Graphics2D g2d, Point start, Point end) { |
|
|
|
|
try{ |
|
|
|
|
double dealtPointX = start.x - end.x; |
|
|
|
|
double dealtPointY = -(start.y - end.y); |
|
|
|
|
|
|
|
|
|
double pointDistance = calDistance(dealtPointX, dealtPointY); |
|
|
|
|
double triangleHeight = Math.min(DEFAULT_ARROW_HEIGHT, pointDistance); |
|
|
|
|
double triangleWidth = triangleHeight * (DEFAULT_ARROW_WIDTH / 2) / DEFAULT_ARROW_WIDTH; |
|
|
|
|
if (triangleHeight < 1 || triangleWidth < 1 || pointDistance < 1) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
double pointAngle; |
|
|
|
|
double abs = 1; |
|
|
|
|
if (dealtPointX == 0) { |
|
|
|
|
pointAngle = Math.PI / 2; |
|
|
|
|
} else { |
|
|
|
|
pointAngle = Math.atan(dealtPointY / dealtPointX); |
|
|
|
|
} |
|
|
|
|
if (dealtPointY < 0) { |
|
|
|
|
pointAngle += Math.PI; |
|
|
|
|
abs = -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
double deltaAngle = Math.atan(triangleWidth / triangleHeight); |
|
|
|
|
double triangleDistance = calDistance(triangleWidth, triangleHeight); |
|
|
|
|
|
|
|
|
|
Point p1 =calPoint(end, triangleDistance, pointAngle - deltaAngle, abs); |
|
|
|
|
Point p2 = calPoint(end, triangleDistance, pointAngle + deltaAngle, abs); |
|
|
|
|
|
|
|
|
|
int xPoints[] = {end.x, p1.x, p2.x}; |
|
|
|
|
int yPoints[] = {end.y, p1.y, p2.y}; |
|
|
|
|
|
|
|
|
|
g2d.fillPolygon(xPoints, yPoints, 3); |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
e.printStackTrace(); |
|
|
|
|
GuideManager.getInstance().getCurrentGuide().terminate(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private double calDistance(double x, double y) { |
|
|
|
|
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Point calPoint(Point relativePoint, double distance, double angle, double abs) { |
|
|
|
|
int x = (int)(relativePoint.x + abs * distance * Math.cos(angle)); |
|
|
|
|
int y = (int)(relativePoint.y - abs * distance * Math.sin(angle)); |
|
|
|
|
return new Point(x, y); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|