From 9d7085cd0fc07094d492300c3b27300c6f801156 Mon Sep 17 00:00:00 2001 From: zhouping Date: Thu, 28 Jul 2016 20:36:41 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E8=A1=A8=E5=8D=95=E7=BB=9D=E5=AF=B9?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E7=9A=84=E5=9F=BA=E6=9C=AC=E5=8A=9F=E8=83=BD?= =?UTF-8?q?1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hanlder/BottomCornerMouseHanlder.java | 42 +++- .../design/beans/location/Absorptionline.java | 165 ++++++++++++- .../fr/design/beans/location/MoveUtils.java | 227 +++++++++++++++++- .../beans/location/WidgetForbidWindow.java | 48 ++++ .../layout/FRAbsoluteLayoutAdapter.java | 35 ++- .../adapters/layout/FRFitLayoutAdapter.java | 3 - .../beans/location/AccessDirection.java | 60 +++-- .../design/designer/beans/location/Inner.java | 76 +++++- .../designer/beans/models/StateModel.java | 13 + .../painters/FRAbsoluteLayoutPainter.java | 26 ++ .../designer/creator/XWAbsoluteLayout.java | 90 ++++++- .../design/designer/creator/XWFitLayout.java | 2 +- .../designer/creator/XWParameterLayout.java | 11 + .../fr/design/gui/core/FormWidgetOption.java | 2 +- .../mainframe/EditingMouseListener.java | 23 +- .../com/fr/design/mainframe/FormDesigner.java | 17 ++ 16 files changed, 796 insertions(+), 44 deletions(-) create mode 100644 designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java create mode 100644 designer_form/src/com/fr/design/designer/beans/painters/FRAbsoluteLayoutPainter.java diff --git a/designer/src/com/fr/poly/hanlder/BottomCornerMouseHanlder.java b/designer/src/com/fr/poly/hanlder/BottomCornerMouseHanlder.java index e98ce6d02..7668411c8 100644 --- a/designer/src/com/fr/poly/hanlder/BottomCornerMouseHanlder.java +++ b/designer/src/com/fr/poly/hanlder/BottomCornerMouseHanlder.java @@ -103,7 +103,7 @@ public class BottomCornerMouseHanlder extends MouseInputAdapter { Rectangle bounds = block.getBounds().toRectangle(resolution); Point resultPoint = MoveUtils.sorption(bounds.x + dragStart.x < 0 ? 0 : bounds.x + dragStart.x, bounds.y - + dragStart.y < 0 ? 0 : bounds.y + dragStart.y, bounds.width, bounds.height, rectDesigner); + + dragStart.y < 0 ? 0 : bounds.y + dragStart.y, bounds.width, bounds.height, rectDesigner, false); block.setBounds(new UnitRectangle(new Rectangle(resultPoint.x, resultPoint.y, bounds.width, bounds.height), resolution)); designer.repaint(); @@ -124,7 +124,17 @@ public class BottomCornerMouseHanlder extends MouseInputAdapter { public RectangleIterator createRectangleIterator() { return getRectangleIt(); } - + + /** + * 设置等距线 + * + * @param line 吸附线 + */ + @Override + public void setEquidistantLine(Absorptionline line) { + + } + /** * 获取当前选中块的垂直线数组 * @@ -145,6 +155,34 @@ public class BottomCornerMouseHanlder extends MouseInputAdapter { return editor.getValue().getHorizontalLine(); } + /** + * 设置designer内部组件是否重叠的标志位 + * + * @param isIntersects 是否重叠 + */ + @Override + public void setWidgetsIntersects(boolean isIntersects) { + } + + /** + * 获取designer内部组件是否重叠的标志位 + * + * @return 重叠 + */ + @Override + public boolean getWidgetsIntersects() { + return false; + } + + /** + * 获取designer相对屏幕的位置 + * + * @return 位置 + */ + @Override + public Point getDesignerLocationOnScreen() { + return null; + } }; private RectangleIterator getRectangleIt(){ diff --git a/designer_base/src/com/fr/design/beans/location/Absorptionline.java b/designer_base/src/com/fr/design/beans/location/Absorptionline.java index f72892eef..a0ff0d0e4 100644 --- a/designer_base/src/com/fr/design/beans/location/Absorptionline.java +++ b/designer_base/src/com/fr/design/beans/location/Absorptionline.java @@ -1,23 +1,42 @@ package com.fr.design.beans.location; -import java.awt.Color; -import java.awt.Graphics; +import java.awt.*; import com.fr.base.GraphHelper; import com.fr.design.scrollruler.ScrollRulerComponent; import com.fr.stable.ArrayUtils; +import com.fr.third.org.hsqldb.lib.Collection; public class Absorptionline { + //箭头线前段为4px的等边三角形,给定了一个点的坐标,计算一下剩下两个点的坐标偏移量 + //而且箭头分为四个朝向,故有四组坐标(2根号3 约为 3) + // 1.(x,y)(x+2,y±2根号3)(x-2,y±2根号3) + // 2.(x,y)(x±2根号3,y-2)(x±2根号3,y+2) + private static int RECTANGLE_OFFSET_X = 2; + private static int RECTANGLE_OFFSET_Y = 3; + //控件周围八个拖拽框的大小 + private static int RESIZE_BOX_SIZE = 5; + private static Absorptionline lineInX = new Absorptionline(null, null, null, true); private static Absorptionline lineInY = new Absorptionline(null, null, null, false); + private static Absorptionline lineEquidistant = new Absorptionline(null, null, null, true); + private Color lineColor = new Color(228, 225, 199); private Color midLineColor = new Color(196, 227, 237); + private Color equidistantLineColor = new Color(0xff, 0x0d, 0x7b); + private Integer x1; private Integer x2; private Integer middle; private int[] verticalLines; private int[] horizontalLines; + + private int top; + private int left; + private int bottom; + private int right; + private Rectangle equidistantStart; private boolean trans; @@ -89,6 +108,19 @@ public class Absorptionline { return lineInY; } + /** + * 创建等距线 + * @return 等距线 + */ + public static Absorptionline createEquidistantAbsorptionline(Rectangle equidistantStart, int top, int left, int bottom, int right) { + lineEquidistant.equidistantStart = equidistantStart; + lineEquidistant.top = top; + lineEquidistant.left = left; + lineEquidistant.bottom = bottom; + lineEquidistant.right = right; + return lineEquidistant; + } + private Absorptionline(Integer x1, Integer x2, Integer middleInX, boolean trans) { this.x1 = x1; this.x2 = x2; @@ -186,5 +218,134 @@ public class Absorptionline { } } + //画等距线 + if (equidistantStart != null) { + g.setColor(equidistantLineColor); + if (top > 0) { + paintTopEquidistantLine(g); + } + if (left > 0) { + paintLeftEquidistantLine(g); + } + if (bottom > 0) { + paintBottomEquidistantLine(g); + } + if (right > 0) { + paintRightEquidistantLine(g); + } + } + } + + //朝向上方的等距线 + private void paintTopEquidistantLine(Graphics g){ + int x1[] = { + equidistantStart.x + equidistantStart.width / 2, + equidistantStart.x + equidistantStart.width / 2 - RECTANGLE_OFFSET_X, + equidistantStart.x + equidistantStart.width / 2 + RECTANGLE_OFFSET_X + }; + int y1[] = { + top, + top + RECTANGLE_OFFSET_Y, + top + RECTANGLE_OFFSET_Y + }; + int x2[] = { + equidistantStart.x + equidistantStart.width / 2, + equidistantStart.x + equidistantStart.width / 2 + RECTANGLE_OFFSET_X, + equidistantStart.x + equidistantStart.width / 2 - RECTANGLE_OFFSET_X + }; + int y2[] = { + equidistantStart.y - RESIZE_BOX_SIZE, + equidistantStart.y - RESIZE_BOX_SIZE - RECTANGLE_OFFSET_Y, + equidistantStart.y - RESIZE_BOX_SIZE - RECTANGLE_OFFSET_Y + }; + g.fillPolygon(x1, y1, 3); + g.fillPolygon(x2, y2, 3); + GraphHelper.drawLine(g, + equidistantStart.x + equidistantStart.width / 2, top, + equidistantStart.x + equidistantStart.width / 2, equidistantStart.y - RESIZE_BOX_SIZE); + } + //朝向左侧的等距线 + private void paintLeftEquidistantLine(Graphics g){ + int x1[] = { + left, + left + RECTANGLE_OFFSET_Y, + left + RECTANGLE_OFFSET_Y, + }; + int y1[] = { + equidistantStart.y + equidistantStart.height / 2, + equidistantStart.y + equidistantStart.height / 2 - RECTANGLE_OFFSET_X, + equidistantStart.y + equidistantStart.height / 2 + RECTANGLE_OFFSET_X, + }; + int x2[] = { + equidistantStart.x - RESIZE_BOX_SIZE, + equidistantStart.x - RESIZE_BOX_SIZE - RECTANGLE_OFFSET_Y, + equidistantStart.x - RESIZE_BOX_SIZE - RECTANGLE_OFFSET_Y + }; + int y2[] = { + equidistantStart.y + equidistantStart.height / 2, + equidistantStart.y + equidistantStart.height / 2 + RECTANGLE_OFFSET_X, + equidistantStart.y + equidistantStart.height / 2 - RECTANGLE_OFFSET_X + }; + g.fillPolygon(x1, y1, 3); + g.fillPolygon(x2, y2, 3); + GraphHelper.drawLine(g, + left, equidistantStart.y + equidistantStart.height / 2, + equidistantStart.x - RESIZE_BOX_SIZE, equidistantStart.y + equidistantStart.height / 2); + } + //朝向下方的等距线 + private void paintBottomEquidistantLine(Graphics g) { + int x1[] = { + equidistantStart.x + equidistantStart.width / 2, + equidistantStart.x + equidistantStart.width / 2 + RECTANGLE_OFFSET_X, + equidistantStart.x + equidistantStart.width / 2 - RECTANGLE_OFFSET_X, + }; + int y1[] = { + equidistantStart.y + equidistantStart.height + RESIZE_BOX_SIZE, + equidistantStart.y + equidistantStart.height + RESIZE_BOX_SIZE + RECTANGLE_OFFSET_Y, + equidistantStart.y + equidistantStart.height + RESIZE_BOX_SIZE + RECTANGLE_OFFSET_Y, + }; + int x2[] = { + equidistantStart.x + equidistantStart.width / 2, + equidistantStart.x + equidistantStart.width / 2 + RECTANGLE_OFFSET_X, + equidistantStart.x + equidistantStart.width / 2 - RECTANGLE_OFFSET_X + }; + int y2[] = { + bottom, + bottom - RECTANGLE_OFFSET_Y, + bottom - RECTANGLE_OFFSET_Y + }; + g.fillPolygon(x1, y1, 3); + g.fillPolygon(x2, y2, 3); + GraphHelper.drawLine(g, + equidistantStart.x + equidistantStart.width / 2, equidistantStart.y + equidistantStart.height + RESIZE_BOX_SIZE, + equidistantStart.x + equidistantStart.width / 2, bottom); + } + //朝向右侧的等距线 + private void paintRightEquidistantLine(Graphics g){ + int x1[] = { + right, + right - 3, + right - 3 + }; + int y1[] = { + equidistantStart.y + equidistantStart.height / 2, + equidistantStart.y + equidistantStart.height / 2 - RECTANGLE_OFFSET_X, + equidistantStart.y + equidistantStart.height / 2 + RECTANGLE_OFFSET_X + }; + int x2[] = { + equidistantStart.x + equidistantStart.width + RESIZE_BOX_SIZE, + equidistantStart.x + equidistantStart.width + RESIZE_BOX_SIZE + RECTANGLE_OFFSET_Y, + equidistantStart.x + equidistantStart.width + RESIZE_BOX_SIZE + RECTANGLE_OFFSET_Y + }; + int y2[] = { + equidistantStart.y + equidistantStart.height / 2, + equidistantStart.y + equidistantStart.height / 2 - RECTANGLE_OFFSET_X, + equidistantStart.y + equidistantStart.height / 2 + RECTANGLE_OFFSET_X, + }; + g.fillPolygon(x1, y1, 3); + g.fillPolygon(x2, y2, 3); + GraphHelper.drawLine(g, + equidistantStart.x + equidistantStart.width + RESIZE_BOX_SIZE, equidistantStart.y + equidistantStart.height / 2, + right, equidistantStart.y + equidistantStart.height / 2); } } \ No newline at end of file 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 fddb87648..e0bed7ca1 100644 --- a/designer_base/src/com/fr/design/beans/location/MoveUtils.java +++ b/designer_base/src/com/fr/design/beans/location/MoveUtils.java @@ -3,6 +3,8 @@ */ package com.fr.design.beans.location; +import com.fr.stable.ArrayUtils; + import javax.swing.*; import java.awt.*; import java.util.ArrayList; @@ -17,6 +19,10 @@ public class MoveUtils { public static final int SORPTION_UNIT = 5; + public static WidgetForbidWindow widgetForbidWindow = new WidgetForbidWindow(); + + public static ArrayList equidistantLines = new ArrayList<>(); + private MoveUtils() { } @@ -68,6 +74,30 @@ public class MoveUtils { * */ int[] getHorizontalLine(); + + /** + * 设置designer内部组件是否重叠的标志位 + * @param isIntersects 是否重叠 + */ + void setWidgetsIntersects(boolean isIntersects); + + /** + * 获取designer内部组件是否重叠的标志位 + * @return 重叠 + */ + boolean getWidgetsIntersects(); + + /** + * 获取designer相对屏幕的位置 + * @return 位置 + */ + Point getDesignerLocationOnScreen(); + + /** + * 设置等距线 + * @param line 吸附线 + */ + void setEquidistantLine(Absorptionline line); } public interface RectangleIterator { @@ -183,6 +213,53 @@ public class MoveUtils { } } + 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(); + } + /** * 吸附 * @@ -197,28 +274,67 @@ public class MoveUtils { * @date 2015-2-12-下午2:39:16 * */ - public static Point sorption(int x, int y, int width, int height, RectangleDesigner designer) { + 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 (px.isFind() && py.isFind()) { - break; + + if(isIntersects && !isParameterLayout){ + isWidgetsIntersects = true; + } + else{ + findEquidistantLine(bounds, left, top, height, width); } } + showForbiddenWindow(designer, x, y, isWidgetsIntersects); createXAbsorptionline(px, designer, width, cacheRecs); createYAbsorptionline(py, designer, height, cacheRecs); - return new Point(px.palce, py.palce); + 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.setWidgetsIntersects(true); + } + else{ + designer.setWidgetsIntersects(false); + hideForbidWindow(); + } } private static void createXAbsorptionline(PlacePointing px, RectangleDesigner designer, int width, java.util.List cacheRecs) { @@ -300,6 +416,70 @@ public class MoveUtils { } 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(); + } + } + line = Absorptionline.createEquidistantAbsorptionline(operatingRectangle, top, left, bottom, right); + } + designer.setEquidistantLine(line); + } + + private static void processEquidistantLinesList(PlacePointing pEquidistantX, PlacePointing pEquidistantY, Rectangle operatingRectangle){ + EquidistantLine[] equidistantLines1 = new EquidistantLine[4]; + //先按方向处理,只保留四个方向上距离最近 + for(int count = 0; count < equidistantLines.size(); count++){ + for (int direction = 0; direction < 4; 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; + } + } + 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; + } + } + } //更新纵向行列线 private static void updateVerticalLine(int[] selfVertical, RectangleIterator iterator, Absorptionline line){ @@ -329,4 +509,43 @@ public class MoveUtils { 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 new file mode 100644 index 000000000..089a242da --- /dev/null +++ b/designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java @@ -0,0 +1,48 @@ +package com.fr.design.beans.location; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.icon.IconPathConstants; +import com.fr.general.Inter; + +import javax.swing.*; + +/** + * Created by zhouping on 2016/7/24. + */ +public class WidgetForbidWindow extends JWindow { + + private static final int WIDTH = 150; + private static final int HEIGHT = 20; + + private UIButton promptButton = new UIButton("禁止组件相互重叠", 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); + } +} diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java index dadfed504..8ce0d0529 100644 --- a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java +++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java @@ -1,8 +1,10 @@ package com.fr.design.designer.beans.adapters.layout; -import java.awt.Rectangle; +import java.awt.*; import com.fr.design.designer.beans.ConstraintsGroupModel; +import com.fr.design.designer.beans.HoverPainter; +import com.fr.design.designer.beans.painters.FRAbsoluteLayoutPainter; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreatorUtils; import com.fr.design.designer.creator.XLayoutContainer; @@ -13,10 +15,16 @@ import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.LayoutUtils; public class FRAbsoluteLayoutAdapter extends AbstractLayoutAdapter { - + private HoverPainter painter; public FRAbsoluteLayoutAdapter(XLayoutContainer container) { super(container); + painter = new FRAbsoluteLayoutPainter(container); } + + @Override + public HoverPainter getPainter() { + return painter; + } /** * 是否能在指定位置添加组件 @@ -27,8 +35,15 @@ public class FRAbsoluteLayoutAdapter extends AbstractLayoutAdapter { */ @Override public boolean accept(XCreator creator, int x, int y) { - return x >= 0 && y >= 0 && creator.getHeight() <= container.getHeight() + Component comp = container.getComponentAt(x, y); + //布局控件要先判断是不是可编辑 + XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator)comp).getTopLayout(); + if(topLayout != null && !topLayout.isEditable()){ + return false; + } + boolean isAccept = x >= 0 && y >= 0 && creator.getHeight() <= container.getHeight() && creator.getWidth() <= container.getWidth(); + return isAccept; } @Override @@ -46,10 +61,20 @@ public class FRAbsoluteLayoutAdapter extends AbstractLayoutAdapter { } fix(creator, x, y); - container.add(creator); + + if (creator.shouldScaleCreator() || creator.hasTitleStyle()) { + addParentCreator(creator); + } else { + container.add(creator, creator.toData().getWidgetName()); + } LayoutUtils.layoutRootContainer(container); } - + + private void addParentCreator(XCreator child) { + XLayoutContainer parentPanel = child.initCreatorWrapper(child.getHeight()); + container.add(parentPanel, child.toData().getWidgetName()); + } + /** * 组件拖拽后调整大小 * @param creator 组件 diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java index 840d3a7db..2777c4476 100644 --- a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java +++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java @@ -117,9 +117,6 @@ public class FRFitLayoutAdapter extends AbstractLayoutAdapter { */ @Override public void addComp(XCreator child, int x, int y) { - if (ComparatorUtils.equals(child.getIconPath(), WIDGETPANEICONPATH)) { - return; - } fix(child, x, y); if (child.shouldScaleCreator() || child.hasTitleStyle()) { addParentCreator(child); diff --git a/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java b/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java index a5758639b..b44145c0c 100644 --- a/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java +++ b/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java @@ -3,20 +3,17 @@ */ package com.fr.design.designer.beans.location; -import java.awt.Cursor; -import java.awt.Point; -import java.awt.Rectangle; +import java.awt.*; import com.fr.design.beans.location.Absorptionline; import com.fr.design.beans.location.MoveUtils; +import com.fr.design.designer.creator.*; import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.FormSelection; -import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWBorderLayout; -import com.fr.design.designer.creator.XWParameterLayout; +import com.fr.design.utils.ComponentUtils; import com.fr.form.ui.container.WAbsoluteLayout; import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget; +import com.fr.form.ui.container.WParameterLayout; /** * @author richer @@ -39,10 +36,7 @@ public abstract class AccessDirection implements Direction { return new int[] { x, y }; } else { int posy = current_bounds.y; - if (posy >= designer.getParaHeight() && !designer.isFormParaDesigner()) { - return new int[] { x, y }; - } - + Point relativePoint = getRelativePoint(x, y, current_bounds,designer); sorptionPoint(relativePoint,current_bounds, designer); return new int[] { relativePoint.x, relativePoint.y }; @@ -72,12 +66,14 @@ public abstract class AccessDirection implements Direction { WAbsoluteLayout layout =getLayout(designer); FormSelection selection = designer.getSelectionModel().getSelection(); + + boolean isWidgetsIntersect = false; for (int i = 0, count = layout.getWidgetCount(); i < count; i++) { BoundsWidget temp = (BoundsWidget) layout.getWidget(i); if (!temp.isVisible() || selection.contains(temp.getWidget())) { continue; } - Rectangle bounds = temp.getBounds(); + Rectangle bounds = getWidgetRelativeBounds(temp.getBounds(), selection); if (!findInX) { int x1 = bounds.x; if (Math.abs(x1 - point.x) <= MoveUtils.SORPTION_UNIT) { @@ -106,18 +102,54 @@ public abstract class AccessDirection implements Direction { if (findInX && findInY) { break; } + + if (current_bounds.intersects(bounds) && !(layout instanceof WParameterLayout)){ + isWidgetsIntersect = true; + } } + processRectangleIntersects(designer, point.x, point.y, isWidgetsIntersect); designer.getStateModel().setXAbsorptionline(findInX && current_bounds.getWidth() > MoveUtils.SORPTION_UNIT ? Absorptionline.createXAbsorptionline(point.x) : null); designer.getStateModel().setYAbsorptionline(findInY && current_bounds.getHeight() > MoveUtils.SORPTION_UNIT ? Absorptionline.createYAbsorptionline(point.y) : null); } + private Rectangle getWidgetRelativeBounds(Rectangle bounds, FormSelection selection){ + Rectangle relativeRec = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator()); + if (parent == null) { + return relativeRec; + } + Rectangle rec = ComponentUtils.getRelativeBounds(parent); + relativeRec.x += rec.x; + relativeRec.y += rec.y; + return relativeRec; + } + + private void processRectangleIntersects(FormDesigner designer, int x, int y, boolean isIntersects){ + if(isIntersects){ + if(designer.getLocationOnScreen() != null) { + MoveUtils.displayForbidWindow(x + designer.getLocationOnScreen().x, y + designer.getLocationOnScreen().y); + } + designer.setWidgetsIntersect(true); + } + else{ + MoveUtils.hideForbidWindow(); + designer.setWidgetsIntersect(false); + } + } + private WAbsoluteLayout getLayout(final FormDesigner designer){ XLayoutContainer formLayoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator( designer.getTarget().getContainer()); WAbsoluteLayout layout; - if (formLayoutContainer.acceptType(XWBorderLayout.class)){ - layout = (WAbsoluteLayout) designer.getParaComponent().toData(); + if (formLayoutContainer.acceptType(XWBorderLayout.class)){//看起来这边的作用应该是为了区别cpt(得到XWParameterLayout)还是frm(得到XWBorderLayout)的参数界面 + Container container = designer.getSelectionModel().getSelection().getSelectedCreator().getParent(); + if(container instanceof XWAbsoluteLayout){ + layout = ((XWAbsoluteLayout)container).toData(); + } + else { + layout = (WAbsoluteLayout) designer.getParaComponent().toData(); + } } else{ layout = (WAbsoluteLayout) designer.getTarget().getContainer(); } diff --git a/designer_form/src/com/fr/design/designer/beans/location/Inner.java b/designer_form/src/com/fr/design/designer/beans/location/Inner.java index 68db5241e..f6c5bdef6 100644 --- a/designer_form/src/com/fr/design/designer/beans/location/Inner.java +++ b/designer_form/src/com/fr/design/designer/beans/location/Inner.java @@ -4,16 +4,17 @@ import com.fr.design.beans.location.Absorptionline; import com.fr.design.beans.location.MoveUtils; import com.fr.design.beans.location.MoveUtils.RectangleDesigner; import com.fr.design.beans.location.MoveUtils.RectangleIterator; -import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWBorderLayout; +import com.fr.design.designer.creator.*; import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.FormSelection; +import com.fr.design.utils.ComponentUtils; import com.fr.form.ui.container.WAbsoluteLayout; import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget; import com.fr.stable.ArrayUtils; +import com.fr.third.com.lowagie.text.*; import java.awt.*; +import java.awt.Rectangle; public class Inner extends AccessDirection { @@ -78,17 +79,72 @@ public class Inner extends AccessDirection { public RectangleIterator createRectangleIterator() { return getRectangleIterator(designer); } + + /** + * 设置designer内部组件是否重叠的标志位 + * + * @param isIntersects 是否重叠 + */ + @Override + public void setWidgetsIntersects(boolean isIntersects) { + designer.setWidgetsIntersect(isIntersects); + } + + /** + * 获取designer内部组件是否重叠的标志位 + * + * @return 重叠 + */ + @Override + public boolean getWidgetsIntersects() { + return designer.isWidgetsIntersect(); + } + + /** + * 获取designer相对屏幕的位置 + * + * @return 位置 + */ + @Override + public Point getDesignerLocationOnScreen() { + return designer.getLocationOnScreen(); + } + + /** + * 设置等距线 + * + * @param line 吸附线 + */ + @Override + public void setEquidistantLine(Absorptionline line) { + designer.getStateModel().setEquidistantLine(line); + } }; - point.setLocation(MoveUtils.sorption(point.x, point.y, current_bounds.width, current_bounds.height, rd)); + //判断当前操作的是不是参数面板,要特殊处理 + boolean isParameterLayout = (designer.getSelectionModel().getSelection().getSelectedCreator().getParent()) instanceof XWParameterLayout; + point.setLocation(MoveUtils.sorption(point.x, point.y, current_bounds.width, current_bounds.height, rd, isParameterLayout)); } private RectangleIterator getRectangleIterator(final FormDesigner designer){ + return new RectangleIterator() { private int i; private WAbsoluteLayout layout = getLayout(designer); private int count = layout.getWidgetCount(); private FormSelection selection = designer.getSelectionModel().getSelection(); + private Rectangle getWidgetRelativeBounds(Rectangle bounds){ + Rectangle relativeRec = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator()); + if (parent == null) { + return relativeRec; + } + Rectangle rec = ComponentUtils.getRelativeBounds(parent); + relativeRec.x += rec.x; + relativeRec.y += rec.y; + return relativeRec; + } + public boolean hasNext() { if (i >= count) { return false; @@ -110,7 +166,7 @@ public class Inner extends AccessDirection { } public Rectangle nextRectangle() { BoundsWidget temp = (BoundsWidget) layout.getWidget(i++); - return temp.getBounds(); + return getWidgetRelativeBounds(temp.getBounds()); } }; } @@ -119,8 +175,14 @@ public class Inner extends AccessDirection { XLayoutContainer formLayoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator( designer.getTarget().getContainer()); WAbsoluteLayout layout; - if (formLayoutContainer.acceptType(XWBorderLayout.class)){ - layout = (WAbsoluteLayout) designer.getParaComponent().toData(); + if (formLayoutContainer.acceptType(XWBorderLayout.class)){//看起来这边的作用应该是为了区别cpt(得到XWParameterLayout)还是frm(得到XWBorderLayout)的参数界面 + Container container = designer.getSelectionModel().getSelection().getSelectedCreator().getParent(); + if(container instanceof XWAbsoluteLayout){ + layout = ((XWAbsoluteLayout)container).toData(); + } + else { + layout = (WAbsoluteLayout) designer.getParaComponent().toData(); + } } else{ layout = (WAbsoluteLayout) designer.getTarget().getContainer(); } diff --git a/designer_form/src/com/fr/design/designer/beans/models/StateModel.java b/designer_form/src/com/fr/design/designer/beans/models/StateModel.java index d92cd9c76..a623caddc 100644 --- a/designer_form/src/com/fr/design/designer/beans/models/StateModel.java +++ b/designer_form/src/com/fr/design/designer/beans/models/StateModel.java @@ -44,6 +44,8 @@ public class StateModel { private Absorptionline lineInX; private Absorptionline lineInY; + //等距线 + private Absorptionline lineEquidistant; // 当前是否处于拖拽选择状态 private boolean selecting; @@ -357,6 +359,14 @@ public class StateModel { this.lineInY = line; } + /** + * 等距线赋值 + * @param line 线 + */ + public void setEquidistantLine(Absorptionline line){ + this.lineEquidistant = line; + } + /** *画吸附线 * @param g Graphics类 @@ -368,6 +378,9 @@ public class StateModel { if(lineInY != null) { lineInY.paint(g,designer.getArea()); } + if(lineEquidistant != null){ + lineEquidistant.paint(g,designer.getArea()); + } } /** diff --git a/designer_form/src/com/fr/design/designer/beans/painters/FRAbsoluteLayoutPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/FRAbsoluteLayoutPainter.java new file mode 100644 index 000000000..04e6018fc --- /dev/null +++ b/designer_form/src/com/fr/design/designer/beans/painters/FRAbsoluteLayoutPainter.java @@ -0,0 +1,26 @@ +package com.fr.design.designer.beans.painters; + +import com.fr.design.designer.creator.XLayoutContainer; + +import java.awt.*; + +/** + * Created by zhouping on 2016/7/11. + */ +public class FRAbsoluteLayoutPainter extends AbstractPainter { + public FRAbsoluteLayoutPainter(XLayoutContainer container) { + super(container); + } + + /** + * 组件渲染 + * + * @param g 画图类 + * @param startX 开始位置x + * @param startY 开始位置y + */ + @Override + public void paint(Graphics g, int startX, int startY) { + super.paint(g, startX, startY); + } +} diff --git a/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java b/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java index 6cf0fc216..46e1c42c2 100644 --- a/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java +++ b/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java @@ -3,26 +3,38 @@ */ package com.fr.design.designer.creator; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Rectangle; +import java.awt.*; import java.awt.event.ContainerEvent; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; import java.util.HashMap; +import com.fr.design.designer.beans.AdapterBus; +import com.fr.design.designer.beans.ComponentAdapter; import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.beans.adapters.layout.AbsoluteLayoutAdapter; import com.fr.design.designer.beans.adapters.layout.FRAbsoluteLayoutAdapter; import com.fr.design.designer.beans.location.Direction; +import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.form.layout.FRAbsoluteLayout; +import com.fr.design.icon.IconPathConstants; +import com.fr.design.mainframe.EditingMouseListener; +import com.fr.design.mainframe.FormDesigner; import com.fr.form.ui.Connector; import com.fr.form.ui.Widget; import com.fr.form.ui.container.WAbsoluteLayout; import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget; +import com.fr.general.IOUtils; +import com.fr.general.Inter; /** * @author richer * @since 6.5.3 */ public class XWAbsoluteLayout extends XLayoutContainer { + + private static final int EDIT_BTN_WIDTH = 60; + private static final int EDIT_BTN_HEIGHT = 24; private HashMap xConnectorMap; @@ -158,7 +170,7 @@ public class XWAbsoluteLayout extends XLayoutContainer { WAbsoluteLayout wabs = this.toData(); if (!creator.acceptType(XWFitLayout.class)) { creator.setDirections(Direction.ALL); - } + } wabs.addWidget(new BoundsWidget(creator.toData(), creator.getBounds())); } @@ -187,4 +199,74 @@ public class XWAbsoluteLayout extends XLayoutContainer { public LayoutAdapter getLayoutAdapter() { return new FRAbsoluteLayoutAdapter(this); } + + @Override + public XLayoutContainer getTopLayout() { + XLayoutContainer xTopLayout = XCreatorUtils.getParentXLayoutContainer(this).getTopLayout(); + if (xTopLayout != null && !xTopLayout.isEditable()){ + return xTopLayout; + } + else{ + return this; + } + } + + public void paint(Graphics g) { + super.paint(g); + //如果鼠标移动到布局内且布局不可编辑,画出编辑蒙层 + if (isMouseEnter && !this.editable) { + int x = 0; + int y = 0; + int w = getWidth(); + int h = getHeight(); + + Graphics2D g2d = (Graphics2D) g; + Composite oldComposite = g2d.getComposite(); + //画白色的编辑层 + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 60 / 100.0F)); + g2d.setColor(Color.WHITE); + g2d.fillRect(x, y, w, h); + //画编辑按钮所在框 + g2d.setComposite(oldComposite); + g2d.setColor(new Color(176, 196, 222)); + g2d.fillRect((x + w / 2 - EDIT_BTN_WIDTH / 2), (y + h / 2 - EDIT_BTN_HEIGHT / 2), EDIT_BTN_WIDTH, EDIT_BTN_HEIGHT); + //画编辑按钮图标 + BufferedImage image = IOUtils.readImage(IconPathConstants.TD_EDIT_ICON_PATH); + g2d.drawImage( + image, + (x + w / 2 - 23), + (y + h / 2 - image.getHeight() / 2), + image.getWidth(), + image.getHeight(), + null, + this + ); + g2d.setColor(Color.BLACK); + //画编辑文字 + g2d.drawString(Inter.getLocText("Edit"), x + w / 2 - 2, y + h / 2 + 5); + } + } + + /** + * 响应点击事件 + * + * @param editingMouseListener 鼠标点击,位置处理器 + * @param e 鼠标点击事件 + */ + public void respondClick(EditingMouseListener editingMouseListener,MouseEvent e){ + FormDesigner designer = editingMouseListener.getDesigner(); + SelectionModel selectionModel = editingMouseListener.getSelectionModel(); + boolean isEditing = isEditable() || designer.getCursor().getType() == Cursor.HAND_CURSOR || e.getClickCount() == 2; + setEditable(isEditing); + + selectionModel.selectACreatorAtMouseEvent(e); + designer.repaint(); + + if (editingMouseListener.stopEditing()) { + if (this != designer.getRootComponent()) { + ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, this); + editingMouseListener.startEditing(this, isEditing ? adapter.getDesignerEditor() : null, adapter); + } + } + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java b/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java index 38652b3d4..489aab52b 100644 --- a/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java +++ b/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java @@ -825,7 +825,7 @@ public class XWFitLayout extends XLayoutContainer { /** * 处理自适应布局的directions - * @param creator 组件 + * @param xcreator 组件 */ private void dealDirections(XCreator xcreator, boolean isInit) { if (xcreator == null) { diff --git a/designer_form/src/com/fr/design/designer/creator/XWParameterLayout.java b/designer_form/src/com/fr/design/designer/creator/XWParameterLayout.java index 9e5520716..890612ccc 100644 --- a/designer_form/src/com/fr/design/designer/creator/XWParameterLayout.java +++ b/designer_form/src/com/fr/design/designer/creator/XWParameterLayout.java @@ -163,4 +163,15 @@ public class XWParameterLayout extends XWAbsoluteLayout { public void setBackground(Background background){ this.toData().setBackground(background); } + + @Override + public void paint(Graphics g) { + //参数面板特殊处理,不出现编辑层 + setEditable(true); + super.paint(g); + } + @Override + public XLayoutContainer getTopLayout() { + return this; + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java b/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java index 229b54943..76287c30f 100644 --- a/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java +++ b/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java @@ -1 +1 @@ -package com.fr.design.gui.core; import javax.swing.Icon; import com.fr.base.BaseUtils; import com.fr.form.ui.ElementCaseEditor; import com.fr.form.ui.Widget; import com.fr.form.ui.container.WAbsoluteLayout; import com.fr.form.ui.container.WBorderLayout; import com.fr.form.ui.container.WCardLayout; import com.fr.form.ui.container.WFitLayout; import com.fr.form.ui.container.WHorizontalBoxLayout; import com.fr.form.ui.container.WParameterLayout; import com.fr.form.ui.container.WVerticalBoxLayout; import com.fr.general.Inter; /** * Author : Shockway * Date: 13-6-17 * Time: 上午10:40 */ public class FormWidgetOption extends WidgetOption { /** * 返回名字 * @return 名字 */ @Override public String optionName() { return null; } /** * 返回图标 * @return 图标 */ @Override public Icon optionIcon() { return null; } /** * 组件类 * @return 类 */ @Override public Class widgetClass() { return null; } /** * 返回组件 * @return 控件 */ @Override public Widget createWidget() { return null; } /* * 表单容器 */ public static WidgetOption[] getFormContainerInstance() { return new WidgetOption[] { ABSOLUTELAYOUTCONTAINER, BORDERLAYOUTCONTAINER, HORIZONTALBOXLAYOUTCONTAINER, VERTICALBOXLAYOUTCONTAINER, CARDLAYOUTCONTAINER, FITLAYOUTCONTAINER }; } /** * 表单工具栏上的布局 * @return 控件 */ public static WidgetOption[] getFormLayoutInstance() { return new WidgetOption[] {CARDLAYOUTCONTAINER}; } public static final WidgetOption ABSOLUTELAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_AbsoluteLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_absolute.png"), WAbsoluteLayout.class); public static final WidgetOption BORDERLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_BorderLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_border.png"), WBorderLayout.class); public static final WidgetOption CARDLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_CardLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/card_layout_16.png"), WCardLayout.class); public static final WidgetOption HORIZONTALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_Layout-HBox"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_h_16.png"), WHorizontalBoxLayout.class); public static final WidgetOption VERTICALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_VerticalBoxLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"), WVerticalBoxLayout.class); public static final WidgetOption FITLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter.getLocText("FR-Designer-Layout_Adaptive_Layout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"), WFitLayout.class); public static final WidgetOption PARAMETERCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_Para-Body"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_parameter.png"), WParameterLayout.class); public static final WidgetOption ELEMENTCASE = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_Form-Report"), BaseUtils.readIcon("/com/fr/web/images/form/resources/report_16.png"), ElementCaseEditor.class); } \ No newline at end of file +package com.fr.design.gui.core; import javax.swing.Icon; import com.fr.base.BaseUtils; import com.fr.form.ui.ElementCaseEditor; import com.fr.form.ui.Widget; import com.fr.form.ui.container.WAbsoluteLayout; import com.fr.form.ui.container.WBorderLayout; import com.fr.form.ui.container.WCardLayout; import com.fr.form.ui.container.WFitLayout; import com.fr.form.ui.container.WHorizontalBoxLayout; import com.fr.form.ui.container.WParameterLayout; import com.fr.form.ui.container.WVerticalBoxLayout; import com.fr.general.Inter; /** * Author : Shockway * Date: 13-6-17 * Time: 上午10:40 */ public class FormWidgetOption extends WidgetOption { /** * 返回名字 * @return 名字 */ @Override public String optionName() { return null; } /** * 返回图标 * @return 图标 */ @Override public Icon optionIcon() { return null; } /** * 组件类 * @return 类 */ @Override public Class widgetClass() { return null; } /** * 返回组件 * @return 控件 */ @Override public Widget createWidget() { return null; } /* * 表单容器 */ public static WidgetOption[] getFormContainerInstance() { return new WidgetOption[] { ABSOLUTELAYOUTCONTAINER, BORDERLAYOUTCONTAINER, HORIZONTALBOXLAYOUTCONTAINER, VERTICALBOXLAYOUTCONTAINER, CARDLAYOUTCONTAINER, FITLAYOUTCONTAINER }; } /** * 表单工具栏上的布局 * @return 控件 */ public static WidgetOption[] getFormLayoutInstance() { return new WidgetOption[] {CARDLAYOUTCONTAINER, ABSOLUTELAYOUTCONTAINER}; } public static final WidgetOption ABSOLUTELAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_AbsoluteLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_absolute.png"), WAbsoluteLayout.class); public static final WidgetOption BORDERLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_BorderLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_border.png"), WBorderLayout.class); public static final WidgetOption CARDLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_CardLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/card_layout_16.png"), WCardLayout.class); public static final WidgetOption HORIZONTALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_Layout-HBox"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_h_16.png"), WHorizontalBoxLayout.class); public static final WidgetOption VERTICALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_VerticalBoxLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"), WVerticalBoxLayout.class); public static final WidgetOption FITLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter.getLocText("FR-Designer-Layout_Adaptive_Layout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"), WFitLayout.class); public static final WidgetOption PARAMETERCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_Para-Body"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_parameter.png"), WParameterLayout.class); public static final WidgetOption ELEMENTCASE = WidgetOptionFactory.createByWidgetClass(Inter .getLocText("FR-Designer_Form-Report"), BaseUtils.readIcon("/com/fr/web/images/form/resources/report_16.png"), ElementCaseEditor.class); } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java b/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java index a4ccae7c2..fc25bd124 100644 --- a/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java +++ b/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java @@ -1,12 +1,16 @@ package com.fr.design.mainframe; -import java.awt.*; +import java.awt.Color; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Rectangle; import java.awt.event.MouseEvent; import javax.swing.*; import javax.swing.event.MouseInputAdapter; import com.fr.base.BaseUtils; +import com.fr.design.beans.location.MoveUtils; import com.fr.design.designer.beans.AdapterBus; import com.fr.design.designer.beans.ComponentAdapter; import com.fr.design.designer.beans.events.DesignerEditor; @@ -69,6 +73,9 @@ public class EditingMouseListener extends MouseInputAdapter { private DesignerEditor current_editor; private XCreator current_creator; + //备份开始拖动的位置和大小 + private Rectangle dragBackupBounds; + /** * 获取最小移动距离 * @@ -186,6 +193,14 @@ public class EditingMouseListener extends MouseInputAdapter { if (stateModel.isDragging()) { // 当前鼠标所在的组件 XCreator hoveredComponent = designer.getComponentAt(e.getX(), e.getY()); + if(designer.isWidgetsIntersect() && dragBackupBounds != null && hoveredComponent != null){ + XCreator selectionXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); + if(selectionXCreator != null){ + selectionXCreator.setBounds(dragBackupBounds.x, dragBackupBounds.y, dragBackupBounds.width, dragBackupBounds.height); + MoveUtils.hideForbidWindow(); + } + } + dragBackupBounds = null; // 拉伸时鼠标拖动过快,导致所在组件获取会为空 if (hoveredComponent == null && e.getY() < 0) { // bug63538 @@ -384,6 +399,12 @@ public class EditingMouseListener extends MouseInputAdapter { stateModel.dragging(e); // 获取e所在的焦点组件 XCreator hotspot = designer.getComponentAt(e.getX(), e.getY()); + if(dragBackupBounds == null) { + XCreator selectingXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); + if(selectingXCreator != null){ + dragBackupBounds = new Rectangle(selectingXCreator.getX(), selectingXCreator.getY(), selectingXCreator.getWidth(), selectingXCreator.getHeight()); + } + } // 拉伸时鼠标拖动过快,导致所在组件获取会为空 if (hotspot == null) { return; diff --git a/designer_form/src/com/fr/design/mainframe/FormDesigner.java b/designer_form/src/com/fr/design/mainframe/FormDesigner.java index 19bf64c70..40add6915 100644 --- a/designer_form/src/com/fr/design/mainframe/FormDesigner.java +++ b/designer_form/src/com/fr/design/mainframe/FormDesigner.java @@ -84,6 +84,9 @@ public class FormDesigner extends TargetComponent
implements TreeSelection private ConnectorHelper ConnectorHelper; private boolean isReportBlockEditing = false; + //组件重叠 + private boolean isWidgetsIntersect = false; + /** * 下面的变量都是非序列化成员,不记录设计状态,只作为设计时临时状态使用。 */ @@ -539,6 +542,12 @@ public class FormDesigner extends TargetComponent implements TreeSelection if (paraComponent != null && paraComponent.acceptType(XWParameterLayout.class)){ return true; } + else{ + if (this.getSelectionModel().getSelection().getSelectedCreator().getParent() != null + && ((XLayoutContainer)this.getSelectionModel().getSelection().getSelectedCreator().getParent()).acceptType(XWAbsoluteLayout.class)){ + return true; + } + } return false; } @@ -558,6 +567,14 @@ public class FormDesigner extends TargetComponent implements TreeSelection return this.isReportBlockEditing; } + public void setWidgetsIntersect(boolean isWidgetsIntersect){ + this.isWidgetsIntersect = isWidgetsIntersect; + } + + public boolean isWidgetsIntersect(){ + return this.isWidgetsIntersect; + } + /** * 是否重命名控件 * @param creator 组件 From 0374fd648c17d3d1e07dfc05f198bdf9fe651951 Mon Sep 17 00:00:00 2001 From: zhouping Date: Fri, 29 Jul 2016 09:26:04 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/com/fr/design/beans/location/WidgetForbidWindow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 089a242da..acf934e25 100644 --- a/designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java +++ b/designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java @@ -15,7 +15,7 @@ public class WidgetForbidWindow extends JWindow { private static final int WIDTH = 150; private static final int HEIGHT = 20; - private UIButton promptButton = new UIButton("禁止组件相互重叠", BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); + private UIButton promptButton = new UIButton(Inter.getLocText("FR-Designer_Forbid_Widgets_Intersects"), BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); /** * 构造函数 From b930df76890e627ca4271dea752888d09f7e8361 Mon Sep 17 00:00:00 2001 From: zhouping Date: Fri, 29 Jul 2016 10:18:31 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=8Binstanceof?= =?UTF-8?q?=EF=BC=8C=E6=94=B9=E6=88=90acceptType=E5=A5=BD=E4=B8=80?= =?UTF-8?q?=E4=BA=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/com/fr/design/designer/beans/location/Inner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/designer_form/src/com/fr/design/designer/beans/location/Inner.java b/designer_form/src/com/fr/design/designer/beans/location/Inner.java index f6c5bdef6..9e17b4ac3 100644 --- a/designer_form/src/com/fr/design/designer/beans/location/Inner.java +++ b/designer_form/src/com/fr/design/designer/beans/location/Inner.java @@ -121,7 +121,7 @@ public class Inner extends AccessDirection { } }; //判断当前操作的是不是参数面板,要特殊处理 - boolean isParameterLayout = (designer.getSelectionModel().getSelection().getSelectedCreator().getParent()) instanceof XWParameterLayout; + boolean isParameterLayout = ((XCreator)(designer.getSelectionModel().getSelection().getSelectedCreator().getParent())).acceptType(XWParameterLayout.class); point.setLocation(MoveUtils.sorption(point.x, point.y, current_bounds.width, current_bounds.height, rd, isParameterLayout)); }