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
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; |
|
} |
|
}
|
|
|