帆软报表设计器源代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

232 lines
10 KiB

package com.fr.design.mainframe;
import com.fr.design.designer.creator.XChartEditor;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XElementCase;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.form.parameter.FormParaDesigner;
import com.fr.design.form.util.FormDesignerUtils;
import com.fr.design.utils.ComponentUtils;
import com.fr.stable.Constants;
import com.fr.stable.GraphDrawHelper;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;
public class FormSpacingLineDrawer {
private static final Color LINE_COLOR = new Color(230, 82, 81);
private static final Color TEXT_COLOR = new Color(255, 255, 255);
private static final int TEXT_PADDING_HORIZONTAL = 8;
private static final int TEXT_PADDING_VERTICAL = 2;
private static final int MIN_SPACING = 10;
private static final float TIP_FONT_SIZE = 10F;
private FormDesigner designer;
private XCreator hoverCreator = null;
private XCreator selectedCreator = null;
private Rectangle selectedRec;
private Rectangle hoveredRec;
private boolean isMouseMoveEvent = false;
public FormSpacingLineDrawer(FormDesigner designer) {
this.designer = designer;
}
public void updateMouseEvent(MouseEvent e, boolean isMouseMoveEvent) {
selectedCreator = designer.getSelectionModel().getSelection().getSelectedCreator();
if (selectedCreator != null) {
this.hoverCreator = getHoverComponentAt(e.getX(), e.getY());
}
this.isMouseMoveEvent = isMouseMoveEvent;
}
public void draw(Graphics g) {
if (!isMouseMoveEvent || selectedCreator == null || hoverCreator == null) {
return;
}
if (!isDrawSpacingLine()) {
return;
}
this.selectedRec = designer.getSelectionModel().getSelection().getRelativeBounds();
this.hoveredRec = ComponentUtils.getRelativeBounds(hoverCreator);
drawHorizontalSpacingLine(g);
drawVerticalSpacingLine(g);
}
private void drawHorizontalSpacingLine(Graphics g) {
AbstractFormParallelLine[] lines = getNearestHorizontalSide();
drawSpacingLine(g, lines);
}
private void drawVerticalSpacingLine(Graphics g) {
AbstractFormParallelLine[] lines = getNearestVerticalSide();
drawSpacingLine(g, lines);
}
private void drawSpacingLine(Graphics g, int startX, int startY, int endX, int endY) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(LINE_COLOR);
GraphDrawHelper.drawLine(g2d, startX, startY, endX, endY, Constants.LINE_THIN);
}
private void drawSpacingLine(Graphics g, AbstractFormParallelLine[] nearestSides) {
if (nearestSides.length != 2) {
return;
}
int gap = nearestSides[0].getDistanceWithLine(nearestSides[1]);
if (gap <= MIN_SPACING) {
return;
}
int startX = (int) nearestSides[0].getStartPointOnVerticalCenterLine().getX() - designer.getHorizontalScaleValue();
int startY = (int) nearestSides[0].getStartPointOnVerticalCenterLine().getY() - designer.getVerticalScaleValue();
int endX = (int) nearestSides[0].getEndPointOnVerticalCenterLine(nearestSides[1].getParallelValue()).getX() - designer.getHorizontalScaleValue();
int endY = (int) nearestSides[0].getEndPointOnVerticalCenterLine(nearestSides[1].getParallelValue()).getY() - designer.getVerticalScaleValue();
drawSpacingLine(g, startX, startY, endX, endY);
drawSpacingText(g, String.valueOf(gap), (startX + endX) / 2, (startY + endY) / 2);
drawExtendedLine(g, nearestSides);
}
private void drawExtendedLine(Graphics g, int startX, int startY, int endX, int endY) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(LINE_COLOR);
GraphDrawHelper.drawLine(g2d, startX, startY, endX, endY, Constants.LINE_DASH);
}
private void drawExtendedLine(Graphics g, AbstractFormParallelLine[] nearestSides) {
if (isNeedExtendedLine(nearestSides)) {
int startX = (int) nearestSides[1].getExtendedLineStartPoint(nearestSides[0]).getX() - designer.getHorizontalScaleValue();
int startY = (int) nearestSides[1].getExtendedLineStartPoint(nearestSides[0]).getY() - designer.getVerticalScaleValue();
int endX = (int) nearestSides[1].getExtendedLineEndPoint(nearestSides[0]).getX() - designer.getHorizontalScaleValue();
int endY = (int) nearestSides[1].getExtendedLineEndPoint(nearestSides[0]).getY() - designer.getVerticalScaleValue();
drawExtendedLine(g, startX, startY, endX, endY);
}
}
private void drawSpacingText(Graphics g, String text, int x, int y) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(LINE_COLOR);
Font newFont = g2d.getFont().deriveFont(TIP_FONT_SIZE).deriveFont(Font.BOLD);
g2d.setFont(newFont);
FontMetrics metrics = g2d.getFontMetrics();
int lineHeight = metrics.getAscent(); // 这里由于都是数字,要居中必须忽略掉leading和descent的高度
int lineWidth = metrics.stringWidth(text);
int labelPaneX = x - lineWidth / 2 - TEXT_PADDING_HORIZONTAL;
int labelPaneY = y - lineHeight / 2 - TEXT_PADDING_VERTICAL;
int labelPaneWidth = lineWidth + 2 * TEXT_PADDING_HORIZONTAL;
int labelPaneHeight = lineHeight + 2 * TEXT_PADDING_VERTICAL;
int labelPaneArc = Math.min(labelPaneWidth, labelPaneHeight);
GraphDrawHelper.fill(g2d, new RoundRectangle2D.Double(labelPaneX, labelPaneY, labelPaneWidth, labelPaneHeight, labelPaneArc, labelPaneArc));
g2d.setColor(TEXT_COLOR);
int labelX = x - lineWidth / 2;
int labelY = y + (lineHeight - 2) / 2; // 由于ascent里面包含了一小段空白,数字又没有大写的情况,相当于五线行第一行是空的,所以往上微调一点来居中
GraphDrawHelper.drawString(g2d, text, labelX, labelY);
}
private boolean isNeedExtendedLine(AbstractFormParallelLine[] nearestSides) {
return nearestSides[0].isVerticalCenterLineBeforeTheParallelLine(nearestSides[1]) || nearestSides[0].isVerticalCenterLineBehindTheParallelLine(nearestSides[1]);
}
// 当前组件是否在参数面板里面
private boolean isComponentInBody(XCreator creator) {
XLayoutContainer container = XCreatorUtils.getHotspotContainer(creator);
return container != null && !container.acceptType(XWParameterLayout.class);
}
private boolean isSelectedComponentInBody() {
return isComponentInBody(selectedCreator);
}
private boolean isHoveredComponentInBody() {
return isComponentInBody(hoverCreator);
}
private boolean isBodyAbsoluteLayout() {
return !(designer instanceof FormParaDesigner) && FormDesignerUtils.isBodyAbsolute(designer);
}
private boolean isInAbsoluteLayout() {
return isBodyAbsoluteLayout() && hoverCreator.isParentAbsolute() && selectedCreator.isParentAbsolute();
}
private boolean isDrawSpacingLine() {
return isInAbsoluteLayout() && isSelectedComponentInBody() && isHoveredComponentInBody();
}
private AbstractFormParallelLine[] getNearestHorizontalSide() {
AbstractFormParallelLine[] selectedRecSides = new AbstractFormParallelLine[] {
new FormHorizontalParallelLine(selectedRec.y, selectedRec.x, selectedRec.x + selectedRec.width),
new FormHorizontalParallelLine(selectedRec.y + selectedRec.height, selectedRec.x, selectedRec.x + selectedRec.width)
};
AbstractFormParallelLine[] hoveredCreatorSides = new AbstractFormParallelLine[] {
new FormHorizontalParallelLine(hoveredRec.y, hoveredRec.x, hoveredRec.x + hoveredRec.width),
new FormHorizontalParallelLine(hoveredRec.y + hoveredRec.height, hoveredRec.x, hoveredRec.x + hoveredRec.width)
};
return getNearestSide(selectedRecSides, hoveredCreatorSides);
}
private AbstractFormParallelLine[] getNearestVerticalSide() {
AbstractFormParallelLine[] selectedRecSides = new AbstractFormParallelLine[] {
new FormVerticalParallelLine(selectedRec.x, selectedRec.y, selectedRec.y + selectedRec.height),
new FormVerticalParallelLine(selectedRec.x + selectedRec.width, selectedRec.y, selectedRec.y + selectedRec.height)
};
AbstractFormParallelLine[] hoveredCreatorSides = new AbstractFormParallelLine[] {
new FormVerticalParallelLine(hoveredRec.x, hoveredRec.y, hoveredRec.y + hoveredRec.height),
new FormVerticalParallelLine(hoveredRec.x + hoveredRec.width, hoveredRec.y, hoveredRec.y + hoveredRec.height)
};
return getNearestSide(selectedRecSides, hoveredCreatorSides);
}
private AbstractFormParallelLine[] getNearestSide(AbstractFormParallelLine[] lines1, AbstractFormParallelLine[] lines2) {
AbstractFormParallelLine[] nearestSides = new AbstractFormParallelLine[] {lines1[0], lines2[0]};
int minDistance = lines1[0].getDistanceWithLine(lines2[0]);
for (int i = 0; i < lines1.length; i++) {
for (int j = 0; j < lines2.length; j++) {
int distance = lines1[i].getDistanceWithLine(lines2[j]);
if (distance < minDistance) {
minDistance = distance;
nearestSides[0] = lines1[i];
nearestSides[1] = lines2[j];
}
}
}
return nearestSides;
}
private XCreator getHoverComponentAt(int x, int y) {
XCreator component = designer.getComponentAt(x, y);
XLayoutContainer parent = XCreatorUtils.getHotspotContainer(component).getTopLayout();
if (parent != null) {
if (!parent.isEditable()) {
return parent;
} else {
if (parent == component) {
return null;
}
if (component instanceof XChartEditor || component instanceof XElementCase) {
return (XCreator) component.getParent();
}
return component;
}
} else {
return component;
}
}
}