Merge in DESIGN/design from ~FANGLEI/design10.0:feature/10.0 to feature/10.0 * commit '897230cfaa4f3156df586bb5436cac407f07f09a': REPORT-54885 添加注释,便于理解 REPORT-54885 优化获取延长线方法的实现 REPORT-54885 优化方法命名 REPORT-54885 优化api命名 REPORT-54885 优化重复代码 REPORT-54885 【10.0.19】FRM布局推荐之布局优化部分 REPORT-54885 【10.0.19】FRM布局推荐之布局优化部分feature/10.0
@ -0,0 +1,63 @@
|
||||
package com.fr.design.gui.ibutton; |
||||
|
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.Icon; |
||||
|
||||
public class UIHead { |
||||
private String text = StringUtils.EMPTY; |
||||
private Icon icon = null; |
||||
private boolean enable = true; |
||||
private int index = 0; |
||||
|
||||
public UIHead(String text, int index) { |
||||
this.text = text; |
||||
this.index = index; |
||||
} |
||||
|
||||
public UIHead(String text, int index, boolean enable) { |
||||
this(text, index); |
||||
this.enable = enable; |
||||
} |
||||
|
||||
public UIHead(Icon icon, int index) { |
||||
this.icon = icon; |
||||
this.index = index; |
||||
} |
||||
|
||||
public UIHead(Icon icon, int index, boolean enable) { |
||||
this(icon, index); |
||||
this.enable = enable; |
||||
} |
||||
|
||||
public UIHead(String text, Icon icon, int index) { |
||||
this.text = text; |
||||
this.icon = icon; |
||||
this.index = index; |
||||
} |
||||
|
||||
public UIHead(String text, Icon icon, int index, boolean enable) { |
||||
this(text, icon, index); |
||||
this.enable = enable; |
||||
} |
||||
|
||||
public boolean isOnlyText() { |
||||
return StringUtils.isNotEmpty(text) && icon == null; |
||||
} |
||||
|
||||
public String getText() { |
||||
return text; |
||||
} |
||||
|
||||
public Icon getIcon() { |
||||
return icon; |
||||
} |
||||
|
||||
public boolean isEnable() { |
||||
return enable; |
||||
} |
||||
|
||||
public int getIndex() { |
||||
return index; |
||||
} |
||||
} |
After Width: | Height: | Size: 401 B |
After Width: | Height: | Size: 131 B |
After Width: | Height: | Size: 133 B |
After Width: | Height: | Size: 133 B |
After Width: | Height: | Size: 271 B |
After Width: | Height: | Size: 132 B |
After Width: | Height: | Size: 130 B |
After Width: | Height: | Size: 126 B |
After Width: | Height: | Size: 137 B |
After Width: | Height: | Size: 147 B |
After Width: | Height: | Size: 249 B |
@ -0,0 +1,70 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import java.awt.Point; |
||||
|
||||
public abstract class AbstractFormParallelLine { |
||||
protected int parallelValue; |
||||
protected int startPosition; |
||||
protected int endPosition; |
||||
|
||||
public AbstractFormParallelLine(int parallelValue, int startPosition, int endPosition) { |
||||
this.parallelValue = parallelValue; |
||||
this.startPosition = startPosition; |
||||
this.endPosition = endPosition; |
||||
} |
||||
|
||||
public int getCenterPosition() { |
||||
return (startPosition + endPosition) / 2; |
||||
} |
||||
|
||||
/** |
||||
* 获取当前直线的中垂线起点位置 |
||||
* @return 中垂线起点位置 |
||||
*/ |
||||
abstract public Point getStartPointOnVerticalCenterLine(); |
||||
|
||||
/** |
||||
* 获取当前直线的中垂线的重点位置,重点位置即为重垂线与另一条平行线相交的点 |
||||
* @param parallelValue 平行线 |
||||
* @return 中垂线重点位置 |
||||
*/ |
||||
abstract public Point getEndPointOnVerticalCenterLine(int parallelValue); |
||||
|
||||
public boolean isVerticalCenterLineBeforeTheParallelLine(AbstractFormParallelLine parallelLine) { |
||||
return this.getCenterPosition() < parallelLine.getStartPosition(); |
||||
} |
||||
|
||||
public boolean isVerticalCenterLineBehindTheParallelLine(AbstractFormParallelLine parallelLine) { |
||||
return this.getCenterPosition() > parallelLine.getEndPosition(); |
||||
} |
||||
|
||||
/** |
||||
* 传一个平行线,当 当前直线和平行线中心点位置无平行相交的部分的时候,需要绘制一条延长线,一直延长到平行线边界位置 |
||||
* @param parallelLine 平行线 |
||||
* @return 延长线的起点位置 |
||||
*/ |
||||
abstract public Point getExtendedLineStartPoint(AbstractFormParallelLine parallelLine); |
||||
|
||||
/** |
||||
* 传一个平行线,当 当前直线和平行线中心点位置无平行相交的部分的时候,需要绘制一条延长线,一直延长到平行线边界位置 |
||||
* @param parallelLine 平行线 |
||||
* @return 延长线的重点位置 |
||||
*/ |
||||
abstract public Point getExtendedLineEndPoint(AbstractFormParallelLine parallelLine); |
||||
|
||||
public int getDistanceWithLine(AbstractFormParallelLine parallelLine) { |
||||
return Math.abs(this.getParallelValue() - parallelLine.getParallelValue()); |
||||
} |
||||
|
||||
public int getParallelValue() { |
||||
return parallelValue; |
||||
} |
||||
|
||||
public int getStartPosition() { |
||||
return startPosition; |
||||
} |
||||
|
||||
public int getEndPosition() { |
||||
return endPosition; |
||||
} |
||||
} |
@ -0,0 +1,45 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import java.awt.Point; |
||||
|
||||
public class FormHorizontalParallelLine extends AbstractFormParallelLine { |
||||
public FormHorizontalParallelLine(int parallelValue, int startPosition, int endPosition) { |
||||
super(parallelValue, startPosition, endPosition); |
||||
} |
||||
|
||||
@Override |
||||
public Point getStartPointOnVerticalCenterLine() { |
||||
Point point = new Point(); |
||||
point.setLocation(getCenterPosition(), parallelValue); |
||||
return point; |
||||
} |
||||
|
||||
@Override |
||||
public Point getEndPointOnVerticalCenterLine(int parallelValue) { |
||||
Point point = new Point(); |
||||
point.setLocation(getCenterPosition(), parallelValue); |
||||
return point; |
||||
} |
||||
|
||||
@Override |
||||
public Point getExtendedLineStartPoint(AbstractFormParallelLine parallelLine) { |
||||
Point point = new Point(); |
||||
if (parallelLine.isVerticalCenterLineBeforeTheParallelLine(this)) { |
||||
point.setLocation(getStartPosition(), getParallelValue()); |
||||
} else if (parallelLine.isVerticalCenterLineBehindTheParallelLine(this)) { |
||||
point.setLocation(getEndPosition(), getParallelValue()); |
||||
} |
||||
return point; |
||||
} |
||||
|
||||
@Override |
||||
public Point getExtendedLineEndPoint(AbstractFormParallelLine parallelLine) { |
||||
Point point = new Point(); |
||||
if (parallelLine.isVerticalCenterLineBeforeTheParallelLine(this)) { |
||||
point.setLocation(parallelLine.getStartPosition(), getParallelValue()); |
||||
} else if (parallelLine.isVerticalCenterLineBehindTheParallelLine(this)) { |
||||
point.setLocation(parallelLine.getEndPosition(), getParallelValue()); |
||||
} |
||||
return point; |
||||
} |
||||
} |
@ -0,0 +1,198 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.design.designer.creator.XCreator; |
||||
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 = 6; |
||||
private static final int TEXT_PADDING_VERTICAL = 1; |
||||
private static final int MIN_SPACING = 10; |
||||
|
||||
private FormDesigner designer; |
||||
private XCreator hoverCreator; |
||||
private Rectangle selectedRec; |
||||
private boolean isMouseMoveEvent = false; |
||||
|
||||
public FormSpacingLineDrawer(FormDesigner designer) { |
||||
this.designer = designer; |
||||
} |
||||
|
||||
public void updateMouseEvent(MouseEvent e, boolean isMouseMoveEvent) { |
||||
this.hoverCreator = designer.getComponentAt(e); |
||||
this.isMouseMoveEvent = isMouseMoveEvent; |
||||
} |
||||
|
||||
public void draw(Graphics g) { |
||||
this.selectedRec = designer.getSelectionModel().getSelection().getSelctionBounds(); |
||||
if (!isDrawSpacingLine()) { |
||||
return; |
||||
} |
||||
|
||||
if (!hoverCreator.isParentAbsolute()) { |
||||
return; |
||||
} |
||||
|
||||
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(); |
||||
int startY = (int) nearestSides[0].getStartPointOnVerticalCenterLine().getY(); |
||||
int endX = (int) nearestSides[0].getEndPointOnVerticalCenterLine(nearestSides[1].getParallelValue()).getX(); |
||||
int endY = (int) nearestSides[0].getEndPointOnVerticalCenterLine(nearestSides[1].getParallelValue()).getY(); |
||||
|
||||
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(); |
||||
int startY = (int) nearestSides[1].getExtendedLineStartPoint(nearestSides[0]).getY(); |
||||
int endX = (int) nearestSides[1].getExtendedLineEndPoint(nearestSides[0]).getX(); |
||||
int endY = (int) nearestSides[1].getExtendedLineEndPoint(nearestSides[0]).getY(); |
||||
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(8F).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 isSelectedRootComponent() { |
||||
return designer.getSelectionModel().getSelection().size() == 1 && |
||||
designer.isRoot(designer.getSelectionModel().getSelection().getSelectedCreator()); |
||||
} |
||||
|
||||
private boolean isSelectedForm() { |
||||
return designer.getSelectionModel().getSelection().size() == 1 && |
||||
designer.getSelectionModel().getSelection().getSelectedCreator().getParent() == null; |
||||
} |
||||
|
||||
private boolean isHoveredRootComponent() { |
||||
return designer.isRoot(hoverCreator); |
||||
} |
||||
|
||||
private boolean isHoveredForm() { |
||||
return hoverCreator.getParent() == null; |
||||
} |
||||
|
||||
private boolean isNeedExtendedLine(AbstractFormParallelLine[] nearestSides) { |
||||
return nearestSides[0].isVerticalCenterLineBeforeTheParallelLine(nearestSides[1]) || nearestSides[0].isVerticalCenterLineBehindTheParallelLine(nearestSides[1]); |
||||
} |
||||
|
||||
private boolean isSelectedRootPane() { |
||||
return isSelectedForm() || isSelectedRootComponent(); |
||||
} |
||||
|
||||
private boolean isHoveredRootPane() { |
||||
return isHoveredForm() || isHoveredRootComponent(); |
||||
} |
||||
|
||||
private boolean isDrawSpacingLine() { |
||||
return !isSelectedRootPane() && !isHoveredRootPane() && isMouseMoveEvent; |
||||
} |
||||
|
||||
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(hoverCreator.getY(), hoverCreator.getX(), hoverCreator.getX() + hoverCreator.getWidth()), |
||||
new FormHorizontalParallelLine(hoverCreator.getY() + hoverCreator.getHeight(), hoverCreator.getX(), hoverCreator.getX() + hoverCreator.getWidth()) |
||||
}; |
||||
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(hoverCreator.getX(), hoverCreator.getY(), hoverCreator.getY() + hoverCreator.getHeight()), |
||||
new FormVerticalParallelLine(hoverCreator.getX() + hoverCreator.getWidth(), hoverCreator.getY(), hoverCreator.getY() + hoverCreator.getHeight()) |
||||
}; |
||||
return getNearestSide(selectedRecSides, hoveredCreatorSides); |
||||
} |
||||
|
||||
private AbstractFormParallelLine[] getNearestSide(AbstractFormParallelLine[] lines1, AbstractFormParallelLine[] lines2) { |
||||
AbstractFormParallelLine[] nearestSides = new AbstractFormParallelLine[2]; |
||||
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) { |
||||
nearestSides[0] = lines1[i]; |
||||
nearestSides[1] = lines2[j]; |
||||
} |
||||
} |
||||
} |
||||
return nearestSides; |
||||
} |
||||
} |
@ -0,0 +1,45 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import java.awt.Point; |
||||
|
||||
public class FormVerticalParallelLine extends AbstractFormParallelLine { |
||||
public FormVerticalParallelLine(int parallelValue, int startPosition, int endPosition) { |
||||
super(parallelValue, startPosition, endPosition); |
||||
} |
||||
|
||||
@Override |
||||
public Point getStartPointOnVerticalCenterLine() { |
||||
Point point = new Point(); |
||||
point.setLocation(parallelValue, getCenterPosition()); |
||||
return point; |
||||
} |
||||
|
||||
@Override |
||||
public Point getEndPointOnVerticalCenterLine(int parallelValue) { |
||||
Point point = new Point(); |
||||
point.setLocation(parallelValue, getCenterPosition()); |
||||
return point; |
||||
} |
||||
|
||||
@Override |
||||
public Point getExtendedLineStartPoint(AbstractFormParallelLine parallelLine) { |
||||
Point point = new Point(); |
||||
if (parallelLine.isVerticalCenterLineBeforeTheParallelLine(this)) { |
||||
point.setLocation(getParallelValue(), getStartPosition()); |
||||
} else if (parallelLine.isVerticalCenterLineBehindTheParallelLine(this)) { |
||||
point.setLocation(getParallelValue(), getEndPosition()); |
||||
} |
||||
return point; |
||||
} |
||||
|
||||
@Override |
||||
public Point getExtendedLineEndPoint(AbstractFormParallelLine parallelLine) { |
||||
Point point = new Point(); |
||||
if (parallelLine.isVerticalCenterLineBeforeTheParallelLine(this)) { |
||||
point.setLocation(getParallelValue(), parallelLine.getStartPosition()); |
||||
} else if (parallelLine.isVerticalCenterLineBehindTheParallelLine(this)) { |
||||
point.setLocation(getParallelValue(), parallelLine.getEndPosition()); |
||||
} |
||||
return point; |
||||
} |
||||
} |
@ -0,0 +1,218 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.design.designer.creator.XCreator; |
||||
|
||||
import java.awt.Rectangle; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.Comparator; |
||||
import java.util.List; |
||||
|
||||
public class MultiSelectionArrangement { |
||||
private FormDesigner designer; |
||||
private List<XCreator> selectedCreators; |
||||
private Rectangle rec; |
||||
|
||||
public MultiSelectionArrangement(FormDesigner designer) { |
||||
this.designer = designer; |
||||
update(); |
||||
} |
||||
|
||||
public void leftAlign() { |
||||
for (XCreator creator : selectedCreators) { |
||||
creator.setLocation(rec.x, creator.getY()); |
||||
} |
||||
repaint(); |
||||
} |
||||
|
||||
public void rightAlign() { |
||||
for (XCreator creator : selectedCreators) { |
||||
creator.setLocation(rec.x + rec.width - creator.getWidth(), creator.getY()); |
||||
} |
||||
repaint(); |
||||
} |
||||
|
||||
public void topAlign() { |
||||
for (XCreator creator : selectedCreators) { |
||||
creator.setLocation(creator.getX(), rec.y); |
||||
} |
||||
repaint(); |
||||
} |
||||
|
||||
public void bottomAlign() { |
||||
for (XCreator creator : selectedCreators) { |
||||
creator.setLocation(creator.getX(), rec.y + rec.height - creator.getHeight()); |
||||
} |
||||
repaint(); |
||||
} |
||||
|
||||
public void horizontalCenterAlign() { |
||||
for (XCreator creator : selectedCreators) { |
||||
creator.setLocation(rec.x + rec.width / 2 - creator.getWidth() / 2, creator.getY()); |
||||
} |
||||
repaint(); |
||||
} |
||||
|
||||
public void verticalCenterAlign() { |
||||
for (XCreator creator : selectedCreators) { |
||||
creator.setLocation(creator.getX(), rec.y + rec.height / 2 - creator.getHeight() / 2); |
||||
} |
||||
repaint(); |
||||
} |
||||
|
||||
// 水平分布,自动,间距由selectedCreators和border共同计算而来
|
||||
public void horizontalAutoDistribution() { |
||||
int gap = calculateHorizontalGap(); |
||||
horizontalDistribution(gap); |
||||
} |
||||
|
||||
// 水平分布,手动,传入一个间距,排列selectedCreators
|
||||
public void horizontalManualDistribution(int gap) { |
||||
reSizeRecByHorizontal(gap); |
||||
horizontalDistribution(gap); |
||||
} |
||||
|
||||
private void horizontalDistribution(int gap) { |
||||
sortHorizontal(); |
||||
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() + gap, creator.getY()); |
||||
} |
||||
repaint(); |
||||
} |
||||
|
||||
private void reSizeRecByHorizontal(int gap) { |
||||
sortHorizontal(); |
||||
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 calculateHorizontalGap() { |
||||
int sum = 0; |
||||
for (XCreator creator : selectedCreators) { |
||||
sum += creator.getWidth(); |
||||
} |
||||
return (rec.width - sum) / (selectedCreators.size() - 1); |
||||
} |
||||
|
||||
public void verticalAutoDistribution() { |
||||
int gap = calculateVerticalGap(); |
||||
verticalDistribution(gap); |
||||
} |
||||
|
||||
public void verticalManualDistribution(int gap) { |
||||
reSizeRecByVertical(gap); |
||||
verticalDistribution(gap); |
||||
} |
||||
|
||||
private void verticalDistribution(int gap) { |
||||
sortVertical(); |
||||
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() + gap); |
||||
} |
||||
repaint(); |
||||
} |
||||
|
||||
private void reSizeRecByVertical(int gap) { |
||||
sortVertical(); |
||||
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 calculateVerticalGap() { |
||||
int sum = 0; |
||||
for (XCreator creator : selectedCreators) { |
||||
sum += creator.getHeight(); |
||||
} |
||||
return (rec.height - sum) / (selectedCreators.size() - 1); |
||||
} |
||||
|
||||
private void update() { |
||||
FormSelection selection = designer.getSelectionModel().getSelection(); |
||||
this.selectedCreators = Arrays.asList(selection.getSelectedCreators()); |
||||
this.rec = selection.getSelctionBounds(); |
||||
} |
||||
|
||||
private void repaint() { |
||||
designer.repaint(); |
||||
update(); |
||||
} |
||||
} |
@ -0,0 +1,23 @@
|
||||
package com.fr.design.mainframe.widget.arrangement.buttons; |
||||
|
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.mainframe.MultiSelectionArrangement; |
||||
|
||||
public abstract class AbstractMultiSelectionArrangementButton implements MultiSelectionArrangementButton { |
||||
protected MultiSelectionArrangement arrangement; |
||||
|
||||
public AbstractMultiSelectionArrangementButton(MultiSelectionArrangement arrangement) { |
||||
this.arrangement = arrangement; |
||||
} |
||||
|
||||
@Override |
||||
public UIButton create() { |
||||
UIButton btn = new UIButton(); |
||||
btn.setNormalPainted(false); |
||||
btn.setBorderPaintedOnlyWhenPressed(true); |
||||
btn.setIcon(getIcon()); |
||||
btn.setToolTipText(getTipText()); |
||||
btn.addActionListener(getActionListener()); |
||||
return btn; |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
package com.fr.design.mainframe.widget.arrangement.buttons; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.MultiSelectionArrangement; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.Icon; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class BottomAlignButton extends AbstractMultiSelectionArrangementButton { |
||||
public BottomAlignButton(MultiSelectionArrangement arrangement) { |
||||
super(arrangement); |
||||
} |
||||
|
||||
@Override |
||||
public Icon getIcon() { |
||||
return IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_bottom_align.png"); |
||||
} |
||||
|
||||
@Override |
||||
public String getTipText() { |
||||
return Toolkit.i18nText("Fine-Design_Multi_Selection_Bottom_Align"); |
||||
} |
||||
|
||||
@Override |
||||
public ActionListener getActionListener() { |
||||
return new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
arrangement.bottomAlign(); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
package com.fr.design.mainframe.widget.arrangement.buttons; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.MultiSelectionArrangement; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.Icon; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class HorizontalCenterButton extends AbstractMultiSelectionArrangementButton { |
||||
public HorizontalCenterButton(MultiSelectionArrangement arrangement) { |
||||
super(arrangement); |
||||
} |
||||
|
||||
@Override |
||||
public Icon getIcon() { |
||||
return IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_horizontal_center_align.png"); |
||||
} |
||||
|
||||
@Override |
||||
public String getTipText() { |
||||
return Toolkit.i18nText("Fine-Design_Multi_Selection_Horizontal_Center_Align"); |
||||
} |
||||
|
||||
@Override |
||||
public ActionListener getActionListener() { |
||||
return new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
arrangement.horizontalCenterAlign(); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
package com.fr.design.mainframe.widget.arrangement.buttons; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.MultiSelectionArrangement; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.Icon; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class HorizontalDistributionButton extends AbstractMultiSelectionArrangementButton { |
||||
public HorizontalDistributionButton(MultiSelectionArrangement arrangement) { |
||||
super(arrangement); |
||||
} |
||||
|
||||
@Override |
||||
public Icon getIcon() { |
||||
return IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_horizontal_auto_spacing.png"); |
||||
} |
||||
|
||||
@Override |
||||
public String getTipText() { |
||||
return Toolkit.i18nText("Fine-Design_Multi_Selection_Auto_Horizontal_Spacing"); |
||||
} |
||||
|
||||
@Override |
||||
public ActionListener getActionListener() { |
||||
return new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
arrangement.horizontalAutoDistribution(); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
package com.fr.design.mainframe.widget.arrangement.buttons; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.MultiSelectionArrangement; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.Icon; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class LeftAlignButton extends AbstractMultiSelectionArrangementButton { |
||||
public LeftAlignButton(MultiSelectionArrangement arrangement) { |
||||
super(arrangement); |
||||
} |
||||
|
||||
@Override |
||||
public Icon getIcon() { |
||||
return IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_left_align.png"); |
||||
} |
||||
|
||||
@Override |
||||
public String getTipText() { |
||||
return Toolkit.i18nText("Fine-Design_Multi_Selection_Left_Align"); |
||||
} |
||||
|
||||
@Override |
||||
public ActionListener getActionListener() { |
||||
return new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
arrangement.leftAlign(); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,16 @@
|
||||
package com.fr.design.mainframe.widget.arrangement.buttons; |
||||
|
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
|
||||
import javax.swing.Icon; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public interface MultiSelectionArrangementButton { |
||||
Icon getIcon(); |
||||
|
||||
String getTipText(); |
||||
|
||||
ActionListener getActionListener(); |
||||
|
||||
UIButton create(); |
||||
} |
@ -0,0 +1,35 @@
|
||||
package com.fr.design.mainframe.widget.arrangement.buttons; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.MultiSelectionArrangement; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.Icon; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class RightAlignButton extends AbstractMultiSelectionArrangementButton { |
||||
public RightAlignButton(MultiSelectionArrangement arrangement) { |
||||
super(arrangement); |
||||
} |
||||
|
||||
@Override |
||||
public Icon getIcon() { |
||||
return IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_right_align.png"); |
||||
} |
||||
|
||||
@Override |
||||
public String getTipText() { |
||||
return Toolkit.i18nText("Fine-Design_Multi_Selection_Right_Align"); |
||||
} |
||||
|
||||
@Override |
||||
public ActionListener getActionListener() { |
||||
return new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
arrangement.rightAlign(); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
package com.fr.design.mainframe.widget.arrangement.buttons; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.MultiSelectionArrangement; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.Icon; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class TopAlignButton extends AbstractMultiSelectionArrangementButton { |
||||
public TopAlignButton(MultiSelectionArrangement arrangement) { |
||||
super(arrangement); |
||||
} |
||||
|
||||
@Override |
||||
public Icon getIcon() { |
||||
return IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_top_align.png"); |
||||
} |
||||
|
||||
@Override |
||||
public String getTipText() { |
||||
return Toolkit.i18nText("Fine-Design_Multi_Selection_Top_Align"); |
||||
} |
||||
|
||||
@Override |
||||
public ActionListener getActionListener() { |
||||
return new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
arrangement.topAlign(); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
package com.fr.design.mainframe.widget.arrangement.buttons; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.MultiSelectionArrangement; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.Icon; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class VerticalCenterButton extends AbstractMultiSelectionArrangementButton { |
||||
public VerticalCenterButton(MultiSelectionArrangement arrangement) { |
||||
super(arrangement); |
||||
} |
||||
|
||||
@Override |
||||
public Icon getIcon() { |
||||
return IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_vertical_center_align.png"); |
||||
} |
||||
|
||||
@Override |
||||
public String getTipText() { |
||||
return Toolkit.i18nText("Fine-Design_Multi_Selection_Vertical_Center_Align"); |
||||
} |
||||
|
||||
@Override |
||||
public ActionListener getActionListener() { |
||||
return new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
arrangement.verticalCenterAlign(); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
package com.fr.design.mainframe.widget.arrangement.buttons; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.MultiSelectionArrangement; |
||||
import com.fr.general.IOUtils; |
||||
|
||||
import javax.swing.Icon; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
public class VerticalDistributionButton extends AbstractMultiSelectionArrangementButton { |
||||
public VerticalDistributionButton(MultiSelectionArrangement arrangement) { |
||||
super(arrangement); |
||||
} |
||||
|
||||
@Override |
||||
public Icon getIcon() { |
||||
return IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_vertical_auto_spacing.png"); |
||||
} |
||||
|
||||
@Override |
||||
public String getTipText() { |
||||
return Toolkit.i18nText("Fine-Design_Multi_Selection_Auto_Vertical_Spacing"); |
||||
} |
||||
|
||||
@Override |
||||
public ActionListener getActionListener() { |
||||
return new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
arrangement.verticalAutoDistribution(); |
||||
} |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,178 @@
|
||||
package com.fr.design.mainframe.widget.ui; |
||||
|
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.itextfield.UIIntNumberField; |
||||
import com.fr.design.gui.itextfield.UITextField; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.TableLayout; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.design.mainframe.FormDesigner; |
||||
import com.fr.design.mainframe.MultiSelectionArrangement; |
||||
import com.fr.design.mainframe.widget.arrangement.buttons.BottomAlignButton; |
||||
import com.fr.design.mainframe.widget.arrangement.buttons.HorizontalCenterButton; |
||||
import com.fr.design.mainframe.widget.arrangement.buttons.HorizontalDistributionButton; |
||||
import com.fr.design.mainframe.widget.arrangement.buttons.LeftAlignButton; |
||||
import com.fr.design.mainframe.widget.arrangement.buttons.RightAlignButton; |
||||
import com.fr.design.mainframe.widget.arrangement.buttons.TopAlignButton; |
||||
import com.fr.design.mainframe.widget.arrangement.buttons.VerticalCenterButton; |
||||
import com.fr.design.mainframe.widget.arrangement.buttons.VerticalDistributionButton; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.stable.StableUtils; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JPanel; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Component; |
||||
import java.awt.event.FocusAdapter; |
||||
import java.awt.event.FocusEvent; |
||||
|
||||
public class FormMultiWidgetCardPane extends FormWidgetCardPane { |
||||
private MultiSelectionArrangement arrangement; |
||||
|
||||
public FormMultiWidgetCardPane(FormDesigner designer) { |
||||
super(designer); |
||||
arrangement = new MultiSelectionArrangement(designer); |
||||
} |
||||
|
||||
public void initPropertyPane() { |
||||
content.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0)); |
||||
content.add(createArrangementLayoutPane(), BorderLayout.CENTER); |
||||
} |
||||
|
||||
// 整个排列分布面板的layout,可以看成一个三行一列的表格,第一行是分布,第二行是自动间距,第三行是手动间距
|
||||
private JPanel createArrangementLayoutPane() { |
||||
double[] rowSize = {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}; |
||||
double[] columnSize = {TableLayout.PREFERRED}; |
||||
Component[][] components = new Component[][] { |
||||
new Component[] { |
||||
createAlignmentPane() |
||||
}, |
||||
new Component[] { |
||||
createAutoSpacingPane() |
||||
}, |
||||
new Component[] { |
||||
createManualSpacingPane() |
||||
} |
||||
}; |
||||
return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, 0, 16); |
||||
} |
||||
|
||||
// 对齐
|
||||
private JPanel createAlignmentPane() { |
||||
double[] rowSize = {TableLayout.PREFERRED}; |
||||
double[] columnSize = { |
||||
TableLayout.PREFERRED, |
||||
TableLayout.PREFERRED, |
||||
TableLayout.PREFERRED, |
||||
TableLayout.PREFERRED, |
||||
TableLayout.PREFERRED, |
||||
TableLayout.PREFERRED |
||||
}; |
||||
Component[][] components = new Component[][] { |
||||
new Component[] { |
||||
new LeftAlignButton(arrangement).create(), |
||||
new HorizontalCenterButton(arrangement).create(), |
||||
new RightAlignButton(arrangement).create(), |
||||
new TopAlignButton(arrangement).create(), |
||||
new VerticalCenterButton(arrangement).create(), |
||||
new BottomAlignButton(arrangement).create() |
||||
} |
||||
}; |
||||
JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, 18, 0); |
||||
return createTitleLayout(Toolkit.i18nText("Fine-Design_Multi_Selection_Align"), centerPane); |
||||
} |
||||
|
||||
// 自动间距
|
||||
private JPanel createAutoSpacingPane() { |
||||
double[] rowSize = {TableLayout.PREFERRED}; |
||||
double[] columnSize = { |
||||
TableLayout.PREFERRED, |
||||
TableLayout.PREFERRED |
||||
}; |
||||
UIButton horizontalAutoSpacingBtn = new HorizontalDistributionButton(arrangement).create(); |
||||
UIButton verticalAutoSpacingBtn = new VerticalDistributionButton(arrangement).create(); |
||||
if (designer.getSelectionModel().getSelection().size() < 3) { |
||||
horizontalAutoSpacingBtn.setEnabled(false); |
||||
verticalAutoSpacingBtn.setEnabled(false); |
||||
} |
||||
Component[][] components = new Component[][] { |
||||
new Component[] { |
||||
horizontalAutoSpacingBtn, |
||||
verticalAutoSpacingBtn |
||||
} |
||||
}; |
||||
JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, 18, 0); |
||||
|
||||
|
||||
UILabel tip = new UILabel(IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_auto_spacing_tip.png")); |
||||
tip.setToolTipText(Toolkit.i18nText("Fine-Design_Multi_Selection_Auto_Spacing_Tip")); |
||||
Component[][] titleComponents = new Component[][] { |
||||
new Component[] { |
||||
new UILabel(Toolkit.i18nText("Fine-Design_Multi_Selection_Auto_Spacing")), |
||||
tip |
||||
} |
||||
}; |
||||
JPanel northPane = TableLayoutHelper.createGapTableLayoutPane(titleComponents, rowSize, columnSize, 5, 0); |
||||
|
||||
JPanel jPanel = new JPanel(); |
||||
jPanel.setLayout(new BorderLayout(0, 8)); |
||||
jPanel.add(northPane, BorderLayout.NORTH); |
||||
jPanel.add(centerPane, BorderLayout.CENTER); |
||||
return jPanel; |
||||
} |
||||
|
||||
// 手动间距
|
||||
private JPanel createManualSpacingPane() { |
||||
double[] rowSize = {TableLayout.PREFERRED, TableLayout.PREFERRED}; |
||||
double[] columnSize = { |
||||
TableLayout.PREFERRED, |
||||
TableLayout.FILL |
||||
}; |
||||
UITextField horizontalSpacingNumberField = new UIIntNumberField(); |
||||
horizontalSpacingNumberField.addFocusListener(new FocusAdapter() { |
||||
@Override |
||||
public void focusLost(FocusEvent e) { |
||||
distributionDoChange(horizontalSpacingNumberField.getText(), false); |
||||
} |
||||
}); |
||||
UITextField verticalSpacingNumberField = new UIIntNumberField(); |
||||
verticalSpacingNumberField.addFocusListener(new FocusAdapter() { |
||||
@Override |
||||
public void focusLost(FocusEvent e) { |
||||
distributionDoChange(verticalSpacingNumberField.getText(), true); |
||||
} |
||||
}); |
||||
Component[][] components = new Component[][] { |
||||
new Component[] { |
||||
new UILabel(IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_horizontal_spacing.png")), |
||||
horizontalSpacingNumberField |
||||
}, |
||||
new Component[] { |
||||
new UILabel(IOUtils.readIcon("/com/fr/design/images/buttonicon/multi_selection_vertical_spacing.png")), |
||||
verticalSpacingNumberField |
||||
} |
||||
}; |
||||
JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, 21, 9); |
||||
return createTitleLayout(Toolkit.i18nText("Fine-Design_Multi_Selection_Manual_Spacing"), centerPane); |
||||
} |
||||
|
||||
private void distributionDoChange(String text, boolean isVertical) { |
||||
if (StableUtils.isNumber(text)) { |
||||
if (isVertical) { |
||||
arrangement.verticalManualDistribution(Math.round(Float.parseFloat(text))); |
||||
} else { |
||||
arrangement.horizontalManualDistribution(Math.round(Float.parseFloat(text))); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// 创建一个BorderLayout布局,上面是标题,例如“对齐”,下面是个容器
|
||||
private JPanel createTitleLayout(String title, JPanel centerPane) { |
||||
JPanel jPanel = new JPanel(); |
||||
jPanel.setLayout(new BorderLayout(0, 8)); |
||||
jPanel.add(new UILabel(title), BorderLayout.NORTH); |
||||
jPanel.add(centerPane, BorderLayout.CENTER); |
||||
return jPanel; |
||||
} |
||||
} |
@ -0,0 +1,297 @@
|
||||
package com.fr.design.mainframe.widget.ui; |
||||
|
||||
import com.fr.design.data.DataCreatorUI; |
||||
import com.fr.design.designer.beans.events.DesignerEvent; |
||||
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.XWAbsoluteBodyLayout; |
||||
import com.fr.design.designer.creator.XWAbsoluteLayout; |
||||
import com.fr.design.designer.creator.XWFitLayout; |
||||
import com.fr.design.designer.creator.XWParameterLayout; |
||||
import com.fr.design.designer.creator.XWScaleLayout; |
||||
import com.fr.design.designer.creator.XWTitleLayout; |
||||
import com.fr.design.designer.creator.cardlayout.XWCardTagLayout; |
||||
import com.fr.design.file.HistoryTemplateListCache; |
||||
import com.fr.design.foldablepane.UIExpandablePane; |
||||
import com.fr.design.gui.frpane.AttributeChangeListener; |
||||
import com.fr.design.gui.itextfield.UITextField; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.EastRegionContainerPane; |
||||
import com.fr.design.mainframe.FormDesigner; |
||||
import com.fr.design.mainframe.JForm; |
||||
import com.fr.design.mainframe.JTemplate; |
||||
import com.fr.design.widget.DataModify; |
||||
import com.fr.design.widget.FormWidgetDefinePaneFactoryBase; |
||||
import com.fr.design.widget.Operator; |
||||
import com.fr.design.widget.ui.designer.component.WidgetAbsoluteBoundPane; |
||||
import com.fr.design.widget.ui.designer.component.WidgetBoundPane; |
||||
import com.fr.design.widget.ui.designer.component.WidgetCardTagBoundPane; |
||||
import com.fr.form.ui.ChartEditor; |
||||
import com.fr.form.ui.Widget; |
||||
import com.fr.form.ui.container.WScaleLayout; |
||||
import com.fr.form.ui.container.WTitleLayout; |
||||
import com.fr.form.ui.widget.CRBoundsWidget; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JComponent; |
||||
import javax.swing.JOptionPane; |
||||
import javax.swing.JPanel; |
||||
import java.awt.BorderLayout; |
||||
|
||||
public class FormSingleWidgetCardPane extends FormWidgetCardPane { |
||||
private AttributeChangeListener listener; |
||||
|
||||
//当前的编辑器属性定义面板
|
||||
private DataModify<Widget> currentEditorDefinePane; |
||||
private FormBasicPropertyPane widgetPropertyPane; |
||||
private JPanel attriCardPane; |
||||
|
||||
private XCreator xCreator; |
||||
private WidgetBoundPane widgetBoundPane; |
||||
|
||||
|
||||
public FormSingleWidgetCardPane(FormDesigner designer) { |
||||
super(designer); |
||||
} |
||||
|
||||
public void initPropertyPane() { |
||||
this.xCreator = findXcreator(designer); |
||||
initComponents(); |
||||
initDefinePane(); |
||||
} |
||||
|
||||
public XLayoutContainer getParent(XCreator source) { |
||||
XLayoutContainer container = XCreatorUtils.getParentXLayoutContainer(source); |
||||
if (source.acceptType(XWFitLayout.class) || source.acceptType(XWParameterLayout.class)) { |
||||
container = null; |
||||
} |
||||
return container; |
||||
} |
||||
|
||||
public WidgetBoundPane createWidgetBoundPane(XCreator xCreator) { |
||||
XLayoutContainer xLayoutContainer = getParent(xCreator); |
||||
if (xLayoutContainer == null || xCreator.acceptType(XWParameterLayout.class) || xCreator.acceptType(XWAbsoluteBodyLayout.class)) { |
||||
return null; |
||||
} else if (xLayoutContainer.acceptType(XWAbsoluteLayout.class)) { |
||||
return new WidgetAbsoluteBoundPane(xCreator); |
||||
} else if (xCreator.acceptType(XWCardTagLayout.class)) { |
||||
return new WidgetCardTagBoundPane(xCreator); |
||||
} |
||||
return new WidgetBoundPane(xCreator); |
||||
} |
||||
|
||||
public XCreator findXcreator(FormDesigner designer) { |
||||
XCreator creator = designer.getSelectionModel().getSelection().getSelectedCreator(); |
||||
return creator != null ? creator : designer.getRootComponent(); |
||||
} |
||||
|
||||
/** |
||||
* 后台初始化所有事件. |
||||
*/ |
||||
@Override |
||||
public void initAllListeners() { |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 后台初始化所有事件. |
||||
*/ |
||||
public void reinitAllListeners() { |
||||
initListener(this); |
||||
} |
||||
|
||||
@Override |
||||
protected void initContentPane() { |
||||
|
||||
} |
||||
|
||||
private void initComponents() { |
||||
XCreator innerCreator = getXCreatorDedicated(); |
||||
|
||||
attriCardPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
content.add(attriCardPane, BorderLayout.CENTER); |
||||
content.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); |
||||
|
||||
final boolean isExtraWidget = FormWidgetDefinePaneFactoryBase.isExtraXWidget(innerCreator.toData()); |
||||
this.listener = new AttributeChangeListener() { |
||||
@Override |
||||
public void attributeChange() { |
||||
if (!isExtraWidget) { |
||||
updateCreator(); |
||||
} |
||||
updateWidgetBound(); |
||||
firePropertyEdit(); |
||||
} |
||||
}; |
||||
|
||||
freshPropertyMode(innerCreator); |
||||
if (isExtraWidget) { |
||||
// REPORT-55603: 仅对于插件控件,将尺寸*位置面板放置在definePane下方,其余控件将尺寸*位置面板放置在definePane上方
|
||||
widgetBoundPane = createWidgetBoundPane(xCreator); |
||||
if (widgetBoundPane != null) { |
||||
attriCardPane.add(widgetBoundPane, BorderLayout.CENTER); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
widgetPropertyPane = WidgetBasicPropertyPaneFactory.createBasicPropertyPane(innerCreator); |
||||
|
||||
UIExpandablePane uiExpandablePane = new UIExpandablePane(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Basic"), 280, 20, widgetPropertyPane); |
||||
|
||||
content.add(uiExpandablePane, BorderLayout.NORTH); |
||||
|
||||
widgetBoundPane = createWidgetBoundPane(xCreator); |
||||
if (widgetBoundPane != null) { |
||||
attriCardPane.add(widgetBoundPane, BorderLayout.NORTH); |
||||
} |
||||
} |
||||
|
||||
private static void freshPropertyMode(XCreator xCreator) { |
||||
JTemplate jTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); |
||||
if (!(jTemplate instanceof JForm) && jTemplate.isUpMode()) { |
||||
if (xCreator instanceof XWParameterLayout) { |
||||
EastRegionContainerPane.getInstance().switchMode(EastRegionContainerPane.PropertyMode.REPORT_PARA); |
||||
} else { |
||||
EastRegionContainerPane.getInstance().switchMode(EastRegionContainerPane.PropertyMode.REPORT_PARA_WIDGET); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void initDefinePane() { |
||||
currentEditorDefinePane = null; |
||||
XCreator creator = getXCreatorDedicated(); |
||||
FormWidgetDefinePaneFactoryBase.RN rn = FormWidgetDefinePaneFactoryBase.createWidgetDefinePane(creator, designer, creator.toData(), new Operator() { |
||||
@Override |
||||
public void did(DataCreatorUI ui, String cardName) { |
||||
//todo
|
||||
} |
||||
}); |
||||
DataModify<Widget> definePane = rn.getDefinePane(); |
||||
|
||||
JComponent definePaneComponent = definePane.toSwingComponent(); |
||||
boolean isExtraWidget = FormWidgetDefinePaneFactoryBase.isExtraXWidget(creator.toData()); |
||||
|
||||
if (isExtraWidget) { |
||||
// REPORT-55603: 仅对于插件控件,将尺寸*位置面板放置在definePane下方,其余控件将尺寸*位置面板放置在definePane上方
|
||||
attriCardPane.add(definePaneComponent, BorderLayout.NORTH); |
||||
} else { |
||||
// 使用单独的JPane和BorderLayout.North进行包装,避免出现CENTER嵌套CENTER后,内容高度变大的情况
|
||||
JPanel definePaneWrapContent = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
definePaneWrapContent.add(definePaneComponent, BorderLayout.NORTH); |
||||
attriCardPane.add(definePaneWrapContent, BorderLayout.CENTER); |
||||
} |
||||
currentEditorDefinePane = definePane; |
||||
} |
||||
|
||||
private XCreator getXCreatorDedicated() { |
||||
boolean dedicateLayout = xCreator.acceptType(XWScaleLayout.class) && xCreator.getComponentCount() > 0 && ((XCreator) xCreator.getComponent(0)).shouldScaleCreator() || xCreator.acceptType(XWTitleLayout.class); |
||||
return dedicateLayout ? (XCreator) xCreator.getComponent(0) : xCreator; |
||||
} |
||||
|
||||
@Override |
||||
public String title4PopupWindow() { |
||||
return "Widget"; |
||||
} |
||||
|
||||
public void populate() { |
||||
//populate之前先移除所有的监听
|
||||
removeAttributeChangeListener(); |
||||
Widget cellWidget = xCreator.toData(); |
||||
if (widgetBoundPane != null) { |
||||
widgetBoundPane.populate(); |
||||
} |
||||
Widget innerWidget = cellWidget; |
||||
if (cellWidget.acceptType(WScaleLayout.class)) { |
||||
Widget crBoundsWidget = ((WScaleLayout) cellWidget).getBoundsWidget(); |
||||
innerWidget = ((CRBoundsWidget) crBoundsWidget).getWidget(); |
||||
} else if (cellWidget.acceptType(WTitleLayout.class)) { |
||||
CRBoundsWidget crBoundsWidget = ((WTitleLayout) cellWidget).getBodyBoundsWidget(); |
||||
innerWidget = crBoundsWidget.getWidget(); |
||||
} |
||||
if (currentEditorDefinePane != null) { |
||||
currentEditorDefinePane.populateBean(innerWidget); |
||||
} |
||||
if (widgetPropertyPane != null) { |
||||
widgetPropertyPane.populate(innerWidget); |
||||
} |
||||
reinitAllListeners(); |
||||
this.addAttributeChangeListener(listener); |
||||
} |
||||
|
||||
|
||||
public void updateCreator() { |
||||
currentEditorDefinePane.setGlobalName(getGlobalName()); |
||||
Widget widget = currentEditorDefinePane.updateBean(); |
||||
if (ComparatorUtils.equals(getGlobalName(), Toolkit.i18nText("Fine-Design_Report_Basic")) && widgetPropertyPane != null) { |
||||
UITextField widgetNameField = widgetPropertyPane.getWidgetNameField(); |
||||
String toSetWidgetName = widgetNameField.getText(); |
||||
String currentWidgetName = widget.getWidgetName(); |
||||
if (toSetWidgetName.isEmpty()) { |
||||
widgetNameField.setText(currentWidgetName); |
||||
return; |
||||
} |
||||
|
||||
boolean exist = designer.getTarget().isNameExist(toSetWidgetName, widget) && !ComparatorUtils.equals(toSetWidgetName, currentWidgetName); |
||||
if (exist) { |
||||
widgetNameField.setText(currentWidgetName); |
||||
showNameInvalidDialog(Toolkit.i18nText("Fine-Design_Form_Widget_Rename_Failure")); |
||||
return; |
||||
} |
||||
|
||||
//图表名称的合法性检查
|
||||
if (widget instanceof ChartEditor && toSetWidgetName.startsWith("Chart")) { |
||||
widgetNameField.setText(currentWidgetName); |
||||
showNameInvalidDialog(Toolkit.i18nText("Fine-Design_Form_Chart_Widget_Rename_Failure")); |
||||
return; |
||||
} |
||||
widgetPropertyPane.update(widget); |
||||
// 上面一行更新了组件 这里必须重新调用getWidgetName
|
||||
xCreator.resetCreatorName(widget.getWidgetName()); |
||||
xCreator.resetVisible(widget.isVisible()); |
||||
designer.getEditListenerTable().fireCreatorModified(xCreator, DesignerEvent.CREATOR_RENAMED); |
||||
return; |
||||
} |
||||
fireValueChanged(); |
||||
} |
||||
|
||||
private void showNameInvalidDialog(String message) { |
||||
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), message, Toolkit.i18nText("Fine-Design_Form_Joption_News"), JOptionPane.ERROR_MESSAGE, IOUtils.readIcon("com/fr/design/form/images/joption_failure.png")); |
||||
} |
||||
|
||||
public void updateWidgetBound() { |
||||
if (widgetBoundPane != null && ComparatorUtils.equals(getGlobalName(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Coords_And_Size"))) { |
||||
widgetBoundPane.update(); |
||||
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_RESIZED); |
||||
} |
||||
designer.refreshDesignerUI(); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
/** |
||||
*检查 |
||||
*/ |
||||
public void checkValid() throws Exception { |
||||
currentEditorDefinePane.checkValid(); |
||||
} |
||||
|
||||
public void fireValueChanged() { |
||||
XCreator creator = getXCreatorDedicated(); |
||||
creator.firePropertyChange(); |
||||
} |
||||
|
||||
@Override |
||||
public String getIconPath() { |
||||
return StringUtils.EMPTY; |
||||
} |
||||
|
||||
public void firePropertyEdit() { |
||||
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED); |
||||
} |
||||
} |
@ -0,0 +1,13 @@
|
||||
package com.fr.design.mainframe.widget.ui; |
||||
|
||||
import com.fr.design.mainframe.FormDesigner; |
||||
|
||||
public class FormWidgetCardPaneFactory { |
||||
public static FormWidgetCardPane create(FormDesigner designer) { |
||||
if (designer.isMultiSelection()) { |
||||
return new FormMultiWidgetCardPane(designer); |
||||
} else { |
||||
return new FormSingleWidgetCardPane(designer); |
||||
} |
||||
} |
||||
} |