From 6a1e4bcca7274778e11a87fae317e5cc1ad95ffe Mon Sep 17 00:00:00 2001 From: "yaoh.wu" Date: Tue, 28 Mar 2017 15:47:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A0=E4=BB=BB=E5=8A=A1=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fr/design/beans/location/MoveUtils.java | 1094 ++++++++--------- .../beans/location/WidgetForbidWindow.java | 53 +- .../designer/beans/models/SelectionModel.java | 1 - .../design/mainframe/FormSelectionUtils.java | 74 +- 4 files changed, 589 insertions(+), 633 deletions(-) diff --git a/designer_base/src/com/fr/design/beans/location/MoveUtils.java b/designer_base/src/com/fr/design/beans/location/MoveUtils.java index 4ba477ffa..f96782ba8 100644 --- a/designer_base/src/com/fr/design/beans/location/MoveUtils.java +++ b/designer_base/src/com/fr/design/beans/location/MoveUtils.java @@ -9,580 +9,536 @@ import java.util.ArrayList; /** * Created by IntelliJ IDEA. - * + * * @author: Richer * @since : 6.5.5 Date: 11-7-1 Time: 下午2:22 */ public class MoveUtils { - public static final int SORPTION_UNIT = 5; + public static final int SORPTION_UNIT = 5; private static final int EQUIDISTANTLINE_UNIT = 4; - public static WidgetForbidWindow widgetForbidWindow = new WidgetForbidWindow(); - - public static ArrayList equidistantLines = new ArrayList<>(); - - private MoveUtils() { - - } - - public interface RectangleDesigner { - - /** - * 获取块边界的迭代器 - * - * @return 块边界的迭代器 - * - * @date 2015-2-12-下午2:43:47 - * - */ - RectangleIterator createRectangleIterator(); - - /** - * 设置X轴的线 - * - * @param line 连接线 - * - * @date 2015-2-12-下午2:44:04 - * - */ - void setXAbsorptionline(Absorptionline line); - - /** - * 设置Y轴的线 - * - * @param line 连接线 - * - * @date 2015-2-12-下午2:44:04 - * - */ - void setYAbsorptionline(Absorptionline line); - - /** - * 获取当前选中块的垂直线数组 - * - * @return 块的垂直线数组 - * - */ - int[] getVerticalLine(); - - /** - * 获取当前选中块的水平线数组 - * - * @return 块的水平线数组 - * - */ - int[] getHorizontalLine(); - - /** - * 设置designer内部组件是否重叠的标志位 - * @param isIntersects 是否重叠 - */ - void setWidgetsIntersected(boolean isIntersects); - - /** - * 获取designer内部组件是否重叠的标志位 - * @return 重叠 - */ - boolean isWidgetsIntersected(); - - /** - * 获取designer相对屏幕的位置 - * @return 位置 - */ - Point getDesignerLocationOnScreen(); - - /** - * 设置等距线 - * @param line 吸附线 - */ - void setEquidistantLine(Absorptionline line); - - /** - * 获取设计器垂直滚动条的值 - * @return 滚动条的值 - */ - int getDesignerScrollVerticalValue(); - - /** - * 获取设计器水平滚动条的值 - * @return 滚动条的值 - */ - int getDesignerScrollHorizontalValue(); - } - - public interface RectangleIterator { - - /** - * 是否存在下一个块 - * - * @return 是否存在下一个块 - * - * @date 2015-2-12-下午2:41:32 - * - */ - boolean hasNext(); - - /** - * 获取下一个块的bounds - * - * @return 下一个块的bounds - * - * @date 2015-2-12-下午2:41:55 - * - */ - Rectangle nextRectangle(); - - /** - * 获取块的垂直线数组 - * - * @return 块的垂直线数组 - * - * @date 2015-2-12-下午2:42:27 - * - */ - int[] getVerticalLine(); - - /** - * 获取块的水平线数组 - * - * @return 块的水平线数组 - * - * @date 2015-2-12-下午2:42:27 - * - */ - int[] getHorizontalLine(); - } - - private static class PlacePointing { - public PlacePointing(int x) { - this.palce = x; - } - - private boolean isFind() { - return direction != -1; - } - - private int palce; - private int direction = -1; - } - - private static void findX(PlacePointing px, Rectangle bounds, int left, int right, int width) { - if (px.isFind()) { - return; - } - if (Math.abs(bounds.x + bounds.width / 2 - (left + right) / 2) <= SORPTION_UNIT) { - px.palce = bounds.x + bounds.width / 2 - width / 2; - px.direction = SwingConstants.CENTER; - } - int x1 = bounds.x; - if (Math.abs(x1 - left) <= SORPTION_UNIT) { - px.palce = x1; - px.direction = SwingConstants.LEFT; - } - if (Math.abs(x1 - right) <= SORPTION_UNIT) { - px.palce = x1 - width; - px.direction = SwingConstants.RIGHT; - } - int x2 = bounds.x + bounds.width; - if (Math.abs(x2 - left) <= SORPTION_UNIT) { - px.palce = x2; - px.direction = SwingConstants.LEFT; - } - if (Math.abs(x2 - right) <= SORPTION_UNIT) { - px.palce = x2 - width; - px.direction = SwingConstants.RIGHT; - } - if (Math.abs(bounds.x + bounds.width / 2 - left) <= SORPTION_UNIT) { - px.palce = bounds.x + bounds.width / 2; - px.direction = SwingConstants.LEFT; - } - if (Math.abs(bounds.x + bounds.width / 2 - right) <= SORPTION_UNIT) { - px.palce = bounds.x + bounds.width / 2 - width; - px.direction = SwingConstants.RIGHT; - } - } - - private static void findY(PlacePointing py, Rectangle bounds, int top, int bottom, int height) { - if (py.isFind()) { - return; - } - - if (Math.abs(bounds.y + bounds.height / 2 - (top + bottom) / 2) <= SORPTION_UNIT) { - py.palce = bounds.y + bounds.height / 2 - height / 2; - py.direction = SwingConstants.CENTER; - } - int y1 = bounds.y; - if (Math.abs(y1 - top) <= SORPTION_UNIT) { - py.palce = y1; - py.direction = SwingConstants.TOP; - } - if (Math.abs(y1 - bottom) <= SORPTION_UNIT) { - py.palce = y1 - height; - py.direction = SwingConstants.BOTTOM; - } - int y2 = bounds.y + bounds.height; - if (Math.abs(y2 - top) <= SORPTION_UNIT) { - py.palce = y2; - py.direction = SwingConstants.TOP; - } - if (Math.abs(y2 - bottom) <= SORPTION_UNIT) { - py.palce = y2 - height; - py.direction = SwingConstants.BOTTOM; - } - if (Math.abs(bounds.y + bounds.height / 2 - top) <= SORPTION_UNIT) { - py.palce = bounds.y + bounds.height / 2; - py.direction = SwingConstants.TOP; - } - if (Math.abs(bounds.y + bounds.height / 2 - bottom) <= SORPTION_UNIT) { - py.palce = bounds.y + bounds.height / 2 - height; - py.direction = SwingConstants.BOTTOM; - } - } - - private static void findEquidistantLine(Rectangle bounds, int left, int top, int height, int width) { - //最近的距离与坐标 - EquidistantLine equidistantLineInfo = new EquidistantLine(0, 0, 0); - //等距线从各边中点画出,先要判断是不是在范围内 - int topMiddleX = left + width / 2; - int leftMiddleY = top + height / 2; - if ((topMiddleX > bounds.getX()) && (topMiddleX < (bounds.getX() + bounds.getWidth()))){ - //当前操作rec在bounds的下方 - if (top > (bounds.getY() + bounds.getHeight())){ - equidistantLineInfo.setDistance(top - (bounds.y + bounds.height)); - equidistantLineInfo.setReference(bounds.y + bounds.height); - equidistantLineInfo.setDirection(SwingConstants.TOP); - } - //当前操作rec在bounds上方 - if ((top + height) < bounds.getY()){ - equidistantLineInfo.setDistance(bounds.y - (top + height)); - equidistantLineInfo.setReference(bounds.y); - equidistantLineInfo.setDirection(SwingConstants.BOTTOM); - } - } - else if ((leftMiddleY > bounds.getY()) && (leftMiddleY < (bounds.getY() + bounds.getHeight()))){ - //当前操作rec在bounds的右侧 - if (left > (bounds.getX() + bounds.getWidth())){ - equidistantLineInfo.setDistance(left - (bounds.x + bounds.width)); - equidistantLineInfo.setReference(bounds.x + bounds.width); - equidistantLineInfo.setDirection(SwingConstants.LEFT); - } - //当前操作rec在bounds的左侧 - if ((left + width) < bounds.getX()){ - equidistantLineInfo.setDistance(bounds.x - (left + width)); - equidistantLineInfo.setReference(bounds.x); - equidistantLineInfo.setDirection(SwingConstants.RIGHT); - } - } - if(equidistantLineInfo.getDistance() > 0) { - equidistantLines.add(equidistantLineInfo); - } - } - -// public static void displayForbidWindow(int x, int y) { -// widgetForbidWindow.showWindow(x, y); -// } - -// public static void hideForbidWindow() { -// widgetForbidWindow.hideWindow(); -// } - - /** - * 吸附 - * - * @param x x坐标 - * @param y y坐标 - * @param width 宽度 - * @param height 高度 - * @param designer 块设计器 - * - * @return 吸附后坐标 - * - * @date 2015-2-12-下午2:39:16 - * - */ - public static Point sorption(int x, int y, int width, int height, RectangleDesigner designer, boolean isParameterLayout) { - - int left = x, top = y, bottom = top + height, right = left + width; - - Rectangle operatingRectangle = new Rectangle(x, y, width, height); - - equidistantLines.clear(); - - PlacePointing px = new PlacePointing(x); - PlacePointing py = new PlacePointing(y); - - PlacePointing pEquidistantX = new PlacePointing(x); - PlacePointing pEquidistantY = new PlacePointing(y); - - RectangleIterator iterator = designer.createRectangleIterator(); - - java.util.List cacheRecs = new ArrayList(); - //是否存在控件重叠 -// boolean isWidgetsIntersects = false; - while (iterator.hasNext()) { - Rectangle bounds = iterator.nextRectangle(); - cacheRecs.add(bounds); -// boolean isIntersects = operatingRectangle.intersects(bounds); - findX(px, bounds, left, right, width); - findY(py, bounds, top, bottom, height); - - if(!isParameterLayout){ -// if(isIntersects) { -// isWidgetsIntersects = true; -// } -// else{ - findEquidistantLine(bounds, left, top, height, width); -// } - } - } - //showForbiddenWindow(designer, x, y, isWidgetsIntersects); - - createXAbsorptionline(px, designer, width, cacheRecs); - createYAbsorptionline(py, designer, height, cacheRecs); - operatingRectangle.x = px.palce; - operatingRectangle.y = py.palce; - createEquidistantLine(pEquidistantX, pEquidistantY, operatingRectangle, designer); - Point sorptionPoint = new Point(px.palce,py.palce); - if (!px.isFind()){ - sorptionPoint.x = pEquidistantX.palce; - } - if (!py.isFind()){ - sorptionPoint.y = pEquidistantY.palce; - } - return sorptionPoint; - } - -// public static void showForbiddenWindow(RectangleDesigner designer, int x, int y, boolean isIntersects){ -// if (isIntersects){ -// if(designer.getDesignerLocationOnScreen() != null) { -// displayForbidWindow(x + designer.getDesignerLocationOnScreen().x, y + designer.getDesignerLocationOnScreen().y); -// } -// designer.setWidgetsIntersected(true); -// } -// else{ -// designer.setWidgetsIntersected(false); -// hideForbidWindow(); -// } -// } - - private static void createXAbsorptionline(PlacePointing px, RectangleDesigner designer, int width, java.util.List cacheRecs) { - Absorptionline line = null; - RectangleIterator iterator = designer.createRectangleIterator(); - int[] selfVertical = designer.getVerticalLine(); - if (px.direction == SwingConstants.CENTER) { - line = Absorptionline.createXMidAbsorptionline(px.palce + width / 2); - int left = px.palce; - int right = px.palce + width; - for (Rectangle bounds : cacheRecs) { - if (bounds.x == left || bounds.x + bounds.width == left) { - line.setFirstLine(left); - } - if (bounds.x == right || bounds.x + bounds.width == right) { - line.setSecondLine(right); - } - updateVerticalLine(selfVertical, iterator, line); - if (line.isFull()) { - break; - } - } - } else if (px.direction == SwingConstants.LEFT || px.direction == SwingConstants.RIGHT) { - int left = px.direction == SwingConstants.LEFT ? px.palce + width : px.palce; - line = Absorptionline.createXAbsorptionline(px.direction == SwingConstants.LEFT ? px.palce : px.palce + width); - int middle = px.palce + width / 2; - for (Rectangle bounds : cacheRecs) { - if (bounds.x == left || bounds.x + bounds.width == left) { - line.setSecondLine(left); - } - if (bounds.x + bounds.width / 2 == middle) { - line.setMidLine(middle); - } - updateVerticalLine(selfVertical, iterator, line); - if (line.isFull()) { - break; - } - } - } - designer.setXAbsorptionline(line); - } - - private static void createYAbsorptionline(PlacePointing py, RectangleDesigner designer, int height, java.util.List cacheRecs) { - Absorptionline line = null; - RectangleIterator iterator = designer.createRectangleIterator(); - int[] selfHorizontal = designer.getHorizontalLine(); - if (py.direction == SwingConstants.CENTER) { - line = Absorptionline.createYMidAbsorptionline(py.palce + height / 2); - int top = py.palce; - int bottom = py.palce + height; - for (Rectangle bounds : cacheRecs) { - if (bounds.y == top || bounds.y + bounds.height == top) { - line.setFirstLine(top); - } - if (bounds.y == bottom || bounds.y + bounds.height == bottom) { - line.setSecondLine(bottom); - } - updateHorizontalLine(selfHorizontal, iterator, line); - if (line.isFull()) { - break; - } - } - } else if (py.direction == SwingConstants.TOP || py.direction == SwingConstants.BOTTOM) { - int top = py.direction == SwingConstants.TOP ? py.palce + height : py.palce; - line = Absorptionline.createYAbsorptionline(py.direction == SwingConstants.TOP ? py.palce : py.palce + height); - int middle = py.palce + height / 2; - for (Rectangle bounds : cacheRecs) { - if (bounds.y == top || bounds.y + bounds.height == top) { - line.setSecondLine(top); - } - if (bounds.y + bounds.height / 2 == middle) { - line.setMidLine(middle); - } - updateHorizontalLine(selfHorizontal, iterator, line); - if (line.isFull()) { - break; - } - } - } - designer.setYAbsorptionline(line); - } - - private static void createEquidistantLine(PlacePointing px, PlacePointing py, Rectangle operatingRectangle, RectangleDesigner designer){ - processEquidistantLinesList(px, py, operatingRectangle); - Absorptionline line = null; - if(equidistantLines.size() > 0) { - int top = -1; - int left = -1; - int bottom = -1; - int right = -1; - for(int i = 0; i < equidistantLines.size(); i++){ - if (equidistantLines.get(i).getDirection() == SwingConstants.TOP){ - top = equidistantLines.get(i).getReference(); - } - if (equidistantLines.get(i).getDirection() == SwingConstants.LEFT){ - left = equidistantLines.get(i).getReference(); - } - if (equidistantLines.get(i).getDirection() == SwingConstants.BOTTOM){ - bottom = equidistantLines.get(i).getReference(); - } - if (equidistantLines.get(i).getDirection() == SwingConstants.RIGHT){ - right = equidistantLines.get(i).getReference(); - } - } - operatingRectangle.x -= designer.getDesignerScrollHorizontalValue(); - operatingRectangle.y -= designer.getDesignerScrollVerticalValue(); - line = Absorptionline.createEquidistantAbsorptionline(operatingRectangle, - top - designer.getDesignerScrollVerticalValue(), - left - designer.getDesignerScrollHorizontalValue(), - bottom - designer.getDesignerScrollVerticalValue(), - right - designer.getDesignerScrollHorizontalValue()); - } - designer.setEquidistantLine(line); - } - - private static void processEquidistantLinesList(PlacePointing pEquidistantX, PlacePointing pEquidistantY, Rectangle operatingRectangle){ - EquidistantLine[] equidistantLines1 = new EquidistantLine[EQUIDISTANTLINE_UNIT]; - //先按方向处理,只保留四个方向上距离最近 - for(int count = 0; count < equidistantLines.size(); count++){ - for (int direction = 0; direction < EQUIDISTANTLINE_UNIT; direction++){ - if(equidistantLines.get(count).getDirection() == (direction + 1)){//direction 1,2,3,4 分别对应top,left,bottom,right - if(equidistantLines1[direction] != null - && equidistantLines1[direction].getDistance() > equidistantLines.get(count).getDistance() - || equidistantLines1[direction] == null) { - equidistantLines1[direction] = equidistantLines.get(count); - } - } - } - } - - equidistantLines.clear(); - //找list中横纵分别等距的组合 - if (equidistantLines1[0] != null && equidistantLines1[2] != null){//top, bottom - int offset = equidistantLines1[0].getDistance() - equidistantLines1[2].getDistance(); - if (Math.abs(offset) <= SORPTION_UNIT * 2){ - pEquidistantY.direction = SwingConstants.TOP; - equidistantLines.add(equidistantLines1[0]); - equidistantLines.add(equidistantLines1[2]); - pEquidistantY.palce = operatingRectangle.y - offset / 2; - operatingRectangle.y = pEquidistantY.palce; - } - } - if (equidistantLines1[1] != null && equidistantLines1[3] != null){//left, right - int offset = equidistantLines1[1].getDistance() - equidistantLines1[3].getDistance(); - if (Math.abs(offset) <= SORPTION_UNIT * 2){ - pEquidistantX.direction = SwingConstants.LEFT; - equidistantLines.add(equidistantLines1[1]); - equidistantLines.add(equidistantLines1[3]); - pEquidistantX.palce = operatingRectangle.x - offset / 2; - operatingRectangle.x = pEquidistantX.palce; - } - } - } - - //更新纵向行列线 - private static void updateVerticalLine(int[] selfVertical, RectangleIterator iterator, Absorptionline line){ - int[] targetArray = iterator.getVerticalLine(); - if (intersectArrays(targetArray, selfVertical)){ - line.setVerticalLines(targetArray); - } - } - - //更新横向行列线 - private static void updateHorizontalLine(int[] selfHorizontal, RectangleIterator iterator, Absorptionline line){ - int[] targetArray = iterator.getHorizontalLine(); - if (intersectArrays(targetArray, selfHorizontal)){ - line.setHorizontalLines(targetArray); - } - } - - //检测两个数组是否有相交的部分 - private static boolean intersectArrays(int[] targetArray, int[] selfArray){ - for (int i : targetArray) { - for (int j : selfArray) { - if(i == j){ - return true; - } - } - } - - return false; - } - - private static class EquidistantLine{ - //与操作rectangle的距离 - private int distance; - //参考rectangle的位置 - private int reference; - //等距线的方向 - private int direction; - - EquidistantLine(int distance, int reference, int direction){ - this.distance = distance; - this.reference = reference; - this.direction = direction; - } - - public void setDistance(int distance){ - this.distance = distance; - } - - public int getDistance(){ - return this.distance; - } - - public void setReference(int reference){ - this.reference = reference; - } - - public int getReference(){ - return this.reference; - } - - public void setDirection(int direction){ - this.direction = direction; - } - - public int getDirection(){ - return this.direction; - } - } + public static ArrayList equidistantLines = new ArrayList<>(); + + private MoveUtils() { + + } + + public interface RectangleDesigner { + + /** + * 获取块边界的迭代器 + * + * @return 块边界的迭代器 + * @date 2015-2-12-下午2:43:47 + */ + RectangleIterator createRectangleIterator(); + + /** + * 设置X轴的线 + * + * @param line 连接线 + * @date 2015-2-12-下午2:44:04 + */ + void setXAbsorptionline(Absorptionline line); + + /** + * 设置Y轴的线 + * + * @param line 连接线 + * @date 2015-2-12-下午2:44:04 + */ + void setYAbsorptionline(Absorptionline line); + + /** + * 获取当前选中块的垂直线数组 + * + * @return 块的垂直线数组 + */ + int[] getVerticalLine(); + + /** + * 获取当前选中块的水平线数组 + * + * @return 块的水平线数组 + */ + int[] getHorizontalLine(); + + /** + * 设置designer内部组件是否重叠的标志位 + * + * @param isIntersects 是否重叠 + */ + void setWidgetsIntersected(boolean isIntersects); + + /** + * 获取designer内部组件是否重叠的标志位 + * + * @return 重叠 + */ + boolean isWidgetsIntersected(); + + /** + * 获取designer相对屏幕的位置 + * + * @return 位置 + */ + Point getDesignerLocationOnScreen(); + + /** + * 设置等距线 + * + * @param line 吸附线 + */ + void setEquidistantLine(Absorptionline line); + + /** + * 获取设计器垂直滚动条的值 + * + * @return 滚动条的值 + */ + int getDesignerScrollVerticalValue(); + + /** + * 获取设计器水平滚动条的值 + * + * @return 滚动条的值 + */ + int getDesignerScrollHorizontalValue(); + } + + public interface RectangleIterator { + + /** + * 是否存在下一个块 + * + * @return 是否存在下一个块 + * @date 2015-2-12-下午2:41:32 + */ + boolean hasNext(); + + /** + * 获取下一个块的bounds + * + * @return 下一个块的bounds + * @date 2015-2-12-下午2:41:55 + */ + Rectangle nextRectangle(); + + /** + * 获取块的垂直线数组 + * + * @return 块的垂直线数组 + * @date 2015-2-12-下午2:42:27 + */ + int[] getVerticalLine(); + + /** + * 获取块的水平线数组 + * + * @return 块的水平线数组 + * @date 2015-2-12-下午2:42:27 + */ + int[] getHorizontalLine(); + } + + private static class PlacePointing { + public PlacePointing(int x) { + this.palce = x; + } + + private boolean isFind() { + return direction != -1; + } + + private int palce; + private int direction = -1; + } + + private static void findX(PlacePointing px, Rectangle bounds, int left, int right, int width) { + if (px.isFind()) { + return; + } + if (Math.abs(bounds.x + bounds.width / 2 - (left + right) / 2) <= SORPTION_UNIT) { + px.palce = bounds.x + bounds.width / 2 - width / 2; + px.direction = SwingConstants.CENTER; + } + int x1 = bounds.x; + if (Math.abs(x1 - left) <= SORPTION_UNIT) { + px.palce = x1; + px.direction = SwingConstants.LEFT; + } + if (Math.abs(x1 - right) <= SORPTION_UNIT) { + px.palce = x1 - width; + px.direction = SwingConstants.RIGHT; + } + int x2 = bounds.x + bounds.width; + if (Math.abs(x2 - left) <= SORPTION_UNIT) { + px.palce = x2; + px.direction = SwingConstants.LEFT; + } + if (Math.abs(x2 - right) <= SORPTION_UNIT) { + px.palce = x2 - width; + px.direction = SwingConstants.RIGHT; + } + if (Math.abs(bounds.x + bounds.width / 2 - left) <= SORPTION_UNIT) { + px.palce = bounds.x + bounds.width / 2; + px.direction = SwingConstants.LEFT; + } + if (Math.abs(bounds.x + bounds.width / 2 - right) <= SORPTION_UNIT) { + px.palce = bounds.x + bounds.width / 2 - width; + px.direction = SwingConstants.RIGHT; + } + } + + private static void findY(PlacePointing py, Rectangle bounds, int top, int bottom, int height) { + if (py.isFind()) { + return; + } + + if (Math.abs(bounds.y + bounds.height / 2 - (top + bottom) / 2) <= SORPTION_UNIT) { + py.palce = bounds.y + bounds.height / 2 - height / 2; + py.direction = SwingConstants.CENTER; + } + int y1 = bounds.y; + if (Math.abs(y1 - top) <= SORPTION_UNIT) { + py.palce = y1; + py.direction = SwingConstants.TOP; + } + if (Math.abs(y1 - bottom) <= SORPTION_UNIT) { + py.palce = y1 - height; + py.direction = SwingConstants.BOTTOM; + } + int y2 = bounds.y + bounds.height; + if (Math.abs(y2 - top) <= SORPTION_UNIT) { + py.palce = y2; + py.direction = SwingConstants.TOP; + } + if (Math.abs(y2 - bottom) <= SORPTION_UNIT) { + py.palce = y2 - height; + py.direction = SwingConstants.BOTTOM; + } + if (Math.abs(bounds.y + bounds.height / 2 - top) <= SORPTION_UNIT) { + py.palce = bounds.y + bounds.height / 2; + py.direction = SwingConstants.TOP; + } + if (Math.abs(bounds.y + bounds.height / 2 - bottom) <= SORPTION_UNIT) { + py.palce = bounds.y + bounds.height / 2 - height; + py.direction = SwingConstants.BOTTOM; + } + } + + private static void findEquidistantLine(Rectangle bounds, int left, int top, int height, int width) { + //最近的距离与坐标 + EquidistantLine equidistantLineInfo = new EquidistantLine(0, 0, 0); + //等距线从各边中点画出,先要判断是不是在范围内 + int topMiddleX = left + width / 2; + int leftMiddleY = top + height / 2; + if ((topMiddleX > bounds.getX()) && (topMiddleX < (bounds.getX() + bounds.getWidth()))) { + //当前操作rec在bounds的下方 + if (top > (bounds.getY() + bounds.getHeight())) { + equidistantLineInfo.setDistance(top - (bounds.y + bounds.height)); + equidistantLineInfo.setReference(bounds.y + bounds.height); + equidistantLineInfo.setDirection(SwingConstants.TOP); + } + //当前操作rec在bounds上方 + if ((top + height) < bounds.getY()) { + equidistantLineInfo.setDistance(bounds.y - (top + height)); + equidistantLineInfo.setReference(bounds.y); + equidistantLineInfo.setDirection(SwingConstants.BOTTOM); + } + } else if ((leftMiddleY > bounds.getY()) && (leftMiddleY < (bounds.getY() + bounds.getHeight()))) { + //当前操作rec在bounds的右侧 + if (left > (bounds.getX() + bounds.getWidth())) { + equidistantLineInfo.setDistance(left - (bounds.x + bounds.width)); + equidistantLineInfo.setReference(bounds.x + bounds.width); + equidistantLineInfo.setDirection(SwingConstants.LEFT); + } + //当前操作rec在bounds的左侧 + if ((left + width) < bounds.getX()) { + equidistantLineInfo.setDistance(bounds.x - (left + width)); + equidistantLineInfo.setReference(bounds.x); + equidistantLineInfo.setDirection(SwingConstants.RIGHT); + } + } + if (equidistantLineInfo.getDistance() > 0) { + equidistantLines.add(equidistantLineInfo); + } + } + + + /** + * 吸附 + * + * @param x x坐标 + * @param y y坐标 + * @param width 宽度 + * @param height 高度 + * @param designer 块设计器 + * @return 吸附后坐标 + * @date 2015-2-12-下午2:39:16 + */ + public static Point sorption(int x, int y, int width, int height, RectangleDesigner designer, boolean isParameterLayout) { + + int left = x, top = y, bottom = top + height, right = left + width; + + Rectangle operatingRectangle = new Rectangle(x, y, width, height); + + equidistantLines.clear(); + + PlacePointing px = new PlacePointing(x); + PlacePointing py = new PlacePointing(y); + + PlacePointing pEquidistantX = new PlacePointing(x); + PlacePointing pEquidistantY = new PlacePointing(y); + + RectangleIterator iterator = designer.createRectangleIterator(); + + java.util.List cacheRecs = new ArrayList(); + while (iterator.hasNext()) { + Rectangle bounds = iterator.nextRectangle(); + cacheRecs.add(bounds); + findX(px, bounds, left, right, width); + findY(py, bounds, top, bottom, height); + + if (!isParameterLayout) { + findEquidistantLine(bounds, left, top, height, width); + } + } + + createXAbsorptionline(px, designer, width, cacheRecs); + createYAbsorptionline(py, designer, height, cacheRecs); + operatingRectangle.x = px.palce; + operatingRectangle.y = py.palce; + createEquidistantLine(pEquidistantX, pEquidistantY, operatingRectangle, designer); + Point sorptionPoint = new Point(px.palce, py.palce); + if (!px.isFind()) { + sorptionPoint.x = pEquidistantX.palce; + } + if (!py.isFind()) { + sorptionPoint.y = pEquidistantY.palce; + } + return sorptionPoint; + } + + + private static void createXAbsorptionline(PlacePointing px, RectangleDesigner designer, int width, java.util.List cacheRecs) { + Absorptionline line = null; + RectangleIterator iterator = designer.createRectangleIterator(); + int[] selfVertical = designer.getVerticalLine(); + if (px.direction == SwingConstants.CENTER) { + line = Absorptionline.createXMidAbsorptionline(px.palce + width / 2); + int left = px.palce; + int right = px.palce + width; + for (Rectangle bounds : cacheRecs) { + if (bounds.x == left || bounds.x + bounds.width == left) { + line.setFirstLine(left); + } + if (bounds.x == right || bounds.x + bounds.width == right) { + line.setSecondLine(right); + } + updateVerticalLine(selfVertical, iterator, line); + if (line.isFull()) { + break; + } + } + } else if (px.direction == SwingConstants.LEFT || px.direction == SwingConstants.RIGHT) { + int left = px.direction == SwingConstants.LEFT ? px.palce + width : px.palce; + line = Absorptionline.createXAbsorptionline(px.direction == SwingConstants.LEFT ? px.palce : px.palce + width); + int middle = px.palce + width / 2; + for (Rectangle bounds : cacheRecs) { + if (bounds.x == left || bounds.x + bounds.width == left) { + line.setSecondLine(left); + } + if (bounds.x + bounds.width / 2 == middle) { + line.setMidLine(middle); + } + updateVerticalLine(selfVertical, iterator, line); + if (line.isFull()) { + break; + } + } + } + designer.setXAbsorptionline(line); + } + + private static void createYAbsorptionline(PlacePointing py, RectangleDesigner designer, int height, java.util.List cacheRecs) { + Absorptionline line = null; + RectangleIterator iterator = designer.createRectangleIterator(); + int[] selfHorizontal = designer.getHorizontalLine(); + if (py.direction == SwingConstants.CENTER) { + line = Absorptionline.createYMidAbsorptionline(py.palce + height / 2); + int top = py.palce; + int bottom = py.palce + height; + for (Rectangle bounds : cacheRecs) { + if (bounds.y == top || bounds.y + bounds.height == top) { + line.setFirstLine(top); + } + if (bounds.y == bottom || bounds.y + bounds.height == bottom) { + line.setSecondLine(bottom); + } + updateHorizontalLine(selfHorizontal, iterator, line); + if (line.isFull()) { + break; + } + } + } else if (py.direction == SwingConstants.TOP || py.direction == SwingConstants.BOTTOM) { + int top = py.direction == SwingConstants.TOP ? py.palce + height : py.palce; + line = Absorptionline.createYAbsorptionline(py.direction == SwingConstants.TOP ? py.palce : py.palce + height); + int middle = py.palce + height / 2; + for (Rectangle bounds : cacheRecs) { + if (bounds.y == top || bounds.y + bounds.height == top) { + line.setSecondLine(top); + } + if (bounds.y + bounds.height / 2 == middle) { + line.setMidLine(middle); + } + updateHorizontalLine(selfHorizontal, iterator, line); + if (line.isFull()) { + break; + } + } + } + designer.setYAbsorptionline(line); + } + + private static void createEquidistantLine(PlacePointing px, PlacePointing py, Rectangle operatingRectangle, RectangleDesigner designer) { + processEquidistantLinesList(px, py, operatingRectangle); + Absorptionline line = null; + if (equidistantLines.size() > 0) { + int top = -1; + int left = -1; + int bottom = -1; + int right = -1; + for (int i = 0; i < equidistantLines.size(); i++) { + if (equidistantLines.get(i).getDirection() == SwingConstants.TOP) { + top = equidistantLines.get(i).getReference(); + } + if (equidistantLines.get(i).getDirection() == SwingConstants.LEFT) { + left = equidistantLines.get(i).getReference(); + } + if (equidistantLines.get(i).getDirection() == SwingConstants.BOTTOM) { + bottom = equidistantLines.get(i).getReference(); + } + if (equidistantLines.get(i).getDirection() == SwingConstants.RIGHT) { + right = equidistantLines.get(i).getReference(); + } + } + operatingRectangle.x -= designer.getDesignerScrollHorizontalValue(); + operatingRectangle.y -= designer.getDesignerScrollVerticalValue(); + line = Absorptionline.createEquidistantAbsorptionline(operatingRectangle, + top - designer.getDesignerScrollVerticalValue(), + left - designer.getDesignerScrollHorizontalValue(), + bottom - designer.getDesignerScrollVerticalValue(), + right - designer.getDesignerScrollHorizontalValue()); + } + designer.setEquidistantLine(line); + } + + private static void processEquidistantLinesList(PlacePointing pEquidistantX, PlacePointing pEquidistantY, Rectangle operatingRectangle) { + EquidistantLine[] equidistantLines1 = new EquidistantLine[EQUIDISTANTLINE_UNIT]; + //先按方向处理,只保留四个方向上距离最近 + for (int count = 0; count < equidistantLines.size(); count++) { + for (int direction = 0; direction < EQUIDISTANTLINE_UNIT; direction++) { + if (equidistantLines.get(count).getDirection() == (direction + 1)) {//direction 1,2,3,4 分别对应top,left,bottom,right + if (equidistantLines1[direction] != null + && equidistantLines1[direction].getDistance() > equidistantLines.get(count).getDistance() + || equidistantLines1[direction] == null) { + equidistantLines1[direction] = equidistantLines.get(count); + } + } + } + } + + equidistantLines.clear(); + //找list中横纵分别等距的组合 + if (equidistantLines1[0] != null && equidistantLines1[2] != null) {//top, bottom + int offset = equidistantLines1[0].getDistance() - equidistantLines1[2].getDistance(); + if (Math.abs(offset) <= SORPTION_UNIT * 2) { + pEquidistantY.direction = SwingConstants.TOP; + equidistantLines.add(equidistantLines1[0]); + equidistantLines.add(equidistantLines1[2]); + pEquidistantY.palce = operatingRectangle.y - offset / 2; + operatingRectangle.y = pEquidistantY.palce; + } + } + if (equidistantLines1[1] != null && equidistantLines1[3] != null) {//left, right + int offset = equidistantLines1[1].getDistance() - equidistantLines1[3].getDistance(); + if (Math.abs(offset) <= SORPTION_UNIT * 2) { + pEquidistantX.direction = SwingConstants.LEFT; + equidistantLines.add(equidistantLines1[1]); + equidistantLines.add(equidistantLines1[3]); + pEquidistantX.palce = operatingRectangle.x - offset / 2; + operatingRectangle.x = pEquidistantX.palce; + } + } + } + + //更新纵向行列线 + private static void updateVerticalLine(int[] selfVertical, RectangleIterator iterator, Absorptionline line) { + int[] targetArray = iterator.getVerticalLine(); + if (intersectArrays(targetArray, selfVertical)) { + line.setVerticalLines(targetArray); + } + } + + //更新横向行列线 + private static void updateHorizontalLine(int[] selfHorizontal, RectangleIterator iterator, Absorptionline line) { + int[] targetArray = iterator.getHorizontalLine(); + if (intersectArrays(targetArray, selfHorizontal)) { + line.setHorizontalLines(targetArray); + } + } + + //检测两个数组是否有相交的部分 + private static boolean intersectArrays(int[] targetArray, int[] selfArray) { + for (int i : targetArray) { + for (int j : selfArray) { + if (i == j) { + return true; + } + } + } + + return false; + } + + private static class EquidistantLine { + //与操作rectangle的距离 + private int distance; + //参考rectangle的位置 + private int reference; + //等距线的方向 + private int direction; + + EquidistantLine(int distance, int reference, int direction) { + this.distance = distance; + this.reference = reference; + this.direction = direction; + } + + public void setDistance(int distance) { + this.distance = distance; + } + + public int getDistance() { + return this.distance; + } + + public void setReference(int reference) { + this.reference = reference; + } + + public int getReference() { + return this.reference; + } + + public void setDirection(int direction) { + this.direction = direction; + } + + public int getDirection() { + return this.direction; + } + } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java b/designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java index 9ff080afb..7c645d0ad 100644 --- a/designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java +++ b/designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java @@ -17,32 +17,29 @@ public class WidgetForbidWindow extends JWindow { private UIButton promptButton = new UIButton(Inter.getLocText("FR-Designer_Forbid_Widgets_Intersects"), BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); -// /** -// * 构造函数 -// */ -// public WidgetForbidWindow() { -// this.add(promptButton); -// -// this.setSize(WIDTH, HEIGHT); -// } -// -// /** -// * 在指定位置显示窗口, 默认将window的中心点放到指定位置上 -// * -// * @param x x坐标 -// * @param y y坐标 -// * -// */ -// public void showWindow(int x, int y){ -// this.setLocation(x - WIDTH / 2, y - HEIGHT / 2); -// this.setVisible(true); -// } -// -// /** -// * 隐藏当前窗口 -// * -// */ -// public void hideWindow(){ -// this.setVisible(false); -// } + /** + * 构造函数 + */ + public WidgetForbidWindow() { + this.add(promptButton); + this.setSize(WIDTH, HEIGHT); + } + + /** + * 在指定位置显示窗口, 默认将window的中心点放到指定位置上 + * + * @param x x坐标 + * @param y y坐标 + */ + public void showWindow(int x, int y) { + this.setLocation(x - WIDTH / 2, y - HEIGHT / 2); + this.setVisible(true); + } + + /** + * 隐藏当前窗口 + */ + public void hideWindow() { + this.setVisible(false); + } } diff --git a/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java b/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java index aa7d9932c..5f3c3ac82 100644 --- a/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java +++ b/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java @@ -123,7 +123,6 @@ public class SelectionModel { if (selection.getSelectedCreator().getClass().equals(XWTabFitLayout.class)) { Rectangle rec = selection.getRelativeBounds(); //Tab布局 - System.out.println("ADD: " + (rec.x + rec.width / 2) + "\t" + (rec.y + BORDER_PROPORTION)); FormSelectionUtils.paste2Container(designer, (XLayoutContainer) selection.getSelectedCreator(), CLIP_BOARD, rec.x + rec.width / 2, diff --git a/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java b/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java index d1c088d40..f52af750f 100644 --- a/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java +++ b/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java @@ -1,19 +1,18 @@ package com.fr.design.mainframe; -import java.awt.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import com.fr.base.FRContext; +import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.adapters.layout.AbstractLayoutAdapter; +import com.fr.design.designer.beans.events.DesignerEvent; import com.fr.design.designer.creator.*; -import com.fr.form.ui.container.WLayout; +import com.fr.form.ui.Widget; import com.fr.form.ui.container.WTitleLayout; import com.fr.general.ComparatorUtils; -import com.fr.design.designer.beans.LayoutAdapter; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.form.ui.Widget; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class FormSelectionUtils { @@ -22,10 +21,14 @@ public class FormSelectionUtils { private static final int DELAY_Y = 20; //组件复制时是否已经向左上偏移 - private static boolean BACK_OFFSET = false; + private static boolean backoffset = false; //组件重命名后缀 - private static final String postfix = "_c"; + private static final String POSTFIX = "_c"; + + private FormSelectionUtils() { + + } /** * @param designer 编辑器 @@ -67,12 +70,10 @@ public class FormSelectionUtils { } else if (parent instanceof XWFitLayout) { //相对布局 designer.getSelectionModel().getSelection().reset(); - Rectangle rec = clipBoard.getSelctionBounds(); for (XCreator creator : clipBoard.getSelectedCreators()) { try { Widget copied = copyWidget(designer, creator); XCreator copiedCreator = XCreatorUtils.createXCreator(copied, creator.getSize()); - // TODO 获取位置 boolean addSuccess = adapter.addBean(copiedCreator, x, y); if (addSuccess) { @@ -104,14 +105,14 @@ public class FormSelectionUtils { */ private static Point getPasteLocation(AbstractLayoutAdapter layoutAdapter, XCreator copiedCreator, int x, int y) { //当宽度为奇数时 设置偏移 - int x_offset = (copiedCreator.getWidth() & 1) == 1 ? 1 : 0; + int xoffset = (copiedCreator.getWidth() & 1) == 1 ? 1 : 0; //当高度为奇数时 设置偏移 - int y_offset = (copiedCreator.getHeight() & 1) == 1 ? 1 : 0; + int yoffset = (copiedCreator.getHeight() & 1) == 1 ? 1 : 0; if (!layoutAdapter.accept(copiedCreator, x, y)) { XLayoutContainer container = layoutAdapter.getContainer(); - boolean xOut = x < 0 || x + copiedCreator.getWidth() / 2 + x_offset > container.getWidth(); - boolean yOut = y < 0 || y + copiedCreator.getHeight() / 2 + y_offset > container.getHeight(); + boolean xOut = x < 0 || x + copiedCreator.getWidth() / 2 + xoffset > container.getWidth(); + boolean yOut = y < 0 || y + copiedCreator.getHeight() / 2 + yoffset > container.getHeight(); /* * 组件原始位置位于布局的右下角, * 和布局右下边界线紧挨, @@ -119,12 +120,12 @@ public class FormSelectionUtils { * x,y同时越界 */ if (xOut && yOut) { - x = BACK_OFFSET ? container.getWidth() - copiedCreator.getWidth() / 2 - x_offset - : container.getWidth() - copiedCreator.getWidth() / 2 - DELAY_X - x_offset; - y = BACK_OFFSET ? - container.getHeight() - copiedCreator.getHeight() / 2 - y_offset - : container.getHeight() - copiedCreator.getHeight() / 2 - DELAY_Y - y_offset; - BACK_OFFSET = !BACK_OFFSET; + x = backoffset ? container.getWidth() - copiedCreator.getWidth() / 2 - xoffset + : container.getWidth() - copiedCreator.getWidth() / 2 - DELAY_X - xoffset; + y = backoffset ? + container.getHeight() - copiedCreator.getHeight() / 2 - yoffset + : container.getHeight() - copiedCreator.getHeight() / 2 - DELAY_Y - yoffset; + backoffset = !backoffset; return new Point(x, y); } /* @@ -134,8 +135,8 @@ public class FormSelectionUtils { * x,y中只有一个越界 */ else if ((xOut || yOut)) { - x = xOut ? container.getWidth() - copiedCreator.getWidth() / 2 - x_offset : x; - y = yOut ? container.getHeight() - copiedCreator.getHeight() / 2 - y_offset : y; + x = xOut ? container.getWidth() - copiedCreator.getWidth() / 2 - xoffset : x; + y = yOut ? container.getHeight() - copiedCreator.getHeight() / 2 - yoffset : y; return new Point(x, y); } } @@ -143,6 +144,14 @@ public class FormSelectionUtils { } + /** + * 拷贝组件 + * + * @param formDesigner + * @param xCreator + * @return + * @throws CloneNotSupportedException + */ private static Widget copyWidget(FormDesigner formDesigner, XCreator xCreator) throws CloneNotSupportedException { ArrayList nameSpace = new ArrayList(); @@ -155,11 +164,6 @@ public class FormSelectionUtils { } else { copied.setWidgetName(name); } -// if (copied instanceof WLayout) { -// for (int i = 0; i < ((WLayout) copied).getWidgetCount(); i++) { -// setCopiedName(formDesigner, ((WLayout) copied).getWidget(i), clonedNameList); -// } -// } return copied; } @@ -172,12 +176,12 @@ public class FormSelectionUtils { * @return name */ private static String getCopiedName(FormDesigner formDesigner, Widget copied, ArrayList nameSpace) { - String name = copied.getWidgetName(); + StringBuffer name = new StringBuffer(copied.getWidgetName()); do { - name += postfix; - } while (formDesigner.getTarget().isNameExist(name) || nameSpace.contains(name)); - nameSpace.add(name); - return name; + name.append(POSTFIX); + } while (formDesigner.getTarget().isNameExist(name.toString()) || nameSpace.contains(name.toString())); + nameSpace.add(name.toString()); + return name.toString(); } public static void rebuildSelection(FormDesigner designer) {