帆软报表设计器源代码。
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.
 
 
 
 

317 lines
11 KiB

package com.fr.design.mainframe;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.designer.creator.cardlayout.XWCardTagLayout;
import com.fr.form.ui.container.WLayout;
import java.awt.Rectangle;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MultiSelectionArrangement {
private static final int DEFAULT_GAP = 10;
private FormDesigner designer;
private List<XCreator> selectedCreators;
private Rectangle rec;
public MultiSelectionArrangement(FormDesigner designer) {
this.designer = designer;
}
public void doArrangement(ArrangementType type) {
doArrangement(type, DEFAULT_GAP);
}
public void doArrangement(ArrangementType type, int gap) {
updatePosition();
switch (type) {
case RIGHT_ALIGN:
rightAlign();
break;
case TOP_ALIGN:
topAlign();
break;
case BOTTOM_ALIGN:
bottomAlign();
break;
case HORIZONTAL_CENTER_ALIGN:
horizontalCenterAlign();
break;
case VERTICAL_CENTER_ALIGN:
verticalCenterAlign();
break;
case HORIZONTAL_AUTO_DISTRIBUTION:
horizontalAutoDistribution();
break;
case HORIZONTAL_MANUAL_DISTRIBUTION:
horizontalManualDistribution(gap);
break;
case VERTICAL_AUTO_DISTRIBUTION:
verticalAutoDistribution();
break;
case VERTICAL_MANUAL_DISTRIBUTION:
verticalManualDistribution(gap);
break;
case LEFT_ALIGN:
default:
leftAlign();
break;
}
updateModel();
}
private void leftAlign() {
for (XCreator creator : selectedCreators) {
creator.setLocation(rec.x, creator.getY());
}
}
private void rightAlign() {
for (XCreator creator : selectedCreators) {
creator.setLocation(rec.x + rec.width - creator.getWidth(), creator.getY());
}
}
private void topAlign() {
for (XCreator creator : selectedCreators) {
creator.setLocation(creator.getX(), rec.y);
}
}
private void bottomAlign() {
for (XCreator creator : selectedCreators) {
creator.setLocation(creator.getX(), rec.y + rec.height - creator.getHeight());
}
}
private void horizontalCenterAlign() {
for (XCreator creator : selectedCreators) {
creator.setLocation(rec.x + rec.width / 2 - creator.getWidth() / 2, creator.getY());
}
}
private void verticalCenterAlign() {
for (XCreator creator : selectedCreators) {
creator.setLocation(creator.getX(), rec.y + rec.height / 2 - creator.getHeight() / 2);
}
}
// 水平分布,自动,间距由selectedCreators和border共同计算而来
private void horizontalAutoDistribution() {
sortHorizontal();
int[] gaps = calculateHorizontalGaps();
horizontalDistribution(gaps);
}
// 水平分布,手动,传入一个间距,排列selectedCreators
private void horizontalManualDistribution(int gap) {
sortHorizontal();
reSizeRecByHorizontal(gap);
horizontalDistribution(fillGaps(gap, selectedCreators.size() - 1));
}
private void horizontalDistribution(int[] gaps) {
for (int i = 1; i < selectedCreators.size() - 1; i++) {
XCreator creator = selectedCreators.get(i);
XCreator preCreator = selectedCreators.get(i - 1);
creator.setLocation(preCreator.getX() + preCreator.getWidth() + gaps[i - 1], creator.getY());
}
}
private void reSizeRecByHorizontal(int gap) {
int width = 0;
for (XCreator creator : selectedCreators) {
width += creator.getWidth();
}
width += (selectedCreators.size() - 1) * gap;
rec.x = rec.x + (rec.width - width) / 2;
rec.width = width;
XCreator first = selectedCreators.get(0);
first.setLocation(rec.x, first.getY());
XCreator last = selectedCreators.get(selectedCreators.size() - 1);
last.setLocation(rec.x + rec.width - last.getWidth(), last.getY());
}
private void sortHorizontal() {
Collections.sort(selectedCreators, new Comparator<XCreator>() {
@Override
public int compare(XCreator o1, XCreator o2) {
int diffX = o1.getX() - o2.getX();
if (diffX > 0) {
return 1;
} else if (diffX < 0) {
return -1;
} else {
int diffY = o1.getY() - o2.getY();
if (diffY > 0) {
return 1;
} else if (diffY < 0) {
return -1;
} else {
int diffZOrder = o1.getParent().getComponentZOrder(o1) - o2.getParent().getComponentZOrder(o2);
if (diffZOrder > 0) {
return -1;
} else {
return 1;
}
}
}
}
});
}
// 计算selectedCreators的均分间距
private int[] calculateHorizontalGaps() {
int sum = 0;
for (XCreator creator : selectedCreators) {
sum += creator.getWidth();
}
int gapCount = selectedCreators.size() - 1;
XCreator head = selectedCreators.get(0);
XCreator tail = selectedCreators.get(gapCount);
int distanceBetweenHeadAndTailCreators = Math.abs(head.getX() - tail.getX()) + tail.getWidth();
return calculateIntegerGaps(distanceBetweenHeadAndTailCreators - sum, gapCount);
}
private void verticalAutoDistribution() {
sortVertical();
int[] gaps = calculateVerticalGaps();
verticalDistribution(gaps);
}
private void verticalManualDistribution(int gap) {
sortVertical();
reSizeRecByVertical(gap);
verticalDistribution(fillGaps(gap, selectedCreators.size() - 1));
}
private void verticalDistribution(int[] gaps) {
for (int i = 1; i < selectedCreators.size() - 1; i++) {
XCreator creator = selectedCreators.get(i);
XCreator preCreator = selectedCreators.get(i - 1);
creator.setLocation(creator.getX(), preCreator.getY() + preCreator.getHeight() + gaps[i - 1]);
}
}
private void reSizeRecByVertical(int gap) {
int height = 0;
for (XCreator creator : selectedCreators) {
height += creator.getHeight();
}
height += (selectedCreators.size() - 1) * gap;
rec.y = rec.y + (rec.height - height) / 2;
rec.height = height;
XCreator first = selectedCreators.get(0);
first.setLocation(first.getX(), rec.y);
XCreator last = selectedCreators.get(selectedCreators.size() - 1);
last.setLocation(last.getX(), rec.y + rec.height - last.getHeight());
}
private void sortVertical() {
Collections.sort(selectedCreators, new Comparator<XCreator>() {
@Override
public int compare(XCreator o1, XCreator o2) {
int diffY = o1.getY() - o2.getY();
if (diffY > 0) {
return 1;
} else if (diffY < 0) {
return -1;
} else {
int diffX = o1.getX() - o2.getX();
if (diffX > 0) {
return 1;
} else if (diffX < 0) {
return -1;
} else {
int diffZOrder = o1.getParent().getComponentZOrder(o1) - o2.getParent().getComponentZOrder(o2);
if (diffZOrder > 0) {
return -1;
} else {
return 1;
}
}
}
}
});
}
private int[] calculateVerticalGaps() {
int sum = 0;
for (XCreator creator : selectedCreators) {
sum += creator.getHeight();
}
int gapCount = selectedCreators.size() - 1;
XCreator head = selectedCreators.get(0);
XCreator tail = selectedCreators.get(gapCount);
int distanceBetweenHeadAndTailCreators = Math.abs(head.getY() - tail.getY()) + tail.getHeight();
return calculateIntegerGaps(distanceBetweenHeadAndTailCreators - sum, gapCount);
}
private int[] calculateIntegerGaps(int gapTotalSize, int gapCount) {
int finalGap[] = new int[gapCount];
// gapTotalSize: 原先的所有未取整的gap的总和,是一个整数
int intGap = Math.round((float) gapTotalSize / gapCount);
// 把所有取整的gap求和,得到的整数gap
int intTotalSize = intGap * (gapCount);
// 求差,可以知道总误差
int difference = intTotalSize - gapTotalSize;
// 遍历,由于取整是四舍五入得到的,取整后每个gap和取整前的gap最多相差0.5,故difference绝对值小于gapCount的
for (int i = 0; i < gapCount; i++) {
if (i < Math.abs(difference)) {
if (difference < 0) {
// 说明取整后gap总误差小于取整前总gap,一个个加1补上
finalGap[i] = intGap + 1;
} else {
// 说明取整后gap总误差大于取整前总gap,一个个减1去掉
finalGap[i] = intGap - 1;
}
} else {
finalGap[i] = intGap;
}
}
return finalGap;
}
// 创建用gap填满一个size大小的数组
private int[] fillGaps(int gap, int size) {
int[] gaps = new int[size];
Arrays.fill(gaps, gap);
return gaps;
}
private void updatePosition() {
FormSelection selection = designer.getSelectionModel().getSelection();
this.selectedCreators = Arrays.asList(selection.getSelectedCreators());
this.rec = selection.getSelctionBounds();
}
private void updateModel() {
FormSelection selection = designer.getSelectionModel().getSelection();
XLayoutContainer parent = getParent(selection.getSelectedCreator());
if (parent != null) {
// 这里要修改修改engine里面的对象才能成功保存,光修改设计器对象没用
WLayout wabs = parent.toData();
for (XCreator creator : selectedCreators) {
wabs.setBounds(creator.toData(), creator.getBounds());
}
}
}
private XLayoutContainer getParent(XCreator source) {
if(source.acceptType(XWCardTagLayout.class)){
return (XLayoutContainer)source.getParent();
}
XLayoutContainer container = XCreatorUtils.getParentXLayoutContainer(source);
if (source.acceptType(XWFitLayout.class) || source.acceptType(XWParameterLayout.class)) {
container = null;
}
return container;
}
}