diff --git a/designer_base/build.dev.gradle b/designer_base/build.dev.gradle index b02f751e7..9b2b65770 100644 --- a/designer_base/build.dev.gradle +++ b/designer_base/build.dev.gradle @@ -1,8 +1,25 @@ - -apply plugin: 'java' tasks.withType(JavaCompile){ options.encoding = 'UTF-8' } + +buildscript { + repositories { + maven { + url "http://www.eveoh.nl/files/maven2" + } + } + + dependencies { + classpath "nl.eveoh:gradle-aspectj:1.2" + } +} + +ext.aspectjVersion = '1.7.4' +apply plugin: 'aspectj' + +repositories { + mavenCentral() +} //指定构建的jdk版本 sourceCompatibility=1.7 //指定生成jar包版本 diff --git a/designer_base/build.dev.gradle.bak b/designer_base/build.dev.gradle.bak new file mode 100644 index 000000000..b02f751e7 --- /dev/null +++ b/designer_base/build.dev.gradle.bak @@ -0,0 +1,70 @@ + +apply plugin: 'java' +tasks.withType(JavaCompile){ + options.encoding = 'UTF-8' +} +//指定构建的jdk版本 +sourceCompatibility=1.7 +//指定生成jar包版本 +version='8.0' +//生成jar包重命名 +jar{ + baseName='fr-designer-core' +} + + +def srcDir="." + +//指定源码路径 +sourceSets{ + main{ + java{ + srcDirs=["${srcDir}/src"] + } + } +} +//获取什么分支名 +FileTree files =fileTree(dir:'./',include:'build.*.gradle') +def buildDir=files[0].path.substring(0,files[0].path.lastIndexOf ('\\')) +buildDir=buildDir.substring(0,buildDir.lastIndexOf ('\\')) +def branchName=buildDir.substring(buildDir.lastIndexOf ('\\')+1) + +//声明外部依赖 +dependencies{ + +compile fileTree(dir:"../../../finereport-lib-stable/${branchName}",include:'**/*.jar') +compile fileTree(dir:'../../../',include:"finereport-*-stable/${branchName}/**/build/libs/*.jar") + + testCompile 'junit:junit:4.12' +} +//复制非.java文件到classes文件夹下参与打包 +task copyFile(type:Copy,dependsOn:compileJava){ + copy{ + from ("${srcDir}/src"){ + exclude '**/.setting/**','.classpath','.project','**/*.java','**/*.db','**/*.g','**/package.html' + } + into 'build/classes/main' + } + +} + + +//压缩项目中的js文件 +task compressJS{ + ant.taskdef(name:'yuicompress',classname:'com.yahoo.platform.yui.compressor.YUICompressTask'){ + classpath { + fileset(dir:'../../../finereport-lib4build-stable',includes:'**/*.jar') + } + } + ant.yuicompress(linebreak:"500",warn:"false", munge:"yes",preserveallsemicolons:"false",charset:"utf-8",encoding:"utf-8",outputfolder:'build/classes/main'){ + fileset (dir:"${srcDir}/src"){ + include (name:'**/*.js') + include (name:'**/*.css') + } + + } +} +jar.dependsOn compressJS + + + diff --git a/designer_base/src/com/fr/design/actions/edit/CopyAction.java b/designer_base/src/com/fr/design/actions/edit/CopyAction.java index 6f7ec1c4d..d0579a579 100644 --- a/designer_base/src/com/fr/design/actions/edit/CopyAction.java +++ b/designer_base/src/com/fr/design/actions/edit/CopyAction.java @@ -1,37 +1,35 @@ -/* - * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. - */ -package com.fr.design.actions.edit; - -import java.awt.event.KeyEvent; - -import javax.swing.KeyStroke; - -import com.fr.base.BaseUtils; -import com.fr.design.actions.TemplateComponentAction; -import com.fr.design.designer.TargetComponent; -import com.fr.general.Inter; - -/** - * Copy. - */ -public class CopyAction extends TemplateComponentAction { - public CopyAction(TargetComponent t) { - super(t); - - this.setName(Inter.getLocText("M_Edit-Copy")); - this.setMnemonic('C'); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); - this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK)); - } - - @Override - public boolean executeActionReturnUndoRecordNeeded() { - TargetComponent tc = getEditingComponent(); - if (tc != null) { - tc.copy(); - } - - return false; - } +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.edit; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.TemplateComponentAction; +import com.fr.design.designer.TargetComponent; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.event.KeyEvent; + +/** + * Copy. + */ +public class CopyAction extends TemplateComponentAction { + public CopyAction(TargetComponent t) { + super(t); + + this.setName(Inter.getLocText("M_Edit-Copy")); + this.setMnemonic('C'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); + this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK)); + } + + @Override + public boolean executeActionReturnUndoRecordNeeded() { + TargetComponent tc = getEditingComponent(); + if (tc != null) { + tc.copy(); + } + return false; + } } \ 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 d89848446..91a62ed5f 100644 --- a/designer_base/src/com/fr/design/beans/location/MoveUtils.java +++ b/designer_base/src/com/fr/design/beans/location/MoveUtils.java @@ -1,588 +1,544 @@ -/* - * Copyright(c) 2001-2011, FineReport Inc, All Rights Reserved. - */ -package com.fr.design.beans.location; - -import javax.swing.*; -import java.awt.*; -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; - 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; - } - } +/* + * Copyright(c) 2001-2011, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.beans.location; + +import javax.swing.*; +import java.awt.*; +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; + private static final int EQUIDISTANTLINE_UNIT = 4; + + private 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 acf934e25..7c645d0ad 100644 --- a/designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java +++ b/designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java @@ -22,7 +22,6 @@ public class WidgetForbidWindow extends JWindow { */ public WidgetForbidWindow() { this.add(promptButton); - this.setSize(WIDTH, HEIGHT); } @@ -31,18 +30,16 @@ public class WidgetForbidWindow extends JWindow { * * @param x x坐标 * @param y y坐标 - * */ - public void showWindow(int x, int y){ + public void showWindow(int x, int y) { this.setLocation(x - WIDTH / 2, y - HEIGHT / 2); this.setVisible(true); } /** * 隐藏当前窗口 - * */ - public void hideWindow(){ + public void hideWindow() { this.setVisible(false); } } diff --git a/designer_base/src/com/fr/design/locale/designer.properties b/designer_base/src/com/fr/design/locale/designer.properties index 7ed85365d..7c4847f3c 100644 --- a/designer_base/src/com/fr/design/locale/designer.properties +++ b/designer_base/src/com/fr/design/locale/designer.properties @@ -543,7 +543,7 @@ FR-Designer_Left_Display=Left FR-Designer_About_Version=Version FR-Designer_About_CopyRight=Copy Right FR-Designer_Service_Phone=Service Phone -FR-Designer_Allow_Blank=Allow Blank +FR-Designer_Allow_Null=Allow Null FR-Designer_PageSetup_Page=Page FR-Designer_Custom_Job_Description=Description FR-Designer_Property=Property diff --git a/designer_base/src/com/fr/design/locale/designer_en_US.properties b/designer_base/src/com/fr/design/locale/designer_en_US.properties index e7604d42c..fab277ad6 100644 --- a/designer_base/src/com/fr/design/locale/designer_en_US.properties +++ b/designer_base/src/com/fr/design/locale/designer_en_US.properties @@ -544,7 +544,7 @@ FR-Designer_Left_Display=Left FR-Designer_About_Version=Version FR-Designer_About_CopyRight=Copy Right FR-Designer_Service_Phone=Service Phone -FR-Designer_Allow_Blank=Allow Null +FR-Designer_Allow_Null=Allow Null FR-Designer_PageSetup_Page=Page FR-Designer_Custom_Job_Description=Description FR-Designer_Property=Property diff --git a/designer_base/src/com/fr/design/locale/designer_ja_JP.properties b/designer_base/src/com/fr/design/locale/designer_ja_JP.properties index 7cc3163c0..4d68093c7 100644 --- a/designer_base/src/com/fr/design/locale/designer_ja_JP.properties +++ b/designer_base/src/com/fr/design/locale/designer_ja_JP.properties @@ -518,7 +518,7 @@ FR-Designer_Left_Display=\u5DE6\u8868\u793A FR-Designer_About_Version=\u30D0\u30FC\u30B8\u30E7\u30F3 FR-Designer_About_CopyRight=\u8457\u4F5C\u6A29\u6240\u6709 FR-Designer_Service_Phone=\u30B5\u30FC\u30D3\u30B9\u96FB\u8A71\uFF1A -FR-Designer_Allow_Blank=\u7A7A\u6B04\u3042\u308A +FR-Designer_Allow_Null=\u7A7A\u6B04\u3042\u308A FR-Designer_PageSetup_Page=\u30DA\u30FC\u30B8 FR-Designer_Custom_Job_Description=\u8A18\u8FF0 FR-Designer_Property=\u5C5E\u6027 diff --git a/designer_base/src/com/fr/design/locale/designer_ko_KR.properties b/designer_base/src/com/fr/design/locale/designer_ko_KR.properties index 9942d0e86..14086e881 100644 --- a/designer_base/src/com/fr/design/locale/designer_ko_KR.properties +++ b/designer_base/src/com/fr/design/locale/designer_ko_KR.properties @@ -514,7 +514,7 @@ FR-Designer_Left_Display=\uC67C\uCABD\uBCF4\uC774\uAE30 FR-Designer_About_Version=\uBC84\uC804 FR-Designer_About_CopyRight=\uD310\uAD8C\uC18C\uC720 FR-Designer_Service_Phone=\uC11C\uBE44\uC2A4\uC804\uD654\uFF1A -FR-Designer_Allow_Blank=\uBE48\uCE78\uD5C8\uC6A9 +FR-Designer_Allow_Null=\uBE48\uCE78\uD5C8\uC6A9 FR-Designer_PageSetup_Page=\uC6F9\uD398\uC774\uC9C0 FR-Designer_Custom_Job_Description=\uC124\uBA85 FR-Designer_Property=\uC18D\uC131 diff --git a/designer_base/src/com/fr/design/locale/designer_zh_CN.properties b/designer_base/src/com/fr/design/locale/designer_zh_CN.properties index d8789a58c..5139b301f 100644 --- a/designer_base/src/com/fr/design/locale/designer_zh_CN.properties +++ b/designer_base/src/com/fr/design/locale/designer_zh_CN.properties @@ -548,7 +548,7 @@ FR-Designer_Left_Display=\u5DE6\u5C55\u793A FR-Designer_About_Version=\u7248\u672C FR-Designer_About_CopyRight=\u7248\u6743\u6240\u6709 FR-Designer_Service_Phone=\u670D\u52A1\u7535\u8BDD\uFF1A -FR-Designer_Allow_Blank=\u5141\u8BB8\u4E3A\u7A7A +FR-Designer_Allow_Null=\u5141\u8BB8\u4E3A\u7A7A FR-Designer_PageSetup_Page=\u9875\u9762 FR-Designer_Custom_Job_Description=\u63CF\u8FF0 FR-Designer_Property=\u5C5E\u6027 diff --git a/designer_base/src/com/fr/design/locale/designer_zh_TW.properties b/designer_base/src/com/fr/design/locale/designer_zh_TW.properties index 68648424c..10edd2d16 100644 --- a/designer_base/src/com/fr/design/locale/designer_zh_TW.properties +++ b/designer_base/src/com/fr/design/locale/designer_zh_TW.properties @@ -536,7 +536,7 @@ FR-Designer_Left_Display=\u5DE6\u986F\u793A FR-Designer_About_Version=\u7248\u672C FR-Designer_About_CopyRight=\u7248\u6B0A\u6240\u6709 FR-Designer_Service_Phone=\u670D\u52D9\u96FB\u8A71\uFF1A -FR-Designer_Allow_Blank=\u5141\u8A31\u70BA\u7A7A\u767D +FR-Designer_Allow_Null=\u5141\u8A31\u70BA\u7A7A\u767D FR-Designer_PageSetup_Page=\u9801\u9762 FR-Designer_Custom_Job_Description=\u63CF\u8FF0 FR-Designer_Property=\u5C6C\u6027 diff --git a/designer_base/src/com/fr/design/mainframe/BaseJForm.java b/designer_base/src/com/fr/design/mainframe/BaseJForm.java index c0fd09f17..559387b20 100644 --- a/designer_base/src/com/fr/design/mainframe/BaseJForm.java +++ b/designer_base/src/com/fr/design/mainframe/BaseJForm.java @@ -1 +1,66 @@ -package com.fr.design.mainframe; import javax.swing.JComponent; import com.fr.form.FormElementCaseContainerProvider; /** * Author : Shockway * Date: 13-7-15 * Time: 上午10:28 */ public interface BaseJForm extends JTemplateProvider{ public static final String XML_TAG = "JForm"; public static final int FORM_TAB = 0; public static final int ELEMENTCASE_TAB = 1; public static final int ELEMENTCASE_CHANGE_TAB = 2; /** * 刷新所有控件 */ public void refreshAllNameWidgets(); /** * 刷新参数 */ public void populateParameter(); /** * 刷新选中的控件 */ public void refreshSelectedWidget(); /** * 获取当前的Target */ public Object getTarget(); /** * 执行撤销 * * @param o 之前保存的状态 */ public void applyUndoState4Form(BaseUndoState o); /** * 获取当前编辑的组件 */ public JComponent getEditingPane(); /** * 只在Form和ElementCase之间切换 * @param index 切换位置 */ public void tabChanged(int index); /** * 在Form和ElementCase, 以及ElementCase和ElementCase之间切换 * @param index 切换位置 * @param ecContainer ElementCase所在container */ public void tabChanged(int index, FormElementCaseContainerProvider ecContainer); } \ No newline at end of file +package com.fr.design.mainframe; + +import javax.swing.JComponent; + +import com.fr.form.FormElementCaseContainerProvider; + + +/** + * Author : Shockway + * Date: 13-7-15 + * Time: 上午10:28 + */ +public interface BaseJForm extends JTemplateProvider { + + String XML_TAG = "JForm"; + int FORM_TAB = 0; + int ELEMENTCASE_TAB = 1; + int ELEMENTCASE_CHANGE_TAB = 2; + + /** + * 刷新所有控件 + */ + void refreshAllNameWidgets(); + + /** + * 刷新参数 + */ + void populateParameter(); + + /** + * 刷新选中的控件 + */ + void refreshSelectedWidget(); + + /** + * 获取当前的Target + */ + Object getTarget(); + + /** + * 执行撤销 + * + * @param o 之前保存的状态 + */ + void applyUndoState4Form(BaseUndoState o); + + /** + * 获取当前编辑的组件 + */ + JComponent getEditingPane(); + + /** + * 只在Form和ElementCase之间切换 + * + * @param index 切换位置 + */ + void tabChanged(int index); + + /** + * 在Form和ElementCase, 以及ElementCase和ElementCase之间切换 + * + * @param index 切换位置 + * @param ecContainer ElementCase所在container + */ + void tabChanged(int index, FormElementCaseContainerProvider ecContainer); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/mainframe/toolbar/ToolBarMenuDockPlus.java b/designer_base/src/com/fr/design/mainframe/toolbar/ToolBarMenuDockPlus.java index 6c85ce214..ada075aeb 100644 --- a/designer_base/src/com/fr/design/mainframe/toolbar/ToolBarMenuDockPlus.java +++ b/designer_base/src/com/fr/design/mainframe/toolbar/ToolBarMenuDockPlus.java @@ -12,52 +12,52 @@ public interface ToolBarMenuDockPlus { * * @return 工具 */ - public ToolBarDef[] toolbars4Target(); + ToolBarDef[] toolbars4Target(); /** * 文件菜单的子菜单 * * @return 子菜单 */ - public ShortCut[] shortcut4FileMenu(); + ShortCut[] shortcut4FileMenu(); /** * 目标的菜单 * * @return 菜单 */ - public MenuDef[] menus4Target(); + MenuDef[] menus4Target(); /** * 表单的工具栏 * * @return 表单工具栏 */ - public JPanel[] toolbarPanes4Form(); + JPanel[] toolbarPanes4Form(); /** * 表单的工具按钮 * * @return 工具按钮 */ - public JComponent[] toolBarButton4Form(); + JComponent[] toolBarButton4Form(); /** * 权限细粒度状态下的工具面板 * * @return 工具面板 */ - public JComponent toolBar4Authority(); + JComponent toolBar4Authority(); - public int getMenuState(); + int getMenuState(); - public int getToolBarHeight(); + int getToolBarHeight(); /** * 导出菜单的子菜单 ,目前用于图表设计器 * * @return 子菜单 */ - public ShortCut[] shortcut4ExportMenu(); - + ShortCut[] shortcut4ExportMenu(); + } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java b/designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java index 2e2743048..3ba3d610d 100644 --- a/designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java +++ b/designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java @@ -1 +1,72 @@ -package com.fr.design.parameter; import com.fr.base.Parameter; import com.fr.base.parameter.ParameterUI; import com.fr.design.mainframe.AuthorityEditPane; import javax.swing.*; import java.awt.*; /** * 参数设计界面接口 */ public interface ParameterDesignerProvider { public void addListener(ParaDefinitePane paraDefinitePane); public Component createWrapper(); public void setDesignHeight(int height); public Dimension getDesignSize(); public Dimension getPreferredSize(); public void populate(ParameterUI p); public void refreshAllNameWidgets(); public void refresh4TableData(String oldName, String newName); public void refreshParameter(ParaDefinitePane paraDefinitePane); public boolean isWithQueryButton(); public java.util.List getAllXCreatorNameList(); public boolean isWithoutParaXCreator(Parameter[] ps); public boolean isBlank(); public ParameterUI getParaTarget(); public boolean addingParameter2Editor(Parameter parameter, int index); public boolean addingParameter2EditorWithQueryButton(Parameter parameter, int index); public void addingAllParameter2Editor(Parameter[] parameterArray, int currentIndex); public JPanel[] toolbarPanes4Form(); public JComponent[] toolBarButton4Form(); public void initBeforeUpEdit(); public void populateParameterPropertyPane(ParaDefinitePane p); public void initWidgetToolbarPane(); public AuthorityEditPane getAuthorityEditPane(); public JPanel getEastUpPane(); public JPanel getEastDownPane(); public boolean isSupportAuthority(); public void removeSelection(); public ParameterBridge getParaComponent(); } \ No newline at end of file +package com.fr.design.parameter; + +import com.fr.base.Parameter; +import com.fr.base.parameter.ParameterUI; +import com.fr.design.mainframe.AuthorityEditPane; + +import javax.swing.*; +import java.awt.*; + + +/** + * 参数设计界面接口 + */ +public interface ParameterDesignerProvider { + + void addListener(ParaDefinitePane paraDefinitePane); + + Component createWrapper(); + + void setDesignHeight(int height); + + Dimension getDesignSize(); + + Dimension getPreferredSize(); + + void populate(ParameterUI p); + + void refreshAllNameWidgets(); + + void refresh4TableData(String oldName, String newName); + + void refreshParameter(ParaDefinitePane paraDefinitePane); + + boolean isWithQueryButton(); + + java.util.List getAllXCreatorNameList(); + + boolean isWithoutParaXCreator(Parameter[] ps); + + boolean isBlank(); + + ParameterUI getParaTarget(); + + boolean addingParameter2Editor(Parameter parameter, int index); + + boolean addingParameter2EditorWithQueryButton(Parameter parameter, int index); + + void addingAllParameter2Editor(Parameter[] parameterArray, int currentIndex); + + JPanel[] toolbarPanes4Form(); + + JComponent[] toolBarButton4Form(); + + void initBeforeUpEdit(); + + void populateParameterPropertyPane(ParaDefinitePane p); + + void initWidgetToolbarPane(); + + AuthorityEditPane getAuthorityEditPane(); + + JPanel getEastUpPane(); + + JPanel getEastDownPane(); + + boolean isSupportAuthority(); + + void removeSelection(); + + ParameterBridge getParaComponent(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/utils/ComponentUtils.java b/designer_base/src/com/fr/design/utils/ComponentUtils.java index 4fcc52124..1d9361138 100644 --- a/designer_base/src/com/fr/design/utils/ComponentUtils.java +++ b/designer_base/src/com/fr/design/utils/ComponentUtils.java @@ -1,151 +1,154 @@ -package com.fr.design.utils; - -import com.fr.general.ComparatorUtils; - -import javax.swing.*; -import java.awt.*; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; - -/** - * 工具类,提供常用的工具方法 - */ -public class ComponentUtils { - - public static boolean isComponentVisible(Component comp) { - if (!comp.isVisible() && !isRootComponent(comp)) { - return false; - } - Component parent = comp.getParent(); - - return parent == null || isComponentVisible(parent); - - } - - /** - * 获取component所在的容器的绝对位置 - */ - public static Rectangle getRelativeBounds(Component component) { - Rectangle bounds = new Rectangle(0, 0, component.getWidth(), component.getHeight()); - Container parent = component.getParent(); - - while (parent != null) { - bounds.x += component.getX(); - bounds.y += component.getY(); - component = parent; - parent = component.getParent(); - } - - return bounds; - } - - /** - * 恢复双缓冲状态,dbcomponents保存着初始状态为启动双缓冲的组件 - */ - public static void resetBuffer(ArrayList dbcomponents) { - for (JComponent jcomponent : dbcomponents) { - jcomponent.setDoubleBuffered(true); - } - } - - /** - * 禁止双缓冲状态,并将初始状态为启动双缓冲的组件保存到dbcomponents中 - */ - public static void disableBuffer(Component comp, ArrayList dbcomponents) { - if ((comp instanceof JComponent) && comp.isDoubleBuffered()) { - JComponent jcomponent = (JComponent) comp; - - dbcomponents.add(jcomponent); - jcomponent.setDoubleBuffered(false); - } - - if (comp instanceof Container) { - Container container = (Container) comp; - int count = container.getComponentCount(); - - if (count > 0) { - for (int i = 0; i < count; i++) { - Component component = container.getComponent(i); - - disableBuffer(component, dbcomponents); - } - } - } - } - - public static int indexOfComponent(Container container, Component target) { - int count = container.getComponentCount(); - - for (int i = 0; i < count; i++) { - Component child = container.getComponent(i); - - if (child == target) { - return i; - } - } - - return -1; - } - - /** - * 计算组件root相对于其顶层容器的可见区域 - */ - public static Rectangle computeVisibleRectRel2Root(Component root) { - Container container = findAncestorScrollPane(root); - - if (container == null) { - return getRelativeBounds(root); - } else { - // 如果是JScrollPane的子组件,需要计算其viewport与改组件的交叉的可见区域 - return getBoundsRel2Parent(root, container); - } - } - - /** - * 计算组件root相对于其顶层容器的可见区域 - */ - public static Rectangle computeVisibleRect(JComponent root) { - Rectangle root_bounds = ComponentUtils.getRelativeBounds(root); - Rectangle rect = computeVisibleRectRel2Root(root); - rect.x -= root_bounds.x; - rect.y -= root_bounds.y; - - return rect; - } - - private static Rectangle getBoundsRel2Parent(Component child, Container parent) { - Rectangle cRect = getRelativeBounds(child); - Rectangle pRect = getRelativeBounds(parent); - Rectangle bounds = new Rectangle(); - Rectangle2D.intersect(cRect, pRect, bounds); - - return bounds; - } - - public static Container findAncestorScrollPane(Component p) { - if ((p == null) || !(p instanceof Container)) { - return null; - } - - Container c = p.getParent(); - - return findAncestorScrollPane(c); - } - - public static boolean isRootComponent(Component root) { - Container parent = root.getParent(); - return parent == null; - } - - public static boolean isChildOf(Component component, Class parent) { - Container container = component.getParent(); - if (container != null) { - if (ComparatorUtils.equals(container.getClass(), parent)) { - return true; - } else { - return isChildOf(container, parent); - } - } - return false; - } +package com.fr.design.utils; + +import com.fr.general.ComparatorUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; + +/** + * 工具类,提供常用的工具方法 + */ +public class ComponentUtils { + + private ComponentUtils() { + } + + public static boolean isComponentVisible(Component comp) { + if (!comp.isVisible() && !isRootComponent(comp)) { + return false; + } + Component parent = comp.getParent(); + + return parent == null || isComponentVisible(parent); + + } + + /** + * 获取component所在的容器的绝对位置 + */ + public static Rectangle getRelativeBounds(Component component) { + Rectangle bounds = new Rectangle(0, 0, component.getWidth(), component.getHeight()); + Container parent = component.getParent(); + + while (parent != null) { + bounds.x += component.getX(); + bounds.y += component.getY(); + component = parent; + parent = component.getParent(); + } + + return bounds; + } + + /** + * 恢复双缓冲状态,dbcomponents保存着初始状态为启动双缓冲的组件 + */ + public static void resetBuffer(ArrayList dbcomponents) { + for (JComponent jcomponent : dbcomponents) { + jcomponent.setDoubleBuffered(true); + } + } + + /** + * 禁止双缓冲状态,并将初始状态为启动双缓冲的组件保存到dbcomponents中 + */ + public static void disableBuffer(Component comp, ArrayList dbcomponents) { + if ((comp instanceof JComponent) && comp.isDoubleBuffered()) { + JComponent jcomponent = (JComponent) comp; + + dbcomponents.add(jcomponent); + jcomponent.setDoubleBuffered(false); + } + + if (comp instanceof Container) { + Container container = (Container) comp; + int count = container.getComponentCount(); + + if (count > 0) { + for (int i = 0; i < count; i++) { + Component component = container.getComponent(i); + + disableBuffer(component, dbcomponents); + } + } + } + } + + public static int indexOfComponent(Container container, Component target) { + int count = container.getComponentCount(); + + for (int i = 0; i < count; i++) { + Component child = container.getComponent(i); + + if (child.equals(target)) { + return i; + } + } + + return -1; + } + + /** + * 计算组件root相对于其顶层容器的可见区域 + */ + public static Rectangle computeVisibleRectRel2Root(Component root) { + Container container = findAncestorScrollPane(root); + + if (container == null) { + return getRelativeBounds(root); + } else { + // 如果是JScrollPane的子组件,需要计算其viewport与改组件的交叉的可见区域 + return getBoundsRel2Parent(root, container); + } + } + + /** + * 计算组件root相对于其顶层容器的可见区域 + */ + public static Rectangle computeVisibleRect(JComponent root) { + Rectangle rootBounds = ComponentUtils.getRelativeBounds(root); + Rectangle rect = computeVisibleRectRel2Root(root); + rect.x -= rootBounds.x; + rect.y -= rootBounds.y; + + return rect; + } + + private static Rectangle getBoundsRel2Parent(Component child, Container parent) { + Rectangle cRect = getRelativeBounds(child); + Rectangle pRect = getRelativeBounds(parent); + Rectangle bounds = new Rectangle(); + Rectangle2D.intersect(cRect, pRect, bounds); + + return bounds; + } + + public static Container findAncestorScrollPane(Component p) { + if ((p == null) || !(p instanceof Container)) { + return null; + } + + Container c = p.getParent(); + + return findAncestorScrollPane(c); + } + + public static boolean isRootComponent(Component root) { + Container parent = root.getParent(); + return parent == null; + } + + public static boolean isChildOf(Component component, Class parent) { + Container container = component.getParent(); + if (container != null) { + if (ComparatorUtils.equals(container.getClass(), parent)) { + return true; + } else { + return isChildOf(container, parent); + } + } + return false; + } } \ No newline at end of file diff --git a/designer_chart/build.dev.gradle b/designer_chart/build.dev.gradle index ba6df992b..db1478361 100644 --- a/designer_chart/build.dev.gradle +++ b/designer_chart/build.dev.gradle @@ -1,8 +1,26 @@ -apply plugin: 'java' tasks.withType(JavaCompile){ options.encoding = 'UTF-8' } + +buildscript { + repositories { + maven { + url "http://www.eveoh.nl/files/maven2" + } + } + + dependencies { + classpath "nl.eveoh:gradle-aspectj:1.2" + } +} + +ext.aspectjVersion = '1.7.4' +apply plugin: 'aspectj' + +repositories { + mavenCentral() +} //指定构建的jdk版本 sourceCompatibility=1.7 //指定生成jar包的版本 diff --git a/designer_chart/build.dev.gradle.bak b/designer_chart/build.dev.gradle.bak new file mode 100644 index 000000000..7566bcc82 --- /dev/null +++ b/designer_chart/build.dev.gradle.bak @@ -0,0 +1,85 @@ + +apply plugin: 'java' +tasks.withType(JavaCompile){ + options.encoding = 'UTF-8' +} + +buildscript { + repositories { + maven { + url "http://www.eveoh.nl/files/maven2" + } + } + + dependencies { + classpath "nl.eveoh:gradle-aspectj:1.2" + } +} + +ext.aspectjVersion = '1.7.4' +apply plugin: 'aspectj' + +repositories { + mavenCentral() +} +//指定构建的jdk版本 +sourceCompatibility=1.7 +//指定生成jar包的版本 +version='8.0' + +def srcDir="." + +//对生成的jar包进行重命名 + +jar{ + baseName='fr-designer-chart' +} + +sourceSets{ + main{ + java{ + srcDirs=["${srcDir}/src"] + } + } +} +FileTree files =fileTree(dir:'./',include:'build.*.gradle') +def buildDir=files[0].path.substring(0,files[0].path.lastIndexOf ('\\')) +buildDir=buildDir.substring(0,buildDir.lastIndexOf ('\\')) +def branchName=buildDir.substring(buildDir.lastIndexOf ('\\')+1) + +//指定外部依赖 +dependencies{ +compile fileTree(dir:"../../../finereport-lib-stable/${branchName}",include:'**/*.jar') +compile fileTree(dir:'../../../',include:"finereport-*-stable/${branchName}/**/build/libs/*.jar") + + testCompile 'junit:junit:4.12' +} +//将非.java 文件复制到classes文件夹下参与打包 +task copyFile(type:Copy,dependsOn:compileJava){ + copy{ + from ("${srcDir}/src"){ + exclude '**/.setting/**','.classpath','.project','**/*.java','**/*.db','**/*.g','**/package.html' + + } + into 'build/classes/main' + } + +} + +//压缩项目中的js文件 +task compressJS{ + ant.taskdef(name:'yuicompress',classname:'com.yahoo.platform.yui.compressor.YUICompressTask'){ + classpath { + fileset(dir:'../../../finereport-lib4build-stable',includes:'**/*.jar') + } + } + ant.yuicompress(linebreak:"500",warn:"false", munge:"yes",preserveallsemicolons:"false",charset:"utf-8",encoding:"utf-8",outputfolder:'build/classes/main'){ + fileset (dir:"${srcDir}/src"){ + include (name:'**/*.js') + include (name:'**/*.css') + } + + } +} +jar.dependsOn compressJS + diff --git a/designer_chart/src/com/fr/design/chart/fun/IndependentChartUIProvider.java b/designer_chart/src/com/fr/design/chart/fun/IndependentChartUIProvider.java index 031ecd3d6..1b90382d6 100644 --- a/designer_chart/src/com/fr/design/chart/fun/IndependentChartUIProvider.java +++ b/designer_chart/src/com/fr/design/chart/fun/IndependentChartUIProvider.java @@ -22,7 +22,7 @@ public interface IndependentChartUIProvider extends Level { String XML_TAG = "IndependentChartUIProvider"; - int CURRENT_API_LEVEL = 4; + int CURRENT_API_LEVEL = 3; /** * 图表的类型定义界面类型,就是属性表的第一个界面 diff --git a/designer_form/build.dev.gradle b/designer_form/build.dev.gradle index ae16b033e..4b71fed5f 100644 --- a/designer_form/build.dev.gradle +++ b/designer_form/build.dev.gradle @@ -1,8 +1,25 @@ -apply plugin: 'java' tasks.withType(JavaCompile){ options.encoding = 'UTF-8' } +buildscript { + repositories { + maven { + url "http://www.eveoh.nl/files/maven2" + } + } + + dependencies { + classpath "nl.eveoh:gradle-aspectj:1.2" + } +} + +ext.aspectjVersion = '1.7.4' +apply plugin: 'aspectj' + +repositories { + mavenCentral() +} //指定构建的jdk版本 sourceCompatibility=1.7 //指定生成的jar包版本 diff --git a/designer_form/build.dev.gradle.bak b/designer_form/build.dev.gradle.bak index 2b727caac..ae16b033e 100644 --- a/designer_form/build.dev.gradle.bak +++ b/designer_form/build.dev.gradle.bak @@ -4,7 +4,7 @@ tasks.withType(JavaCompile){ options.encoding = 'UTF-8' } //指定构建的jdk版本 -sourceCompatibility=1.8 +sourceCompatibility=1.7 //指定生成的jar包版本 version='8.0' @@ -20,7 +20,7 @@ sourceSets{ main{ java{ srcDirs=["${srcDir}/src", -"${srcDir}/../designer/src"] + "${srcDir}/../designer/src"] } } } diff --git a/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java index fffc1c587..c087d78fe 100644 --- a/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java +++ b/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java @@ -1,85 +1,94 @@ -package com.fr.design.designer.beans; - -import com.fr.design.beans.GroupModel; -import com.fr.design.designer.creator.XCreator; - -/** - * 该接口是LayoutManager的BeanInfo类。标准Java平台没有提供布局管理器的BeanInfo类, - * 对于界面设计工具来说还需一些特殊的行为。 - * @since 6.5.3 - */ -public interface LayoutAdapter { - - /** - * 在添加组件状态时,当鼠标移动到某个容器上方时,如果该容器有布局管理器,则会调用该布局 - * 管理适配器的accept来决定当前位置是否可以放置,并提供特殊的标识,比如红色区域标识。比 - * 如在BorderLayout中,如果某个方位已经放置了组件,则此时应该返回false标识该区域不可以 - * 放置。 - *@param creator 组件 - *@param x 添加的位置x,该位置是相对于container的 - *@param y 添加的位置y,该位置是相对于container的 - *@return 是否可以放置 - */ - boolean accept(XCreator creator, int x, int y); - - /** - * 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适,如果不合适,就需要重新fix一下 - * @param creator 组件 - */ - void fix(XCreator creator); - - /** - * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 - * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 - * @param creator 被添加的新组件 - * @param x 添加的位置x,该位置是相对于container的 - * @param y 添加的位置y,该位置是相对于container的 - * @return 是否添加成功,成功返回true,否则false - */ - boolean addBean(XCreator creator, int x, int y); - - /** - * 返回该布局管理适配器的Painter,为容器提供放置位置的标识。 - */ - HoverPainter getPainter(); - - /** - * 显示parent的字组件child,解决CardLayout中显示某个非显示组件的特殊情况 - * @param child 组件 - */ - void showComponent(XCreator child); - - void addNextComponent(XCreator dragged); - - /** - * 组件叠放顺序前插入 - * @param target 目标组件 - * @param added 插入组件 - */ - void addBefore(XCreator target, XCreator added); - - /** - * 组件叠放顺序后插入 - * @param target 目标组件 - * @param added 放置组件 - */ - void addAfter(XCreator target, XCreator added); - - /** - * 能否放置更多组件 - * @return 能则返回true - */ - boolean canAcceptMoreComponent(); - - ConstraintsGroupModel getLayoutConstraints(XCreator creator); - - GroupModel getLayoutProperties(); - - /** - * 删除组件 - * @param creator 组件 - * @param initWidth 组件之前宽度 - * @param initHeight 组件之前高度 - */ - void removeBean(XCreator creator, int initWidth, int initHeight); +package com.fr.design.designer.beans; + +import com.fr.design.beans.GroupModel; +import com.fr.design.designer.creator.XCreator; + +/** + * 该接口是LayoutManager的BeanInfo类。标准Java平台没有提供布局管理器的BeanInfo类, + * 对于界面设计工具来说还需一些特殊的行为。 + * + * @since 6.5.3 + */ +public interface LayoutAdapter { + + /** + * 在添加组件状态时,当鼠标移动到某个容器上方时,如果该容器有布局管理器,则会调用该布局 + * 管理适配器的accept来决定当前位置是否可以放置,并提供特殊的标识,比如红色区域标识。比 + * 如在BorderLayout中,如果某个方位已经放置了组件,则此时应该返回false标识该区域不可以 + * 放置。 + * + * @param creator 组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否可以放置 + */ + boolean accept(XCreator creator, int x, int y); + + /** + * 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适,如果不合适,就需要重新fix一下 + * + * @param creator 组件 + */ + void fix(XCreator creator); + + /** + * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 + * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 + * + * @param creator 被添加的新组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否添加成功,成功返回true,否则false + */ + boolean addBean(XCreator creator, int x, int y); + + /** + * 返回该布局管理适配器的Painter,为容器提供放置位置的标识。 + */ + HoverPainter getPainter(); + + /** + * 显示parent的字组件child,解决CardLayout中显示某个非显示组件的特殊情况 + * + * @param child 组件 + */ + void showComponent(XCreator child); + + void addNextComponent(XCreator dragged); + + /** + * 组件叠放顺序前插入 + * + * @param target 目标组件 + * @param added 插入组件 + */ + void addBefore(XCreator target, XCreator added); + + /** + * 组件叠放顺序后插入 + * + * @param target 目标组件 + * @param added 放置组件 + */ + void addAfter(XCreator target, XCreator added); + + /** + * 能否放置更多组件 + * + * @return 能则返回true + */ + boolean canAcceptMoreComponent(); + + ConstraintsGroupModel getLayoutConstraints(XCreator creator); + + GroupModel getLayoutProperties(); + + /** + * 删除组件 + * + * @param creator 组件 + * @param initWidth 组件之前宽度 + * @param initHeight 组件之前高度 + */ + void removeBean(XCreator creator, int initWidth, int initHeight); } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java b/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java index e32ece18e..23686f651 100644 --- a/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java +++ b/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java @@ -1,31 +1,30 @@ -package com.fr.design.designer.beans.actions; - -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; - -import javax.swing.KeyStroke; - -import com.fr.base.BaseUtils; -import com.fr.general.Inter; -import com.fr.design.mainframe.FormDesigner; - -public class CopyAction extends FormEditAction { - - public CopyAction(FormDesigner t) { - super(t); - this.setName(Inter.getLocText("M_Edit-Copy")); - this.setMnemonic('C'); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); - this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK)); - } - - @Override - public boolean executeActionReturnUndoRecordNeeded() { - FormDesigner tc = getEditingComponent(); - if (tc != null) { - tc.copy(); - } - return false; - } - +package com.fr.design.designer.beans.actions; + +import com.fr.base.BaseUtils; +import com.fr.design.mainframe.FormDesigner; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +public class CopyAction extends FormEditAction { + + public CopyAction(FormDesigner t) { + super(t); + this.setName(Inter.getLocText("M_Edit-Copy")); + this.setMnemonic('C'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); + this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK)); + } + + @Override + public boolean executeActionReturnUndoRecordNeeded() { + FormDesigner tc = getEditingComponent(); + if (tc != null) { + tc.copy(); + } + return false; + } + } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java index d5232d26a..493dd02aa 100644 --- a/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java +++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java @@ -1,174 +1,189 @@ -package com.fr.design.designer.beans.adapters.layout; - -import java.awt.LayoutManager; - -import com.fr.general.ComparatorUtils; -import com.fr.design.beans.GroupModel; -import com.fr.design.designer.beans.ConstraintsGroupModel; -import com.fr.design.designer.beans.HoverPainter; -import com.fr.design.designer.beans.LayoutAdapter; -import com.fr.design.designer.beans.painters.NullPainter; -import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWidgetCreator; -import com.fr.design.utils.ComponentUtils; -import com.fr.design.utils.gui.LayoutUtils; - -public abstract class AbstractLayoutAdapter implements LayoutAdapter { - - protected XLayoutContainer container; - protected LayoutManager layout; - - public AbstractLayoutAdapter(XLayoutContainer container) { - this.container = container; - this.layout = container.getLayout(); - } - - /** - * 是否使用控件备份大小 - * @param xCreator 控件 - * @return 所在容器相同,且支持备份的话返回true - */ - public boolean whetherUseBackupSize(XCreator xCreator) { - Class clazz = container.getClass(); - Class bkClazz = null; - if(xCreator.getBackupParent() != null) { - bkClazz = xCreator.getBackupParent().getClass(); - } - return ComparatorUtils.equals(bkClazz, clazz) - && supportBackupSize(); - } - - /** - * 是否支持用备份大小 - * @return 否 - */ - public boolean supportBackupSize() { - return false; - } - - /** - * 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适,如果不合适,就需要重新fix一下 - * @param creator 组件 - */ - public void fix(XCreator creator) { - } - - /** - * 显示parent的字组件child,解决CardLayout中显示某个非显示组件的特殊情况 - * @param child 组件 - */ - @Override - public void showComponent(XCreator child) { - child.setVisible(true); - } - - /** - * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 - * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 - * @param creator 被添加的新组件 - * @param x 添加的位置x,该位置是相对于container的 - * @param y 添加的位置y,该位置是相对于container的 - * @return 是否添加成功,成功返回true,否则false - */ - @Override - public boolean addBean(XCreator creator, int x, int y) { - if (!accept(creator, x, y)) { - return false; - } - addComp(creator, x, y); - ((XWidgetCreator) creator).recalculateChildrenSize(); - return true; - } - - /** - * 删除组件 - * @param creator 组件 - * @param initWidth 组件之前宽度 - * @param initHeight 组件之前高度 - */ - public void removeBean(XCreator creator, int creatorWidth, int creatorHeight) { - delete(creator, creatorWidth, creatorHeight); - } - - protected void delete(XCreator creator, int creatorWidth, int creatorHeight) { - } - - protected abstract void addComp(XCreator creator, int x, int y); - - /** - * 增加下一个组件 - * @param dragged 组件 - */ - @Override - public void addNextComponent(XCreator dragged) { - container.add(dragged); - LayoutUtils.layoutRootContainer(container); - } - - /** - * 目标控件位置插入组件 - * @param target 目标 - * @param added 增加组件 - */ - @Override - public void addBefore(XCreator target, XCreator added) { - int index = ComponentUtils.indexOfComponent(container, target); - - if (index == -1) { - container.add(added, 0); - } else { - container.add(added, index); - } - - LayoutUtils.layoutRootContainer(container); - } - - /** - * 插在目标组件后面 - * @param target 目标 - * @param added 增加组件 - */ - @Override - public void addAfter(XCreator target, XCreator added) { - int index = ComponentUtils.indexOfComponent(container, target); - - if (index == -1) { - container.add(added); - } else { - index++; - - if (index >= container.getComponentCount()) { - container.add(added); - } else { - container.add(added, index); - } - } - - LayoutUtils.layoutRootContainer(container); - } - - @Override - public HoverPainter getPainter() { - return new NullPainter(container); - } - - /** - * 是否能接收更多的组件 - * @return 能则返回true - */ - @Override - public boolean canAcceptMoreComponent() { - return true; - } - - @Override - public ConstraintsGroupModel getLayoutConstraints(XCreator creator) { - return null; - } - - @Override - public GroupModel getLayoutProperties() { - return null; - } +package com.fr.design.designer.beans.adapters.layout; + +import com.fr.design.beans.GroupModel; +import com.fr.design.designer.beans.ConstraintsGroupModel; +import com.fr.design.designer.beans.HoverPainter; +import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.beans.painters.NullPainter; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWidgetCreator; +import com.fr.design.utils.ComponentUtils; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.general.ComparatorUtils; + +import java.awt.*; + +public abstract class AbstractLayoutAdapter implements LayoutAdapter { + + protected XLayoutContainer container; + protected LayoutManager layout; + + public AbstractLayoutAdapter(XLayoutContainer container) { + this.container = container; + this.layout = container.getLayout(); + } + + /** + * 是否使用控件备份大小 + * + * @param xCreator 控件 + * @return 所在容器相同,且支持备份的话返回true + */ + public boolean whetherUseBackupSize(XCreator xCreator) { + Class clazz = container.getClass(); + Class bkClazz = null; + if (xCreator.getBackupParent() != null) { + bkClazz = xCreator.getBackupParent().getClass(); + } + return ComparatorUtils.equals(bkClazz, clazz) + && supportBackupSize(); + } + + /** + * 是否支持用备份大小 + * + * @return 否 + */ + public boolean supportBackupSize() { + return false; + } + + /** + * 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适,如果不合适,就需要重新fix一下 + * + * @param creator 组件 + */ + public void fix(XCreator creator) { + } + + /** + * 显示parent的字组件child,解决CardLayout中显示某个非显示组件的特殊情况 + * + * @param child 组件 + */ + @Override + public void showComponent(XCreator child) { + child.setVisible(true); + } + + /** + * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 + * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 + * + * @param creator 被添加的新组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否添加成功,成功返回true,否则false + */ + @Override + public boolean addBean(XCreator creator, int x, int y) { + if (!accept(creator, x, y)) { + return false; + } + addComp(creator, x, y); + ((XWidgetCreator) creator).recalculateChildrenSize(); + return true; + } + + /** + * 删除组件 + * + * @param creator 组件 + * @param creatorWidth + * @param creatorHeight + */ + public void removeBean(XCreator creator, int creatorWidth, int creatorHeight) { + delete(creator, creatorWidth, creatorHeight); + } + + protected void delete(XCreator creator, int creatorWidth, int creatorHeight) { + } + + protected abstract void addComp(XCreator creator, int x, int y); + + /** + * 增加下一个组件 + * + * @param dragged 组件 + */ + @Override + public void addNextComponent(XCreator dragged) { + container.add(dragged); + LayoutUtils.layoutRootContainer(container); + } + + /** + * 目标控件位置插入组件 + * + * @param target 目标 + * @param added 增加组件 + */ + @Override + public void addBefore(XCreator target, XCreator added) { + int index = ComponentUtils.indexOfComponent(container, target); + + if (index == -1) { + container.add(added, 0); + } else { + container.add(added, index); + } + + LayoutUtils.layoutRootContainer(container); + } + + /** + * 插在目标组件后面 + * + * @param target 目标 + * @param added 增加组件 + */ + @Override + public void addAfter(XCreator target, XCreator added) { + int index = ComponentUtils.indexOfComponent(container, target); + + if (index == -1) { + container.add(added); + } else { + index++; + + if (index >= container.getComponentCount()) { + container.add(added); + } else { + container.add(added, index); + } + } + + LayoutUtils.layoutRootContainer(container); + } + + @Override + public HoverPainter getPainter() { + return new NullPainter(container); + } + + /** + * 是否能接收更多的组件 + * + * @return 能则返回true + */ + @Override + public boolean canAcceptMoreComponent() { + return true; + } + + @Override + public ConstraintsGroupModel getLayoutConstraints(XCreator creator) { + return null; + } + + @Override + public GroupModel getLayoutProperties() { + return null; + } + + + public XLayoutContainer getContainer() { + return this.container; + } } \ No newline at end of file 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 140204e75..b8a8e8ad1 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,354 +1,349 @@ -package com.fr.design.designer.beans.adapters.layout; - -import java.awt.*; - -import com.fr.design.beans.GroupModel; -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.*; -import com.fr.design.designer.properties.BoundsGroupModel; -import com.fr.design.designer.properties.FRAbsoluteLayoutPropertiesGroupModel; -import com.fr.form.ui.container.WAbsoluteLayout; -import com.fr.design.utils.ComponentUtils; -import com.fr.design.utils.gui.LayoutUtils; -import com.fr.form.ui.widget.BoundsWidget; -import com.fr.general.ComparatorUtils; -import com.fr.general.FRLogger; - -public class FRAbsoluteLayoutAdapter extends FRBodyLayoutAdapter { - //是不是添加到父容器上 - private boolean isAdd2ParentLayout = false; - private HoverPainter painter; - - public FRAbsoluteLayoutAdapter(XLayoutContainer container) { - super(container); - painter = new FRAbsoluteLayoutPainter(container); - initMinSize(); - } - - private void initMinSize() { - XWAbsoluteLayout layout = (XWAbsoluteLayout) container; - minWidth = layout.getActualMinWidth(); - minHeight = layout.getActualMinHeight(); - actualVal = layout.getAcualInterval(); - margin = layout.toData().getMargin(); - } - - @Override - public HoverPainter getPainter() { - return painter; - } - - /** - * 是否能在指定位置添加组件 - * @param creator 组件 - * @param x 坐标x - * @param y 坐标y - * @return 能则返回true - */ - //这个地方的逻辑非常复杂, - // 1.当前绝对布局是不可编辑且是最外层,那么其他控件添加在它周围, - // 2.当前绝对布局是不可编辑且不是最外层,那么控件不可添加,(嵌套) - // 3.当前绝对布局可编辑,那么控件添加 - @Override - public boolean accept(XCreator creator, int x, int y) { - Component comp = container.getComponentAt(x, y); - //布局控件要先判断是不是可编辑 - //可以编辑,按原有逻辑判断 - //不可编辑,当成一整个控件处理 - if (comp == null){ - return false; - } - //参数面板内的组件不允许拖往绝对布局中 - if (creator.getParent() != null && ((XCreator)creator.getParent()).acceptType(XWParameterLayout.class)){ - Rectangle rec = creator.getBounds(); - rec.y = creator.getParent().getHeight() - rec.height; - creator.setBounds(rec); - return false; - } - //判断下组件能不能拖入绝对布局 - if (!creator.canEnterIntoAbsolutePane()){ - return false; - } - XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator)comp).getTopLayout(); - if(topLayout != null){ - if (topLayout.isEditable()){ - return topLayoutAccept(creator, x, y, topLayout); - } - //绝对布局嵌套,处于内层,不可编辑,不添加,topLayout只能获取到最外层可编辑的布局 - else if (((XLayoutContainer)topLayout.getParent()).acceptType(XWAbsoluteLayout.class)) { - return false; - } - else { - return acceptWidget(creator, x, y); - } - } - else{ - FRLogger.getLogger().error("top layout is null!"); - } - - return false; - } - - //toplayout假如可以编辑的话就往里面添加组件 - private boolean topLayoutAccept(XCreator creator, int x, int y, XLayoutContainer topLayout) { - //判断有没有和当前控件重叠 - //先计算当前控件的位置 - int creatorX, creatorY; - if (XCreatorUtils.getParentXLayoutContainer(creator) != null) { - - Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator); - creatorX = creatorRectangle.x; - creatorY = creatorRectangle.y; - } else { - int w = creator.getWidth() / 2; - int h = creator.getHeight() / 2; - creatorX = x - w; - creatorY = y - h; - } - //再判断和布局中其他控件重叠 - Rectangle curRec = new Rectangle(creatorX, creatorY, creator.getWidth(), creator.getHeight()); - WAbsoluteLayout wAbsoluteLayout = (WAbsoluteLayout)topLayout.toData(); - for (int i = 0, count = wAbsoluteLayout.getWidgetCount(); i < count; i++) { - BoundsWidget temp = (BoundsWidget) wAbsoluteLayout.getWidget(i); - Rectangle rectangle = temp.getBounds(); - if (curRec.intersects(rectangle)){ - return false; - } - } - if (creatorX < 0 || creatorX + creator.getWidth() > container.getWidth()) { - return false; - } - if (creatorY < 0 || creatorY + creator.getHeight() > container.getHeight()){ - return false; - } - return x >= 0 && y >= 0 && creator.getHeight() <= container.getHeight() - && creator.getWidth() <= container.getWidth(); - } - - /** - * 判断是否鼠标在组件的三等分区域,如果组件在布局管理器中间,上下左右都可能会三等分 - * @param parentComp 鼠标所在区域的组件 - * @param x 坐标x - * @param y 坐标y - * @return 是则返回true - */ - public boolean isTrisectionArea(Component parentComp, int x, int y) { - XCreator creator = (XCreator)parentComp; - trisectAreaDirect = 0; - if (container.getComponentCount()<=1) { - return false; - } - int maxWidth = parentComp.getWidth(); - int maxHeight = parentComp.getHeight(); - int xL = parentComp.getX(); - int yL = parentComp.getY(); - // 组件宽高的十分之一和默认值取大 - int minRangeWidth = Math.max(maxWidth/BORDER_PROPORTION, DEFAULT_AREA_LENGTH); - int minRangeHeight = Math.max(maxHeight/BORDER_PROPORTION, DEFAULT_AREA_LENGTH); - if(yyL+maxHeight-minRangeHeight) { - // 在组件下侧三等分 - trisectAreaDirect = COMP_BOTTOM; - } else if (xxL+maxWidth-minRangeWidth) { - // 在组件右侧三等分 - trisectAreaDirect = COMP_RIGHT; - } - // tab布局的边界特殊处理,不进行三等分 - if(!creator.getTargetChildrenList().isEmpty()){ - return false; - } - - return !ComparatorUtils.equals(trisectAreaDirect, 0); - } - - //当前绝对布局不可编辑,就当成一个控件,组件添加在周围 - private boolean acceptWidget(XCreator creator, int x, int y){ - isFindRelatedComps = false; - //拖入组件判断时,先判断是否为交叉点区域,其次三等分区域,再次平分区域 - Component comp = container.getComponentAt(x, y); - boolean isMatchEdge = false; - //如果当前处于边缘地带, 那么就把他贴到父容器上 - XLayoutContainer parent = container.findNearestFit(); - container = parent != null ? parent : container; - isAdd2ParentLayout = true; - - int componentHeight = comp.getHeight(); - int componentWidth = comp.getWidth(); - //上半部分高度 - int upHeight = (int) (componentHeight * TOP_HALF) + comp.getY(); - //下半部分高度 - int downHeight = (int) (componentHeight * BOTTOM_HALF) + comp.getY(); - - if (isCrossPointArea(comp, x, y)) { - return canAcceptWhileCrossPoint(comp, x, y); - } - - if (isTrisectionArea(comp, x, y)) { - return canAcceptWhileTrisection(comp, x, y); - } - - boolean horizonValid = componentWidth >= minWidth * 2 + actualVal; - boolean verticalValid = componentHeight >= minHeight * 2 + actualVal; - return y > upHeight && y < downHeight ? horizonValid : verticalValid; - } - - /** - * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 - * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 - * - * @param creator 被添加的新组件 - * @param x 添加的位置x,该位置是相对于container的 - * @param y 添加的位置y,该位置是相对于container的 - * @return 是否添加成功,成功返回true,否则false - */ - @Override - public boolean addBean(XCreator creator, int x, int y) { - Rectangle rect = ComponentUtils.getRelativeBounds(container); - - int posX = x + rect.x; - int posY = y + rect.y; - if (!accept(creator, x, y)) { - return false; - } - addComp(creator, posX, posY); - ((XWidgetCreator) creator).recalculateChildrenSize(); - return true; - } - - @Override - protected void addComp(XCreator creator, int x, int y) { - if(!isAdd2ParentLayout) { - Rectangle r = ComponentUtils.getRelativeBounds(container); - x = x - r.x; - y = y - r.y; - if (XCreatorUtils.getParentXLayoutContainer(creator) != null) { - - Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator); - x = creatorRectangle.x - r.x; - y = creatorRectangle.y - r.y; - } else { - int w = creator.getWidth() / 2; - int h = creator.getHeight() / 2; - x = x - w; - y = y - h; - } - fix(creator, x, y); - - if (creator.hasTitleStyle()) { - addParentCreator(creator); - } else { - container.add(creator, creator.toData().getWidgetName()); - } - XWAbsoluteLayout layout = (XWAbsoluteLayout) container; - layout.updateBoundsWidget(creator); - updateCreatorBackBound(); - LayoutUtils.layoutRootContainer(container); - }else{ - fixAbsolute(creator, x, y); - if (creator.shouldScaleCreator() || creator.hasTitleStyle()) { - addParentCreator(creator); - } else { - container.add(creator, creator.toData().getWidgetName()); - } - XWFitLayout layout = (XWFitLayout) container; - // 更新对应的BoundsWidget - layout.updateBoundsWidget(); - updateCreatorBackBound(); - } - } - - private void updateCreatorBackBound() { - for (int i=0,size=container.getComponentCount(); i container.getWidth()) { - width = container.getWidth() - x; - } - - if (y < 0) { - height += y; - y = 0; - } else if (y + creator.getHeight() > container.getHeight()) { - height = container.getHeight() - y; - } - - creator.setBounds(x, y, width, height); - } - - @Override - public ConstraintsGroupModel getLayoutConstraints(XCreator creator) { - return new BoundsGroupModel((XWAbsoluteLayout)container, creator); - } - - @Override - public GroupModel getLayoutProperties() { - XWAbsoluteLayout xwAbsoluteLayout = (XWAbsoluteLayout) container; - return new FRAbsoluteLayoutPropertiesGroupModel(xwAbsoluteLayout); - } +package com.fr.design.designer.beans.adapters.layout; + +import com.fr.design.beans.GroupModel; +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.*; +import com.fr.design.designer.properties.BoundsGroupModel; +import com.fr.design.designer.properties.FRAbsoluteLayoutPropertiesGroupModel; +import com.fr.design.utils.ComponentUtils; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.form.ui.container.WAbsoluteLayout; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; + +import java.awt.*; + +public class FRAbsoluteLayoutAdapter extends FRBodyLayoutAdapter { + //是不是添加到父容器上 + private boolean isAdd2ParentLayout = false; + private HoverPainter painter; + + public FRAbsoluteLayoutAdapter(XLayoutContainer container) { + super(container); + painter = new FRAbsoluteLayoutPainter(container); + initMinSize(); + } + + private void initMinSize() { + XWAbsoluteLayout layout = (XWAbsoluteLayout) container; + minWidth = layout.getActualMinWidth(); + minHeight = layout.getActualMinHeight(); + actualVal = layout.getAcualInterval(); + margin = layout.toData().getMargin(); + } + + @Override + public HoverPainter getPainter() { + return painter; + } + + /** + * 是否能在指定位置添加组件 + * + * @param creator 组件 + * @param x 坐标x + * @param y 坐标y + * @return 能则返回true + */ + //这个地方的逻辑非常复杂, + // 1.当前绝对布局是不可编辑且是最外层,那么其他控件添加在它周围, + // 2.当前绝对布局是不可编辑且不是最外层,那么控件不可添加,(嵌套) + // 3.当前绝对布局可编辑,那么控件添加 + @Override + public boolean accept(XCreator creator, int x, int y) { + Component comp = container.getComponentAt(x, y); + //布局控件要先判断是不是可编辑 + //可以编辑,按原有逻辑判断 + //不可编辑,当成一整个控件处理 + if (comp == null) { + return false; + } + //参数面板内的组件不允许拖往绝对布局中 + if (creator.getParent() != null && ((XCreator) creator.getParent()).acceptType(XWParameterLayout.class)) { + Rectangle rec = creator.getBounds(); + rec.y = creator.getParent().getHeight() - rec.height; + creator.setBounds(rec); + return false; + } + //判断组件能不能拖入绝对布局 + if (!creator.canEnterIntoAbsolutePane()) { + return false; + } + XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator) comp).getTopLayout(); + if (topLayout != null) { + if (topLayout.isEditable()) { + return topLayoutAccept(creator, x, y); + } + //绝对布局嵌套,处于内层,不可编辑,不添加,topLayout只能获取到最外层可编辑的布局 + else if (((XLayoutContainer) topLayout.getParent()).acceptType(XWAbsoluteLayout.class)) { + return false; + } else { + return acceptWidget(x, y); + } + } else { + FRLogger.getLogger().error("top layout is null!"); + } + + return false; + } + + //topLayout假如可以编辑的话就往里面添加组件 + private boolean topLayoutAccept(XCreator creator, int x, int y) { + //允许组件重叠,可以不判断有没有和当前控件重叠 + //先计算当前控件的位置 + int creatorX, creatorY; + if (XCreatorUtils.getParentXLayoutContainer(creator) != null) { + Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator); + creatorX = creatorRectangle.x; + creatorY = creatorRectangle.y; + } else { + //这边计算得到的组件其实位置是正确的, + //因为传入的x和y已经加上了宽度或者高度的一半,再减去相同的宽度和高度的一半是没区别的, + // 例如高度为21,那么就是+10-10; + // 高度为20,那么就是+10-10; 没区别 + int w = creator.getWidth() / 2; + int h = creator.getHeight() / 2; + creatorX = x - w; + creatorY = y - h; + } + if (creatorX < 0 || creatorX + creator.getWidth() > container.getWidth()) { + return false; + } + if (creatorY < 0 || creatorY + creator.getHeight() > container.getHeight()) { + return false; + } + return x >= 0 && y >= 0 && creator.getHeight() <= container.getHeight() + && creator.getWidth() <= container.getWidth(); + } + + /** + * 判断是否鼠标在组件的三等分区域,如果组件在布局管理器中间,上下左右都可能会三等分 + * + * @param parentComp 鼠标所在区域的组件 + * @param x 坐标x + * @param y 坐标y + * @return 是则返回true + */ + public boolean isTrisectionArea(Component parentComp, int x, int y) { + XCreator creator = (XCreator) parentComp; + trisectAreaDirect = 0; + if (container.getComponentCount() <= 1) { + return false; + } + int maxWidth = parentComp.getWidth(); + int maxHeight = parentComp.getHeight(); + int xL = parentComp.getX(); + int yL = parentComp.getY(); + // 组件宽高的十分之一和默认值取大 + int minRangeWidth = Math.max(maxWidth / BORDER_PROPORTION, DEFAULT_AREA_LENGTH); + int minRangeHeight = Math.max(maxHeight / BORDER_PROPORTION, DEFAULT_AREA_LENGTH); + if (y < yL + minRangeHeight) { + // 在组件上侧三等分 + trisectAreaDirect = COMP_TOP; + } else if (y > yL + maxHeight - minRangeHeight) { + // 在组件下侧三等分 + trisectAreaDirect = COMP_BOTTOM; + } else if (x < xL + minRangeWidth) { + // 在组件左侧三等分 + trisectAreaDirect = COMP_LEFT; + } else if (x > xL + maxWidth - minRangeWidth) { + // 在组件右侧三等分 + trisectAreaDirect = COMP_RIGHT; + } + // tab布局的边界特殊处理,不进行三等分 + if (!creator.getTargetChildrenList().isEmpty()) { + return false; + } + + return !ComparatorUtils.equals(trisectAreaDirect, 0); + } + + //当前绝对布局不可编辑,就当成一个控件,组件添加在周围 + private boolean acceptWidget(int x, int y) { + isFindRelatedComps = false; + //拖入组件判断时,先判断是否为交叉点区域,其次三等分区域,再次平分区域 + Component comp = container.getComponentAt(x, y); + //如果当前处于边缘地带, 那么就把他贴到父容器上 + XLayoutContainer parent = container.findNearestFit(); + container = parent != null ? parent : container; + isAdd2ParentLayout = true; + + int componentHeight = comp.getHeight(); + int componentWidth = comp.getWidth(); + //上半部分高度 + int upHeight = (int) (componentHeight * TOP_HALF) + comp.getY(); + //下半部分高度 + int downHeight = (int) (componentHeight * BOTTOM_HALF) + comp.getY(); + + if (isCrossPointArea(comp, x, y)) { + return canAcceptWhileCrossPoint(comp, x, y); + } + + if (isTrisectionArea(comp, x, y)) { + return canAcceptWhileTrisection(comp, x, y); + } + + boolean horizonValid = componentWidth >= minWidth * 2 + actualVal; + boolean verticalValid = componentHeight >= minHeight * 2 + actualVal; + return y > upHeight && y < downHeight ? horizonValid : verticalValid; + } + + /** + * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 + * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 + * + * @param creator 被添加的新组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否添加成功,成功返回true,否则false + */ + @Override + public boolean addBean(XCreator creator, int x, int y) { + Rectangle rect = ComponentUtils.getRelativeBounds(container); + + int posX = x + rect.x; + int posY = y + rect.y; + if (!accept(creator, x, y)) { + return false; + } + addComp(creator, posX, posY); + ((XWidgetCreator) creator).recalculateChildrenSize(); + return true; + } + + @Override + protected void addComp(XCreator creator, int x, int y) { + if (!isAdd2ParentLayout) { + Rectangle r = ComponentUtils.getRelativeBounds(container); + x = x - r.x; + y = y - r.y; + if (XCreatorUtils.getParentXLayoutContainer(creator) != null) { + + Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator); + x = creatorRectangle.x - r.x; + y = creatorRectangle.y - r.y; + } else { + int w = creator.getWidth() / 2; + int h = creator.getHeight() / 2; + x = x - w; + y = y - h; + } + fix(creator, x, y); + + if (creator.hasTitleStyle()) { + addParentCreator(creator); + } else { + container.add(creator, creator.toData().getWidgetName()); + } + XWAbsoluteLayout layout = (XWAbsoluteLayout) container; + layout.updateBoundsWidget(creator); + updateCreatorBackBound(); + LayoutUtils.layoutRootContainer(container); + } else { + fixAbsolute(creator, x, y); + if (creator.shouldScaleCreator() || creator.hasTitleStyle()) { + addParentCreator(creator); + } else { + container.add(creator, creator.toData().getWidgetName()); + } + XWFitLayout layout = (XWFitLayout) container; + // 更新对应的BoundsWidget + layout.updateBoundsWidget(); + updateCreatorBackBound(); + } + } + + private void updateCreatorBackBound() { + for (int i = 0, size = container.getComponentCount(); i < size; i++) { + XCreator creator = (XCreator) container.getComponent(i); + creator.updateChildBound(minHeight); + creator.setBackupBound(creator.getBounds()); + } + } + + private void addParentCreator(XCreator child) { + XLayoutContainer parentPanel = child.initCreatorWrapper(child.getHeight()); + container.add(parentPanel, child.toData().getWidgetName()); + } + + /** + * 新拖入组件时,计算调整其他关联组件位置大小 + * + * @param child 新拖入的组件 + * @param x 鼠标所在x坐标 + * @param y 鼠标所在y坐标 + */ + private void fixAbsolute(XCreator child, int x, int y) { + Component parentComp = container.getComponentAt(x, y); + if (container.getComponentCount() == 0) { + child.setLocation(0, 0); + child.setSize(parentComp.getWidth(), parentComp.getHeight()); + } else if (isCrossPointArea(parentComp, x, y)) { + //交叉区域插入组件时,根据具体位置进行上下或者左右或者相邻三个组件的位置大小插入 + fixCrossPointArea(parentComp, child, x, y); + //TODO 尽量不要出现这种写法吧?if else条件要么互斥,要么多个if判断return,不要在一条if else语句里面return吧? + return; + } else if (isTrisectionArea(parentComp, x, y)) { + // 在边界三等分区域,就不再和组件二等分了 + fixTrisect(parentComp, child, x, y); + return; + } else { + fixHalve(parentComp, child, x, y); + } + } + + /** + * 组件拖拽后调整大小 + * + * @param creator 组件 + */ + @Override + public void fix(XCreator creator) { + WAbsoluteLayout wabs = (WAbsoluteLayout) container.toData(); + fix(creator, creator.getX(), creator.getY()); + wabs.setBounds(creator.toData(), creator.getBounds()); + + XWAbsoluteLayout layout = (XWAbsoluteLayout) container; + layout.updateBoundsWidget(creator); + } + + /** + * 调整组件大小到合适尺寸位置 + * + * @param creator 组件 + * @param x 坐标x + * @param y 坐标y + */ + public void fix(XCreator creator, int x, int y) { + int height = creator.getHeight(); + int width = creator.getWidth(); + if (x < 0) { + width += x; + x = 0; + } else if (x + creator.getWidth() > container.getWidth()) { + width = container.getWidth() - x; + } + + if (y < 0) { + height += y; + y = 0; + } else if (y + creator.getHeight() > container.getHeight()) { + height = container.getHeight() - y; + } + + creator.setBounds(x, y, width, height); + } + + @Override + public ConstraintsGroupModel getLayoutConstraints(XCreator creator) { + return new BoundsGroupModel((XWAbsoluteLayout) container, creator); + } + + @Override + public GroupModel getLayoutProperties() { + XWAbsoluteLayout xwAbsoluteLayout = (XWAbsoluteLayout) container; + return new FRAbsoluteLayoutPropertiesGroupModel(xwAbsoluteLayout); + } } \ No newline at end of file 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 f578b28ab..e31ee6a5d 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 @@ -1,1198 +1,1189 @@ -/** - * - */ -package com.fr.design.designer.beans.adapters.layout; - -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; - -import com.fr.design.beans.GroupModel; -import com.fr.design.designer.beans.ConstraintsGroupModel; -import com.fr.design.designer.beans.HoverPainter; -import com.fr.design.designer.beans.painters.FRFitLayoutPainter; -import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWFitLayout; -import com.fr.design.designer.creator.cardlayout.XWCardLayout; -import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; -import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; -import com.fr.design.designer.properties.FRFitLayoutConstraints; -import com.fr.design.designer.properties.FRFitLayoutPropertiesGroupModel; -import com.fr.design.file.HistoryTemplateListPane; -import com.fr.design.mainframe.JForm; -import com.fr.design.utils.ComponentUtils; -import com.fr.form.ui.LayoutBorderStyle; -import com.fr.form.ui.container.WLayout; -import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; -import com.fr.form.ui.widget.BoundsWidget; -import com.fr.general.ComparatorUtils; - -/** - * 自适应布局的容器适配器 - * - * @author jim - * @date 2014-6-24 - */ -public class FRFitLayoutAdapter extends FRBodyLayoutAdapter { - - public static final String WIDGETPANEICONPATH = "/com/fr/web/images/form/resources/layout_absolute.png"; - private static final int DEPENDING_SCOPE = 3; - private HoverPainter painter; - //区分拖拽和编辑宽高 - private boolean isEdit; - - public boolean isEdit() { - return isEdit; - } - - public void setEdit(boolean edit) { - isEdit = edit; - } - /** - * 构造函数 - * - * @param container XWFitLayout容器 - */ - public FRFitLayoutAdapter(XLayoutContainer container) { - super(container); - painter = new FRFitLayoutPainter(container); - initMinSize(); - } - - private void initMinSize() { - XWFitLayout layout = (XWFitLayout) container; - minWidth = layout.getActualMinWidth(); - minHeight = layout.getActualMinHeight(); - actualVal = layout.getAcualInterval(); - margin = layout.toData().getMargin(); - } - - @Override - public HoverPainter getPainter() { - return painter; - } - - /** - * 返回布局自身属性,方便一些特有设置在layout刷新时处理 - */ - @Override - public GroupModel getLayoutProperties() { - XWFitLayout xfl = (XWFitLayout) container; - return new FRFitLayoutPropertiesGroupModel(xfl); - } - - /** - * 添加组件 - * - * @param child 待添加的组件 - * @param x 坐标x - * @param y 坐标y - */ - @Override - public void addComp(XCreator child, int x, int y) { - fix(child, x, y); - if (child.shouldScaleCreator() || child.hasTitleStyle()) { - addParentCreator(child); - } else { - container.add(child, child.toData().getWidgetName()); - } - XWFitLayout layout = (XWFitLayout) container; - // 更新对应的BoundsWidget - layout.updateBoundsWidget(); - updateCreatorBackBound(); - } - - public void updateCreatorBackBound() { - for (int i = 0, size = container.getComponentCount(); i < size; i++) { - XCreator creator = (XCreator) container.getComponent(i); - creator.updateChildBound(minHeight); - creator.setBackupBound(creator.getBounds()); - } - } - - - private void addParentCreator(XCreator child) { - XLayoutContainer parentPanel = child.initCreatorWrapper(minHeight); - container.add(parentPanel, child.toData().getWidgetName()); - } - - /** - * 能否对应位置放置当前组件 - * - * @param creator 组件 - * @param x 添加的位置x,该位置是相对于container的 - * @param y 添加的位置y,该位置是相对于container的 - * @return 是否可以放置 - */ - @Override - public boolean accept(XCreator creator, int x, int y) { - // 计算是否能拖入鼠标区域时,会用到fix 的方法 - isFindRelatedComps = false; - //拖入组件判断时,先判断是否为交叉点区域,其次三等分区域,再次平分区域 - Component comp = container.getComponentAt(x, y); - if (checkInterval(comp)) { - return false; - } - //如果当前处于边缘地带, 那么就把他贴到父容器上 - boolean isMatchEdge = matchEdge(x, y); - - int componentHeight = comp.getHeight(); - int componentWidth = comp.getWidth(); - //上半部分高度 - int upHeight = (int) (componentHeight * TOP_HALF) + comp.getY(); - //下半部分高度 - int downHeight = (int) (componentHeight * BOTTOM_HALF) + comp.getY(); - - //布局控件要先判断是不是可编辑 - XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator) comp).getTopLayout(); - if (topLayout != null && !isMatchEdge && !topLayout.isEditable()) { - return false; - } - - if (isCrossPointArea(comp, x, y)) { - return canAcceptWhileCrossPoint(comp, x, y); - } - - if (isTrisectionArea(comp, x, y)) { - return canAcceptWhileTrisection(comp, x, y); - } - - boolean horizonValid = componentWidth >= minWidth * 2 + actualVal; - boolean verticalValid = componentHeight >= minHeight * 2 + actualVal; - return y > upHeight && y < downHeight ? horizonValid : verticalValid; - } - - // 间隔区域 - private boolean checkInterval(Component comp) { - return container.getComponentCount() > 0 && comp == container; - } - - /** - * 是否在组件边缘 - * - * @param x 横坐标 - * @param y 纵坐标 - * @return 是否在组件边缘 - */ - public boolean matchEdge(int x, int y) { - if (intersectsEdge(x, y, container)) { - //寻找最近的fit, 在边缘地段添加的控件, 将其送给该fit - XLayoutContainer parent = container.findNearestFit(); - container = parent != null ? parent : container; - return true; - } - return false; - } - - /** - * 是否在组件边缘 - * - * @param x 横坐标 - * @param y 纵坐标 - * @param container 参照组件 - * @return 是否在组件边缘 - */ - //是否包含于边缘地段, 按顺序上, 下, 左, 右检测 - public boolean intersectsEdge(int x, int y, XLayoutContainer container) { - int containerX = container.getX(); - int containerY = container.getY(); - int containerWidth = container.getWidth(); - int containerHeight = container.getHeight(); - - // 当前坐标点 - Rectangle currentXY = new Rectangle(x, y, 1, 1); - // 上边缘 - Rectangle upEdge = new Rectangle(containerX, containerY, containerWidth, BORDER_PROPORTION); - if (upEdge.intersects(currentXY)) { - return true; - } - - int bottomY = containerY + containerHeight - BORDER_PROPORTION; - // 下边缘 - Rectangle bottomEdge = new Rectangle(containerX, bottomY, containerWidth, BORDER_PROPORTION); - if (bottomEdge.intersects(currentXY)) { - return true; - } - - //左右边缘的高度 -10*2 是为了不和上下边缘重合 - int verticalHeight = containerHeight - BORDER_PROPORTION * 2; - int leftY = containerY + BORDER_PROPORTION; - // 左边缘 - Rectangle leftEdge = new Rectangle(containerX, leftY, BORDER_PROPORTION, verticalHeight); - if (leftEdge.intersects(currentXY)) { - return true; - } - - int rightY = containerY + BORDER_PROPORTION; - int rightX = containerX + containerWidth - BORDER_PROPORTION; - // 右边缘 - Rectangle rightEdge = new Rectangle(rightX, rightY, BORDER_PROPORTION, verticalHeight); - return rightEdge.intersects(currentXY); - } - - /** - * 交叉点区域时,能否对应位置放入组件 - */ - protected boolean canAcceptWhileCrossPoint(Component comp, int x, int y) { - return super.canAcceptWhileCrossPoint(comp, x, y); - } - - protected boolean canAcceptWhileTrisection(Component comp, int x, int y) { - return super.canAcceptWhileTrisection(comp, x, y); - } - - /** - * 判断是否鼠标在组件的三等分区域,如果组件在布局管理器中间,上下左右都可能会三等分 - * - * @param parentComp 鼠标所在区域的组件 - * @param x 坐标x - * @param y 坐标y - * @return 是则返回true - */ - public boolean isTrisectionArea(Component parentComp, int x, int y) { - return super.isTrisectionArea(parentComp, x, y); - } - - /** - * 是否为组件交叉点区域 或者是相邻三组建中间点 - * - * @param currentComp 当前组件 - * @param x 坐标x - * @param y 坐标y - * @return 是则返回true - */ - public boolean isCrossPointArea(Component currentComp, int x, int y) { - return super.isCrossPointArea(currentComp, x, y); - } - - protected void initCompsList() { - super.initCompsList(); - } - - protected void clearCompsList() { - super.clearCompsList(); - } - - protected Rectangle getLayoutBound(XWCardMainBorderLayout mainLayout){ - return mainLayout.getBounds(); - } - - private Rectangle adjustBackupBound(Rectangle backupBound, XWCardMainBorderLayout mainLayout) { - // 参数界面高度对纵坐标产生的影响 - JForm jform = (JForm) (HistoryTemplateListPane.getInstance().getCurrentEditingTemplate()); - if (jform.getFormDesign().getParaComponent() != null) { - backupBound.y -= jform.getFormDesign().getParaHeight(); - } - - Rectangle rec = getLayoutBound(mainLayout); - // XWTabLayout里面的横纵坐标收到外层XWCardMainBorderLayout的横纵坐标影响 - // 减掉之后可以按照它原来的逻辑执行 - backupBound.x -= rec.x; - backupBound.y -= rec.y; - XWCardLayout cardLayout = mainLayout.getCardPart(); - LayoutBorderStyle style = cardLayout.toData().getBorderStyle(); - // 当tab布局为标题样式时,才需要处理标题栏高度产生的影响 - if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) { - backupBound.y -= WCardMainBorderLayout.TAB_HEIGHT; - } - return backupBound; - } - - /** - * 拖拽控件边框后,根据控件的大小尺寸,进行相关组件的调整 - * - * @param creator 组件 - */ - @Override - public void fix(XCreator creator) { - //拖拽组件原大小、位置 - Rectangle backupBound = creator.getBackupBound(); - backupBound.x -= container.getX(); - backupBound.y -= container.getY(); - //当前拖拽组件的位置 - int x = creator.getX(); - int y = creator.getY(); - - // 获取容器所有内部组件横坐标 - int[] posXs = container.getHors(); - // 获取容器所有内部组件纵坐标 - int[] posYs = container.getVeris(); - - XLayoutContainer outerLayout = container.getOuterLayout(); - if (!ComparatorUtils.equals(outerLayout, container.getBackupParent())) { - XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout) outerLayout; - backupBound = adjustBackupBound(backupBound, mainLayout); - } - - //拖拽组件拖拽以后的大小 - int w = creator.getWidth(); - int h = creator.getHeight(); - initCompsList(); - creator.setBounds(backupBound); - int difference = 0; - if (x != backupBound.x) { - dealLeft(backupBound, x, posXs, difference, creator); - } else if (w != backupBound.width) { - dealRight(backupBound, x, w, posXs, difference, creator); - } else if (y != backupBound.y) { - dealTop(backupBound, y, posYs, difference, creator); - } else if (h != backupBound.height) { - dealButtom(backupBound, y, h, posYs, difference, creator); - } - clearCompsList(); - XWFitLayout layout = (XWFitLayout) container; - layout.updateBoundsWidget(); // 更新对应的BoundsWidget - updateCreatorBackBound(); - } - - /** - * 拖拽控件边框后,根据控件的大小尺寸,进行相关组件的调整 - * - * @param backupBound 边界备份 - * @param bounds 组件边界 - * @param xCreator 组件 - * @param row 选中的行 - * @param difference 偏移量 - */ - public void calculateBounds(Rectangle backupBound, Rectangle bounds, XCreator xCreator, int row, int difference) { - Rectangle rc = new Rectangle(0,0,0,0); - XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xCreator); - if (parent != null) { - Rectangle rec = ComponentUtils.getRelativeBounds(parent); - rc.x = rec.x; - rc.y = rec.y; - } - int x = backupBound.x - rc.x, y = backupBound.y - rc.y; - //处理左右延伸 - switch (row) { - case 0: - if (backupBound.width + backupBound.x == container.getWidth() - margin.getRight() +rc.x) { - x += difference; - } - break; - case 1: - if(backupBound.y + backupBound.height == container.getHeight() - margin.getBottom() +rc.y){ - y += difference; - } - break; - } - bounds.setLocation(x,y); - xCreator.setBackupBound(backupBound); - xCreator.setBounds(bounds); - this.fix(xCreator); - } - - private void dealLeft(Rectangle backupBound, int x, int[] posXs, int difference, XCreator creator) { - if (backupBound.x == margin.getLeft()) { - return; - } - x = adjustCoordinateByDependingLine(x, posXs); - difference = x - backupBound.x; - dealDirectionAtLeft(backupBound, difference, creator); - } - - private void dealRight(Rectangle backupBound, int x, int w, int[] posXs, int difference, XCreator creator) { - if (backupBound.width + backupBound.x == container.getWidth() - margin.getRight()) { - return; - } - w = adjustDiffByDependingLine(x, posXs, w); - difference = w - backupBound.width; //拖拽长度 - dealDirectionAtRight(backupBound, difference, creator); - } - - private void dealTop(Rectangle backupBound, int y, int[] posYs, int difference, XCreator creator) { - if (backupBound.y == margin.getTop()) { - return; - } - y = adjustCoordinateByDependingLine(y, posYs); - difference = y - backupBound.y; - dealDirectionAtTop(backupBound, difference, creator); - } - - private void dealButtom(Rectangle backupBound, int y, int h, int[] posYs, int difference, XCreator creator) { - if (backupBound.y + backupBound.height == container.getHeight() - margin.getBottom()) { - return; - } - h = adjustDiffByDependingLine(y, posYs, h); - difference = h - backupBound.height; - dealDirectionABottom(backupBound, difference, creator); - } - - // 根据需要依附的位置调整拖拽的坐标值 - private int adjustCoordinateByDependingLine(int coordinate, int[] coordinates) { - if(!isEdit) { - for (int i = 0; i < coordinates.length; i++) { - if (coordinate == coordinates[i]) { - continue; - } - if (coordinate > coordinates[i] - DEPENDING_SCOPE && coordinate < coordinates[i] + DEPENDING_SCOPE) { - coordinate = coordinates[i]; - break; - } - } - } - return coordinate; - } - - // 根据需要依附的位置调整拖拽的距离 - private int adjustDiffByDependingLine(int coordinate, int[] coordinates, int diff) { - if(!isEdit) { - for (int i = 0; i < coordinates.length; i++) { - if (coordinate + diff > coordinates[i] - DEPENDING_SCOPE && coordinate + diff < coordinates[i] + DEPENDING_SCOPE) { - diff = coordinates[i] - coordinate; - break; - } - } - } - return diff; - } - - // 左侧边框拉伸,循环找出对齐的两侧控件 - private void dealDirectionAtLeft(Rectangle backupBound, int difference, Component creator) { - rightComps.add(creator); - Component rightComp = null; - int leftx = backupBound.x - DEFAULT_AREA_LENGTH - actualVal; - // 取左侧边框右面的组件x值 - int rightx = backupBound.x + DEFAULT_AREA_LENGTH; - Component leftComp = container.getLeftComp(backupBound.x, backupBound.y); - leftComps.add(leftComp); - //先找上侧对齐时(y相等)的左右两边组件 - int ry = backupBound.y; - int ly = leftComp.getY(); - int min = margin.getTop(); - int max = container.getHeight() - margin.getBottom(); - while (ry >= min && ly >= min) { - if (ry == ly) { - break; - } else { - if (ry > ly) { - rightComp = container.getTopComp(rightx, ry); - ry = rightComp.getY(); - rightComps.add(rightComp); - } else { - leftComp = container.getTopComp(leftx, ly); - ly = leftComp.getY(); - leftComps.add(leftComp); - } - } - } - // 下侧对齐时(y+h相等)两边组件 - ry = backupBound.y + backupBound.height; - ly = leftComps.get(0).getY() + leftComps.get(0).getHeight(); - while (ry <= max && ly <= max) { - if (ry == ly) { - break; - } else { - if (ry > ly) { - leftComp = container.getComponentAt(leftx, ly + DEFAULT_AREA_LENGTH + actualVal); - ly = leftComp.getY() + leftComp.getHeight(); - leftComps.add(leftComp); - } else { - rightComp = container.getComponentAt(rightx, ry + DEFAULT_AREA_LENGTH + actualVal); - ry = rightComp.getY() + rightComp.getHeight(); - rightComps.add(rightComp); - } - } - } - dealHorDirection(backupBound.x, difference); - } - - // 右侧边框拉伸,循环找出对齐的两侧控件 - private void dealDirectionAtRight(Rectangle backupBound, int difference, Component creator) { - leftComps.add(creator); - Component leftComp = null; - int leftx = backupBound.x + backupBound.width - DEFAULT_AREA_LENGTH; - // 取右侧边框右面的组件x值 - int rightx = backupBound.x + backupBound.width + DEFAULT_AREA_LENGTH + actualVal; - Component rightComp = container.getRightComp(backupBound.x, backupBound.y, backupBound.width); - rightComps.add(rightComp); - int ly = backupBound.y, ry = rightComp.getY(); - int min = margin.getTop(); - int max = container.getHeight() - margin.getBottom(); - while (ry >= min && ly >= min) { - if (ry == ly) { - break; - } else { - if (ry > ly) { - rightComp = container.getTopComp(rightx, ry); - ry = rightComp.getY(); - rightComps.add(rightComp); - } else { - leftComp = container.getTopComp(leftx, ly); - ly = leftComp.getY(); - leftComps.add(leftComp); - } - } - } - ly = backupBound.y + backupBound.height; - ry = rightComps.get(0).getY() + rightComps.get(0).getHeight(); - while (ry <= max && ly <= max) { - if (ry == ly) { - break; - } else { - if (ry > ly) { - leftComp = container.getComponentAt(leftx, ly + DEFAULT_AREA_LENGTH + actualVal); - ly = leftComp.getY() + leftComp.getHeight(); - leftComps.add(leftComp); - } else { - rightComp = container.getComponentAt(rightx, ry + DEFAULT_AREA_LENGTH + actualVal); - ry = rightComp.getY() + rightComp.getHeight(); - rightComps.add(rightComp); - } - } - } - dealHorDirection(backupBound.x + backupBound.width + actualVal, difference); - } - - /** - * 水平方向上拉伸边框的处理 - */ - private void dealHorDirection(int objx, int difference) { - if (difference > 0) { - difference = Math.min(getMinWidth(rightComps) - minWidth, difference); - } else { - difference = Math.max(difference, minWidth - getMinWidth(leftComps)); - } - //重新计算左右两侧组件size、point - if (CalculateLefttRelatComponent(difference)) { - CalculateRightRelatComponent(objx + difference, -difference); - } - } - - // 上侧边框拉伸,循环找出对齐的两侧控件 - private void dealDirectionAtTop(Rectangle backupBound, int difference, Component creator) { - downComps.add(creator); - // 取上侧边框上面的组件用的y值 - int topy = backupBound.y - DEFAULT_AREA_LENGTH - actualVal; - // 上侧边框下面的组件y值 - int bottomy = backupBound.y + DEFAULT_AREA_LENGTH; - Component topComp = container.getTopComp(backupBound.x, backupBound.y); - upComps.add(topComp); - Component bottomComp = null; - int min = margin.getLeft(); - int max = container.getWidth() - margin.getRight(); - //先找左侧侧对齐时(x相等)的上下两边组件 - int ux = topComp.getX(); - int dx = backupBound.x; - while (ux >= min && dx >= min) { - if (ux == dx) { - break; - } else { - if (ux < dx) { - bottomComp = container.getLeftComp(dx, bottomy); - dx = bottomComp.getX(); - downComps.add(bottomComp); - } else { - topComp = container.getLeftComp(ux, topy); - ux = topComp.getX(); - upComps.add(topComp); - } - } - } - // 右侧对齐时(x+w相等)两边组件 - ux = upComps.get(0).getX() + upComps.get(0).getWidth(); - dx = backupBound.x + backupBound.width; - while (ux <= max && dx <= max) { - if (ux == dx) { - break; - } else { - if (ux < dx) { - topComp = container.getComponentAt(ux + DEFAULT_AREA_LENGTH + actualVal, topy); - ux = topComp.getX() + topComp.getWidth(); - upComps.add(topComp); - } else { - bottomComp = container.getComponentAt(dx + DEFAULT_AREA_LENGTH + actualVal, bottomy); - dx = bottomComp.getX() + bottomComp.getWidth(); - downComps.add(bottomComp); - } - } - } - - dealVertiDirection(backupBound.y, difference); - } - - // 下侧边框拉伸,循环找出对齐的两侧控件 - private void dealDirectionABottom(Rectangle backupBound, int difference, Component creator) { - upComps.add(creator); - Component topComp = null; - Component bottomComp = container.getBottomComp(backupBound.x, backupBound.y, backupBound.height); - // 下侧边框下面的组件y坐标 - int bottomy = backupBound.y + backupBound.height + DEFAULT_AREA_LENGTH + actualVal; - // 取下侧边框上面的组件用的y值 - int topy = backupBound.y + backupBound.height - DEFAULT_AREA_LENGTH; - downComps.add(bottomComp); - int dx = bottomComp.getX(); - int ux = backupBound.x; - int min = margin.getLeft(); - int max = container.getWidth() - margin.getRight(); - while (ux >= min && dx >= min) { - if (ux == dx) { - break; - } else { - if (ux < dx) { - bottomComp = container.getLeftComp(dx, bottomy); - dx = bottomComp.getX(); - downComps.add(bottomComp); - } else { - topComp = container.getLeftComp(ux, topy); - ux = topComp.getX(); - upComps.add(topComp); - } - } - } - dx = downComps.get(0).getX() + downComps.get(0).getWidth(); - ux = backupBound.x + backupBound.width; - while (ux <= max && dx <= max) { - if (ux == dx) { - break; - } else { - if (ux < dx) { - topComp = container.getComponentAt(ux + DEFAULT_AREA_LENGTH + actualVal, topy); - ux = topComp.getX() + topComp.getWidth(); - upComps.add(topComp); - } else { - bottomComp = container.getComponentAt(dx + DEFAULT_AREA_LENGTH + actualVal, bottomy); - dx = bottomComp.getX() + bottomComp.getWidth(); - downComps.add(bottomComp); - } - } - } - dealVertiDirection(backupBound.y + backupBound.height + actualVal, difference); - } - - /** - * 垂直方向上拉伸边框的处理 - */ - private void dealVertiDirection(int objY, int difference) { - if (difference > 0) { - difference = Math.min(getMinHeight(downComps) - minHeight, difference); - } else { - difference = Math.max(difference, minHeight - getMinHeight(upComps)); - } - //重新计算上下两侧组件size、point - if (CalculateUpRelatComponent(difference)) { - CalculateDownRelatComponent(objY + difference, -difference); - } - ; - } - - /** - * 新拖入组件时,计算调整其他关联组件位置大小 - * - * @param child 新拖入的组件 - * @param x 鼠标所在x坐标 - * @param y 鼠标所在y坐标 - */ - public void fix(XCreator child, int x, int y) { - Component parentComp = container.getComponentAt(x, y); - if (container.getComponentCount() == 0) { - child.setLocation(0, 0); - child.setSize(parentComp.getWidth(), parentComp.getHeight()); - } else if (isCrossPointArea(parentComp, x, y)) { - //交叉区域插入组件时,根据具体位置进行上下或者左右或者相邻三个组件的位置大小插入 - fixCrossPointArea(parentComp, child, x, y); - return; - } else if (isTrisectionArea(parentComp, x, y)) { - // 在边界三等分区域,就不再和组件二等分了 - fixTrisect(parentComp, child, x, y); - return; - } else { - fixHalve(parentComp, child, x, y); - } - } - - /** - * 平分,正常情况拖入组件时,按照上1/4区域、下1/4区域为上下平分,中左侧1/2区域、中右侧1/2区域为左右平分 - */ - protected void fixHalve(Component currentComp, XCreator child, int x, int y) { - super.fixHalve(currentComp, child, x, y); - } - - /** - * 组件交叉区域进行插入时,调整受到变动的其他组件,之前是交叉区域插入也按照三等分逻辑,后面测试中发现有bug,改为和bi一样的鼠标所在侧平分 - * 默认左上角、右下角区域是垂直方向插入组件 - * 右上角和左下角是水平方向插入组件,这样避免田字块时重复 - */ - protected void fixCrossPointArea(Component currentComp, XCreator child, int x, int y) { - super.fixCrossPointArea(currentComp, child, x, y); - } - - /** - * 三等分区域时,调整相关联的组件 - * - * @param currentComp 鼠标所在组件 - * @param child 待插入组件 - */ - protected void fixTrisect(Component currentComp, XCreator child, int x, int y) { - super.fixTrisect(currentComp, child, x, y); - } - - /** - * 删除组件或者重新拖动时,其它组件重新计算位置大小 - */ - protected void delete(XCreator creator, int creatorWidth, int creatorHeight) { - int x = creator.getX(); - int y = creator.getY(); - recalculateChildrenSize(x, y, creatorWidth, creatorHeight); - } - - /** - * 重新计算内部组件大小 - * - * @param x 坐标x - * @param y 坐标y - * @param creatorWidth 删除的组件之前所在布局的宽度 - * @param creatorHeight 删除的组件之前所在布局的高度 - */ - public void recalculateChildrenSize(int x, int y, int creatorWidth, int creatorHeight) { - if (container.getComponentCount() == 0) { - return; - } else { - initCompsList(); - int width = creatorWidth; - int height = creatorHeight; - calculateRelatedComponent(x, y, width, height); - if (!rightComps.isEmpty() && getAllHeight(rightComps) == height) { - CalculateRightRelatComponent(x, width + actualVal); - } else if (!leftComps.isEmpty() && getAllHeight(leftComps) == height) { - CalculateLefttRelatComponent(width + actualVal); - } else if (!downComps.isEmpty() && getAllWidth(downComps) == width) { - CalculateDownRelatComponent(y, height + actualVal); - } else if (!upComps.isEmpty() && getAllWidth(upComps) == width) { - CalculateUpRelatComponent(height + actualVal); - } else { - // 由于布局三等分的存在,可能会出现删除组件时,找不到关联的组件填充,此时特殊处理 - calculateNoRelatedComponent(x, y, width, height); - } - } - clearCompsList(); - } - - /** - * 四侧边框都没有对齐的,此时每侧有且只有一个方向不对齐 - * 比如右侧不对齐,那么必然右上或右下没对齐,不会同时不对齐,否则不会出现此情况 - * 正常删除是右左下上优先原则,这边目前只调整右侧以至填充完整, - * 右侧不对齐时的组件先上下微调,再向左侧填充。 - */ - private void calculateNoRelatedComponent(int x, int y, int width, int height) { - // 只有最后一个组件了,直接删除 - if (container.getComponentCount() <= 1) { - return; - } - // 删除当前组件时,由于没有刚好边框对齐的其他组件,这时候需要调整的组件 - Component rightComp = container.getRightComp(x, y, width); - if (rightComp == null) { - return; - } - - int ry = rightComp.getY(); - clearCompsList(); - initCompsList(); - Rectangle rec = new Rectangle(x, y, width, height); - if (ry != y) { - calculateNoRelatedWhileRightTop(rec, rightComp); - } else { - calculateNoRelatedWhileRightBott(rec, rightComp); - } - - } - - private void calculateNoRelatedWhileRightTop(Rectangle bound, Component rcomp) { - if (rcomp == null) { - return; - } - - int ry = rcomp.getY(); - int rh = rcomp.getHeight(); - int rw = rcomp.getWidth(); - int dh = bound.y - ry - actualVal; - // 没法缩小高度 - if (dh < minHeight) { - // 没法缩小时则拉伸rcomp的上边框 - dealDirectionAtTop(rcomp.getBounds(), dh + actualVal, rcomp); - //调整的时候可能有组件达到最小高度,判断下 - if (rcomp.getY() != bound.y) { - clearCompsList(); - initCompsList(); - dealDirectionAtTop(rcomp.getBounds(), bound.y - rcomp.getY() - minHeight - actualVal, rcomp); - ry = rcomp.getY(); - int rx = rcomp.getX(); - rcomp.setBounds(rx, ry, rw, minHeight); - recalculateChildrenSize(rx, bound.y, rw, rh - dh - actualVal); - recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); - return; - } - } else { - // 右侧控件底部对齐 - if (rh + ry == bound.y + bound.height) { - rcomp.setSize(rw, dh); - bound.width += rw; - bound.width += actualVal; - } else { - recalculateChildrenSize(bound.x, ry + rh + actualVal, bound.width, bound.height + bound.y - rh - ry - actualVal); - recalculateChildrenSize(bound.x, bound.y, bound.width, ry + rh - bound.y); - return; - } - } - recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); - } - - private void calculateNoRelatedWhileRightBott(Rectangle bound, Component rcomp) { - rcomp = container.getBottomRightComp(bound.x, bound.y, bound.height, bound.width); - int ry = rcomp.getY(); - int rh = rcomp.getHeight(); - int rw = rcomp.getWidth(); - int dh = ry + rh - bound.y - bound.height - actualVal; - if (dh < minHeight) { - dealDirectionABottom(rcomp.getBounds(), -dh - actualVal, rcomp); - //调整的时候可能有组件达到最小高度,判断下 - if (rcomp.getHeight() + ry != bound.y + bound.height) { - clearCompsList(); - initCompsList(); - dh = ry + rcomp.getHeight() - bound.y - bound.height - actualVal; - dealDirectionABottom(rcomp.getBounds(), minHeight - dh, rcomp); - rh = rcomp.getHeight(); - int rx = rcomp.getX(); - rcomp.setBounds(rx, bound.y + bound.height + actualVal, rw, minHeight); - recalculateChildrenSize(rx, ry, rw, rh - minHeight - actualVal); - recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); - return; - } - } else { - if (ry == bound.y) { - rcomp.setBounds(rcomp.getX(), bound.y + bound.height + actualVal, rw, dh); - bound.width += rw; - bound.width += actualVal; - } else { - recalculateChildrenSize(bound.x, bound.y, bound.width, ry - bound.y - actualVal); - recalculateChildrenSize(bound.x, ry, bound.width, bound.height - ry + bound.y); - return; - } - } - recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); - } - - private int getMinWidth(List comps) { - if (comps.isEmpty()) { - return 0; - } - int minWidth = container.getWidth() - margin.getLeft() - margin.getRight(); - for (int i = 0, size = comps.size(); i < size; i++) { - minWidth = minWidth > comps.get(i).getWidth() ? comps.get(i).getWidth() : minWidth; - } - return minWidth; - } - - private int getMinHeight(List comps) { - if (comps.isEmpty()) { - return 0; - } - int minH = container.getHeight() - margin.getTop() - margin.getBottom(); - for (int i = 0, size = comps.size(); i < size; i++) { - minH = minH > comps.get(i).getHeight() ? comps.get(i).getHeight() : minH; - } - return minH; - } - - // 删除时计算待删除组件上下侧的组件是否何其对齐 - private int getAllHeight(List comps) { - int allHeight = 0; - if (comps.isEmpty()) { - return allHeight; - } - int n = comps.size(); - for (int i = 0; i < n; i++) { - allHeight += comps.get(i).getHeight(); - } - allHeight += (n - 1) * actualVal; - return allHeight; - } - - private int getAllWidth(List comps) { - int allWidth = 0; - if (comps.isEmpty()) { - return allWidth; - } - int n = comps.size(); - for (int i = 0; i < n; i++) { - allWidth += comps.get(i).getWidth(); - } - allWidth += (n - 1) * actualVal; - return allWidth; - } - - /** - * 获取有哪些相关联的组件 - */ - protected void calculateRelatedComponent(int objX, int objY, int objWidth, int objHeight) { - int count = container.getComponentCount(); - for (int i = 0; i < count; i++) { - Component relatComp = container.getComponent(i); - int rx = relatComp.getX(); - int ry = relatComp.getY(); - int rwidth = relatComp.getWidth(); - int rheight = relatComp.getHeight(); - int verti = ry - objY; - int hori = rx - objX; - boolean isHori = verti >= 0 && objHeight >= (rheight + verti); - boolean isVerti = hori >= 0 && objWidth >= (rwidth + hori); - if (isHori && (objX + objWidth + actualVal) == rx) { - rightComps.add(relatComp); - } else if (isHori && objX == (rx + rwidth + actualVal)) { - leftComps.add(relatComp); - } else if (isVerti && (objY + objHeight + actualVal) == ry) { - downComps.add(relatComp); - } else if (isVerti && objY == (ry + rheight + actualVal)) { - upComps.add(relatComp); - } - } - } - - /** - * 拖拽组件时遍历某一侧组件得到该侧组件能够缩放的最小宽度,tab布局最小宽度 = 内部组件数 * 单个组件最小宽度 - * - * @param list 某一侧组件的集合 如:leftComps - * @return int 最小宽度 - */ - private int getCompsMinWidth(List list) { - return getMaxCompsNum(list, true) * WLayout.MIN_WIDTH; - } - - /** - * 拖拽组件遍历某一侧得到该侧组件能够缩放的最小高度,tab布局最小高度 = 内部组件数 * 单个组件最小高度 + 标题高度 - * - * @param list 某一侧组件集合 - * @return int 最小高度 - */ - private int getCompsMinHeight(List list) { - for (int i = 0; i < list.size(); i++) { - XCreator creator = (XCreator) list.get(i); - ArrayList childrenList = creator.getTargetChildrenList(); - if (!childrenList.isEmpty()) { - return getMaxCompsNum(list, false) * WLayout.MIN_HEIGHT + WCardMainBorderLayout.TAB_HEIGHT; - } - } - return WLayout.MIN_HEIGHT; - } - - /** - * 根据子组件的横(纵)坐标获取某一侧组件的最大内部组件数 - * - * @param list 某一侧组件集合 - * @param isHor 是否以横坐标为准 - * @return int 最大内部组件数 - */ - private int getMaxCompsNum(List list, boolean isHor) { - int maxCompNums = 1; - for (int i = 0, size = list.size(); i < size; i++) { - XCreator creator = (XCreator) list.get(i); - ArrayList childrenList = creator.getTargetChildrenList(); - int count = childrenList.size(); - if (count > 0) { - for (int j = 0; j < count; j++) { - XWTabFitLayout tabLayout = (XWTabFitLayout) childrenList.get(j); - int[] positions = isHor ? tabLayout.getHors(true) : tabLayout.getVeris(true); - int compNums = positions.length - 1; - maxCompNums = Math.max(compNums, maxCompNums); - } - } - } - return maxCompNums; - } - - /** - * 根据偏移量缩放内部组件大小,(tab布局用到) - * - * @param creator tab布局 - * @param offset 偏移量 - * @param isHor 是否为横向拖拽 - */ - private void adjustCompsSize(XCreator creator, int offset, boolean isHor) { - ArrayList childrenList = creator.getTargetChildrenList(); - int size = childrenList.size(); - if (size > 0) { - for (int j = 0; j < size; j++) { - XWTabFitLayout tabLayout = (XWTabFitLayout) childrenList.get(j); - tabLayout.setBackupBound(tabLayout.getBounds()); - int refSize = isHor ? tabLayout.getWidth() : tabLayout.getHeight(); - double percent = (double) offset / refSize; - if (percent < 0 && !tabLayout.canReduce(percent)) { - return; - } - setAdjustedSize(tabLayout, offset, isHor); - for (int m = 0; m < tabLayout.getComponentCount(); m++) { - XCreator childCreator = tabLayout.getXCreator(m); - BoundsWidget wgt = tabLayout.toData().getBoundsWidget(childCreator.toData()); - wgt.setBounds(tabLayout.getComponent(m).getBounds()); - } - adjustCreatorsSize(percent, tabLayout, isHor); - } - - } - } - - // 纵向拖拽,先将tab布局的高度设置为拖拽后的实际高度 - private void setAdjustedHeight(XWTabFitLayout tabLayout, int offset) { - tabLayout.setSize(tabLayout.getWidth(), tabLayout.getHeight() + offset); - } - - // 横向拖拽,先将tab布局的宽度设置为拖拽后的实际宽度 - private void setAdjustedSize(XWTabFitLayout tabLayout, int offset, boolean isHor) { - if (offset < 0) { - // 缩放时需要备份原tab布局宽高 - tabLayout.setReferDim(new Dimension(tabLayout.getWidth(), tabLayout.getHeight())); - } - if (isHor) { - tabLayout.setSize(tabLayout.getWidth() + offset, tabLayout.getHeight()); - return; - } - setAdjustedHeight(tabLayout, offset); - } - - // 按照拖拽偏移量,对tab布局进行缩放 - private void adjustCreatorsSize(double percent, XWTabFitLayout tabLayout, boolean isHor) { - if (isHor) { - tabLayout.adjustCreatorsWidth(percent); - return; - } - tabLayout.adjustCreatorsHeight(percent); - } - - - /** - * 删除或拉伸控件右边框 调整右侧组件位置大小 - * - * @param objX 调整后的坐标x - * @param objWidth 调整后的宽度 - */ - protected void CalculateRightRelatComponent(int objX, int objWidth) { - int count = rightComps.size(); - for (int i = 0; i < count; i++) { - XCreator creator = (XCreator) rightComps.get(i); - adjustCompsSize(creator, objWidth, true); - int ry = creator.getY(); - int rwidth = creator.getWidth(); - int rheight = creator.getHeight(); - creator.setLocation(objX, ry); - creator.setSize(rwidth + objWidth, rheight); - } - } - - /** - * 实际拖拽偏移量是否超出了可调整的宽度范围 - * - * @param offset 实际偏移量 - * @return boolean 是否超出调整范围 - */ - private boolean isBeyondAdjustWidthScope(int offset) { - boolean isBeyondScope = false; - isBeyondScope = offset < 0 ? isBeyondWidthScope(offset, leftComps) : isBeyondWidthScope(offset, rightComps); - return isBeyondScope; - } - - // 实际拖拽偏移量是否超出某一侧的可调整宽度 - private boolean isBeyondWidthScope(int offset, List compsList) { - int compMinWidth = getCompsMinWidth(compsList); - for (int i = 0; i < compsList.size(); i++) { - XCreator creator = (XCreator) compsList.get(i); - if (Math.abs(offset) > (creator.getWidth() - compMinWidth)) { - return true; - } - } - return false; - } - - /** - * 删除或拉伸控件左边框时 调整左侧的组件位置大小; - */ - protected boolean CalculateLefttRelatComponent(int objWidth) { - if (isBeyondAdjustWidthScope(objWidth)) { - return false; - } - int count = leftComps.size(); - for (int i = 0; i < count; i++) { - XCreator creator = (XCreator) leftComps.get(i); - adjustCompsSize(creator, objWidth, true); - int rwidth = creator.getWidth(); - int rheight = creator.getHeight(); - creator.setSize(rwidth + objWidth, rheight); - } - return true; - } - - /** - * 删除或拉伸下边框 调整下方的组件位置大小 - */ - protected void CalculateDownRelatComponent(int objY, int objHeight) { - int count = downComps.size(); - for (int i = 0; i < count; i++) { - XCreator creator = (XCreator) downComps.get(i); - adjustCompsSize(creator, objHeight, false); - int rx = creator.getX(); - int rwidth = creator.getWidth(); - int rheight = creator.getHeight(); - creator.setLocation(rx, objY); - creator.setSize(rwidth, rheight + objHeight); - } - } - - /** - * 实际拖拽偏移量是否超出了可调整的高度范围 - * - * @param offset 实际偏移量 - * @return boolean 是否超出调整范围 - */ - private boolean isBeyondAdjustHeightScope(int offset) { - boolean isBeyondScope = false; - isBeyondScope = offset < 0 ? isBeyondHeightScope(offset, upComps) : isBeyondHeightScope(offset, downComps); - return isBeyondScope; - } - - // 实际拖拽偏移量是否超出某一侧的可调整高度 - private boolean isBeyondHeightScope(int offset, List compsList) { - int minHeight = getCompsMinHeight(compsList); - for (int i = 0; i < compsList.size(); i++) { - XCreator creator = (XCreator) compsList.get(i); - if (Math.abs(offset) > (creator.getHeight() - minHeight)) { - return true; - } - } - return false; - } - - /** - * 删除或拉伸上边框 调整上方的组件位置大小 - */ - protected boolean CalculateUpRelatComponent(int objHeight) { - if (isBeyondAdjustHeightScope(objHeight)) { - return false; - } - int count = upComps.size(); - for (int i = 0; i < count; i++) { - XCreator creator = (XCreator) upComps.get(i); - adjustCompsSize(creator, objHeight, false); - int rwidth = creator.getWidth(); - int rheight = creator.getHeight(); - creator.setSize(rwidth, rheight + objHeight); - } - return true; - } - - /** - * 不调整,只计算位置 - * - * @return child的位置 - */ - public int[] getChildPosition(Component currentComp, XCreator child, int x, int y) { - return super.getChildPosition(currentComp, child, x, y); - } - - @Override - public ConstraintsGroupModel getLayoutConstraints(XCreator creator) { - return new FRFitLayoutConstraints((XWFitLayout) container, creator); - } +/** + * + */ +package com.fr.design.designer.beans.adapters.layout; + +import com.fr.design.beans.GroupModel; +import com.fr.design.designer.beans.ConstraintsGroupModel; +import com.fr.design.designer.beans.HoverPainter; +import com.fr.design.designer.beans.painters.FRFitLayoutPainter; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XCreatorUtils; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWFitLayout; +import com.fr.design.designer.creator.cardlayout.XWCardLayout; +import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; +import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; +import com.fr.design.designer.properties.FRFitLayoutConstraints; +import com.fr.design.designer.properties.FRFitLayoutPropertiesGroupModel; +import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.mainframe.JForm; +import com.fr.design.utils.ComponentUtils; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.container.WLayout; +import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; +import com.fr.form.ui.widget.BoundsWidget; +import com.fr.general.ComparatorUtils; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + * 自适应布局的容器适配器 + * + * @author jim + * @date 2014-6-24 + */ +public class FRFitLayoutAdapter extends FRBodyLayoutAdapter { + + public static final String WIDGETPANEICONPATH = "/com/fr/web/images/form/resources/layout_absolute.png"; + private static final int DEPENDING_SCOPE = 3; + private HoverPainter painter; + //区分拖拽和编辑宽高 + private boolean isEdit; + + public boolean isEdit() { + return isEdit; + } + + public void setEdit(boolean edit) { + isEdit = edit; + } + + /** + * 构造函数 + * + * @param container XWFitLayout容器 + */ + public FRFitLayoutAdapter(XLayoutContainer container) { + super(container); + painter = new FRFitLayoutPainter(container); + initMinSize(); + } + + private void initMinSize() { + XWFitLayout layout = (XWFitLayout) container; + minWidth = layout.getActualMinWidth(); + minHeight = layout.getActualMinHeight(); + actualVal = layout.getAcualInterval(); + margin = layout.toData().getMargin(); + } + + @Override + public HoverPainter getPainter() { + return painter; + } + + /** + * 返回布局自身属性,方便一些特有设置在layout刷新时处理 + */ + @Override + public GroupModel getLayoutProperties() { + XWFitLayout xfl = (XWFitLayout) container; + return new FRFitLayoutPropertiesGroupModel(xfl); + } + + /** + * 添加组件 + * + * @param child 待添加的组件 + * @param x 坐标x + * @param y 坐标y + */ + @Override + public void addComp(XCreator child, int x, int y) { + fix(child, x, y); + if (child.shouldScaleCreator() || child.hasTitleStyle()) { + addParentCreator(child); + } else { + container.add(child, child.toData().getWidgetName()); + } + XWFitLayout layout = (XWFitLayout) container; + // 更新对应的BoundsWidget + layout.updateBoundsWidget(); + updateCreatorBackBound(); + } + + public void updateCreatorBackBound() { + for (int i = 0, size = container.getComponentCount(); i < size; i++) { + XCreator creator = (XCreator) container.getComponent(i); + creator.updateChildBound(minHeight); + creator.setBackupBound(creator.getBounds()); + } + } + + + private void addParentCreator(XCreator child) { + XLayoutContainer parentPanel = child.initCreatorWrapper(minHeight); + container.add(parentPanel, child.toData().getWidgetName()); + } + + /** + * 能否对应位置放置当前组件 + * + * @param creator 组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否可以放置 + */ + @Override + public boolean accept(XCreator creator, int x, int y) { + // 计算是否能拖入鼠标区域时,会用到fix 的方法 + isFindRelatedComps = false; + //拖入组件判断时,先判断是否为交叉点区域,其次三等分区域,再次平分区域 + Component comp = container.getComponentAt(x, y); + if (checkInterval(comp)) { + return false; + } + //如果当前处于边缘地带, 那么就把他贴到父容器上 + boolean isMatchEdge = matchEdge(x, y); + + int componentHeight = comp.getHeight(); + int componentWidth = comp.getWidth(); + //上半部分高度 + int upHeight = (int) (componentHeight * TOP_HALF) + comp.getY(); + //下半部分高度 + int downHeight = (int) (componentHeight * BOTTOM_HALF) + comp.getY(); + + //布局控件要先判断是不是可编辑 + XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator) comp).getTopLayout(); + if (topLayout != null && !isMatchEdge && !topLayout.isEditable()) { + return false; + } + + if (isCrossPointArea(comp, x, y)) { + return canAcceptWhileCrossPoint(comp, x, y); + } + + if (isTrisectionArea(comp, x, y)) { + return canAcceptWhileTrisection(comp, x, y); + } + + boolean horizonValid = componentWidth >= minWidth * 2 + actualVal; + boolean verticalValid = componentHeight >= minHeight * 2 + actualVal; + return y > upHeight && y < downHeight ? horizonValid : verticalValid; + } + + // 间隔区域 + private boolean checkInterval(Component comp) { + return container.getComponentCount() > 0 && comp == container; + } + + /** + * 是否在组件边缘 + * + * @param x 横坐标 + * @param y 纵坐标 + * @return 是否在组件边缘 + */ + public boolean matchEdge(int x, int y) { + if (intersectsEdge(x, y, container)) { + //寻找最近的fit, 在边缘地段添加的控件, 将其送给该fit + XLayoutContainer parent = container.findNearestFit(); + container = parent != null ? parent : container; + return true; + } + return false; + } + + /** + * 是否在组件边缘 + * + * @param x 横坐标 + * @param y 纵坐标 + * @param container 参照组件 + * @return 是否在组件边缘 + */ + //是否包含于边缘地段, 按顺序上, 下, 左, 右检测 + public boolean intersectsEdge(int x, int y, XLayoutContainer container) { + int containerX = container.getX(); + int containerY = container.getY(); + int containerWidth = container.getWidth(); + int containerHeight = container.getHeight(); + + // 当前坐标点 + Rectangle currentXY = new Rectangle(x, y, 1, 1); + // 上边缘 + Rectangle upEdge = new Rectangle(containerX, containerY, containerWidth, BORDER_PROPORTION); + if (upEdge.intersects(currentXY)) { + return true; + } + + int bottomY = containerY + containerHeight - BORDER_PROPORTION; + // 下边缘 + Rectangle bottomEdge = new Rectangle(containerX, bottomY, containerWidth, BORDER_PROPORTION); + if (bottomEdge.intersects(currentXY)) { + return true; + } + + //左右边缘的高度 -10*2 是为了不和上下边缘重合 + int verticalHeight = containerHeight - BORDER_PROPORTION * 2; + int leftY = containerY + BORDER_PROPORTION; + // 左边缘 + Rectangle leftEdge = new Rectangle(containerX, leftY, BORDER_PROPORTION, verticalHeight); + if (leftEdge.intersects(currentXY)) { + return true; + } + + int rightY = containerY + BORDER_PROPORTION; + int rightX = containerX + containerWidth - BORDER_PROPORTION; + // 右边缘 + Rectangle rightEdge = new Rectangle(rightX, rightY, BORDER_PROPORTION, verticalHeight); + return rightEdge.intersects(currentXY); + } + + /** + * 交叉点区域时,能否对应位置放入组件 + */ + protected boolean canAcceptWhileCrossPoint(Component comp, int x, int y) { + return super.canAcceptWhileCrossPoint(comp, x, y); + } + + protected boolean canAcceptWhileTrisection(Component comp, int x, int y) { + return super.canAcceptWhileTrisection(comp, x, y); + } + + /** + * 判断是否鼠标在组件的三等分区域,如果组件在布局管理器中间,上下左右都可能会三等分 + * + * @param parentComp 鼠标所在区域的组件 + * @param x 坐标x + * @param y 坐标y + * @return 是则返回true + */ + public boolean isTrisectionArea(Component parentComp, int x, int y) { + return super.isTrisectionArea(parentComp, x, y); + } + + /** + * 是否为组件交叉点区域 或者是相邻三组建中间点 + * + * @param currentComp 当前组件 + * @param x 坐标x + * @param y 坐标y + * @return 是则返回true + */ + public boolean isCrossPointArea(Component currentComp, int x, int y) { + return super.isCrossPointArea(currentComp, x, y); + } + + + protected Rectangle getLayoutBound(XWCardMainBorderLayout mainLayout) { + return mainLayout.getBounds(); + } + + private Rectangle adjustBackupBound(Rectangle backupBound, XWCardMainBorderLayout mainLayout) { + // 参数界面高度对纵坐标产生的影响 + JForm jform = (JForm) (HistoryTemplateListPane.getInstance().getCurrentEditingTemplate()); + if (jform.getFormDesign().getParaComponent() != null) { + backupBound.y -= jform.getFormDesign().getParaHeight(); + } + + Rectangle rec = getLayoutBound(mainLayout); + // XWTabLayout里面的横纵坐标收到外层XWCardMainBorderLayout的横纵坐标影响 + // 减掉之后可以按照它原来的逻辑执行 + backupBound.x -= rec.x; + backupBound.y -= rec.y; + XWCardLayout cardLayout = mainLayout.getCardPart(); + LayoutBorderStyle style = cardLayout.toData().getBorderStyle(); + // 当tab布局为标题样式时,才需要处理标题栏高度产生的影响 + if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) { + backupBound.y -= WCardMainBorderLayout.TAB_HEIGHT; + } + return backupBound; + } + + /** + * 拖拽控件边框后,根据控件的大小尺寸,进行相关组件的调整 + * + * @param creator 组件 + */ + @Override + public void fix(XCreator creator) { + //拖拽组件原大小、位置 + Rectangle backupBound = creator.getBackupBound(); + backupBound.x -= container.getX(); + backupBound.y -= container.getY(); + //当前拖拽组件的位置 + int x = creator.getX(); + int y = creator.getY(); + + // 获取容器所有内部组件横坐标 + int[] posXs = container.getHors(); + // 获取容器所有内部组件纵坐标 + int[] posYs = container.getVeris(); + + XLayoutContainer outerLayout = container.getOuterLayout(); + if (!ComparatorUtils.equals(outerLayout, container.getBackupParent())) { + XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout) outerLayout; + backupBound = adjustBackupBound(backupBound, mainLayout); + } + + //拖拽组件拖拽以后的大小 + int w = creator.getWidth(); + int h = creator.getHeight(); + initCompsList(); + creator.setBounds(backupBound); + int difference = 0; + if (x != backupBound.x) { + dealLeft(backupBound, x, posXs, difference, creator); + } else if (w != backupBound.width) { + dealRight(backupBound, x, w, posXs, difference, creator); + } else if (y != backupBound.y) { + dealTop(backupBound, y, posYs, difference, creator); + } else if (h != backupBound.height) { + dealButtom(backupBound, y, h, posYs, difference, creator); + } + clearCompsList(); + XWFitLayout layout = (XWFitLayout) container; + layout.updateBoundsWidget(); // 更新对应的BoundsWidget + updateCreatorBackBound(); + } + + /** + * 拖拽控件边框后,根据控件的大小尺寸,进行相关组件的调整 + * + * @param backupBound 边界备份 + * @param bounds 组件边界 + * @param xCreator 组件 + * @param row 选中的行 + * @param difference 偏移量 + */ + public void calculateBounds(Rectangle backupBound, Rectangle bounds, XCreator xCreator, int row, int difference) { + Rectangle rc = new Rectangle(0, 0, 0, 0); + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xCreator); + if (parent != null) { + Rectangle rec = ComponentUtils.getRelativeBounds(parent); + rc.x = rec.x; + rc.y = rec.y; + } + int x = backupBound.x - rc.x, y = backupBound.y - rc.y; + //处理左右延伸 + switch (row) { + case 0: + if (backupBound.width + backupBound.x == container.getWidth() - margin.getRight() + rc.x) { + x += difference; + } + break; + case 1: + if (backupBound.y + backupBound.height == container.getHeight() - margin.getBottom() + rc.y) { + y += difference; + } + break; + } + bounds.setLocation(x, y); + xCreator.setBackupBound(backupBound); + xCreator.setBounds(bounds); + this.fix(xCreator); + } + + private void dealLeft(Rectangle backupBound, int x, int[] posXs, int difference, XCreator creator) { + if (backupBound.x == margin.getLeft()) { + return; + } + x = adjustCoordinateByDependingLine(x, posXs); + difference = x - backupBound.x; + dealDirectionAtLeft(backupBound, difference, creator); + } + + private void dealRight(Rectangle backupBound, int x, int w, int[] posXs, int difference, XCreator creator) { + if (backupBound.width + backupBound.x == container.getWidth() - margin.getRight()) { + return; + } + w = adjustDiffByDependingLine(x, posXs, w); + difference = w - backupBound.width; //拖拽长度 + dealDirectionAtRight(backupBound, difference, creator); + } + + private void dealTop(Rectangle backupBound, int y, int[] posYs, int difference, XCreator creator) { + if (backupBound.y == margin.getTop()) { + return; + } + y = adjustCoordinateByDependingLine(y, posYs); + difference = y - backupBound.y; + dealDirectionAtTop(backupBound, difference, creator); + } + + private void dealButtom(Rectangle backupBound, int y, int h, int[] posYs, int difference, XCreator creator) { + if (backupBound.y + backupBound.height == container.getHeight() - margin.getBottom()) { + return; + } + h = adjustDiffByDependingLine(y, posYs, h); + difference = h - backupBound.height; + dealDirectionABottom(backupBound, difference, creator); + } + + // 根据需要依附的位置调整拖拽的坐标值 + private int adjustCoordinateByDependingLine(int coordinate, int[] coordinates) { + if (!isEdit) { + for (int i = 0; i < coordinates.length; i++) { + if (coordinate == coordinates[i]) { + continue; + } + if (coordinate > coordinates[i] - DEPENDING_SCOPE && coordinate < coordinates[i] + DEPENDING_SCOPE) { + coordinate = coordinates[i]; + break; + } + } + } + return coordinate; + } + + // 根据需要依附的位置调整拖拽的距离 + private int adjustDiffByDependingLine(int coordinate, int[] coordinates, int diff) { + if (!isEdit) { + for (int i = 0; i < coordinates.length; i++) { + if (coordinate + diff > coordinates[i] - DEPENDING_SCOPE && coordinate + diff < coordinates[i] + DEPENDING_SCOPE) { + diff = coordinates[i] - coordinate; + break; + } + } + } + return diff; + } + + // 左侧边框拉伸,循环找出对齐的两侧控件 + private void dealDirectionAtLeft(Rectangle backupBound, int difference, Component creator) { + rightComps.add(creator); + Component rightComp = null; + int leftx = backupBound.x - DEFAULT_AREA_LENGTH - actualVal; + // 取左侧边框右面的组件x值 + int rightx = backupBound.x + DEFAULT_AREA_LENGTH; + Component leftComp = container.getLeftComp(backupBound.x, backupBound.y); + leftComps.add(leftComp); + //先找上侧对齐时(y相等)的左右两边组件 + int ry = backupBound.y; + int ly = leftComp.getY(); + int min = margin.getTop(); + int max = container.getHeight() - margin.getBottom(); + while (ry >= min && ly >= min) { + if (ry == ly) { + break; + } else { + if (ry > ly) { + rightComp = container.getTopComp(rightx, ry); + ry = rightComp.getY(); + rightComps.add(rightComp); + } else { + leftComp = container.getTopComp(leftx, ly); + ly = leftComp.getY(); + leftComps.add(leftComp); + } + } + } + // 下侧对齐时(y+h相等)两边组件 + ry = backupBound.y + backupBound.height; + ly = leftComps.get(0).getY() + leftComps.get(0).getHeight(); + while (ry <= max && ly <= max) { + if (ry == ly) { + break; + } else { + if (ry > ly) { + leftComp = container.getComponentAt(leftx, ly + DEFAULT_AREA_LENGTH + actualVal); + ly = leftComp.getY() + leftComp.getHeight(); + leftComps.add(leftComp); + } else { + rightComp = container.getComponentAt(rightx, ry + DEFAULT_AREA_LENGTH + actualVal); + ry = rightComp.getY() + rightComp.getHeight(); + rightComps.add(rightComp); + } + } + } + dealHorDirection(backupBound.x, difference); + } + + // 右侧边框拉伸,循环找出对齐的两侧控件 + private void dealDirectionAtRight(Rectangle backupBound, int difference, Component creator) { + leftComps.add(creator); + Component leftComp = null; + int leftx = backupBound.x + backupBound.width - DEFAULT_AREA_LENGTH; + // 取右侧边框右面的组件x值 + int rightx = backupBound.x + backupBound.width + DEFAULT_AREA_LENGTH + actualVal; + Component rightComp = container.getRightComp(backupBound.x, backupBound.y, backupBound.width); + rightComps.add(rightComp); + int ly = backupBound.y, ry = rightComp.getY(); + int min = margin.getTop(); + int max = container.getHeight() - margin.getBottom(); + while (ry >= min && ly >= min) { + if (ry == ly) { + break; + } else { + if (ry > ly) { + rightComp = container.getTopComp(rightx, ry); + ry = rightComp.getY(); + rightComps.add(rightComp); + } else { + leftComp = container.getTopComp(leftx, ly); + ly = leftComp.getY(); + leftComps.add(leftComp); + } + } + } + ly = backupBound.y + backupBound.height; + ry = rightComps.get(0).getY() + rightComps.get(0).getHeight(); + while (ry <= max && ly <= max) { + if (ry == ly) { + break; + } else { + if (ry > ly) { + leftComp = container.getComponentAt(leftx, ly + DEFAULT_AREA_LENGTH + actualVal); + ly = leftComp.getY() + leftComp.getHeight(); + leftComps.add(leftComp); + } else { + rightComp = container.getComponentAt(rightx, ry + DEFAULT_AREA_LENGTH + actualVal); + ry = rightComp.getY() + rightComp.getHeight(); + rightComps.add(rightComp); + } + } + } + dealHorDirection(backupBound.x + backupBound.width + actualVal, difference); + } + + /** + * 水平方向上拉伸边框的处理 + */ + private void dealHorDirection(int objx, int difference) { + if (difference > 0) { + difference = Math.min(getMinWidth(rightComps) - minWidth, difference); + } else { + difference = Math.max(difference, minWidth - getMinWidth(leftComps)); + } + //重新计算左右两侧组件size、point + if (calculateLefttRelatComponent(difference)) { + calculateRightRelatComponent(objx + difference, -difference); + } + } + + // 上侧边框拉伸,循环找出对齐的两侧控件 + private void dealDirectionAtTop(Rectangle backupBound, int difference, Component creator) { + downComps.add(creator); + // 取上侧边框上面的组件用的y值 + int topy = backupBound.y - DEFAULT_AREA_LENGTH - actualVal; + // 上侧边框下面的组件y值 + int bottomy = backupBound.y + DEFAULT_AREA_LENGTH; + Component topComp = container.getTopComp(backupBound.x, backupBound.y); + upComps.add(topComp); + Component bottomComp = null; + int min = margin.getLeft(); + int max = container.getWidth() - margin.getRight(); + //先找左侧侧对齐时(x相等)的上下两边组件 + int ux = topComp.getX(); + int dx = backupBound.x; + while (ux >= min && dx >= min) { + if (ux == dx) { + break; + } else { + if (ux < dx) { + bottomComp = container.getLeftComp(dx, bottomy); + dx = bottomComp.getX(); + downComps.add(bottomComp); + } else { + topComp = container.getLeftComp(ux, topy); + ux = topComp.getX(); + upComps.add(topComp); + } + } + } + // 右侧对齐时(x+w相等)两边组件 + ux = upComps.get(0).getX() + upComps.get(0).getWidth(); + dx = backupBound.x + backupBound.width; + while (ux <= max && dx <= max) { + if (ux == dx) { + break; + } else { + if (ux < dx) { + topComp = container.getComponentAt(ux + DEFAULT_AREA_LENGTH + actualVal, topy); + ux = topComp.getX() + topComp.getWidth(); + upComps.add(topComp); + } else { + bottomComp = container.getComponentAt(dx + DEFAULT_AREA_LENGTH + actualVal, bottomy); + dx = bottomComp.getX() + bottomComp.getWidth(); + downComps.add(bottomComp); + } + } + } + + dealVertiDirection(backupBound.y, difference); + } + + // 下侧边框拉伸,循环找出对齐的两侧控件 + private void dealDirectionABottom(Rectangle backupBound, int difference, Component creator) { + upComps.add(creator); + Component topComp = null; + Component bottomComp = container.getBottomComp(backupBound.x, backupBound.y, backupBound.height); + // 下侧边框下面的组件y坐标 + int bottomy = backupBound.y + backupBound.height + DEFAULT_AREA_LENGTH + actualVal; + // 取下侧边框上面的组件用的y值 + int topy = backupBound.y + backupBound.height - DEFAULT_AREA_LENGTH; + downComps.add(bottomComp); + int dx = bottomComp.getX(); + int ux = backupBound.x; + int min = margin.getLeft(); + int max = container.getWidth() - margin.getRight(); + while (ux >= min && dx >= min) { + if (ux == dx) { + break; + } else { + if (ux < dx) { + bottomComp = container.getLeftComp(dx, bottomy); + dx = bottomComp.getX(); + downComps.add(bottomComp); + } else { + topComp = container.getLeftComp(ux, topy); + ux = topComp.getX(); + upComps.add(topComp); + } + } + } + dx = downComps.get(0).getX() + downComps.get(0).getWidth(); + ux = backupBound.x + backupBound.width; + while (ux <= max && dx <= max) { + if (ux == dx) { + break; + } else { + if (ux < dx) { + topComp = container.getComponentAt(ux + DEFAULT_AREA_LENGTH + actualVal, topy); + ux = topComp.getX() + topComp.getWidth(); + upComps.add(topComp); + } else { + bottomComp = container.getComponentAt(dx + DEFAULT_AREA_LENGTH + actualVal, bottomy); + dx = bottomComp.getX() + bottomComp.getWidth(); + downComps.add(bottomComp); + } + } + } + dealVertiDirection(backupBound.y + backupBound.height + actualVal, difference); + } + + /** + * 垂直方向上拉伸边框的处理 + */ + private void dealVertiDirection(int objY, int difference) { + if (difference > 0) { + difference = Math.min(getMinHeight(downComps) - minHeight, difference); + } else { + difference = Math.max(difference, minHeight - getMinHeight(upComps)); + } + //重新计算上下两侧组件size、point + if (calculateUpRelatComponent(difference)) { + calculateDownRelatComponent(objY + difference, -difference); + } + } + + /** + * 新拖入组件时,计算调整其他关联组件位置大小 + * + * @param child 新拖入的组件 + * @param x 鼠标所在x坐标 + * @param y 鼠标所在y坐标 + */ + public void fix(XCreator child, int x, int y) { + Component parentComp = container.getComponentAt(x, y); + if (container.getComponentCount() == 0) { + child.setLocation(0, 0); + child.setSize(parentComp.getWidth(), parentComp.getHeight()); + } else if (isCrossPointArea(parentComp, x, y)) { + //交叉区域插入组件时,根据具体位置进行上下或者左右或者相邻三个组件的位置大小插入 + fixCrossPointArea(parentComp, child, x, y); + return; + } else if (isTrisectionArea(parentComp, x, y)) { + // 在边界三等分区域,就不再和组件二等分了 + fixTrisect(parentComp, child, x, y); + return; + } else { + fixHalve(parentComp, child, x, y); + } + } + + /** + * 平分,正常情况拖入组件时,按照上1/4区域、下1/4区域为上下平分,中左侧1/2区域、中右侧1/2区域为左右平分 + */ + protected void fixHalve(Component currentComp, XCreator child, int x, int y) { + super.fixHalve(currentComp, child, x, y); + } + + /** + * 组件交叉区域进行插入时,调整受到变动的其他组件,之前是交叉区域插入也按照三等分逻辑,后面测试中发现有bug,改为和bi一样的鼠标所在侧平分 + * 默认左上角、右下角区域是垂直方向插入组件 + * 右上角和左下角是水平方向插入组件,这样避免田字块时重复 + */ + protected void fixCrossPointArea(Component currentComp, XCreator child, int x, int y) { + super.fixCrossPointArea(currentComp, child, x, y); + } + + /** + * 三等分区域时,调整相关联的组件 + * + * @param currentComp 鼠标所在组件 + * @param child 待插入组件 + */ + protected void fixTrisect(Component currentComp, XCreator child, int x, int y) { + super.fixTrisect(currentComp, child, x, y); + } + + /** + * 删除组件或者重新拖动时,其它组件重新计算位置大小 + */ + protected void delete(XCreator creator, int creatorWidth, int creatorHeight) { + int x = creator.getX(); + int y = creator.getY(); + recalculateChildrenSize(x, y, creatorWidth, creatorHeight); + } + + /** + * 重新计算内部组件大小 + * + * @param x 坐标x + * @param y 坐标y + * @param creatorWidth 删除的组件之前所在布局的宽度 + * @param creatorHeight 删除的组件之前所在布局的高度 + */ + public void recalculateChildrenSize(int x, int y, int creatorWidth, int creatorHeight) { + if (container.getComponentCount() == 0) { + return; + } else { + initCompsList(); + int width = creatorWidth; + int height = creatorHeight; + calculateRelatedComponent(x, y, width, height); + if (!rightComps.isEmpty() && getAllHeight(rightComps) == height) { + calculateRightRelatComponent(x, width + actualVal); + } else if (!leftComps.isEmpty() && getAllHeight(leftComps) == height) { + calculateLefttRelatComponent(width + actualVal); + } else if (!downComps.isEmpty() && getAllWidth(downComps) == width) { + calculateDownRelatComponent(y, height + actualVal); + } else if (!upComps.isEmpty() && getAllWidth(upComps) == width) { + calculateUpRelatComponent(height + actualVal); + } else { + // 由于布局三等分的存在,可能会出现删除组件时,找不到关联的组件填充,此时特殊处理 + calculateNoRelatedComponent(x, y, width, height); + } + } + clearCompsList(); + } + + /** + * 四侧边框都没有对齐的,此时每侧有且只有一个方向不对齐 + * 比如右侧不对齐,那么必然右上或右下没对齐,不会同时不对齐,否则不会出现此情况 + * 正常删除是右左下上优先原则,这边目前只调整右侧以至填充完整, + * 右侧不对齐时的组件先上下微调,再向左侧填充。 + */ + private void calculateNoRelatedComponent(int x, int y, int width, int height) { + // 只有最后一个组件了,直接删除 + if (container.getComponentCount() <= 1) { + return; + } + // 删除当前组件时,由于没有刚好边框对齐的其他组件,这时候需要调整的组件 + Component rightComp = container.getRightComp(x, y, width); + if (rightComp == null) { + return; + } + + int ry = rightComp.getY(); + clearCompsList(); + initCompsList(); + Rectangle rec = new Rectangle(x, y, width, height); + if (ry != y) { + calculateNoRelatedWhileRightTop(rec, rightComp); + } else { + calculateNoRelatedWhileRightBott(rec, rightComp); + } + + } + + private void calculateNoRelatedWhileRightTop(Rectangle bound, Component rcomp) { + if (rcomp == null) { + return; + } + + int ry = rcomp.getY(); + int rh = rcomp.getHeight(); + int rw = rcomp.getWidth(); + int dh = bound.y - ry - actualVal; + // 没法缩小高度 + if (dh < minHeight) { + // 没法缩小时则拉伸rcomp的上边框 + dealDirectionAtTop(rcomp.getBounds(), dh + actualVal, rcomp); + //调整的时候可能有组件达到最小高度,判断下 + if (rcomp.getY() != bound.y) { + clearCompsList(); + initCompsList(); + dealDirectionAtTop(rcomp.getBounds(), bound.y - rcomp.getY() - minHeight - actualVal, rcomp); + ry = rcomp.getY(); + int rx = rcomp.getX(); + rcomp.setBounds(rx, ry, rw, minHeight); + recalculateChildrenSize(rx, bound.y, rw, rh - dh - actualVal); + recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); + return; + } + } else { + // 右侧控件底部对齐 + if (rh + ry == bound.y + bound.height) { + rcomp.setSize(rw, dh); + bound.width += rw; + bound.width += actualVal; + } else { + recalculateChildrenSize(bound.x, ry + rh + actualVal, bound.width, bound.height + bound.y - rh - ry - actualVal); + recalculateChildrenSize(bound.x, bound.y, bound.width, ry + rh - bound.y); + return; + } + } + recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); + } + + private void calculateNoRelatedWhileRightBott(Rectangle bound, Component rcomp) { + rcomp = container.getBottomRightComp(bound.x, bound.y, bound.height, bound.width); + int ry = rcomp.getY(); + int rh = rcomp.getHeight(); + int rw = rcomp.getWidth(); + int dh = ry + rh - bound.y - bound.height - actualVal; + if (dh < minHeight) { + dealDirectionABottom(rcomp.getBounds(), -dh - actualVal, rcomp); + //调整的时候可能有组件达到最小高度,判断下 + if (rcomp.getHeight() + ry != bound.y + bound.height) { + clearCompsList(); + initCompsList(); + dh = ry + rcomp.getHeight() - bound.y - bound.height - actualVal; + dealDirectionABottom(rcomp.getBounds(), minHeight - dh, rcomp); + rh = rcomp.getHeight(); + int rx = rcomp.getX(); + rcomp.setBounds(rx, bound.y + bound.height + actualVal, rw, minHeight); + recalculateChildrenSize(rx, ry, rw, rh - minHeight - actualVal); + recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); + return; + } + } else { + if (ry == bound.y) { + rcomp.setBounds(rcomp.getX(), bound.y + bound.height + actualVal, rw, dh); + bound.width += rw; + bound.width += actualVal; + } else { + recalculateChildrenSize(bound.x, bound.y, bound.width, ry - bound.y - actualVal); + recalculateChildrenSize(bound.x, ry, bound.width, bound.height - ry + bound.y); + return; + } + } + recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); + } + + private int getMinWidth(List comps) { + if (comps.isEmpty()) { + return 0; + } + int minWidth = container.getWidth() - margin.getLeft() - margin.getRight(); + for (int i = 0, size = comps.size(); i < size; i++) { + minWidth = minWidth > comps.get(i).getWidth() ? comps.get(i).getWidth() : minWidth; + } + return minWidth; + } + + private int getMinHeight(List comps) { + if (comps.isEmpty()) { + return 0; + } + int minH = container.getHeight() - margin.getTop() - margin.getBottom(); + for (int i = 0, size = comps.size(); i < size; i++) { + minH = minH > comps.get(i).getHeight() ? comps.get(i).getHeight() : minH; + } + return minH; + } + + // 删除时计算待删除组件上下侧的组件是否何其对齐 + private int getAllHeight(List comps) { + int allHeight = 0; + if (comps.isEmpty()) { + return allHeight; + } + int n = comps.size(); + for (int i = 0; i < n; i++) { + allHeight += comps.get(i).getHeight(); + } + allHeight += (n - 1) * actualVal; + return allHeight; + } + + private int getAllWidth(List comps) { + int allWidth = 0; + if (comps.isEmpty()) { + return allWidth; + } + int n = comps.size(); + for (int i = 0; i < n; i++) { + allWidth += comps.get(i).getWidth(); + } + allWidth += (n - 1) * actualVal; + return allWidth; + } + + /** + * 获取有哪些相关联的组件 + */ + protected void calculateRelatedComponent(int objX, int objY, int objWidth, int objHeight) { + int count = container.getComponentCount(); + for (int i = 0; i < count; i++) { + Component relatComp = container.getComponent(i); + int rx = relatComp.getX(); + int ry = relatComp.getY(); + int rwidth = relatComp.getWidth(); + int rheight = relatComp.getHeight(); + int verti = ry - objY; + int hori = rx - objX; + boolean isHori = verti >= 0 && objHeight >= (rheight + verti); + boolean isVerti = hori >= 0 && objWidth >= (rwidth + hori); + if (isHori && (objX + objWidth + actualVal) == rx) { + rightComps.add(relatComp); + } else if (isHori && objX == (rx + rwidth + actualVal)) { + leftComps.add(relatComp); + } else if (isVerti && (objY + objHeight + actualVal) == ry) { + downComps.add(relatComp); + } else if (isVerti && objY == (ry + rheight + actualVal)) { + upComps.add(relatComp); + } + } + } + + /** + * 拖拽组件时遍历某一侧组件得到该侧组件能够缩放的最小宽度,tab布局最小宽度 = 内部组件数 * 单个组件最小宽度 + * + * @param list 某一侧组件的集合 如:leftComps + * @return int 最小宽度 + */ + private int getCompsMinWidth(List list) { + return getMaxCompsNum(list, true) * WLayout.MIN_WIDTH; + } + + /** + * 拖拽组件遍历某一侧得到该侧组件能够缩放的最小高度,tab布局最小高度 = 内部组件数 * 单个组件最小高度 + 标题高度 + * + * @param list 某一侧组件集合 + * @return int 最小高度 + */ + private int getCompsMinHeight(List list) { + for (int i = 0; i < list.size(); i++) { + XCreator creator = (XCreator) list.get(i); + ArrayList childrenList = creator.getTargetChildrenList(); + if (!childrenList.isEmpty()) { + return getMaxCompsNum(list, false) * WLayout.MIN_HEIGHT + WCardMainBorderLayout.TAB_HEIGHT; + } + } + return WLayout.MIN_HEIGHT; + } + + /** + * 根据子组件的横(纵)坐标获取某一侧组件的最大内部组件数 + * + * @param list 某一侧组件集合 + * @param isHor 是否以横坐标为准 + * @return int 最大内部组件数 + */ + private int getMaxCompsNum(List list, boolean isHor) { + int maxCompNums = 1; + for (int i = 0, size = list.size(); i < size; i++) { + XCreator creator = (XCreator) list.get(i); + ArrayList childrenList = creator.getTargetChildrenList(); + int count = childrenList.size(); + if (count > 0) { + for (int j = 0; j < count; j++) { + XWTabFitLayout tabLayout = (XWTabFitLayout) childrenList.get(j); + int[] positions = isHor ? tabLayout.getHors(true) : tabLayout.getVeris(true); + int compNums = positions.length - 1; + maxCompNums = Math.max(compNums, maxCompNums); + } + } + } + return maxCompNums; + } + + /** + * 根据偏移量缩放内部组件大小,(tab布局用到) + * + * @param creator tab布局 + * @param offset 偏移量 + * @param isHor 是否为横向拖拽 + */ + private void adjustCompsSize(XCreator creator, int offset, boolean isHor) { + ArrayList childrenList = creator.getTargetChildrenList(); + int size = childrenList.size(); + if (size > 0) { + for (int j = 0; j < size; j++) { + XWTabFitLayout tabLayout = (XWTabFitLayout) childrenList.get(j); + tabLayout.setBackupBound(tabLayout.getBounds()); + int refSize = isHor ? tabLayout.getWidth() : tabLayout.getHeight(); + double percent = (double) offset / refSize; + if (percent < 0 && !tabLayout.canReduce(percent)) { + return; + } + setAdjustedSize(tabLayout, offset, isHor); + for (int m = 0; m < tabLayout.getComponentCount(); m++) { + XCreator childCreator = tabLayout.getXCreator(m); + BoundsWidget wgt = tabLayout.toData().getBoundsWidget(childCreator.toData()); + wgt.setBounds(tabLayout.getComponent(m).getBounds()); + } + adjustCreatorsSize(percent, tabLayout, isHor); + } + + } + } + + // 纵向拖拽,先将tab布局的高度设置为拖拽后的实际高度 + private void setAdjustedHeight(XWTabFitLayout tabLayout, int offset) { + tabLayout.setSize(tabLayout.getWidth(), tabLayout.getHeight() + offset); + } + + // 横向拖拽,先将tab布局的宽度设置为拖拽后的实际宽度 + private void setAdjustedSize(XWTabFitLayout tabLayout, int offset, boolean isHor) { + if (offset < 0) { + // 缩放时需要备份原tab布局宽高 + tabLayout.setReferDim(new Dimension(tabLayout.getWidth(), tabLayout.getHeight())); + } + if (isHor) { + tabLayout.setSize(tabLayout.getWidth() + offset, tabLayout.getHeight()); + return; + } + setAdjustedHeight(tabLayout, offset); + } + + // 按照拖拽偏移量,对tab布局进行缩放 + private void adjustCreatorsSize(double percent, XWTabFitLayout tabLayout, boolean isHor) { + if (isHor) { + tabLayout.adjustCreatorsWidth(percent); + return; + } + tabLayout.adjustCreatorsHeight(percent); + } + + + /** + * 删除或拉伸控件右边框 调整右侧组件位置大小 + * + * @param objX 调整后的坐标x + * @param objWidth 调整后的宽度 + */ + protected void calculateRightRelatComponent(int objX, int objWidth) { + int count = rightComps.size(); + for (int i = 0; i < count; i++) { + XCreator creator = (XCreator) rightComps.get(i); + adjustCompsSize(creator, objWidth, true); + int ry = creator.getY(); + int rwidth = creator.getWidth(); + int rheight = creator.getHeight(); + creator.setLocation(objX, ry); + creator.setSize(rwidth + objWidth, rheight); + } + } + + /** + * 实际拖拽偏移量是否超出了可调整的宽度范围 + * + * @param offset 实际偏移量 + * @return boolean 是否超出调整范围 + */ + private boolean isBeyondAdjustWidthScope(int offset) { + boolean isBeyondScope = false; + isBeyondScope = offset < 0 ? isBeyondWidthScope(offset, leftComps) : isBeyondWidthScope(offset, rightComps); + return isBeyondScope; + } + + // 实际拖拽偏移量是否超出某一侧的可调整宽度 + private boolean isBeyondWidthScope(int offset, List compsList) { + int compMinWidth = getCompsMinWidth(compsList); + for (int i = 0; i < compsList.size(); i++) { + XCreator creator = (XCreator) compsList.get(i); + if (Math.abs(offset) > (creator.getWidth() - compMinWidth)) { + return true; + } + } + return false; + } + + /** + * 删除或拉伸控件左边框时 调整左侧的组件位置大小; + */ + protected boolean calculateLefttRelatComponent(int objWidth) { + if (isBeyondAdjustWidthScope(objWidth)) { + return false; + } + int count = leftComps.size(); + for (int i = 0; i < count; i++) { + XCreator creator = (XCreator) leftComps.get(i); + adjustCompsSize(creator, objWidth, true); + int rwidth = creator.getWidth(); + int rheight = creator.getHeight(); + creator.setSize(rwidth + objWidth, rheight); + } + return true; + } + + /** + * 删除或拉伸下边框 调整下方的组件位置大小 + */ + protected void calculateDownRelatComponent(int objY, int objHeight) { + int count = downComps.size(); + for (int i = 0; i < count; i++) { + XCreator creator = (XCreator) downComps.get(i); + adjustCompsSize(creator, objHeight, false); + int rx = creator.getX(); + int rwidth = creator.getWidth(); + int rheight = creator.getHeight(); + creator.setLocation(rx, objY); + creator.setSize(rwidth, rheight + objHeight); + } + } + + /** + * 实际拖拽偏移量是否超出了可调整的高度范围 + * + * @param offset 实际偏移量 + * @return boolean 是否超出调整范围 + */ + private boolean isBeyondAdjustHeightScope(int offset) { + boolean isBeyondScope = false; + isBeyondScope = offset < 0 ? isBeyondHeightScope(offset, upComps) : isBeyondHeightScope(offset, downComps); + return isBeyondScope; + } + + // 实际拖拽偏移量是否超出某一侧的可调整高度 + private boolean isBeyondHeightScope(int offset, List compsList) { + int minHeight = getCompsMinHeight(compsList); + for (int i = 0; i < compsList.size(); i++) { + XCreator creator = (XCreator) compsList.get(i); + if (Math.abs(offset) > (creator.getHeight() - minHeight)) { + return true; + } + } + return false; + } + + /** + * 删除或拉伸上边框 调整上方的组件位置大小 + */ + protected boolean calculateUpRelatComponent(int objHeight) { + if (isBeyondAdjustHeightScope(objHeight)) { + return false; + } + int count = upComps.size(); + for (int i = 0; i < count; i++) { + XCreator creator = (XCreator) upComps.get(i); + adjustCompsSize(creator, objHeight, false); + int rwidth = creator.getWidth(); + int rheight = creator.getHeight(); + creator.setSize(rwidth, rheight + objHeight); + } + return true; + } + + /** + * 不调整,只计算位置 + * + * @return child的位置 + */ + public int[] getChildPosition(Component currentComp, XCreator child, int x, int y) { + return super.getChildPosition(currentComp, child, x, y); + } + + @Override + public ConstraintsGroupModel getLayoutConstraints(XCreator creator) { + return new FRFitLayoutConstraints((XWFitLayout) container, creator); + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java index 63a70e1bb..352a3ba7a 100644 --- a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java +++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java @@ -1,108 +1,104 @@ -/** - * - */ -package com.fr.design.designer.beans.adapters.layout; - - -import com.fr.design.beans.GroupModel; -import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWParameterLayout; -import com.fr.design.designer.creator.XWidgetCreator; -import com.fr.design.designer.creator.cardlayout.XWCardLayout; -import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; -import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; -import com.fr.design.designer.properties.FRTabFitLayoutPropertiesGroupModel; -import com.fr.design.utils.ComponentUtils; -import com.fr.form.ui.LayoutBorderStyle; -import com.fr.form.ui.container.WBorderLayout; -import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; -import com.fr.general.ComparatorUtils; - -import java.awt.*; - -/** - * tab布局tabFit适配器 - * - * @author focus - * @date 2014-6-24 - */ -public class FRTabFitLayoutAdapter extends FRFitLayoutAdapter { - //标题栏高度对tab布局内部组件的y坐标造成了偏移 - private static int TAB_HEIGHT = 40; - - /** - * 构造函数 - * - * @param container XWTabFitLayout容器 - */ - public FRTabFitLayoutAdapter(XLayoutContainer container) { - super(container); - } - - /** - * 返回布局自身属性,方便一些特有设置在layout刷新时处理 - */ - @Override - public GroupModel getLayoutProperties() { - XWTabFitLayout xfl = (XWTabFitLayout) container; - return new FRTabFitLayoutPropertiesGroupModel(xfl); - } - - /** - * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 - * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 - * - * @param creator 被添加的新组件 - * @param x 添加的位置x,该位置是相对于container的 - * @param y 添加的位置y,该位置是相对于container的 - * @return 是否添加成功,成功返回true,否则false - */ - @Override - public boolean addBean(XCreator creator, int x, int y) { - // 经过accept判断后,container会被改变,先备份 - XLayoutContainer backUpContainer = container; - Rectangle rect = ComponentUtils.getRelativeBounds(container); - - int posX = x - rect.x; - int posY = y - rect.y; - if (!accept(creator, posX, posY)) { - return false; - } - // posX,posY是新拖入组件相对于容器的位置,若在tab布局的边缘,则需要把新组件添加到 - // 父层自适应布局中,这时候的添加位置就是tab布局所在的位置 - if (this.intersectsEdge(posX, posY, backUpContainer)) { - if (!ComparatorUtils.equals(backUpContainer.getOuterLayout(), backUpContainer.getBackupParent())) { - XWTabFitLayout tabLayout = (XWTabFitLayout) backUpContainer; - y = adjustY(y, tabLayout); - } - addComp(creator, x, y); - ((XWidgetCreator) creator).recalculateChildrenSize(); - return true; - } - // 如果不在边缘,容器为本自适应布局,增加组件的位置就是相对于容器的位置 - addComp(creator, posX, posY); - ((XWidgetCreator) creator).recalculateChildrenSize(); - return true; - } - - // tab布局的纵坐标受到tab高度的影响,判断的上边界取得是里面XWTabFitLayout的上边界, - // 实际计算的时候的纵坐标用了外层的CardMainBorerLayout,需要将tab高度减掉 - //将y值变为相对坐标以实现获取到鼠标drop位置的控件 - //TODO 可以直接在这边将x,y都变成相对坐标,这样在后面判断拖进来的新控件放置方式的时候就不用再判断了 - private int adjustY(int y, XWTabFitLayout tabLayout) { - XWCardLayout cardLayout = (XWCardLayout) tabLayout.getBackupParent(); - LayoutBorderStyle style = cardLayout.toData().getBorderStyle(); - if (container.getLocation().y == WBorderLayout.DEFAULT_SIZE) { - y = y - WBorderLayout.DEFAULT_SIZE; - } - if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) { - y = y - WCardMainBorderLayout.TAB_HEIGHT; - } - return y; - } - - protected Rectangle getLayoutBound(XWCardMainBorderLayout mainLayout) { - return ComponentUtils.getRelativeBounds(mainLayout); - } +/** + * + */ +package com.fr.design.designer.beans.adapters.layout; + + +import com.fr.design.beans.GroupModel; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWidgetCreator; +import com.fr.design.designer.creator.cardlayout.XWCardLayout; +import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; +import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; +import com.fr.design.designer.properties.FRTabFitLayoutPropertiesGroupModel; +import com.fr.design.utils.ComponentUtils; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.container.WBorderLayout; +import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; +import com.fr.general.ComparatorUtils; + +import java.awt.*; + +/** + * tab布局tabFit适配器 + * + * @author focus + * @date 2014-6-24 + */ +public class FRTabFitLayoutAdapter extends FRFitLayoutAdapter { + + /** + * 构造函数 + * + * @param container XWTabFitLayout容器 + */ + public FRTabFitLayoutAdapter(XLayoutContainer container) { + super(container); + } + + /** + * 返回布局自身属性,方便一些特有设置在layout刷新时处理 + */ + @Override + public GroupModel getLayoutProperties() { + XWTabFitLayout xfl = (XWTabFitLayout) container; + return new FRTabFitLayoutPropertiesGroupModel(xfl); + } + + /** + * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 + * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 + * + * @param creator 被添加的新组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否添加成功,成功返回true,否则false + */ + @Override + public boolean addBean(XCreator creator, int x, int y) { + // 经过accept判断后,container会被改变,先备份 + XLayoutContainer backUpContainer = container; + Rectangle rect = ComponentUtils.getRelativeBounds(container); + int posX = x - rect.x; + int posY = y - rect.y; + if (!accept(creator, posX, posY)) { + return false; + } + // posX,posY是新拖入组件相对于容器的位置,若在tab布局的边缘,则需要把新组件添加到l + // 父层自适应布局中,这时候的添加位置就是tab布局所在的位置 + if (this.intersectsEdge(posX, posY, backUpContainer)) { + if (!ComparatorUtils.equals(backUpContainer.getOuterLayout(), backUpContainer.getBackupParent())) { + XWTabFitLayout tabLayout = (XWTabFitLayout) backUpContainer; + y = adjustY(y, tabLayout); + } + addComp(creator, x, y); + ((XWidgetCreator) creator).recalculateChildrenSize(); + return true; + } + // 如果不在边缘,容器为本自适应布局,增加组件的位置就是相对于容器的位置 + addComp(creator, posX, posY); + ((XWidgetCreator) creator).recalculateChildrenSize(); + return true; + } + + // tab布局的纵坐标受到tab高度的影响,判断的上边界取得是里面XWTabFitLayout的上边界, + // 实际计算的时候的纵坐标用了外层的CardMainBorerLayout,需要将tab高度减掉 + //将y值变为相对坐标以实现获取到鼠标drop位置的控件 + //TODO 可以直接在这边将x,y都变成相对坐标,这样在后面判断拖进来的新控件放置方式的时候就不用再判断了 + private int adjustY(int y, XWTabFitLayout tabLayout) { + XWCardLayout cardLayout = (XWCardLayout) tabLayout.getBackupParent(); + LayoutBorderStyle style = cardLayout.toData().getBorderStyle(); + if (container.getLocation().y == WBorderLayout.DEFAULT_SIZE) { + y = y - WBorderLayout.DEFAULT_SIZE; + } + if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) { + y = y - WCardMainBorderLayout.TAB_HEIGHT; + } + return y; + } + + protected Rectangle getLayoutBound(XWCardMainBorderLayout mainLayout) { + return ComponentUtils.getRelativeBounds(mainLayout); + } } \ No newline at end of file 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 a2a57c4ff..088f29a0a 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,19 +3,17 @@ */ package com.fr.design.designer.beans.location; -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.utils.ComponentUtils; -import com.fr.form.main.Form; import com.fr.form.ui.container.WAbsoluteLayout; -import com.fr.form.ui.container.WParameterLayout; import com.fr.form.ui.widget.BoundsWidget; +import java.awt.*; + /** * @author richer * @since 6.5.3 @@ -26,197 +24,184 @@ public abstract class AccessDirection implements Direction { private int ymin; private int xmin; - abstract int getCursor(); - - protected abstract Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer, - Rectangle oldbounds); - - protected int[] sorption(int x, int y,Rectangle current_bounds, FormDesigner designer) { - // 自适应布局不需要吸附线,但需要对齐线,对齐线后面处理 - if (!designer.hasWAbsoluteLayout()) { - designer.getStateModel().setEquidistantLine(null); - designer.getStateModel().setXAbsorptionline(null); - designer.getStateModel().setYAbsorptionline(null); - return new int[] { x, y }; - } else { - int posy = current_bounds.y; - - Point relativePoint = getRelativePoint(x, y, current_bounds,designer); - sorptionPoint(relativePoint,current_bounds, designer); - return new int[] { relativePoint.x, relativePoint.y }; - } - - } - - protected Point getRelativePoint(int x, int y, Rectangle current_bounds,FormDesigner designer) { - if (x < 0) { - x = 0; - } else if (x > designer.getRootComponent().getWidth() && designer.getSelectionModel().hasSelectionComponent()) { - x = designer.getRootComponent().getWidth(); - } + abstract int getCursor(); + + protected abstract Rectangle getDraggedBounds(int dx, int dy, Rectangle currentBounds, FormDesigner designer, + Rectangle oldBounds); + + protected int[] sorption(int x, int y, Rectangle currentBounds, FormDesigner designer) { + // 自适应布局不需要吸附线,但需要对齐线,对齐线后面处理 + if (!designer.hasWAbsoluteLayout()) { + designer.getStateModel().setEquidistantLine(null); + designer.getStateModel().setXAbsorptionline(null); + designer.getStateModel().setYAbsorptionline(null); + return new int[]{x, y}; + } else { + Point relativePoint = getRelativePoint(x, y, currentBounds, designer); + sorptionPoint(relativePoint, currentBounds, designer); + return new int[]{relativePoint.x, relativePoint.y}; + } + + } + + protected Point getRelativePoint(int x, int y, Rectangle currentBounds, FormDesigner designer) { + if (x < 0) { + x = 0; + } else if (x > designer.getRootComponent().getWidth() && designer.getSelectionModel().hasSelectionComponent()) { + x = designer.getRootComponent().getWidth(); + } //参数面板可以无下限拉长 - if (y < 0) { - y = 0; - } else if (y > designer.getRootComponent().getHeight() + designer.getParaHeight() && designer.getSelectionModel().hasSelectionComponent() + if (y < 0) { + y = 0; + } else if (y > designer.getRootComponent().getHeight() + designer.getParaHeight() && designer.getSelectionModel().hasSelectionComponent() && !designer.getSelectionModel().getSelection().getSelectedCreator().acceptType(XWParameterLayout.class)) { - y = designer.getRootComponent().getHeight() + designer.getParaHeight(); - } - return new Point(x, y); - } - - protected void sorptionPoint(Point point, Rectangle current_bounds,FormDesigner designer) { - boolean findInX = current_bounds.getWidth() <= MoveUtils.SORPTION_UNIT ? true : false; - boolean findInY = current_bounds.getHeight() <= MoveUtils.SORPTION_UNIT ? true : false; - 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 = getWidgetRelativeBounds(temp.getBounds(), selection); - if (!findInX) { - int x1 = bounds.x; - if (Math.abs(x1 - point.x) <= MoveUtils.SORPTION_UNIT) { - point.x = x1; - findInX = true; - } - int x2 = bounds.x + bounds.width; - if (Math.abs(x2 - point.x) <= MoveUtils.SORPTION_UNIT) { - point.x = x2; - findInX = true; - } - } - if (!findInY) { - int y1 = bounds.y; - if (Math.abs(y1 - point.y) <= MoveUtils.SORPTION_UNIT) { - point.y = y1; - findInY = true; - } - int y2 = bounds.y + bounds.height; - if (Math.abs(y2 - point.y) <= MoveUtils.SORPTION_UNIT) { - point.y = y2; - findInY = true; - } - - } - if (findInX && findInY) { - break; - } - - if (current_bounds.intersects(bounds) && !(layout instanceof WParameterLayout)){ - isWidgetsIntersect = true; - } - } - processRectangleIntersects(designer, point.x, point.y, isWidgetsIntersect); - setDesignerStateModelProperties(designer, findInX, findInY, current_bounds, point); - } - - private void setDesignerStateModelProperties (FormDesigner designer, boolean findInX, boolean findInY, Rectangle current_bounds, Point point) { - 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); - designer.getStateModel().setEquidistantLine(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){ + y = designer.getRootComponent().getHeight() + designer.getParaHeight(); + } + return new Point(x, y); + } + + protected void sorptionPoint(Point point, Rectangle currentBounds, FormDesigner designer) { + boolean findInX = currentBounds.getWidth() <= MoveUtils.SORPTION_UNIT; + boolean findInY = currentBounds.getHeight() <= MoveUtils.SORPTION_UNIT; + WAbsoluteLayout layout = getLayout(designer); + FormSelection selection = designer.getSelectionModel().getSelection(); + 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 = getWidgetRelativeBounds(temp.getBounds(), selection); + if (!findInX) { + int x1 = bounds.x; + if (Math.abs(x1 - point.x) <= MoveUtils.SORPTION_UNIT) { + point.x = x1; + findInX = true; + } + int x2 = bounds.x + bounds.width; + if (Math.abs(x2 - point.x) <= MoveUtils.SORPTION_UNIT) { + point.x = x2; + findInX = true; + } + } + if (!findInY) { + int y1 = bounds.y; + if (Math.abs(y1 - point.y) <= MoveUtils.SORPTION_UNIT) { + point.y = y1; + findInY = true; + } + int y2 = bounds.y + bounds.height; + if (Math.abs(y2 - point.y) <= MoveUtils.SORPTION_UNIT) { + point.y = y2; + findInY = true; + } + + } + if (findInX && findInY) { + break; + } + + } + setDesignerStateModelProperties(designer, findInX, findInY, currentBounds, point); + } + + private void setDesignerStateModelProperties(FormDesigner designer, boolean findInX, boolean findInY, Rectangle + currentBounds, Point point) { + designer.getStateModel().setXAbsorptionline(findInX && currentBounds.getWidth() > MoveUtils.SORPTION_UNIT ? Absorptionline.createXAbsorptionline(point.x) : null); + designer.getStateModel().setYAbsorptionline(findInY && currentBounds.getHeight() > MoveUtils.SORPTION_UNIT ? Absorptionline.createYAbsorptionline(point.y) : null); + designer.getStateModel().setEquidistantLine(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 WAbsoluteLayout getLayout(final FormDesigner designer) { XLayoutContainer formLayoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator( designer.getTarget().getContainer()); WAbsoluteLayout layout; - 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{ + 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(); } - return layout; + return layout; } - /** - * 拖拽 - * @param dx 坐标x - * @param dy 坐标y - * @param designer 设计界面 - */ - public void drag(int dx, int dy, FormDesigner designer) { - Rectangle rec = getDraggedBounds(dx, dy, designer.getSelectionModel().getSelection().getRelativeBounds(), designer, designer.getSelectionModel().getSelection().getBackupBounds()); + /** + * 拖拽 + * + * @param dx 坐标x + * @param dy 坐标y + * @param designer 设计界面 + */ + public void drag(int dx, int dy, FormDesigner designer) { + Rectangle rec = getDraggedBounds(dx, dy, designer.getSelectionModel().getSelection().getRelativeBounds(), designer, designer.getSelectionModel().getSelection().getBackupBounds()); + if (rec != null) { + designer.getSelectionModel().getSelection().setSelectionBounds(rec, designer); + } else { + return; + } //设定控件最小高度21,因每次拖曳至少移动1,防止控件高度等于21时,拖曳导致rec.y的变化使得控件不停的向上或向下移动。 - if(rec.height == MINHEIGHT){ + if (rec.height == MINHEIGHT) { ymin = rec.y; } - if(rec.height == MINHEIGHT - 1){ + if (rec.height == MINHEIGHT - 1) { ymin = ymin == rec.y ? rec.y : rec.y - 1; } - if(rec.height < MINHEIGHT){ + if (rec.height < MINHEIGHT) { rec.height = MINHEIGHT; rec.y = ymin; } // 增加下宽度也设最小为21 if (rec.width == MINWIDTH) { - xmin = rec.x; + xmin = rec.x; } - if(rec.width == MINWIDTH - 1){ - xmin = xmin == rec.x ? rec.x : rec.x - 1; + if (rec.width == MINWIDTH - 1) { + xmin = xmin == rec.x ? rec.x : rec.x - 1; } if (rec.width < MINWIDTH) { - rec.width = MINWIDTH; - rec.x = xmin; + rec.width = MINWIDTH; + rec.x = xmin; + } + + } + + /** + * 更新鼠标指针形状 + * + * @param formEditor 设计界面组件 + */ + public void updateCursor(FormDesigner formEditor) { + + // 调用位置枚举的多态方法getCursor获取鼠标形状 + int type = getCursor(); + + if (type != formEditor.getCursor().getType()) { + // 设置当前形状 + formEditor.setCursor(Cursor.getPredefinedCursor(type)); } - if(rec != null) { - designer.getSelectionModel().getSelection().setSelectionBounds(rec, designer); - } - } - - /** - * 更新鼠标指针形状 - * @param formEditor 设计界面组件 - */ - public void updateCursor(FormDesigner formEditor) { - - // 调用位置枚举的多态方法getCursor获取鼠标形状 - int type = getCursor(); - - if (type != formEditor.getCursor().getType()) { - // 设置当前形状 - formEditor.setCursor(Cursor.getPredefinedCursor(type)); - } - } - - /** - * 生成组件备用的bound - * @param formEditor 设计界面组件 - */ - public void backupBounds(FormDesigner formEditor) { - formEditor.getSelectionModel().getSelection().backupBounds(); - } + } + + /** + * 生成组件备用的bound + * + * @param formEditor 设计界面组件 + */ + public void backupBounds(FormDesigner formEditor) { + formEditor.getSelectionModel().getSelection().backupBounds(); + } } \ No newline at end of file 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 834b28d74..c364317f1 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 @@ -1,328 +1,418 @@ -package com.fr.design.designer.beans.models; - -import java.awt.LayoutManager; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.event.MouseEvent; -import java.util.ArrayList; - -import com.fr.design.designer.beans.AdapterBus; -import com.fr.design.designer.beans.LayoutAdapter; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.design.designer.beans.location.Direction; -import com.fr.design.designer.beans.location.Location; -import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWFitLayout; -import com.fr.design.designer.creator.XWParameterLayout; -import com.fr.design.form.util.XCreatorConstants; -import com.fr.design.mainframe.FormDesigner; -import com.fr.design.mainframe.FormSelection; -import com.fr.design.mainframe.FormSelectionUtils; -import com.fr.design.utils.gui.LayoutUtils; -import com.fr.stable.ArrayUtils; - -/** - * 该model保存当前选择的组件和剪切版信息 - */ -public class SelectionModel { - private static final int DELTA_X_Y = 20; //粘贴时候的偏移距离 - private static FormSelection CLIP_BOARD = new FormSelection(); - private FormDesigner designer; - private FormSelection selection; - private Rectangle hotspot_bounds; - - public SelectionModel(FormDesigner designer) { - this.designer = designer; - selection = new FormSelection(); - } - - /** - * 重置。清空formSelction以及选择区域 - */ - public void reset() { - selection.reset(); - hotspot_bounds = null; - } - - /** - * formSelction是否为空 - * @return 是否为空 - */ - public static boolean isEmpty(){ - return CLIP_BOARD.isEmpty(); - } - - /** - * 鼠标点击一下,所选中的单个组件。按下Ctrl或者shift键时鼠标可以进行多选 - * @param e 鼠标事件 - */ - public void selectACreatorAtMouseEvent(MouseEvent e) { - if (!e.isControlDown() && !e.isShiftDown()) { - // 如果Ctrl或者Shift键盘没有按下,则清除已经选择的组件 - selection.reset(); - } - - // 获取e所在的组件 - XCreator comp = designer.getComponentAt(e); - - //布局组件的顶层布局如不可编辑,要获取其顶层布局 - XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(comp).getTopLayout(); - if(topLayout != null && !topLayout.isEditable()){ - comp = topLayout; - } - - // 如果父层是scale和title两个专属容器,返回其父层,组件本身是不让被选中的 - if (comp != designer.getRootComponent() && comp != designer.getParaComponent()) { - XCreator parentContainer = (XCreator) comp.getParent(); - comp = parentContainer.isDedicateContainer() ? parentContainer : comp; - } - if (selection.removeSelectedCreator(comp) || selection.addSelectedCreator(comp)) { - designer.getEditListenerTable().fireCreatorModified(comp, DesignerEvent.CREATOR_SELECTED); - designer.repaint(); - } - } - - /** - * 将所选组件剪切到剪切板上 - */ - public void cutSelectedCreator2ClipBoard() { - if (hasSelectionComponent()) { - selection.cut2ClipBoard(CLIP_BOARD); - designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED); - designer.repaint(); - } - } - - /** - * 复制当前选中的组件到剪切板 - */ - public void copySelectedCreator2ClipBoard() { - if (!selection.isEmpty()) { - selection.copy2ClipBoard(CLIP_BOARD); - } - } - - /** - * 从剪切板粘帖组件 - * @return 否 - */ - public boolean pasteFromClipBoard() { - if (!CLIP_BOARD.isEmpty()) { - XLayoutContainer parent = null; - if (!hasSelectionComponent()) { - FormSelectionUtils.paste2Container(designer, designer.getRootComponent(),CLIP_BOARD, DELTA_X_Y, DELTA_X_Y); - } else { - parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator()); - if (parent != null) { - Rectangle rec = selection.getSelctionBounds(); - FormSelectionUtils.paste2Container(designer, parent,CLIP_BOARD, rec.x + DELTA_X_Y, rec.y + DELTA_X_Y); - } - } - } else { - Toolkit.getDefaultToolkit().beep(); - } - return false; - } - - public FormSelection getSelection() { - return selection; - } - - /** - * 删除当前所有选择的组件 - */ - public void deleteSelection() { - XCreator[] roots = selection.getSelectedCreators(); - - if (roots.length > 0) { - for (XCreator creator : roots) { - if(creator.acceptType(XWParameterLayout.class)){ - designer.removeParaComponent(); - } - - removeCreatorFromContainer(creator, creator.getWidth(), creator.getHeight()); - creator.removeAll(); - // 清除被选中的组件 - selection.reset(); - } - setSelectedCreator(designer.getRootComponent()); - // 触发事件 - designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_DELETED); - designer.repaint(); - } - } - - /** - * 从选择组件中删除某组件 - * - * @param creator 组件 - * @param creatorWidth 组件之前宽度 - * @param creatorHeight 组件之前高度 - */ - public void removeCreator(XCreator creator, int creatorWidth, int creatorHeight) { - selection.removeCreator(creator); - removeCreatorFromContainer(creator, creatorWidth, creatorHeight); - designer.repaint(); - } - - /** - * 设置选择区域 - */ - public void setHotspotBounds(Rectangle rect) { - hotspot_bounds = rect; - } - - /** - * 获得当前选择区域 - */ - public Rectangle getHotspotBounds() { - return hotspot_bounds; - } - - private void removeCreatorFromContainer(XCreator creator, int creatorWidth, int creatorHeight) { - XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator); - if (parent == null) { - return; - } - boolean changeCreator = creator.shouldScaleCreator() || creator.hasTitleStyle(); - if (parent.acceptType(XWFitLayout.class) && changeCreator) { - creator = (XCreator) creator.getParent(); - } - parent.getLayoutAdapter().removeBean(creator, creatorWidth, creatorHeight); - // 删除其根组件,同时就删除了同时被选择的叶子组件 - parent.remove(creator); - LayoutManager layout = parent.getLayout(); - - if (layout != null) { - // 刷新组件容器的布局 - LayoutUtils.layoutContainer(parent); - } - } - - /** - * 是否有组件被选择。如果所选组件是最底层容器,也视为无选择 - * @return 是则返回true - */ - public boolean hasSelectionComponent() { - return !selection.isEmpty() && selection.getSelectedCreator().getParent() != null; - } - - /** - * 移动组件至指定位置 - * @param x 坐标x - * @param y 坐标y - */ - public void move(int x, int y) { - for (XCreator creator : selection.getSelectedCreators()) { - creator.setLocation(creator.getX() + x, creator.getY() + y); - LayoutAdapter layoutAdapter = AdapterBus.searchLayoutAdapter(designer, creator); - if (layoutAdapter != null) { - layoutAdapter.fix(creator); - } - } - designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(), - DesignerEvent.CREATOR_SELECTED); - } - - /** - * 释放捕获 - */ - public void releaseDragging() { - designer.setPainter(null); - selection.fixCreator(designer); - designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(), - DesignerEvent.CREATOR_RESIZED); - } - - public Direction getDirectionAt(MouseEvent e) { - Direction dir; - if (e.isControlDown() || e.isShiftDown()) { - XCreator creator = designer.getComponentAt(e.getX(), e.getY(), selection.getSelectedCreators()); - if (creator != designer.getRootComponent() && selection.addedable(creator)) { - return Location.add; - } - } - if (hasSelectionComponent()) { - int x = e.getX() + designer.getArea().getHorizontalValue(); - int y = e.getY() + designer.getArea().getVerticalValue(); - dir = getDirection(selection.getRelativeBounds(), x, y); - if (selection.size() == 1) { - if (!ArrayUtils.contains(selection.getSelectedCreator().getDirections(), dir.getActual())) { - dir = Location.outer; - } - } - } else { - dir = Location.outer; - } - - if (designer.getDesignerMode().isFormParameterEditor() && dir == Location.outer) { - dir = designer.getLoc2Root(e); - } - return dir; - } - - private Direction getDirection(Rectangle bounds, int x, int y) { - if (x < (bounds.x - XCreatorConstants.RESIZE_BOX_SIZ)) { - return Location.outer; - } else if ((x >= (bounds.x - XCreatorConstants.RESIZE_BOX_SIZ)) && (x <= bounds.x)) { - if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) { - return Location.outer; - } else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) { - return Location.left_top; - } else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) { - return Location.left; - } else if ((y >= (bounds.y + bounds.height)) - && (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) { - return Location.left_bottom; - } else { - return Location.outer; - } - } else if ((x > bounds.x) && (x < (bounds.x + bounds.width))) { - if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) { - return Location.outer; - } else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) { - return Location.top; - } else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) { - return Location.inner; - } else if ((y >= (bounds.y + bounds.height)) - && (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) { - return Location.bottom; - } else { - return Location.outer; - } - } else if ((x >= (bounds.x + bounds.width)) - && (x <= (bounds.x + bounds.width + XCreatorConstants.RESIZE_BOX_SIZ))) { - if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) { - return Location.outer; - } else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) { - return Location.right_top; - } else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) { - return Location.right; - } else if ((y >= (bounds.y + bounds.height)) - && (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) { - return Location.right_bottom; - } else { - return Location.outer; - } - } else { - return Location.outer; - } - } - - private void fireCreatorSelected() { - designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(), - DesignerEvent.CREATOR_SELECTED); - } - - public void setSelectedCreator(XCreator rootComponent) { - selection.setSelectedCreator(rootComponent); - fireCreatorSelected(); - } - - public void setSelectedCreators(ArrayList rebuildSelection) { - selection.setSelectedCreators(rebuildSelection); - fireCreatorSelected(); - } +package com.fr.design.designer.beans.models; + +import com.fr.design.designer.beans.AdapterBus; +import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.beans.location.Direction; +import com.fr.design.designer.beans.location.Location; +import com.fr.design.designer.creator.*; +import com.fr.design.designer.creator.cardlayout.XWCardLayout; +import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; +import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; +import com.fr.design.form.util.XCreatorConstants; +import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.FormSelection; +import com.fr.design.mainframe.FormSelectionUtils; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.stable.ArrayUtils; + +import java.awt.*; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + +/** + * 该model保存当前选择的组件和剪切版信息 + */ +public class SelectionModel { + //被粘贴组件在所选组件位置处往下、往右各错开20像素。执行多次粘贴时,在上一次粘贴的位置处错开20像素。 + private static final int DELTA_X_Y = 20; //粘贴时候的偏移距离 + private static final int BORDER_PROPORTION = 20; + private static FormSelection clipboard = new FormSelection(); + private FormDesigner designer; + private FormSelection selection; + private Rectangle hotspotBounds; + + public SelectionModel(FormDesigner designer) { + this.designer = designer; + selection = new FormSelection(); + } + + /** + * 重置。清空formSelction以及选择区域 + */ + public void reset() { + selection.reset(); + hotspotBounds = null; + } + + /** + * formSelction是否为空 + * + * @return 是否为空 + */ + public static boolean isEmpty() { + return clipboard.isEmpty(); + } + + /** + * 鼠标点击一下,所选中的单个组件。按下Ctrl或者shift键时鼠标可以进行多选 + * + * @param e 鼠标事件 + */ + public void selectACreatorAtMouseEvent(MouseEvent e) { + if (!e.isControlDown() && !e.isShiftDown()) { + // 如果Ctrl或者Shift键盘没有按下,则清除已经选择的组件 + selection.reset(); + } + // 获取e所在的组件 + XCreator comp = designer.getComponentAt(e); + + //布局组件的顶层布局如不可编辑,要获取其顶层布局 + XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(comp).getTopLayout(); + if (topLayout != null && !topLayout.isEditable()) { + comp = topLayout; + } + + // 如果父层是scale和title两个专属容器,返回其父层,组件本身是不让被选中的 + if (comp != designer.getRootComponent() && comp != designer.getParaComponent()) { + XCreator parentContainer = (XCreator) comp.getParent(); + comp = parentContainer.isDedicateContainer() ? parentContainer : comp; + } + if (selection.removeSelectedCreator(comp) || selection.addSelectedCreator(comp)) { + designer.getEditListenerTable().fireCreatorModified(comp, DesignerEvent.CREATOR_SELECTED); + designer.repaint(); + } + } + + /** + * 将所选组件剪切到剪切板上 + */ + public void cutSelectedCreator2ClipBoard() { + if (hasSelectionComponent()) { + selection.cut2ClipBoard(clipboard); + designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED); + designer.repaint(); + } + } + + /** + * 复制当前选中的组件到剪切板 + */ + public void copySelectedCreator2ClipBoard() { + if (!selection.isEmpty()) { + selection.copy2ClipBoard(clipboard); + } + } + + /** + * 从剪切板粘帖组件 + * + * @return 否 + */ + public boolean pasteFromClipBoard() { + if (!clipboard.isEmpty()) { + if (!hasSelectionComponent()) { + //未选 + unselectedPaste(); + } else { + //已选 + selectedPaste(); + } + } else { + Toolkit.getDefaultToolkit().beep(); + } + return false; + } + + public FormSelection getSelection() { + return selection; + } + + /** + * 粘贴时未选择组件 + */ + private void unselectedPaste() { + if (designer.getClass().equals(FormDesigner.class)) { + if (selection.getSelectedCreator() instanceof XWFitLayout) { + if (selection.getSelectedCreator().getClass().equals(XWTabFitLayout.class)) { + Rectangle rec = selection.getRelativeBounds(); + //Tab布局 + FormSelectionUtils.paste2Container(designer, (XLayoutContainer) selection.getSelectedCreator(), + clipboard, + rec.x + rec.width / 2, + rec.y + BORDER_PROPORTION); + } else { + Rectangle rec = selection.getRelativeBounds(); + //自适应布局 + FormSelectionUtils.paste2Container(designer, designer.getRootComponent(), + clipboard, + rec.x + rec.width / 2, + rec.y + BORDER_PROPORTION); + } + } else { + //绝对布局 + //编辑器外面还有两层容器,使用designer.getRootComponent()获取到的是编辑器中层的容器,不是编辑器表层 + //当前选择的就是编辑器表层 + FormSelectionUtils.paste2Container(designer, (XLayoutContainer) selection.getSelectedCreator(), + clipboard, + DELTA_X_Y, + DELTA_X_Y); + } + } else { + //cpt本地组件复用,编辑器就一层,是最底层,使用designer.getRootComponent()就可以获取到 + //使用selection.getSelectedCreator()也应该是可以获取到的。 + FormSelectionUtils.paste2Container(designer, designer.getRootComponent(), + clipboard, + DELTA_X_Y, + DELTA_X_Y); + } + } + + /** + * 粘贴时选择组件 + */ + private void selectedPaste() { + XLayoutContainer parent = null; + //获取到编辑器的表层容器(已选的组件的父容器就是表层容器) + parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator()); + if (parent != null && selection.getSelectedCreator().getParent() instanceof XWFitLayout) { + //自适应布局 + Rectangle rec = selection.getRelativeBounds(); + FormSelectionUtils.paste2Container(designer, parent, clipboard, rec.x + rec.width / 2, rec.y + + rec.height - BORDER_PROPORTION); + } else if (parent != null && selection.getSelectedCreator().getParent() instanceof XWAbsoluteLayout) { + //绝对布局 + Rectangle rec = selection.getSelctionBounds(); + FormSelectionUtils.paste2Container(designer, parent, clipboard, rec.x + DELTA_X_Y, rec.y + DELTA_X_Y); + } + } + + /** + * 删除当前所有选择的组件 + */ + public void deleteSelection() { + XCreator[] roots = selection.getSelectedCreators(); + + if (roots.length > 0) { + for (XCreator creator : roots) { + if (creator.acceptType(XWParameterLayout.class)) { + designer.removeParaComponent(); + } + + removeCreatorFromContainer(creator, creator.getWidth(), creator.getHeight()); + creator.removeAll(); + // 清除被选中的组件 + selection.reset(); + } + setSelectedCreator(designer.getRootComponent()); + // 触发事件 + designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_DELETED); + designer.repaint(); + } + } + + /** + * 从选择组件中删除某组件 + * + * @param creator 组件 + * @param creatorWidth 组件之前宽度 + * @param creatorHeight 组件之前高度 + */ + public void removeCreator(XCreator creator, int creatorWidth, int creatorHeight) { + selection.removeCreator(creator); + removeCreatorFromContainer(creator, creatorWidth, creatorHeight); + designer.repaint(); + } + + /** + * 设置选择区域 + */ + public void setHotspotBounds(Rectangle rect) { + hotspotBounds = rect; + } + + /** + * 获得当前选择区域 + */ + public Rectangle getHotspotBounds() { + return hotspotBounds; + } + + private void removeCreatorFromContainer(XCreator creator, int creatorWidth, int creatorHeight) { + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator); + if (parent == null) { + return; + } + boolean changeCreator = creator.shouldScaleCreator() || creator.hasTitleStyle(); + if (parent.acceptType(XWFitLayout.class) && changeCreator) { + creator = (XCreator) creator.getParent(); + } + parent.getLayoutAdapter().removeBean(creator, creatorWidth, creatorHeight); + // 删除其根组件,同时就删除了同时被选择的叶子组件 + parent.remove(creator); + LayoutManager layout = parent.getLayout(); + + if (layout != null) { + // 刷新组件容器的布局 + LayoutUtils.layoutContainer(parent); + } + } + + /** + * 是否有组件被选择。如果所选组件是最底层容器,也视为无选择 + * + * @return 是则返回true + * yaoh.wu 不应该通过判断是否是最底层容器来判断是否选择了组件 + * 而是应该判断选择的容器是否是编辑器的最表层容器,也就是点击空白地方选择的容器 + * 但是直接判断选择的容器是否是编辑器最表层类型又会引发拖动时选不上的情况, + * 因此通过判断父容器来实现 + *

+ * 举例:frm组件复用 绝对布局情况下,不选择时有三层容器: + * 底层@see {@link com.fr.design.designer.creator.XWBorderLayout} + * 中层@see {@link XWFitLayout} + * 表层@see {@link com.fr.design.designer.creator.XWAbsoluteBodyLayout} + *

+ * 但是编辑窗口的最外层其实是表层@see {@link com.fr.design.designer.creator.XWAbsoluteBodyLayout}, + * 其他两层不是靠添加组件就可以编辑的。 + */ + public boolean hasSelectionComponent() { + XCreator selectionXCreator = selection.getSelectedCreator(); + if (designer.getClass().equals(FormDesigner.class)) { + //frm本地组件复用 + if (selectionXCreator != null) { + //选中的是否是tab布局编辑器本身 + boolean tabEditor = selectionXCreator.getClass().equals(XWCardMainBorderLayout.class) + || selectionXCreator.getClass().equals(XWCardLayout.class) + || selectionXCreator.getClass().equals(XWTabFitLayout.class); + //选中的是否是frm绝对布局编辑器本身 + boolean absoluteEditor = selectionXCreator.getClass().equals(XWAbsoluteBodyLayout.class); + //选中的是否是相对布局编辑器本身 + boolean relativeEditor = selectionXCreator.getClass().equals(XWFitLayout.class); + + return !(tabEditor || absoluteEditor || relativeEditor); + } else { + return false; + } + } else { + //cpt本地组件复用,selection.getSelectedCreator().getParent()=@XWParameterLayout instanceof @XWAbsoluteLayout + return selectionXCreator != null && selectionXCreator.getParent() != null; + } + } + + /** + * 移动组件至指定位置 + * + * @param x 坐标x + * @param y 坐标y + */ + public void move(int x, int y) { + for (XCreator creator : selection.getSelectedCreators()) { + creator.setLocation(creator.getX() + x, creator.getY() + y); + LayoutAdapter layoutAdapter = AdapterBus.searchLayoutAdapter(designer, creator); + if (layoutAdapter != null) { + layoutAdapter.fix(creator); + } + } + designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(), + DesignerEvent.CREATOR_SELECTED); + } + + /** + * 释放捕获 + */ + public void releaseDragging() { + designer.setPainter(null); + selection.fixCreator(designer); + designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(), + DesignerEvent.CREATOR_RESIZED); + } + + public Direction getDirectionAt(MouseEvent e) { + Direction dir; + if (e.isControlDown() || e.isShiftDown()) { + XCreator creator = designer.getComponentAt(e.getX(), e.getY(), selection.getSelectedCreators()); + if (creator != designer.getRootComponent() && selection.addedable(creator)) { + return Location.add; + } + } + if (hasSelectionComponent()) { + int x = e.getX() + designer.getArea().getHorizontalValue(); + int y = e.getY() + designer.getArea().getVerticalValue(); + dir = getDirection(selection.getRelativeBounds(), x, y); + if (selection.size() == 1 && !ArrayUtils.contains(selection.getSelectedCreator().getDirections(), dir + .getActual())) { + dir = Location.outer; + } + } else { + dir = Location.outer; + } + + if (designer.getDesignerMode().isFormParameterEditor() && dir == Location.outer) { + dir = designer.getLoc2Root(e); + } + return dir; + } + + private Direction getDirection(Rectangle bounds, int x, int y) { + if (x < (bounds.x - XCreatorConstants.RESIZE_BOX_SIZ)) { + return Location.outer; + } else if ((x >= (bounds.x - XCreatorConstants.RESIZE_BOX_SIZ)) && (x <= bounds.x)) { + if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) { + return Location.outer; + } else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) { + return Location.left_top; + } else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) { + return Location.left; + } else if ((y >= (bounds.y + bounds.height)) + && (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) { + return Location.left_bottom; + } else { + return Location.outer; + } + } else if ((x > bounds.x) && (x < (bounds.x + bounds.width))) { + if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) { + return Location.outer; + } else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) { + return Location.top; + } else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) { + return Location.inner; + } else if ((y >= (bounds.y + bounds.height)) + && (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) { + return Location.bottom; + } else { + return Location.outer; + } + } else if ((x >= (bounds.x + bounds.width)) + && (x <= (bounds.x + bounds.width + XCreatorConstants.RESIZE_BOX_SIZ))) { + if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) { + return Location.outer; + } else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) { + return Location.right_top; + } else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) { + return Location.right; + } else if ((y >= (bounds.y + bounds.height)) + && (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) { + return Location.right_bottom; + } else { + return Location.outer; + } + } else { + return Location.outer; + } + } + + private void fireCreatorSelected() { + designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(), + DesignerEvent.CREATOR_SELECTED); + } + + public void setSelectedCreator(XCreator rootComponent) { + selection.setSelectedCreator(rootComponent); + fireCreatorSelected(); + } + + public void setSelectedCreators(ArrayList rebuildSelection) { + selection.setSelectedCreators(rebuildSelection); + fireCreatorSelected(); + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java b/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java index 5b2f35c05..f223e5d8f 100644 --- a/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java +++ b/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java @@ -1,88 +1,96 @@ -/** - * - */ -package com.fr.design.designer.creator; - -import com.fr.form.ui.container.WLayout; - -import java.awt.*; -import java.beans.IntrospectionException; -import java.util.ArrayList; - -/** - * 一些控件专属的容器,如标题容器,sclae容器 - * @author jim - * @date 2014-11-7 - */ -public abstract class DedicateLayoutContainer extends XLayoutContainer { - - public DedicateLayoutContainer(WLayout widget, Dimension initSize) { - super(widget, initSize); - } - - /** - * 得到属性名 - * @return 属性名 - * @throws IntrospectionException - */ - public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException { - return new CRPropertyDescriptor[0]; - } - - /** - * 返回容器图标 - * - * @return - */ - @Override - public String getIconPath() { - if(this.getXCreator(XWScaleLayout.INDEX) != null){ - return this.getXCreator(XWScaleLayout.INDEX).getIconPath(); - } - return "/com/fr/web/images/form/resources/text_field_16.png"; - } - - - /** - * 控件树不显示此组件 - * @param path 控件树list - */ - public void notShowInComponentTree(ArrayList path) { - path.remove(path.size()-1); - } - - /** - * 重置组件的名称 - * @param name 名称 - */ - public void resetCreatorName(String name) { - super.resetCreatorName(name); - XCreator child = getXCreator(XWScaleLayout.INDEX); - child.toData().setWidgetName(name); - } - - /** - * 返回对应属性表的组件,scale和title返回其子组件 - * @return 组件 - */ - public XCreator getPropertyDescriptorCreator() { - return getXCreator(XWScaleLayout.INDEX); - } - - /** - * 是否作为控件树的叶子节点 - * @return 是则返回true - */ - public boolean isComponentTreeLeaf() { - return true; - } - - /** - * 是否为sclae和title专属容器 - * @return 是则返回true - */ - public boolean isDedicateContainer() { - return true; - } - +/** + * + */ +package com.fr.design.designer.creator; + +import com.fr.form.ui.container.WLayout; + +import java.awt.*; +import java.beans.IntrospectionException; +import java.util.ArrayList; + +/** + * 一些控件专属的容器,如标题容器,sclae容器 + * + * @author jim + * @date 2014-11-7 + */ +public abstract class DedicateLayoutContainer extends XLayoutContainer { + + public DedicateLayoutContainer(WLayout widget, Dimension initSize) { + super(widget, initSize); + } + + /** + * 得到属性名 + * + * @return 属性名 + * @throws IntrospectionException + */ + public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException { + return new CRPropertyDescriptor[0]; + } + + /** + * 返回容器图标 + * + * @return + */ + @Override + public String getIconPath() { + if (this.getXCreator(XWScaleLayout.INDEX) != null) { + return this.getXCreator(XWScaleLayout.INDEX).getIconPath(); + } + return "/com/fr/web/images/form/resources/text_field_16.png"; + } + + + /** + * 控件树不显示此组件 + * + * @param path 控件树list + */ + public void notShowInComponentTree(ArrayList path) { + path.remove(path.size() - 1); + } + + /** + * 重置组件的名称 + * + * @param name 名称 + */ + public void resetCreatorName(String name) { + super.resetCreatorName(name); + XCreator child = getXCreator(XWScaleLayout.INDEX); + //实现WTitleLayout的SetWidgetName + child.toData().setWidgetName(name); + } + + /** + * 返回对应属性表的组件,scale和title返回其子组件 + * + * @return 组件 + */ + public XCreator getPropertyDescriptorCreator() { + return getXCreator(XWScaleLayout.INDEX); + } + + /** + * 是否作为控件树的叶子节点 + * + * @return 是则返回true + */ + public boolean isComponentTreeLeaf() { + return true; + } + + /** + * 是否为sclae和title专属容器 + * + * @return 是则返回true + */ + public boolean isDedicateContainer() { + return true; + } + } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java b/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java index 692359bbd..589be7e83 100644 --- a/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java +++ b/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java @@ -1,689 +1,701 @@ -/* - * Copyright(c) 2001-2011, FineReport Inc, All Rights Reserved. - */ -package com.fr.design.form.parameter; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Insets; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JComponent; -import javax.swing.JPanel; - -import com.fr.base.BaseUtils; -import com.fr.base.Parameter; -import com.fr.base.parameter.ParameterUI; -import com.fr.design.DesignModelAdapter; -import com.fr.design.designer.beans.actions.CopyAction; -import com.fr.design.designer.beans.actions.CutAction; -import com.fr.design.designer.beans.actions.FormDeleteAction; -import com.fr.design.designer.beans.actions.PasteAction; -import com.fr.design.designer.beans.adapters.layout.FRAbsoluteLayoutAdapter; -import com.fr.design.designer.beans.events.DesignerEditListener; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.design.designer.beans.location.Direction; -import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWAbsoluteLayout; -import com.fr.design.designer.creator.XWParameterLayout; -import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; -import com.fr.design.form.util.XCreatorConstants; -import com.fr.design.mainframe.AuthorityEditPane; -import com.fr.design.mainframe.DesignerContext; -import com.fr.design.mainframe.EastRegionContainerPane; -import com.fr.design.mainframe.FormArea; -import com.fr.design.mainframe.FormDesigner; -import com.fr.design.mainframe.FormDesignerModeForSpecial; -import com.fr.design.mainframe.FormParaPane; -import com.fr.design.mainframe.FormWidgetDetailPane; -import com.fr.design.mainframe.WidgetPropertyPane; -import com.fr.design.mainframe.WidgetToolBarPane; -import com.fr.design.parameter.ParaDefinitePane; -import com.fr.design.parameter.ParameterDesignerProvider; -import com.fr.design.parameter.ParameterPropertyPane; -import com.fr.form.main.Form; -import com.fr.form.main.parameter.FormParameterUI; -import com.fr.form.parameter.FormSubmitButton; -import com.fr.form.ui.EditorHolder; -import com.fr.form.ui.WidgetValue; -import com.fr.form.ui.container.WAbsoluteLayout; -import com.fr.form.ui.container.WLayout; -import com.fr.form.ui.container.WParameterLayout; -import com.fr.general.Inter; -import com.fr.stable.ArrayUtils; - -/** - * Created by IntelliJ IDEA. - * User : Richer - * Version: 6.5.5 - * Date : 11-7-5 - * Time : 下午7:46 - * 表单类型的参数设计器 - */ -// TODO ALEX_SEP FormDesigner和FormParaDesignEditor应该共用Form的编辑,但是FormParaDesignEditor不应该直接就是FormDesigner -public class FormParaDesigner extends FormDesigner implements ParameterDesignerProvider { - private static final int NUM_IN_A_LINE = 4; - private static final int H_COMPONENT_GAP = 165; - private static final int V_COMPONENT_GAP = 25; - private static final int FIRST_V_LOCATION = 35; - private static final int FIRST_H_LOCATION = 90; - private static final int SECOND_H_LOCATION = 170; - private static final int ADD_HEIGHT = 20; - private static final int H_GAP = 105; - - private static Image paraImage = BaseUtils.readImage("/com/fr/design/images/form/parameter.png"); - - public FormParaDesigner() { - this(new FormParameterUI()); - } - - public FormParaDesigner(FormParameterUI ui) { - super(gen(ui)); - } - - private static Form gen(Form form) { - WLayout container = form.getContainer(); - if (container == null) { - container = new WParameterLayout(); - } - container.setWidgetName("para"); - form.setContainer(container); - return form; - } - - protected FormDesignerModeForSpecial createFormDesignerTargetMode() { - return new FormParaTargetMode(this); - } - - /** - * 开始编辑参数面板的时候进行的初始化 - */ - public void initBeforeUpEdit() { - WidgetToolBarPane.getInstance(this); - EastRegionContainerPane.getInstance().replaceDownPane( - FormWidgetDetailPane.getInstance(this)); - if (!BaseUtils.isAuthorityEditing()) { - EastRegionContainerPane.getInstance().addParameterPane(ParameterPropertyPane.getInstance(this)); - EastRegionContainerPane.getInstance().setParameterHeight(ParameterPropertyPane.getInstance(this).getPreferredSize().height); - EastRegionContainerPane.getInstance().replaceUpPane( - WidgetPropertyPane.getInstance(this)); - } else { - EastRegionContainerPane.getInstance().removeParameterPane(); - showAuthorityEditPane(); - } - - } - - /** - * 创建权限编辑面板 - * @return 面板 - */ - public AuthorityEditPane createAuthorityEditPane() { - return new FormWidgetAuthorityEditPane(this); - } - - /** - * 内容属性表面板 - * @return 内容属性表面板 - */ - public JPanel getEastUpPane() { - return WidgetPropertyPane.getInstance(this); - } - - /** - * 参数属性表 - * @return 参数属性表 - */ - - public JPanel getEastDownPane() { - return FormWidgetDetailPane.getInstance(this); - } - - /** - * 权限编辑面板 - * @return 权限编辑面板 - */ - public AuthorityEditPane getAuthorityEditPane() { - FormWidgetAuthorityEditPane formWidgetAuthorityEditPane = new FormWidgetAuthorityEditPane(this); - formWidgetAuthorityEditPane.populateDetials(); - return formWidgetAuthorityEditPane; - } - - /** - * 给包含此FormParaDesigner的ParameterDefinitePane添加事件 - * - * @param paraDefinitePane 面板 - */ - public void addListener(final ParaDefinitePane paraDefinitePane) { - this.getEditListenerTable().addListener(new DesignerEditListener() { - - @Override - public void fireCreatorModified(DesignerEvent evt) { - if (evt.getCreatorEventID() == DesignerEvent.CREATOR_ADDED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_CUTED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_PASTED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_RENAMED) { - paraDefinitePane.setParameterArray( - paraDefinitePane.getNoRepeatParas(DesignModelAdapter.getCurrentModelAdapter().getParameters())); - paraDefinitePane.refreshParameter(); - } - } - }); - } - - /** - * 包裹一层FormArea - * - * @return 区域 - */ - public Component createWrapper() { - FormArea area = new FormArea(this, false); - area.setBorder(BorderFactory.createEmptyBorder(0, 13, 0, 0)); - return area; - } - - /** - * 刷新控件 - */ - public void refreshAllNameWidgets() { - XCreatorUtils.refreshAllNameWidgets(this.getRootComponent()); - } - - /** - * 刷新tableData - * - * @param oldName 旧名称 - * @param newName 新名称 - */ - public void refresh4TableData(String oldName, String newName) { - this.getTarget().renameTableData(oldName, newName); - this.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_SELECTED); - } - - /** - * 刷新参数 - * - * @param p 参数面板 - */ - public void refreshParameter(ParaDefinitePane p) { - XLayoutContainer rootContainer = this.getRootComponent(); - java.util.List namelist = getAllXCreatorNameList(rootContainer); - // parameterArray是报表的所有参数, nameList是已经在参数面板添加过控件的参数名 - // 与已有的参数列表比较 如果已经存在 就除去 - Parameter[] ps = p.getParameterArray(); - if (ps != null) { - for (Parameter parameter : ps) { - for (String name : namelist) { - if (name.equalsIgnoreCase(parameter.getName())) { - p.setParameterArray((Parameter[]) ArrayUtils.removeElement(p.getParameterArray(), parameter)); - } - } - } - } - ParameterPropertyPane.getInstance().getParameterToolbarPane().populateBean( - p.getParameterArray() == null ? new Parameter[0] : p.getParameterArray()); - EastRegionContainerPane.getInstance().setParameterHeight(ParameterPropertyPane.getInstance().getPreferredSize().height); - - } - - /** - * 判断这个参数面板是否没有控件 - * - * @return 参数面板是否没有控件 - */ - public boolean isBlank() { - XLayoutContainer rootContainer = this.getRootComponent(); - List xx = getAllXCreatorNameList(rootContainer); - return xx.isEmpty(); - } - - protected void setToolbarButtons(boolean flag) { - DesignerContext.getDesignerFrame().checkCombineUp(!flag, NAME_ARRAY_LIST); - } - - /** - * 看看参数面板中的控件是否有和模板参数同名的 - * - * @param allParameters 参数 - * @return 是否有同名 - */ - public boolean isWithoutParaXCreator(Parameter[] allParameters) { - XLayoutContainer rootContainer = this.getRootComponent(); - List xx = getAllXCreatorNameList(rootContainer); - for (Parameter parameter : allParameters) { - for (String name : xx) { - if (name.equalsIgnoreCase(parameter.getName())) { - return false; - } - } - } - - return true; - } - - /** - * 参数面板控件的名字 - * - * @return 名字 - */ - public List getAllXCreatorNameList() { - XLayoutContainer rootContainer = this.getRootComponent(); - List namelist = new ArrayList(); - for (int i = 0; i < rootContainer.getXCreatorCount(); i++) { - if (rootContainer.getXCreator(i) instanceof XLayoutContainer) { - namelist.addAll(getAllXCreatorNameList((XLayoutContainer) rootContainer.getXCreator(i))); - } else { - namelist.add(rootContainer.getXCreator(i).toData().getWidgetName()); - } - } - return namelist; - } - - private List getAllXCreatorNameList(XLayoutContainer rootContainer) { - List namelist = new ArrayList(); - for (int i = 0; i < rootContainer.getXCreatorCount(); i++) { - if (rootContainer.getXCreator(i) instanceof XLayoutContainer) { - namelist.addAll(getAllXCreatorNameList((XLayoutContainer) rootContainer.getXCreator(i))); - } else { - namelist.add(rootContainer.getXCreator(i).toData().getWidgetName()); - } - } - return namelist; - } - - /** - * 是否有查询按钮 - * - * @return 有无查询按钮 - */ - public boolean isWithQueryButton() { - XLayoutContainer rootContainer = this.getRootComponent(); - return SearchQueryCreators(rootContainer); - } - - /** - * 返回复制粘贴删除等动作 - * @return 同上 - */ - public Action[] getActions() { - if (designer_actions == null) { - designer_actions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this), - new FormDeleteAction(this)}; - } - return designer_actions; - } - - private boolean SearchQueryCreators(XLayoutContainer rootContainer) { - boolean b = false; - for (int i = 0; i < rootContainer.getXCreatorCount(); i++) { - if (rootContainer.getXCreator(i) instanceof XLayoutContainer) { - b = SearchQueryCreators((XLayoutContainer) rootContainer.getXCreator(i)); - } else if (rootContainer.getXCreator(i) instanceof XFormSubmit) { - b = true; - } - } - return b; - } - - /** - * 就是getTarget 为了返回ParameterUI接口而不冲突另写个 - * - * @return - */ - public ParameterUI getParaTarget() { - return (FormParameterUI) super.getTarget(); - } - - /** - * ParameterDefinitePane通过ParaDesigner来调用ParameterPropertyPane - * - * @param p 面板 - */ - public void populateParameterPropertyPane(ParaDefinitePane p) { - ParameterPropertyPane.getInstance().populateBean(p); - } - - /** - * 初始化 - */ - public void initWidgetToolbarPane() { - WidgetToolBarPane.getInstance(this); - } - - /** - * populate - * - * @param ui - */ - public void populate(ParameterUI ui) { - if (ui == null) { - return; - } - if (this.getTarget() == ui) { - repaint(); - return; - } - this.setTarget((FormParameterUI) ui.convert()); - this.refreshRoot(); - } - - /** - * 报表直接判断底层是否是绝对布局 - * @return 是则返回true - */ - public boolean hasWAbsoluteLayout() { - return this.getTarget().getContainer() instanceof WAbsoluteLayout; - } - - /** - * 刷新底层容器 - */ - public void refreshRoot() { - XLayoutContainer layoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator(this.getTarget() - .getContainer()); - if (layoutContainer == null) { - layoutContainer = new XWParameterLayout(); - } - layoutContainer.setSize(LARGE_PREFERRED_SIZE); - setRootComponent(layoutContainer); - } - - /** - * 是否是报表的参数面板 - * @return 是 - */ - public boolean isFormParaDesigner(){ - return true; - } - - public XLayoutContainer getParaComponent() { - return getRootComponent(); - } - - private void paintLinkParameters(Graphics clipg) { - Parameter[] paras = DesignModelAdapter.getCurrentModelAdapter().getParameters(); - if (paras == null || paras.length == 0) { - return; - } - Graphics g = clipg.create(); - g.setColor(Color.RED); - if (!(this.getRootComponent() instanceof XWAbsoluteLayout)) { - return; - } - XWAbsoluteLayout layout = (XWAbsoluteLayout) this.getRootComponent(); - for (int i = 0; i < layout.getXCreatorCount(); i++) { - XCreator creator = layout.getXCreator(i); - if (!creator.isVisible()) { - continue; - } - for (Parameter p : paras) { - if (p.getName().equalsIgnoreCase(creator.toData().getWidgetName())) { - g.drawImage(paraImage, creator.getX() - 4, creator.getY() + 2, null); - break; - } - } - } - } - - /** - * 得到合适的大小 - * - * @return - */ - public Dimension getPreferredSize() { - return getDesignSize(); - } - - public Dimension getDesignSize() { - return ((FormParameterUI) getTarget()).getDesignSize(); - } - - /** - * 设置高度 - * - * @param height - */ - public void setDesignHeight(int height) { - Dimension dim = getPreferredSize(); - dim.height = height; - ((FormParameterUI) getTarget()).setDesignSize(dim); - } - - /** - * paintContent - * - * @param clipg - */ - public void paintContent(Graphics clipg) { - Dimension dim; - dim = ((FormParameterUI) getTarget()).getDesignSize(); - getRootComponent().setSize(dim); - getRootComponent().paint(clipg); - paintLinkParameters(clipg); - paintOp(clipg, getOutlineBounds()); - } - - private void paintOp(Graphics offg, Rectangle bounds) { - Color oldColor = offg.getColor(); - Insets insets = getOutlineInsets(); - offg.setColor(XCreatorConstants.OP_COLOR); - offg.fillRect(bounds.x, bounds.y + bounds.height, bounds.width + insets.right, insets.bottom); - offg.fillRect(bounds.x + bounds.width, bounds.y, insets.right, bounds.height); - offg.setColor(oldColor); - } - - protected void setRootComponent(XLayoutContainer component) { - component.setDirections(new int[]{Direction.BOTTOM, Direction.RIGHT}); - super.setRootComponent(component); - } - - /** - * 刷新尺寸 - */ - public void populateRootSize() { - ((FormParameterUI) getTarget()).setDesignSize(getRootComponent().getSize()); - if (getParaComponent().acceptType(XWParameterLayout.class)) { - WParameterLayout layout = (WParameterLayout)getParaComponent().toData(); - layout.setDesignWidth(getRootComponent().getWidth()); - } - } - - /** - * 保存参数界面的宽度 - * - * @param width 指定的宽度 - */ - public void updateWidth(int width) { - FormParameterUI parameterUI = ((FormParameterUI) getTarget()); - parameterUI.setDesignSize(new Dimension(width, parameterUI.getDesignSize().height)); - } - - /** - * 保存参数界面的高度 - * - * @param height 指定的高度 - */ - public void updateHeight(int height) { - FormParameterUI parameterUI = ((FormParameterUI) getTarget()); - parameterUI.setDesignSize(new Dimension(parameterUI.getDesignSize().width, height)); - } - - /** - * 在参数很多时,全部添加的时候,可以向下一次排版,若去掉就会在参数面板堆到一起 - * - * @param creator 组件 z - * @param x 长度 - * @param y 长度 c - * @param layout 布局 - * @return 是否扩展 - */ - public boolean prepareForAdd(XCreator creator, int x, int y, XWAbsoluteLayout layout) { - // 参数界面,自动扩展 - if (!isRoot(layout)) { - return false; - } - - Dimension size = layout.getSize(); - Boolean needResize = false; - - if (creator.getWidth() / 2 + x > layout.getWidth()) { - size.width = creator.getWidth() / 2 + x + ADD_HEIGHT; - needResize = true; - } - if (creator.getHeight() / 2 + y > layout.getHeight()) { - size.height = creator.getHeight() / 2 + y + ADD_HEIGHT; - needResize = true; - } - if (needResize) { - layout.setSize(size); - populateRootSize(); - } - return true; - } - - /** - * 加入参数 - * @param parameter 参数 c - * @param currentIndex 位置 w - * @return 是否加入 s - */ - public boolean addingParameter2Editor(Parameter parameter, int currentIndex) { - com.fr.form.ui.Label label = new com.fr.form.ui.Label(); - String name = parameter.getName(); - label.setWidgetName("Label" + name); - label.setWidgetValue(new WidgetValue(name + ":")); - XCreator xCreator = XCreatorUtils.createXCreator(label); - if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE) - + FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { - return false; - } - EditorHolder editor = new EditorHolder(parameter); - xCreator = XCreatorUtils.createXCreator(editor); - if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE) - + SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { - return false; - } - return true; - } - - - /** - * 加入参数 - * @param parameter 参数 c - * @param currentIndex 位置 w - * @return 是否加入 s - */ - public boolean addingParameter2EditorWithQueryButton(Parameter parameter, int currentIndex) { - com.fr.form.ui.Label label = new com.fr.form.ui.Label(); - String name = parameter.getName(); - label.setWidgetName("Label" + name); - label.setWidgetValue(new WidgetValue(name + ":")); - XCreator xCreator = XCreatorUtils.createXCreator(label); - if (!(this.autoAddComponent(xCreator, FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP - * (currentIndex / NUM_IN_A_LINE)))) { - return false; - } - EditorHolder editor = new EditorHolder(parameter); - editor.setWidgetName(name); - xCreator = XCreatorUtils.createXCreator(editor); - if (!(this.autoAddComponent(xCreator, SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP - * (currentIndex / NUM_IN_A_LINE)))) { - return false; - } - FormSubmitButton formSubmitButton = new FormSubmitButton(); - formSubmitButton.setWidgetName("Search"); - formSubmitButton.setText(Inter.getLocText("FR-Designer_Query")); - xCreator = XCreatorUtils.createXCreator(formSubmitButton); - if (!(this.autoAddComponent(xCreator, 270, FIRST_V_LOCATION + V_COMPONENT_GAP - * (currentIndex / NUM_IN_A_LINE)))) { - return false; - } - return true; - } - - /** - * 加入参数 - * @param parameterArray 参数 c - * @param currentIndex 位置 w - * @return 是否加入 s - */ - public void addingAllParameter2Editor(Parameter[] parameterArray, int currentIndex) { - for (int i = 0; i < parameterArray.length; i++) { - com.fr.form.ui.Label label = new com.fr.form.ui.Label(); - label.setWidgetName("Label" + parameterArray[i].getName()); - label.setWidgetValue(new WidgetValue(parameterArray[i].getName() + ":")); - XCreator xCreator = XCreatorUtils.createXCreator(label); - - if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE) - + FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { - break; - } - // 每行显示5组 - EditorHolder editor = new EditorHolder(parameterArray[i]); - editor.setWidgetName(parameterArray[i].getName()); - xCreator = XCreatorUtils.createXCreator(editor); - if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE) - + SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { - break; - } - currentIndex++; - } - if (!isWithQueryButton()) { - FormSubmitButton formSubmitButton = new FormSubmitButton(); - formSubmitButton.setWidgetName("Search"); - formSubmitButton.setText(Inter.getLocText("FR-Designer_Query")); - XCreator xCreator = XCreatorUtils.createXCreator(formSubmitButton); - if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * 3 + H_GAP, FIRST_V_LOCATION - + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { - return; - } - } - } - - /** - * 自动添加 - * - * @param xCreator 组件 z - * @param x 位置 w - * @param y 位置 - * @return 是否添加 s - */ - public boolean autoAddComponent(XCreator xCreator, int x, int y) { - XWAbsoluteLayout layout = (XWAbsoluteLayout) this.getRootComponent(); - FRAbsoluteLayoutAdapter adapter = (FRAbsoluteLayoutAdapter) layout.getLayoutAdapter(); - if (prepareForAdd(xCreator, x, y, layout)) { - adapter.addBean(xCreator, x, y); - } - this.getSelectionModel().setSelectedCreator(xCreator); - repaint(); - return true; - } - - /** - * 工具栏 - * @return 工具栏面板 g - */ - public JPanel[] toolbarPanes4Form() { - return new JPanel[]{FormParaPane.getInstance(this)}; - } - - /** - * 复制等按钮 - * @return 按钮组 a - */ - public JComponent[] toolBarButton4Form() { - return new JComponent[]{new CutAction(this).createToolBarComponent(), new CopyAction(this).createToolBarComponent(), new PasteAction(this).createToolBarComponent(), - new FormDeleteAction(this).createToolBarComponent()}; - } +/* + * Copyright(c) 2001-2011, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.form.parameter; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JPanel; + +import com.fr.base.BaseUtils; +import com.fr.base.Parameter; +import com.fr.base.parameter.ParameterUI; +import com.fr.design.DesignModelAdapter; +import com.fr.design.designer.beans.actions.CopyAction; +import com.fr.design.designer.beans.actions.CutAction; +import com.fr.design.designer.beans.actions.FormDeleteAction; +import com.fr.design.designer.beans.actions.PasteAction; +import com.fr.design.designer.beans.adapters.layout.FRAbsoluteLayoutAdapter; +import com.fr.design.designer.beans.events.DesignerEditListener; +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.beans.location.Direction; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XCreatorUtils; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWAbsoluteLayout; +import com.fr.design.designer.creator.XWParameterLayout; +import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; +import com.fr.design.form.util.XCreatorConstants; +import com.fr.design.mainframe.AuthorityEditPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.EastRegionContainerPane; +import com.fr.design.mainframe.FormArea; +import com.fr.design.mainframe.FormDesigner; +import com.fr.design.mainframe.FormDesignerModeForSpecial; +import com.fr.design.mainframe.FormParaPane; +import com.fr.design.mainframe.FormWidgetDetailPane; +import com.fr.design.mainframe.WidgetPropertyPane; +import com.fr.design.mainframe.WidgetToolBarPane; +import com.fr.design.parameter.ParaDefinitePane; +import com.fr.design.parameter.ParameterDesignerProvider; +import com.fr.design.parameter.ParameterPropertyPane; +import com.fr.form.main.Form; +import com.fr.form.main.parameter.FormParameterUI; +import com.fr.form.parameter.FormSubmitButton; +import com.fr.form.ui.EditorHolder; +import com.fr.form.ui.WidgetValue; +import com.fr.form.ui.container.WAbsoluteLayout; +import com.fr.form.ui.container.WLayout; +import com.fr.form.ui.container.WParameterLayout; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; + +/** + * Created by IntelliJ IDEA. + * User : Richer + * Version: 6.5.5 + * Date : 11-7-5 + * Time : 下午7:46 + * 表单类型的参数设计器 + */ +// TODO ALEX_SEP FormDesigner和FormParaDesignEditor应该共用Form的编辑,但是FormParaDesignEditor不应该直接就是FormDesigner +public class FormParaDesigner extends FormDesigner implements ParameterDesignerProvider { + private static final int NUM_IN_A_LINE = 4; + private static final int H_COMPONENT_GAP = 165; + private static final int V_COMPONENT_GAP = 25; + private static final int FIRST_V_LOCATION = 35; + private static final int FIRST_H_LOCATION = 90; + private static final int SECOND_H_LOCATION = 170; + private static final int ADD_HEIGHT = 20; + private static final int H_GAP = 105; + + private static Image paraImage = BaseUtils.readImage("/com/fr/design/images/form/parameter.png"); + + public FormParaDesigner() { + this(new FormParameterUI()); + } + + public FormParaDesigner(FormParameterUI ui) { + super(gen(ui)); + } + + private static Form gen(Form form) { + WLayout container = form.getContainer(); + if (container == null) { + container = new WParameterLayout(); + } + container.setWidgetName("para"); + form.setContainer(container); + return form; + } + + protected FormDesignerModeForSpecial createFormDesignerTargetMode() { + return new FormParaTargetMode(this); + } + + /** + * 开始编辑参数面板的时候进行的初始化 + */ + public void initBeforeUpEdit() { + WidgetToolBarPane.getInstance(this); + EastRegionContainerPane.getInstance().replaceDownPane( + FormWidgetDetailPane.getInstance(this)); + if (!BaseUtils.isAuthorityEditing()) { + EastRegionContainerPane.getInstance().addParameterPane(ParameterPropertyPane.getInstance(this)); + EastRegionContainerPane.getInstance().setParameterHeight(ParameterPropertyPane.getInstance(this).getPreferredSize().height); + EastRegionContainerPane.getInstance().replaceUpPane( + WidgetPropertyPane.getInstance(this)); + } else { + EastRegionContainerPane.getInstance().removeParameterPane(); + showAuthorityEditPane(); + } + + } + + /** + * 创建权限编辑面板 + * + * @return 面板 + */ + public AuthorityEditPane createAuthorityEditPane() { + return new FormWidgetAuthorityEditPane(this); + } + + /** + * 内容属性表面板 + * + * @return 内容属性表面板 + */ + public JPanel getEastUpPane() { + return WidgetPropertyPane.getInstance(this); + } + + /** + * 参数属性表 + * + * @return 参数属性表 + */ + + public JPanel getEastDownPane() { + return FormWidgetDetailPane.getInstance(this); + } + + /** + * 权限编辑面板 + * + * @return 权限编辑面板 + */ + public AuthorityEditPane getAuthorityEditPane() { + FormWidgetAuthorityEditPane formWidgetAuthorityEditPane = new FormWidgetAuthorityEditPane(this); + formWidgetAuthorityEditPane.populateDetials(); + return formWidgetAuthorityEditPane; + } + + /** + * 给包含此FormParaDesigner的ParameterDefinitePane添加事件 + * + * @param paraDefinitePane 面板 + */ + public void addListener(final ParaDefinitePane paraDefinitePane) { + this.getEditListenerTable().addListener(new DesignerEditListener() { + + @Override + public void fireCreatorModified(DesignerEvent evt) { + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_ADDED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_CUTED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_PASTED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_RENAMED) { + paraDefinitePane.setParameterArray( + paraDefinitePane.getNoRepeatParas(DesignModelAdapter.getCurrentModelAdapter().getParameters())); + paraDefinitePane.refreshParameter(); + } + } + }); + } + + /** + * 包裹一层FormArea + * + * @return 区域 + */ + public Component createWrapper() { + FormArea area = new FormArea(this, false); + area.setBorder(BorderFactory.createEmptyBorder(0, 13, 0, 0)); + return area; + } + + /** + * 刷新控件 + */ + public void refreshAllNameWidgets() { + XCreatorUtils.refreshAllNameWidgets(this.getRootComponent()); + } + + /** + * 刷新tableData + * + * @param oldName 旧名称 + * @param newName 新名称 + */ + public void refresh4TableData(String oldName, String newName) { + this.getTarget().renameTableData(oldName, newName); + this.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_SELECTED); + } + + /** + * 刷新参数 + * + * @param p 参数面板 + */ + public void refreshParameter(ParaDefinitePane p) { + XLayoutContainer rootContainer = this.getRootComponent(); + java.util.List namelist = getAllXCreatorNameList(rootContainer); + // parameterArray是报表的所有参数, nameList是已经在参数面板添加过控件的参数名 + // 与已有的参数列表比较 如果已经存在 就除去 + Parameter[] ps = p.getParameterArray(); + if (ps != null) { + for (Parameter parameter : ps) { + for (String name : namelist) { + if (name.equalsIgnoreCase(parameter.getName())) { + p.setParameterArray((Parameter[]) ArrayUtils.removeElement(p.getParameterArray(), parameter)); + } + } + } + } + ParameterPropertyPane.getInstance().getParameterToolbarPane().populateBean( + p.getParameterArray() == null ? new Parameter[0] : p.getParameterArray()); + EastRegionContainerPane.getInstance().setParameterHeight(ParameterPropertyPane.getInstance().getPreferredSize().height); + + } + + /** + * 判断这个参数面板是否没有控件 + * + * @return 参数面板是否没有控件 + */ + public boolean isBlank() { + XLayoutContainer rootContainer = this.getRootComponent(); + List xx = getAllXCreatorNameList(rootContainer); + return xx.isEmpty(); + } + + protected void setToolbarButtons(boolean flag) { + DesignerContext.getDesignerFrame().checkCombineUp(!flag, NAME_ARRAY_LIST); + } + + /** + * 看看参数面板中的控件是否有和模板参数同名的 + * + * @param allParameters 参数 + * @return 是否有同名 + */ + public boolean isWithoutParaXCreator(Parameter[] allParameters) { + XLayoutContainer rootContainer = this.getRootComponent(); + List xx = getAllXCreatorNameList(rootContainer); + for (Parameter parameter : allParameters) { + for (String name : xx) { + if (name.equalsIgnoreCase(parameter.getName())) { + return false; + } + } + } + + return true; + } + + /** + * 参数面板控件的名字 + * + * @return 名字 + */ + public List getAllXCreatorNameList() { + XLayoutContainer rootContainer = this.getRootComponent(); + List namelist = new ArrayList(); + for (int i = 0; i < rootContainer.getXCreatorCount(); i++) { + if (rootContainer.getXCreator(i) instanceof XLayoutContainer) { + namelist.addAll(getAllXCreatorNameList((XLayoutContainer) rootContainer.getXCreator(i))); + } else { + namelist.add(rootContainer.getXCreator(i).toData().getWidgetName()); + } + } + return namelist; + } + + private List getAllXCreatorNameList(XLayoutContainer rootContainer) { + List namelist = new ArrayList(); + for (int i = 0; i < rootContainer.getXCreatorCount(); i++) { + if (rootContainer.getXCreator(i) instanceof XLayoutContainer) { + namelist.addAll(getAllXCreatorNameList((XLayoutContainer) rootContainer.getXCreator(i))); + } else { + namelist.add(rootContainer.getXCreator(i).toData().getWidgetName()); + } + } + return namelist; + } + + /** + * 是否有查询按钮 + * + * @return 有无查询按钮 + */ + public boolean isWithQueryButton() { + XLayoutContainer rootContainer = this.getRootComponent(); + return searchQueryCreators(rootContainer); + } + + /** + * 返回复制粘贴删除等动作 + * + * @return 同上 + */ + public Action[] getActions() { + if (designerActions == null) { + designerActions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this), + new FormDeleteAction(this)}; + } + return designerActions; + } + + private boolean searchQueryCreators(XLayoutContainer rootContainer) { + boolean b = false; + for (int i = 0; i < rootContainer.getXCreatorCount(); i++) { + if (rootContainer.getXCreator(i) instanceof XLayoutContainer) { + b = searchQueryCreators((XLayoutContainer) rootContainer.getXCreator(i)); + } else if (rootContainer.getXCreator(i) instanceof XFormSubmit) { + b = true; + } + } + return b; + } + + /** + * 就是getTarget 为了返回ParameterUI接口而不冲突另写个 + * + * @return + */ + public ParameterUI getParaTarget() { + return (FormParameterUI) super.getTarget(); + } + + /** + * ParameterDefinitePane通过ParaDesigner来调用ParameterPropertyPane + * + * @param p 面板 + */ + public void populateParameterPropertyPane(ParaDefinitePane p) { + ParameterPropertyPane.getInstance().populateBean(p); + } + + /** + * 初始化 + */ + public void initWidgetToolbarPane() { + WidgetToolBarPane.getInstance(this); + } + + /** + * populate + * + * @param ui + */ + public void populate(ParameterUI ui) { + if (ui == null) { + return; + } + if (this.getTarget() == ui) { + repaint(); + return; + } + this.setTarget((FormParameterUI) ui.convert()); + this.refreshRoot(); + } + + /** + * 报表直接判断底层是否是绝对布局 + * + * @return 是则返回true + */ + public boolean hasWAbsoluteLayout() { + return this.getTarget().getContainer() instanceof WAbsoluteLayout; + } + + /** + * 刷新底层容器 + */ + public void refreshRoot() { + XLayoutContainer layoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator(this.getTarget() + .getContainer()); + if (layoutContainer == null) { + layoutContainer = new XWParameterLayout(); + } + layoutContainer.setSize(LARGE_PREFERRED_SIZE); + setRootComponent(layoutContainer); + } + + /** + * 是否是报表的参数面板 + * + * @return 是 + */ + public boolean isFormParaDesigner() { + return true; + } + + public XLayoutContainer getParaComponent() { + return getRootComponent(); + } + + private void paintLinkParameters(Graphics clipg) { + Parameter[] paras = DesignModelAdapter.getCurrentModelAdapter().getParameters(); + if (paras == null || paras.length == 0) { + return; + } + Graphics g = clipg.create(); + g.setColor(Color.RED); + if (!(this.getRootComponent() instanceof XWAbsoluteLayout)) { + return; + } + XWAbsoluteLayout layout = (XWAbsoluteLayout) this.getRootComponent(); + for (int i = 0; i < layout.getXCreatorCount(); i++) { + XCreator creator = layout.getXCreator(i); + if (!creator.isVisible()) { + continue; + } + for (Parameter p : paras) { + if (p.getName().equalsIgnoreCase(creator.toData().getWidgetName())) { + g.drawImage(paraImage, creator.getX() - 4, creator.getY() + 2, null); + break; + } + } + } + } + + /** + * 得到合适的大小 + * + * @return + */ + public Dimension getPreferredSize() { + return getDesignSize(); + } + + public Dimension getDesignSize() { + return ((FormParameterUI) getTarget()).getDesignSize(); + } + + /** + * 设置高度 + * + * @param height + */ + public void setDesignHeight(int height) { + Dimension dim = getPreferredSize(); + dim.height = height; + ((FormParameterUI) getTarget()).setDesignSize(dim); + } + + /** + * paintContent + * + * @param clipg + */ + public void paintContent(Graphics clipg) { + Dimension dim; + dim = ((FormParameterUI) getTarget()).getDesignSize(); + getRootComponent().setSize(dim); + getRootComponent().paint(clipg); + paintLinkParameters(clipg); + paintOp(clipg, getOutlineBounds()); + } + + private void paintOp(Graphics offg, Rectangle bounds) { + Color oldColor = offg.getColor(); + Insets insets = getOutlineInsets(); + offg.setColor(XCreatorConstants.OP_COLOR); + offg.fillRect(bounds.x, bounds.y + bounds.height, bounds.width + insets.right, insets.bottom); + offg.fillRect(bounds.x + bounds.width, bounds.y, insets.right, bounds.height); + offg.setColor(oldColor); + } + + protected void setRootComponent(XLayoutContainer component) { + component.setDirections(new int[]{Direction.BOTTOM, Direction.RIGHT}); + super.setRootComponent(component); + } + + /** + * 刷新尺寸 + */ + public void populateRootSize() { + ((FormParameterUI) getTarget()).setDesignSize(getRootComponent().getSize()); + if (getParaComponent().acceptType(XWParameterLayout.class)) { + WParameterLayout layout = (WParameterLayout) getParaComponent().toData(); + layout.setDesignWidth(getRootComponent().getWidth()); + } + } + + /** + * 保存参数界面的宽度 + * + * @param width 指定的宽度 + */ + public void updateWidth(int width) { + FormParameterUI parameterUI = ((FormParameterUI) getTarget()); + parameterUI.setDesignSize(new Dimension(width, parameterUI.getDesignSize().height)); + } + + /** + * 保存参数界面的高度 + * + * @param height 指定的高度 + */ + public void updateHeight(int height) { + FormParameterUI parameterUI = ((FormParameterUI) getTarget()); + parameterUI.setDesignSize(new Dimension(parameterUI.getDesignSize().width, height)); + } + + /** + * 在参数很多时,全部添加的时候,可以向下一次排版,若去掉就会在参数面板堆到一起 + * + * @param creator 组件 z + * @param x 长度 + * @param y 长度 c + * @param layout 布局 + * @return 是否扩展 + */ + public boolean prepareForAdd(XCreator creator, int x, int y, XWAbsoluteLayout layout) { + // 参数界面,自动扩展 + if (!isRoot(layout)) { + return false; + } + + Dimension size = layout.getSize(); + Boolean needResize = false; + + if (creator.getWidth() / 2 + x > layout.getWidth()) { + size.width = creator.getWidth() / 2 + x + ADD_HEIGHT; + needResize = true; + } + if (creator.getHeight() / 2 + y > layout.getHeight()) { + size.height = creator.getHeight() / 2 + y + ADD_HEIGHT; + needResize = true; + } + if (needResize) { + layout.setSize(size); + populateRootSize(); + } + return true; + } + + /** + * 加入参数 + * + * @param parameter 参数 c + * @param currentIndex 位置 w + * @return 是否加入 s + */ + public boolean addingParameter2Editor(Parameter parameter, int currentIndex) { + com.fr.form.ui.Label label = new com.fr.form.ui.Label(); + String name = parameter.getName(); + label.setWidgetName("Label" + name); + label.setWidgetValue(new WidgetValue(name + ":")); + XCreator xCreator = XCreatorUtils.createXCreator(label); + if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE) + + FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { + return false; + } + EditorHolder editor = new EditorHolder(parameter); + xCreator = XCreatorUtils.createXCreator(editor); + if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE) + + SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { + return false; + } + return true; + } + + + /** + * 加入参数 + * + * @param parameter 参数 c + * @param currentIndex 位置 w + * @return 是否加入 s + */ + public boolean addingParameter2EditorWithQueryButton(Parameter parameter, int currentIndex) { + com.fr.form.ui.Label label = new com.fr.form.ui.Label(); + String name = parameter.getName(); + label.setWidgetName("Label" + name); + label.setWidgetValue(new WidgetValue(name + ":")); + XCreator xCreator = XCreatorUtils.createXCreator(label); + if (!(this.autoAddComponent(xCreator, FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP + * (currentIndex / NUM_IN_A_LINE)))) { + return false; + } + EditorHolder editor = new EditorHolder(parameter); + editor.setWidgetName(name); + xCreator = XCreatorUtils.createXCreator(editor); + if (!(this.autoAddComponent(xCreator, SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP + * (currentIndex / NUM_IN_A_LINE)))) { + return false; + } + FormSubmitButton formSubmitButton = new FormSubmitButton(); + formSubmitButton.setWidgetName("Search"); + formSubmitButton.setText(Inter.getLocText("FR-Designer_Query")); + xCreator = XCreatorUtils.createXCreator(formSubmitButton); + if (!(this.autoAddComponent(xCreator, 270, FIRST_V_LOCATION + V_COMPONENT_GAP + * (currentIndex / NUM_IN_A_LINE)))) { + return false; + } + return true; + } + + /** + * 加入参数 + * + * @param parameterArray 参数 c + * @param currentIndex 位置 w + * @return 是否加入 s + */ + public void addingAllParameter2Editor(Parameter[] parameterArray, int currentIndex) { + for (int i = 0; i < parameterArray.length; i++) { + com.fr.form.ui.Label label = new com.fr.form.ui.Label(); + label.setWidgetName("Label" + parameterArray[i].getName()); + label.setWidgetValue(new WidgetValue(parameterArray[i].getName() + ":")); + XCreator xCreator = XCreatorUtils.createXCreator(label); + + if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE) + + FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { + break; + } + // 每行显示5组 + EditorHolder editor = new EditorHolder(parameterArray[i]); + editor.setWidgetName(parameterArray[i].getName()); + xCreator = XCreatorUtils.createXCreator(editor); + if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE) + + SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { + break; + } + currentIndex++; + } + if (!isWithQueryButton()) { + FormSubmitButton formSubmitButton = new FormSubmitButton(); + formSubmitButton.setWidgetName("Search"); + formSubmitButton.setText(Inter.getLocText("FR-Designer_Query")); + XCreator xCreator = XCreatorUtils.createXCreator(formSubmitButton); + if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * 3 + H_GAP, FIRST_V_LOCATION + + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { + return; + } + } + } + + /** + * 自动添加 + * + * @param xCreator 组件 z + * @param x 位置 w + * @param y 位置 + * @return 是否添加 s + */ + public boolean autoAddComponent(XCreator xCreator, int x, int y) { + XWAbsoluteLayout layout = (XWAbsoluteLayout) this.getRootComponent(); + FRAbsoluteLayoutAdapter adapter = (FRAbsoluteLayoutAdapter) layout.getLayoutAdapter(); + if (prepareForAdd(xCreator, x, y, layout)) { + adapter.addBean(xCreator, x, y); + } + this.getSelectionModel().setSelectedCreator(xCreator); + repaint(); + return true; + } + + /** + * 工具栏 + * + * @return 工具栏面板 g + */ + public JPanel[] toolbarPanes4Form() { + return new JPanel[]{FormParaPane.getInstance(this)}; + } + + /** + * 复制等按钮 + * + * @return 按钮组 a + */ + public JComponent[] toolBarButton4Form() { + return new JComponent[]{new CutAction(this).createToolBarComponent(), new CopyAction(this).createToolBarComponent(), new PasteAction(this).createToolBarComponent(), + new FormDeleteAction(this).createToolBarComponent()}; + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java b/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java index 2bc38699e..a64005812 100644 --- a/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java +++ b/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java @@ -15,96 +15,96 @@ import com.fr.design.designer.creator.XWAbsoluteLayout; import com.fr.form.ui.Connector; public class ConnectorHelper { - //这个类是用来画连接线的,暂时用不到 - - public static final int NEAR = 5; - private static double ratio = 0.5; - private final static int ADSORPTION = 15; // 吸附距离 - private ArrayList drawingPoint; - private FormDesigner designer; - private boolean drawing; + //这个类是用来画连接线的,暂时用不到 - public ConnectorHelper(FormDesigner formEditor) { - this.designer = formEditor; - } - - public void resetConnector(Connector connector) { - ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(),connector.getStartPoint(),connector.getEndPoint()); - connector.addAll(cc.createPointList()); - } - - public boolean drawLining() { - return this.drawing; - } + public static final int NEAR = 5; + private static double ratio = 0.5; + private final static int ADSORPTION = 15; // 吸附距离 + private ArrayList drawingPoint; + private FormDesigner designer; + private boolean drawing; - public void setDrawLine(boolean d) { - this.drawing = d; - } - - private boolean near(Point p1, Point p2) { - return p1.x - p2.x < NEAR && p2.x - p1.x < NEAR && p1.y - p2.y < NEAR && p2.y - p1.y < NEAR; - } + public ConnectorHelper(FormDesigner formEditor) { + this.designer = formEditor; + } - private Point getNearPoint(MouseEvent e, Rectangle r) { - Point p1 = new Point((int) (r.x + r.getWidth() * ratio), r.y); - Point p2 = new Point((int) (r.x + r.getWidth()), (int) (r.y + r.getHeight() * ratio)); - Point p3 = new Point((int) (r.x + r.getWidth() * (1 - ratio)), (int) (r.y + r.getHeight())); - Point p4 = new Point(r.x, (int) (r.y + r.getHeight() * (1 - ratio))); - Point p = new Point(e.getX() + designer.getArea().getHorizontalValue(), e.getY() + designer.getArea().getVerticalValue()); - if (near(p, p1)) { - return p1; - } else if (near(p, p2)) { - return p2; - } else if (near(p, p3)) { - return p3; - } else if (near(p, p4)) { - return p4; - } - return null; - } - - private ArrayList createDefalutNode(Point startPoint, Point endPoint) { - long s = System.currentTimeMillis(); - ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(), new Point(startPoint), new Point(endPoint)); - ArrayList p = cc.createPointList(); - long e = System.currentTimeMillis(); - return p; - } + public void resetConnector(Connector connector) { + ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(), connector.getStartPoint(), connector.getEndPoint()); + connector.addAll(cc.createPointList()); + } - public void drawAuxiliaryLine(Graphics g) { - Point startPoint = designer.getStateModel().getStartPoint(); - Point endPoint = designer.getStateModel().getEndPoint(); - drawingPoint = createDefalutNode(startPoint, endPoint); - Point[] p = drawingPoint.toArray(new Point[drawingPoint.size()]); - g.setColor(Color.green); - for (int i = 0; i < p.length - 1; i++) { - GraphHelper.drawLine(g, p[i].x - designer.getArea().getHorizontalValue(), p[i].y - - designer.getArea().getVerticalValue(), p[i + 1].x - designer.getArea().getHorizontalValue(), - p[i + 1].y - designer.getArea().getVerticalValue(), Constants.LINE_HAIR); - } - } + public boolean drawLining() { + return this.drawing; + } - public void createDefalutLine() { - if (drawingPoint != null - && drawingPoint.size() > 1 - && ConnectorCreator.getMinimumDistance(drawingPoint.get(0), drawingPoint.get(drawingPoint.size() - 1)) > ADSORPTION) { - ((XWAbsoluteLayout) designer.getRootComponent()).addConnector(new Connector().addAll(drawingPoint)); - } - drawingPoint = null; - } + public void setDrawLine(boolean d) { + this.drawing = d; + } - public Point getNearWidgetPoint(MouseEvent e) { - BoundsWidget widget; - Point p = null; - for (int i = 0, size = designer.getTarget().getContainer().getWidgetCount(); i < size; i++) { - widget = ((BoundsWidget) designer.getTarget().getContainer().getWidget(i)); - if (widget.isVisible()) { - if ((p = getNearPoint(e, widget.getBounds())) != null) { - break; - } - } - } - return p; - } + private boolean near(Point p1, Point p2) { + return p1.x - p2.x < NEAR && p2.x - p1.x < NEAR && p1.y - p2.y < NEAR && p2.y - p1.y < NEAR; + } + + private Point getNearPoint(MouseEvent e, Rectangle r) { + Point p1 = new Point((int) (r.x + r.getWidth() * ratio), r.y); + Point p2 = new Point((int) (r.x + r.getWidth()), (int) (r.y + r.getHeight() * ratio)); + Point p3 = new Point((int) (r.x + r.getWidth() * (1 - ratio)), (int) (r.y + r.getHeight())); + Point p4 = new Point(r.x, (int) (r.y + r.getHeight() * (1 - ratio))); + Point p = new Point(e.getX() + designer.getArea().getHorizontalValue(), e.getY() + designer.getArea().getVerticalValue()); + if (near(p, p1)) { + return p1; + } else if (near(p, p2)) { + return p2; + } else if (near(p, p3)) { + return p3; + } else if (near(p, p4)) { + return p4; + } + return null; + } + + private ArrayList createDefalutNode(Point startPoint, Point endPoint) { + long s = System.currentTimeMillis(); + ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(), new Point(startPoint), new Point(endPoint)); + ArrayList p = cc.createPointList(); + long e = System.currentTimeMillis(); + return p; + } + + public void drawAuxiliaryLine(Graphics g) { + Point startPoint = designer.getStateModel().getStartPoint(); + Point endPoint = designer.getStateModel().getEndPoint(); + drawingPoint = createDefalutNode(startPoint, endPoint); + Point[] p = drawingPoint.toArray(new Point[drawingPoint.size()]); + g.setColor(Color.green); + for (int i = 0; i < p.length - 1; i++) { + GraphHelper.drawLine(g, p[i].x - designer.getArea().getHorizontalValue(), p[i].y + - designer.getArea().getVerticalValue(), p[i + 1].x - designer.getArea().getHorizontalValue(), + p[i + 1].y - designer.getArea().getVerticalValue(), Constants.LINE_HAIR); + } + } + + public void createDefalutLine() { + if (drawingPoint != null + && drawingPoint.size() > 1 + && ConnectorCreator.getMinimumDistance(drawingPoint.get(0), drawingPoint.get(drawingPoint.size() - 1)) > ADSORPTION) { + ((XWAbsoluteLayout) designer.getRootComponent()).addConnector(new Connector().addAll(drawingPoint)); + } + drawingPoint = null; + } + + public Point getNearWidgetPoint(MouseEvent e) { + BoundsWidget widget; + Point p = null; + for (int i = 0, size = designer.getTarget().getContainer().getWidgetCount(); i < size; i++) { + widget = ((BoundsWidget) designer.getTarget().getContainer().getWidget(i)); + if (widget.isVisible()) { + if ((p = getNearPoint(e, widget.getBounds())) != null) { + break; + } + } + } + return p; + } } \ 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 88dc9268f..61323f4b7 100644 --- a/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java +++ b/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java @@ -1,620 +1,621 @@ -package com.fr.design.mainframe; - -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; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.design.designer.beans.location.Direction; -import com.fr.design.designer.beans.location.Location; -import com.fr.design.designer.beans.models.SelectionModel; -import com.fr.design.designer.beans.models.StateModel; -import com.fr.design.designer.creator.*; -import com.fr.design.designer.creator.cardlayout.XCardSwitchButton; -import com.fr.design.form.util.XCreatorConstants; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.gui.xpane.ToolTipEditor; -import com.fr.design.icon.IconPathConstants; -import com.fr.design.utils.ComponentUtils; -import com.fr.design.utils.gui.LayoutUtils; -import com.fr.general.Inter; -import com.fr.stable.Constants; - -import javax.swing.*; -import javax.swing.event.MouseInputAdapter; -import java.awt.*; -import java.awt.event.MouseEvent; - -/** - * 普通模式下的鼠标点击、位置处理器 - */ -public class EditingMouseListener extends MouseInputAdapter { - - private static final int INDEX = 0; - private FormDesigner designer; - - /** - * 普通模式下对应的model - */ - private StateModel stateModel; - - - private XLayoutContainer xTopLayoutContainer; - private XLayoutContainer clickTopLayout; - - /** - * 获取表单设计器 - * - * @return 表单设计器 - */ - public FormDesigner getDesigner() { - return designer; - } - - /** - * 选择模型,存储当前选择的组件和剪切板 - */ - private SelectionModel selectionModel; - /** - * 获取选择模型 - * - * @return 选择 - */ - public SelectionModel getSelectionModel() { - return selectionModel; - } - - private XCreator last_creator; - private MouseEvent lastPressEvent; - private DesignerEditor current_editor; - private XCreator current_creator; - - //备份开始拖动的位置和大小 - private Rectangle dragBackupBounds; - - /** - * 获取最小移动距离 - * - * @return 最小移动距离 - */ - public int getMinMoveSize() { - return minMoveSize; - } - - private int minDragSize = 5; - private int minMoveSize = 8; - - private static final int EDIT_BTN_WIDTH = 60; - private static final int EDIT_BTN_HEIGHT = 24; - //报表块的编辑按钮不灵敏,范围扩大一点 - private static final int GAP = 10; - - private XElementCase xElementCase; - private XChartEditor xChartEditor; - - private JWindow promptWindow = new JWindow(); - - public EditingMouseListener(FormDesigner designer) { - this.designer = designer; - stateModel = designer.getStateModel(); - selectionModel = designer.getSelectionModel(); - UIButton promptButton = new UIButton(Inter.getLocText("FR-Designer_Forbid_Drag_into_Adapt_Pane"), BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); - this.promptWindow.add(promptButton); - } - - private void promptUser(int x, int y, XLayoutContainer container){ - if (!selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)){ - promptWidgetForbidEnter(x ,y , container); - } else { - cancelPromptWidgetForbidEnter(); - } - } - - private void promptWidgetForbidEnter(int x,int y, XLayoutContainer container){ - container.setBorder(BorderFactory.createLineBorder(Color.RED, Constants.LINE_MEDIUM)); - int screen_X = (int)designer.getArea().getLocationOnScreen().getX(); - int screen_Y = (int)designer.getArea().getLocationOnScreen().getY(); - this.promptWindow.setSize(promptWindow.getPreferredSize()); - this.promptWindow.setPreferredSize(promptWindow.getPreferredSize()); - promptWindow.setLocation(screen_X + x + GAP, screen_Y + y + GAP); - promptWindow.setVisible(true); - } - - private void cancelPromptWidgetForbidEnter(){ - designer.getRootComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN)); - promptWindow.setVisible(false); - } - - - /** - * 按下 - * @param e 鼠标事件 - */ - public void mousePressed(MouseEvent e) { - if (!stopEditing()) { - return; - } - if (!designer.isFocusOwner()) { - // 获取焦点,以便获取热键 - designer.requestFocus(); - } - if (e.isPopupTrigger()) { - // 为触发上下文菜单预留 - } else if (e.getButton() == MouseEvent.BUTTON1) { - - Direction dir = selectionModel.getDirectionAt(e); - if (!BaseUtils.isAuthorityEditing()) { - stateModel.setDirection(dir); - } - - if (dir == Location.outer) { - if (designer.isDrawLineMode()) { - designer.updateDrawLineMode(e); - } else { - if (selectionModel.hasSelectionComponent() - && selectionModel.getSelection().getRelativeBounds().contains( - designer.getArea().getHorizontalValue() + e.getX(), - designer.getArea().getVerticalValue() + e.getY())) { - lastPressEvent = e; - last_creator = selectionModel.getSelection().getSelectedCreator(); - } else { - stateModel.startSelecting(e); - } - } - } else { - stateModel.startResizing(e); - } - } - } - - /** - * 释放 - * @param e 鼠标事件 - */ - public void mouseReleased(MouseEvent e) { - if (e.isPopupTrigger()) { - if (stateModel.isDragging()) { - stateModel.draggingCancel(); - } - } else { - if (designer.isDrawLineMode()) { - if (stateModel.prepareForDrawLining()) { - designer.getDrawLineHelper().setDrawLine(false); - designer.getDrawLineHelper().createDefalutLine(); - } - } else if (stateModel.isSelecting()) { - // 如果当前是区域选择状态,则选择该区域所含的组件 - designer.selectComponents(e); - } - if (stateModel.isDragging()) { - mouseDraggingRelease(e); - } - } - lastPressEvent = null; - last_creator = null; - } - - private void mouseDraggingRelease(MouseEvent e) { - // 当前鼠标所在的组件 - 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 - // 不是拖动过快导致的,而是纵坐标为负值导致的,这时参照横坐标为负值时的做法,取边界位置的组件,为鼠标所在点的组件 - // 如果直接return,界面上已经进行了拖拽不能恢复 - hoveredComponent = designer.getComponentAt(0, 0); - } - // 获取该组件所在的焦点容器 - XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent); - - if (container != null) { - boolean formSubmit2Adapt = !selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() - && container.acceptType(XWFitLayout.class); - if ( !formSubmit2Adapt) { - // 如果是处于拖拽状态,则释放组件 - stateModel.releaseDragging(e); - } else { - selectionModel.deleteSelection(); - designer.setPainter(null); - } - cancelPromptWidgetForbidEnter(); - } - } - - /** - * 激活上下文菜单,待完善 - * 6.56暂时不支持右键 bugid 8777 - */ - private void trigger_popup(MouseEvent e) { - - XCreator creator = selectionModel.getSelection().getSelectedCreator(); - - if (creator == null) { - return; - } - - JPopupMenu popupMenu = null; - ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, creator); - popupMenu = adapter.getContextPopupMenu(e); - - if (popupMenu != null) { - popupMenu.show(designer, e.getX(), e.getY()); - } - // 通知组件已经被选择了 - designer.getEditListenerTable().fireCreatorModified(creator, DesignerEvent.CREATOR_SELECTED); - } - - /** - * 移动 - * @param e 鼠标事件 - */ - public void mouseMoved(MouseEvent e) { - XCreator component = designer.getComponentAt(e); - - setCoverPaneNotDisplay(e, false); - - if(processTopLayoutMouseMove(component, e)){ - return; - } - if (component instanceof XEditorHolder) { - XEditorHolder xcreator = (XEditorHolder) component; - Rectangle rect = xcreator.getBounds(); - int min = rect.x + rect.width / 2 - minMoveSize; - int max = rect.x + rect.width / 2 + minMoveSize; - if (e.getX() > min && e.getX() < max) { - if (designer.getCursor().getType() != Cursor.HAND_CURSOR) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - return; - } else { - if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - } - } - Direction dir = selectionModel.getDirectionAt(e); - if (designer.isDrawLineMode() && stateModel.getDirection() == Location.outer) { - designer.updateDrawLineMode(e); - } - if (!BaseUtils.isAuthorityEditing()) { - stateModel.setDirection(dir); - } - - if (component.isReport()) { - elementCaseMouseMoved(e, component); - designer.repaint(); - return; - } - - processChartEditorMouseMove(component, e); - - designer.repaint(); - } - - private void elementCaseMouseMoved(MouseEvent e, XCreator component) { - xElementCase = (XElementCase)component; - UIButton button = (UIButton)xElementCase.getCoverPane().getComponent(0); - if(designer.getCursor().getType() == Cursor.HAND_CURSOR) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } // component.getParent() 是报表块所在的XWTitleLayout - int minX = button.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); - int minY = button.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); - if (e.getX() + GAP - xElementCase.getInsets().left > minX && e.getX() - GAP - xElementCase.getInsets().left < minX + button.getWidth()) { - if (e.getY() + GAP - xElementCase.getInsets().top > minY && e.getY() - GAP - xElementCase.getInsets().top < minY + button.getHeight()) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - } - xElementCase.setHelpBtnOnFocus(false); - if (xElementCase.getCoverPane().getComponentCount() > 1) { - JComponent button1 = (JComponent) xElementCase.getCoverPane().getComponent(1); - int minX1 = button1.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); - int minY1 = button1.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); - if (e.getX() + GAP - xElementCase.getInsets().left > minX1 && e.getX() - GAP - xElementCase.getInsets().left < minX1 + button1.getWidth()) { - if (e.getY() + GAP - xElementCase.getInsets().top > minY1 && e.getY() - GAP - xElementCase.getInsets().top < minY1 + button1.getHeight()) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - xElementCase.setHelpBtnOnFocus(true); - } - } - } - xElementCase.displayCoverPane(true); - xElementCase.setDirections(Direction.TOP_BOTTOM_LEFT_RIGHT); - } - - private void setCoverPaneNotDisplay(MouseEvent e, boolean isLinkedHelpDialog) { - if (xElementCase != null) { - int x = getParentPositionX(xElementCase, 0) - designer.getArea().getHorizontalValue(); - int y = getParentPositionY(xElementCase, 0) - designer.getArea().getVerticalValue(); - Rectangle rect = new Rectangle(x, y, xElementCase.getWidth(), xElementCase.getHeight()); - if (rect.contains(e.getPoint())) { - return; - } - if(isLinkedHelpDialog){ - xElementCase.destroyHelpDialog(); - } - xElementCase.displayCoverPane(false); - } - if (xChartEditor != null){ - xChartEditor.displayCoverPane(false); - } - - if (xTopLayoutContainer != null) { - xTopLayoutContainer.setMouseEnter(false); - } - designer.repaint(); - } - - private boolean processTopLayoutMouseMove(XCreator component, MouseEvent e){ - XLayoutContainer parent = XCreatorUtils.getHotspotContainer(component).getTopLayout(); - if (parent != null){ - xTopLayoutContainer = parent; - xTopLayoutContainer.setMouseEnter(true); - designer.repaint(); - if(!xTopLayoutContainer.isEditable()) { - if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - int minX = getParentPositionX(parent, parent.getX()) + parent.getWidth() / 2; - int minY = getParentPositionY(parent, parent.getY()) + parent.getHeight() / 2; - int offsetX = EDIT_BTN_WIDTH / 2 + GAP; - int offsetY = EDIT_BTN_HEIGHT / 2 + GAP; - if (e.getX() > (minX - offsetX) && e.getX() < (minX + offsetX)) { - if (e.getY() > (minY - offsetY) && e.getY() < (minY + offsetY + designer.getParaHeight())) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - } - return true; - } - } - return false; - } - - private void processChartEditorMouseMove(XCreator component, MouseEvent e){ - if (component instanceof XChartEditor) { - xChartEditor = (XChartEditor)component; - UIButton button = (UIButton)xChartEditor.getCoverPane().getComponent(0); - if(designer.getCursor().getType() ==Cursor.HAND_CURSOR) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - int minX = button.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); - int minY = button.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); - if(e.getX() + GAP > minX && e.getX() - GAP < minX + button.getWidth()){ - if( e.getY() + GAP > minY && e.getY() - GAP < minY + button.getHeight()){ - designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - } - xChartEditor.displayCoverPane(true); - xChartEditor.setDirections(Direction.TOP_BOTTOM_LEFT_RIGHT); - designer.repaint(); - } - } - - private int getParentPositionX(XCreator comp, int x){ - return comp.getParent() == null ? - x : getParentPositionX((XCreator)comp.getParent(), comp.getParent().getX() + x); - } - - private int getParentPositionY(XCreator comp, int y) { - return comp.getParent() == null ? - y : getParentPositionY((XCreator) comp.getParent(), comp.getParent().getY() + y); - } - - /** - * 拖拽 - * @param e 鼠标事件 - */ - public void mouseDragged(MouseEvent e) { - if (BaseUtils.isAuthorityEditing()) { - return; - } - // 如果当前是左键拖拽状态,拖拽组件 - if (stateModel.dragable()) { - if (SwingUtilities.isRightMouseButton(e)) { - return; - } else { - 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; - } - // 获取焦点组件所在的焦点容器 - XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot); - //提示组件是否可以拖入 - promptUser(e.getX(), e.getY(), container); - } - } else if (designer.isDrawLineMode()) { - if (stateModel.prepareForDrawLining()) { - stateModel.drawLine(e); - } - } else if (stateModel.isSelecting() && (selectionModel.getHotspotBounds() != null)) { - // 如果是拖拽选择区域状态,则更新选择区域 - stateModel.changeSelection(e); - } else { - if ((lastPressEvent == null) || (last_creator == null)) { - return; - } - if (e.getPoint().distance(lastPressEvent.getPoint()) > minDragSize) { - //参数面板和自适应布局不支持拖拽 - if (last_creator.isSupportDrag()){ - designer.startDraggingComponent(last_creator, lastPressEvent, e.getX(), e.getY()); - } - e.consume(); - lastPressEvent = null; - } - } - designer.repaint(); - } - - //当前编辑的组件是在布局中,鼠标点击布局外部,需要一次性将布局及其父布局都置为不可编辑 - private void setTopLayoutUnEditable(XLayoutContainer clickedTopLayout, XLayoutContainer clickingTopLayout){ - //双击的前后点击click为相同对象,过滤掉 - if (clickedTopLayout == null || clickedTopLayout == clickingTopLayout){ - return; - } - //位于同一层级的控件,父布局相同,过滤掉 - if (clickingTopLayout != null && clickedTopLayout.getParent() == clickingTopLayout.getParent()){ - return; - } - //前后点击的位于不同层级,要置为不可编辑 - XLayoutContainer xLayoutContainer = (XLayoutContainer)clickedTopLayout.getParent(); - if (xLayoutContainer == clickingTopLayout){ - return; - } - if (xLayoutContainer != null){ - xLayoutContainer.setEditable(false); - setTopLayoutUnEditable((XLayoutContainer) clickedTopLayout.getParent(), clickingTopLayout); - } - } - - private boolean isCreatorInLayout(XCreator creator, XCreator layout){ - if (creator == layout){ - return true; - } - if(layout.getParent() != null){ - return isCreatorInLayout(creator, (XCreator)layout.getParent()); - } - return false; - } - - private XCreator processTopLayoutMouseClick(XCreator creator){ - XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(creator).getTopLayout(); - if(topLayout != null){ - if (clickTopLayout != null && clickTopLayout != topLayout && !isCreatorInLayout(clickTopLayout, topLayout)){ - clickTopLayout.setEditable(false); - setTopLayoutUnEditable(clickTopLayout, topLayout); - } - clickTopLayout = topLayout; - if(!topLayout.isEditable()) { - creator = topLayout; - } - } - else{ - if(clickTopLayout != null){ - clickTopLayout.setEditable(false); - setTopLayoutUnEditable(clickTopLayout, null); - } - } - - return creator; - } - /** - * 点击 - * @param e 鼠标事件 - */ - public void mouseClicked(MouseEvent e) { - XCreator creator = designer.getComponentAt(e); - - if (e.getButton() != MouseEvent.BUTTON1 && !creator.acceptType(XCardSwitchButton.class)) { - return; - } - - creator = processTopLayoutMouseClick(creator); - - if(creator != null){ - creator.respondClick(this, e); - } - creator.doLayout(); - LayoutUtils.layoutRootContainer(designer.getRootComponent()); - } - - - - /** - * 离开 - * @param e 鼠标事件 - */ - public void mouseExited(MouseEvent e) { - if (designer.getCursor().getType() != Cursor.DEFAULT_CURSOR) { - designer.setCursor(Cursor.getDefaultCursor()); - } - - setCoverPaneNotDisplay(e, true); - - cancelPromptWidgetForbidEnter(); - } - - /** - * 开始编辑 - * @param creator 容器 - * @param designerEditor 设计器 - * @param adapter 适配器 - */ - public void startEditing(XCreator creator, DesignerEditor designerEditor, ComponentAdapter adapter) { - if (designerEditor != null) { - Rectangle rect = ComponentUtils.getRelativeBounds(creator); - current_editor = designerEditor; - current_creator = creator; - Rectangle bounds = new Rectangle(1, 1, creator.getWidth() - 2, creator.getHeight() - 2); - bounds.x += (rect.x - designer.getArea().getHorizontalValue()); - bounds.y += (rect.y - designer.getArea().getVerticalValue()); - designerEditor.getEditorTarget().setBounds(bounds); - designer.add(designerEditor.getEditorTarget()); - designer.invalidate(); - designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - designerEditor.getEditorTarget().requestFocus(); - designer.repaint(); - } - } - - /** - * 停止编辑 - * @return 是否编辑成功 - */ - public boolean stopEditing() { - if (current_editor != null) { - designer.remove(current_editor.getEditorTarget()); - current_editor.fireEditStoped(); - - Container container = current_creator.getParent(); - - if (container != null) { - LayoutUtils.layoutRootContainer(container); - } - designer.invalidate(); - designer.repaint(); - current_creator = null; - current_editor = null; - return true; - } - return true; - } - - /** - * 重置编辑控件大小 - */ - public void resetEditorComponentBounds() { - if (current_editor == null) { - return; - } - - if (current_creator.getParent() == null) { - stopEditing(); - return; - } - - Rectangle rect = ComponentUtils.getRelativeBounds(current_creator); - Rectangle bounds = new Rectangle(1, 1, current_creator.getWidth() - 2, current_creator.getHeight() - 2); - bounds.x += (rect.x - designer.getArea().getHorizontalValue()); - bounds.y += (rect.y - designer.getArea().getVerticalValue()); - if (current_creator instanceof XEditorHolder) { - ToolTipEditor.getInstance().resetBounds((XEditorHolder) current_creator, bounds, current_editor.getEditorTarget().getBounds()); - } - current_editor.getEditorTarget().setBounds(bounds); - } +package com.fr.design.mainframe; + +import com.fr.base.BaseUtils; +import com.fr.design.designer.beans.AdapterBus; +import com.fr.design.designer.beans.ComponentAdapter; +import com.fr.design.designer.beans.events.DesignerEditor; +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.beans.location.Direction; +import com.fr.design.designer.beans.location.Location; +import com.fr.design.designer.beans.models.SelectionModel; +import com.fr.design.designer.beans.models.StateModel; +import com.fr.design.designer.creator.*; +import com.fr.design.designer.creator.cardlayout.XCardSwitchButton; +import com.fr.design.form.util.XCreatorConstants; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.xpane.ToolTipEditor; +import com.fr.design.icon.IconPathConstants; +import com.fr.design.utils.ComponentUtils; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.general.Inter; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.MouseInputAdapter; +import java.awt.*; +import java.awt.event.MouseEvent; + +/** + * 普通模式下的鼠标点击、位置处理器 + */ +public class EditingMouseListener extends MouseInputAdapter { + + private FormDesigner designer; + + /** + * 普通模式下对应的model + */ + private StateModel stateModel; + + + private XLayoutContainer xTopLayoutContainer; + private XLayoutContainer clickTopLayout; + + /** + * 获取表单设计器 + * + * @return 表单设计器 + */ + public FormDesigner getDesigner() { + return designer; + } + + /** + * 选择模型,存储当前选择的组件和剪切板 + */ + private SelectionModel selectionModel; + + /** + * 获取选择模型 + * + * @return 选择 + */ + public SelectionModel getSelectionModel() { + return selectionModel; + } + + private XCreator lastXCreator; + private MouseEvent lastPressEvent; + private DesignerEditor currentEditor; + private XCreator currentXCreator; + + //备份开始拖动的位置和大小 + private Rectangle dragBackupBounds; + + /** + * 获取最小移动距离 + * + * @return 最小移动距离 + */ + public int getMinMoveSize() { + return minMoveSize; + } + + private int minDragSize = 5; + private int minMoveSize = 8; + + private static final int EDIT_BTN_WIDTH = 60; + private static final int EDIT_BTN_HEIGHT = 24; + //报表块的编辑按钮不灵敏,范围扩大一点 + private static final int GAP = 10; + + private XElementCase xElementCase; + private XChartEditor xChartEditor; + + private JWindow promptWindow = new JWindow(); + + public EditingMouseListener(FormDesigner designer) { + this.designer = designer; + stateModel = designer.getStateModel(); + selectionModel = designer.getSelectionModel(); + UIButton promptButton = new UIButton(Inter.getLocText("FR-Designer_Forbid_Drag_into_Adapt_Pane"), BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); + this.promptWindow.add(promptButton); + } + + private void promptUser(int x, int y, XLayoutContainer container) { + if (!selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)) { + promptWidgetForbidEnter(x, y, container); + } else { + cancelPromptWidgetForbidEnter(); + } + } + + private void promptWidgetForbidEnter(int x, int y, XLayoutContainer container) { + container.setBorder(BorderFactory.createLineBorder(Color.RED, Constants.LINE_MEDIUM)); + int screenX = (int) designer.getArea().getLocationOnScreen().getX(); + int screenY = (int) designer.getArea().getLocationOnScreen().getY(); + this.promptWindow.setSize(promptWindow.getPreferredSize()); + this.promptWindow.setPreferredSize(promptWindow.getPreferredSize()); + promptWindow.setLocation(screenX + x + GAP, screenY + y + GAP); + promptWindow.setVisible(true); + } + + private void cancelPromptWidgetForbidEnter() { + designer.getRootComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN)); + promptWindow.setVisible(false); + } + + + /** + * 按下 + * + * @param e 鼠标事件 + */ + public void mousePressed(MouseEvent e) { + if (!stopEditing()) { + return; + } + if (!designer.isFocusOwner()) { + // 获取焦点,以便获取热键 + designer.requestFocus(); + } + if (e.getButton() == MouseEvent.BUTTON1) { + + Direction dir = selectionModel.getDirectionAt(e); + if (!BaseUtils.isAuthorityEditing()) { + stateModel.setDirection(dir); + } + + if (dir == Location.outer) { + if (designer.isDrawLineMode()) { + designer.updateDrawLineMode(e); + } else { + if (selectionModel.hasSelectionComponent() + && selectionModel.getSelection().getRelativeBounds().contains( + designer.getArea().getHorizontalValue() + e.getX(), + designer.getArea().getVerticalValue() + e.getY())) { + lastPressEvent = e; + lastXCreator = selectionModel.getSelection().getSelectedCreator(); + } else { + stateModel.startSelecting(e); + } + } + } else { + stateModel.startResizing(e); + } + } + } + + /** + * 释放 + * + * @param e 鼠标事件 + */ + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) { + if (stateModel.isDragging()) { + stateModel.draggingCancel(); + } + } else { + if (designer.isDrawLineMode()) { + if (stateModel.prepareForDrawLining()) { + designer.getDrawLineHelper().setDrawLine(false); + designer.getDrawLineHelper().createDefalutLine(); + } + } else if (stateModel.isSelecting()) { + // 如果当前是区域选择状态,则选择该区域所含的组件 + designer.selectComponents(e); + } + if (stateModel.isDragging()) { + mouseDraggingRelease(e); + } + } + lastPressEvent = null; + lastXCreator = null; + } + + private void mouseDraggingRelease(MouseEvent e) { + // 当前鼠标所在的组件 + 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); + } + } + dragBackupBounds = null; + // 拉伸时鼠标拖动过快,导致所在组件获取会为空 + if (hoveredComponent == null && e.getY() < 0) { + // bug63538 + // 不是拖动过快导致的,而是纵坐标为负值导致的,这时参照横坐标为负值时的做法,取边界位置的组件,为鼠标所在点的组件 + // 如果直接return,界面上已经进行了拖拽不能恢复 + hoveredComponent = designer.getComponentAt(0, 0); + } + // 获取该组件所在的焦点容器 + XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent); + + if (container != null) { + boolean formSubmit2Adapt = !selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() + && container.acceptType(XWFitLayout.class); + if (!formSubmit2Adapt) { + // 如果是处于拖拽状态,则释放组件 + stateModel.releaseDragging(e); + } else { + selectionModel.deleteSelection(); + designer.setPainter(null); + } + cancelPromptWidgetForbidEnter(); + } + } + + /** + * TODO 激活上下文菜单,待完善 + * 6.56暂时不支持右键 bugid 8777 + */ + private void triggerPopup(MouseEvent e) { + XCreator creator = selectionModel.getSelection().getSelectedCreator(); + if (creator == null) { + return; + } + JPopupMenu popupMenu = null; + ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, creator); + popupMenu = adapter.getContextPopupMenu(e); + + if (popupMenu != null) { + popupMenu.show(designer, e.getX(), e.getY()); + } + // 通知组件已经被选择了 + designer.getEditListenerTable().fireCreatorModified(creator, DesignerEvent.CREATOR_SELECTED); + } + + /** + * 移动 + * + * @param e 鼠标事件 + */ + public void mouseMoved(MouseEvent e) { + XCreator component = designer.getComponentAt(e); + + setCoverPaneNotDisplay(e, false); + + if (processTopLayoutMouseMove(component, e)) { + return; + } + if (component instanceof XEditorHolder) { + XEditorHolder xcreator = (XEditorHolder) component; + Rectangle rect = xcreator.getBounds(); + int min = rect.x + rect.width / 2 - minMoveSize; + int max = rect.x + rect.width / 2 + minMoveSize; + if (e.getX() > min && e.getX() < max) { + if (designer.getCursor().getType() != Cursor.HAND_CURSOR) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + return; + } else { + if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + } + Direction dir = selectionModel.getDirectionAt(e); + if (designer.isDrawLineMode() && stateModel.getDirection() == Location.outer) { + designer.updateDrawLineMode(e); + } + if (!BaseUtils.isAuthorityEditing()) { + stateModel.setDirection(dir); + } + + if (component.isReport()) { + elementCaseMouseMoved(e, component); + designer.repaint(); + return; + } + + processChartEditorMouseMove(component, e); + + designer.repaint(); + } + + private void elementCaseMouseMoved(MouseEvent e, XCreator component) { + xElementCase = (XElementCase) component; + UIButton button = (UIButton) xElementCase.getCoverPane().getComponent(0); + if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } // component.getParent() 是报表块所在的XWTitleLayout + int minX = button.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); + int minY = button.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); + if (e.getX() + GAP - xElementCase.getInsets().left > minX && e.getX() - GAP - xElementCase.getInsets().left < minX + button.getWidth()) { + if (e.getY() + GAP - xElementCase.getInsets().top > minY && e.getY() - GAP - xElementCase.getInsets().top < minY + button.getHeight()) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + } + xElementCase.setHelpBtnOnFocus(false); + if (xElementCase.getCoverPane().getComponentCount() > 1) { + JComponent button1 = (JComponent) xElementCase.getCoverPane().getComponent(1); + int minX1 = button1.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); + int minY1 = button1.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); + if (e.getX() + GAP - xElementCase.getInsets().left > minX1 && e.getX() - GAP - xElementCase.getInsets().left < minX1 + button1.getWidth()) { + if (e.getY() + GAP - xElementCase.getInsets().top > minY1 && e.getY() - GAP - xElementCase.getInsets().top < minY1 + button1.getHeight()) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + xElementCase.setHelpBtnOnFocus(true); + } + } + } + xElementCase.displayCoverPane(true); + xElementCase.setDirections(Direction.TOP_BOTTOM_LEFT_RIGHT); + } + + private void setCoverPaneNotDisplay(MouseEvent e, boolean isLinkedHelpDialog) { + if (xElementCase != null) { + int x = getParentPositionX(xElementCase, 0) - designer.getArea().getHorizontalValue(); + int y = getParentPositionY(xElementCase, 0) - designer.getArea().getVerticalValue(); + Rectangle rect = new Rectangle(x, y, xElementCase.getWidth(), xElementCase.getHeight()); + if (rect.contains(e.getPoint())) { + return; + } + if (isLinkedHelpDialog) { + xElementCase.destroyHelpDialog(); + } + xElementCase.displayCoverPane(false); + } + if (xChartEditor != null) { + xChartEditor.displayCoverPane(false); + } + + if (xTopLayoutContainer != null) { + xTopLayoutContainer.setMouseEnter(false); + } + designer.repaint(); + } + + private boolean processTopLayoutMouseMove(XCreator component, MouseEvent e) { + XLayoutContainer parent = XCreatorUtils.getHotspotContainer(component).getTopLayout(); + if (parent != null) { + xTopLayoutContainer = parent; + xTopLayoutContainer.setMouseEnter(true); + designer.repaint(); + if (!xTopLayoutContainer.isEditable()) { + if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + int minX = getParentPositionX(parent, parent.getX()) + parent.getWidth() / 2; + int minY = getParentPositionY(parent, parent.getY()) + parent.getHeight() / 2; + int offsetX = EDIT_BTN_WIDTH / 2 + GAP; + int offsetY = EDIT_BTN_HEIGHT / 2 + GAP; + if (e.getX() > (minX - offsetX) && e.getX() < (minX + offsetX)) { + if (e.getY() > (minY - offsetY) && e.getY() < (minY + offsetY + designer.getParaHeight())) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + } + return true; + } + } + return false; + } + + private void processChartEditorMouseMove(XCreator component, MouseEvent e) { + if (component instanceof XChartEditor) { + xChartEditor = (XChartEditor) component; + UIButton button = (UIButton) xChartEditor.getCoverPane().getComponent(0); + if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + int minX = button.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); + int minY = button.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); + if (e.getX() + GAP > minX && e.getX() - GAP < minX + button.getWidth()) { + if (e.getY() + GAP > minY && e.getY() - GAP < minY + button.getHeight()) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + } + xChartEditor.displayCoverPane(true); + xChartEditor.setDirections(Direction.TOP_BOTTOM_LEFT_RIGHT); + designer.repaint(); + } + } + + private int getParentPositionX(XCreator comp, int x) { + return comp.getParent() == null ? + x : getParentPositionX((XCreator) comp.getParent(), comp.getParent().getX() + x); + } + + private int getParentPositionY(XCreator comp, int y) { + return comp.getParent() == null ? + y : getParentPositionY((XCreator) comp.getParent(), comp.getParent().getY() + y); + } + + /** + * 拖拽 + * + * @param e 鼠标事件 + */ + public void mouseDragged(MouseEvent e) { + if (BaseUtils.isAuthorityEditing()) { + return; + } + // 如果当前是左键拖拽状态,拖拽组件 + if (stateModel.dragable()) { + if (SwingUtilities.isRightMouseButton(e)) { + return; + } else { + 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; + } + // 获取焦点组件所在的焦点容器 + XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot); + //提示组件是否可以拖入 + promptUser(e.getX(), e.getY(), container); + } + } else if (designer.isDrawLineMode()) { + if (stateModel.prepareForDrawLining()) { + stateModel.drawLine(e); + } + } else if (stateModel.isSelecting() && (selectionModel.getHotspotBounds() != null)) { + // 如果是拖拽选择区域状态,则更新选择区域 + stateModel.changeSelection(e); + } else { + if ((lastPressEvent == null) || (lastXCreator == null)) { + return; + } + if (e.getPoint().distance(lastPressEvent.getPoint()) > minDragSize) { + //参数面板和自适应布局不支持拖拽 + if (lastXCreator.isSupportDrag()) { + designer.startDraggingComponent(lastXCreator, lastPressEvent, e.getX(), e.getY()); + } + e.consume(); + lastPressEvent = null; + } + } + designer.repaint(); + } + + //当前编辑的组件是在布局中,鼠标点击布局外部,需要一次性将布局及其父布局都置为不可编辑 + private void setTopLayoutUnEditable(XLayoutContainer clickedTopLayout, XLayoutContainer clickingTopLayout) { + //双击的前后点击click为相同对象,过滤掉 + if (clickedTopLayout == null || clickedTopLayout == clickingTopLayout) { + return; + } + //位于同一层级的控件,父布局相同,过滤掉 + if (clickingTopLayout != null && clickedTopLayout.getParent() == clickingTopLayout.getParent()) { + return; + } + //前后点击的位于不同层级,要置为不可编辑 + XLayoutContainer xLayoutContainer = (XLayoutContainer) clickedTopLayout.getParent(); + if (xLayoutContainer == clickingTopLayout) { + return; + } + if (xLayoutContainer != null) { + xLayoutContainer.setEditable(false); + setTopLayoutUnEditable((XLayoutContainer) clickedTopLayout.getParent(), clickingTopLayout); + } + } + + private boolean isCreatorInLayout(XCreator creator, XCreator layout) { + if (creator.equals(layout)) { + return true; + } + if (layout.getParent() != null) { + return isCreatorInLayout(creator, (XCreator) layout.getParent()); + } + return false; + } + + private XCreator processTopLayoutMouseClick(XCreator creator) { + XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(creator).getTopLayout(); + if (topLayout != null) { + if (clickTopLayout != null && !clickTopLayout.equals(topLayout) && !isCreatorInLayout(clickTopLayout, + topLayout)) { + clickTopLayout.setEditable(false); + setTopLayoutUnEditable(clickTopLayout, topLayout); + } + clickTopLayout = topLayout; + if (!topLayout.isEditable()) { + creator = topLayout; + } + } else { + if (clickTopLayout != null) { + clickTopLayout.setEditable(false); + setTopLayoutUnEditable(clickTopLayout, null); + } + } + + return creator; + } + + /** + * 点击 + * + * @param e 鼠标事件 + */ + public void mouseClicked(MouseEvent e) { + XCreator creator = designer.getComponentAt(e); + + if (e.getButton() != MouseEvent.BUTTON1 && !creator.acceptType(XCardSwitchButton.class)) { + return; + } + + creator = processTopLayoutMouseClick(creator); + + if (creator != null) { + creator.respondClick(this, e); + } + creator.doLayout(); + LayoutUtils.layoutRootContainer(designer.getRootComponent()); + } + + + /** + * 离开 + * + * @param e 鼠标事件 + */ + public void mouseExited(MouseEvent e) { + if (designer.getCursor().getType() != Cursor.DEFAULT_CURSOR) { + designer.setCursor(Cursor.getDefaultCursor()); + } + + setCoverPaneNotDisplay(e, true); + + cancelPromptWidgetForbidEnter(); + } + + /** + * 开始编辑 + * + * @param creator 容器 + * @param designerEditor 设计器 + * @param adapter 适配器 + */ + public void startEditing(XCreator creator, DesignerEditor designerEditor, ComponentAdapter adapter) { + if (designerEditor != null) { + Rectangle rect = ComponentUtils.getRelativeBounds(creator); + currentEditor = designerEditor; + currentXCreator = creator; + Rectangle bounds = new Rectangle(1, 1, creator.getWidth() - 2, creator.getHeight() - 2); + bounds.x += (rect.x - designer.getArea().getHorizontalValue()); + bounds.y += (rect.y - designer.getArea().getVerticalValue()); + designerEditor.getEditorTarget().setBounds(bounds); + designer.add(designerEditor.getEditorTarget()); + designer.invalidate(); + designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + designerEditor.getEditorTarget().requestFocus(); + designer.repaint(); + } + } + + /** + * 停止编辑 + * + * @return 是否编辑成功 + */ + public boolean stopEditing() { + if (currentEditor != null) { + designer.remove(currentEditor.getEditorTarget()); + currentEditor.fireEditStoped(); + + Container container = currentXCreator.getParent(); + + if (container != null) { + LayoutUtils.layoutRootContainer(container); + } + designer.invalidate(); + designer.repaint(); + currentXCreator = null; + currentEditor = null; + return true; + } + return true; + } + + /** + * 重置编辑控件大小 + */ + public void resetEditorComponentBounds() { + if (currentEditor == null) { + return; + } + + if (currentXCreator.getParent() == null) { + stopEditing(); + return; + } + + Rectangle rect = ComponentUtils.getRelativeBounds(currentXCreator); + Rectangle bounds = new Rectangle(1, 1, currentXCreator.getWidth() - 2, currentXCreator.getHeight() - 2); + bounds.x += (rect.x - designer.getArea().getHorizontalValue()); + bounds.y += (rect.y - designer.getArea().getVerticalValue()); + if (currentXCreator instanceof XEditorHolder) { + ToolTipEditor.getInstance().resetBounds((XEditorHolder) currentXCreator, bounds, currentEditor.getEditorTarget().getBounds()); + } + currentEditor.getEditorTarget().setBounds(bounds); + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/FormDesigner.java b/designer_form/src/com/fr/design/mainframe/FormDesigner.java index a3b197e91..1dd61c559 100644 --- a/designer_form/src/com/fr/design/mainframe/FormDesigner.java +++ b/designer_form/src/com/fr/design/mainframe/FormDesigner.java @@ -6,7 +6,10 @@ import com.fr.design.DesignState; import com.fr.design.designer.TargetComponent; import com.fr.design.designer.beans.AdapterBus; import com.fr.design.designer.beans.Painter; +import com.fr.design.designer.beans.actions.CopyAction; +import com.fr.design.designer.beans.actions.CutAction; import com.fr.design.designer.beans.actions.FormDeleteAction; +import com.fr.design.designer.beans.actions.PasteAction; import com.fr.design.designer.beans.adapters.layout.FRParameterLayoutAdapter; import com.fr.design.designer.beans.events.CreatorEventListenerTable; import com.fr.design.designer.beans.events.DesignerEditListener; @@ -43,7 +46,6 @@ import com.fr.form.ui.container.WFitLayout; import com.fr.general.ComparatorUtils; import com.fr.general.FRLogger; import com.fr.general.Inter; -import com.fr.plugin.ExtraClassManager; import com.fr.stable.ArrayUtils; import com.fr.stable.bridge.StableFactory; @@ -65,11 +67,10 @@ import java.util.List; /** * 设计界面组件。该组件是界面设计工具的核心,主要负责的是被设计界面的显示,界面设计操作状态的 显示,编辑状态的显示等等。 */ -public class FormDesigner extends TargetComponent

implements TreeSelectionListener, InvocationHandler, BaseFormDesigner ,ParaDefinitePane{ +public class FormDesigner extends TargetComponent implements TreeSelectionListener, InvocationHandler, BaseFormDesigner, ParaDefinitePane { protected static final ArrayList NAME_ARRAY_LIST = new ArrayList( Arrays.asList(new String[]{Inter.getLocText("M_Edit-Cut"), Inter.getLocText("M_Edit-Copy"), Inter.getLocText("M_Edit-Delete")}) ); - private static final int BORDER_WIDTH = 6; //底层容器的默认大小 protected static final Dimension LARGE_PREFERRED_SIZE = new Dimension(WBorderLayout.DEFAULT_WIDTH, WBorderLayout.DEFAULT_HEIGHT); private int paraHeight = 0; @@ -81,7 +82,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection private XLayoutContainer paraComponent; private boolean drawLineMode; private FormArea formArea; - private ConnectorHelper ConnectorHelper; + private ConnectorHelper connectorHelper; private boolean isReportBlockEditing = false; //组件重叠 @@ -104,7 +105,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection // 编辑状态的事件表 private CreatorEventListenerTable edit; - protected Action[] designer_actions; + protected Action[] designerActions; private FormDesignerModeForSpecial desigerMode; private Action switchAction; private FormElementCaseContainerProvider elementCaseContainer; @@ -159,7 +160,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection ParameterPropertyPane.getInstance().populateBean(this); } - public Parameter[] getNoRepeatParas(Parameter[] paras){ + public Parameter[] getNoRepeatParas(Parameter[] paras) { List paraList = new ArrayList(); java.util.Set set = new java.util.HashSet(); for (Parameter p : paras) { @@ -171,23 +172,23 @@ public class FormDesigner extends TargetComponent implements TreeSelection return paraList.toArray(new Parameter[paraList.size()]); } - public void setParameterArray(Parameter[] ps){ + public void setParameterArray(Parameter[] ps) { parameterArray = ps; } - public Parameter[] getParameterArray(){ + public Parameter[] getParameterArray() { return parameterArray; } /** * 刷新参数 */ - public void refreshParameter(){ + public void refreshParameter() { XLayoutContainer rootContainer = this.getParaComponent(); - if (rootContainer != null){ + if (rootContainer != null) { java.util.List namelist = new ArrayList(); - rootContainer.getAllXCreatorNameList(rootContainer,namelist); + rootContainer.getAllXCreatorNameList(rootContainer, namelist); // parameterArray是报表的所有参数, nameList是已经在参数面板添加过控件的参数名 // 与已有的参数列表比较 如果已经存在 就除去 Parameter[] ps = getParameterArray(); @@ -201,7 +202,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection EastRegionContainerPane.getInstance().setParameterHeight(ParameterPropertyPane.getInstance(this).getPreferredSize().height); } - private void removeSame(Parameter[] parameters, List namelist){ + private void removeSame(Parameter[] parameters, List namelist) { for (Parameter parameter : parameters) { for (String name : namelist) { if (name.equalsIgnoreCase(parameter.getName())) { @@ -214,20 +215,22 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 是否有查询按钮 - * @return 有无查询按钮 + * + * @return 有无查询按钮 */ - public boolean isWithQueryButton(){ + public boolean isWithQueryButton() { XLayoutContainer rootContainer = this.getParaComponent(); return rootContainer != null && rootContainer.SearchQueryCreators(rootContainer); } /** * 加入参数到参数面板 + * * @param parameter 参数 * @return 是否加入 */ - public void addingParameter2Editor(Parameter parameter){ - if(getParaComponent() == null){ + public void addingParameter2Editor(Parameter parameter) { + if (getParaComponent() == null) { addParaPaneTooltips(); return; } @@ -242,11 +245,11 @@ public class FormDesigner extends TargetComponent implements TreeSelection if (!(this.autoAddComponent(xLabel, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE) + FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { - return ; + return; } if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE) + SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { - return ; + return; } currentIndex++; parameterArray = (Parameter[]) ArrayUtils.removeElement(parameterArray, parameter); @@ -256,11 +259,12 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 加入参数到参数面板,有查询按钮 + * * @param parameter 参数 * @return 是否加入 */ - public void addingParameter2EditorWithQueryButton(Parameter parameter){ - if(getParaComponent() == null){ + public void addingParameter2EditorWithQueryButton(Parameter parameter) { + if (getParaComponent() == null) { addParaPaneTooltips(); return; } @@ -276,12 +280,12 @@ public class FormDesigner extends TargetComponent implements TreeSelection if (!(this.autoAddComponent(xLabel, FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { - return ; + return; } if (!(this.autoAddComponent(xCreator, SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { - return ; + return; } FormSubmitButton formSubmitButton = new FormSubmitButton(); formSubmitButton.setWidgetName("Search"); @@ -289,7 +293,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection xCreator = XCreatorUtils.createXCreator(formSubmitButton); if (!(this.autoAddComponent(xCreator, 270, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) { - return ; + return; } currentIndex = currentIndex + NUM_IN_A_LINE - currentIndex % NUM_IN_A_LINE; parameterArray = (Parameter[]) ArrayUtils.removeElement(parameterArray, parameter); @@ -300,8 +304,8 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 一键添加所有参数 */ - public void addingAllParameter2Editor(){ - if(getParaComponent() == null){ + public void addingAllParameter2Editor() { + if (getParaComponent() == null) { addParaPaneTooltips(); return; } @@ -350,16 +354,17 @@ public class FormDesigner extends TargetComponent implements TreeSelection EastRegionContainerPane.getInstance().refreshDownPane(); } - private void addParaPaneTooltips(){ - JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(),Inter.getLocText("FR-Designer-Form-Please_Drag_ParaPane"), + private void addParaPaneTooltips() { + JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("FR-Designer-Form-Please_Drag_ParaPane"), Inter.getLocText("FR-Designer_Tooltips"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); } /** * 自动添加组件 - * @param xCreator 组件 - * @param x 横坐标 - * @param y 纵坐标 + * + * @param xCreator 组件 + * @param x 横坐标 + * @param y 纵坐标 * @return 是否添加成功 */ public boolean autoAddComponent(XCreator xCreator, int x, int y) { @@ -375,10 +380,11 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 在参数很多时,全部添加的时候,可以向下一次排版,若去掉就会在参数面板堆到一起 + * * @param creator 组件 - * @param x 长度 - * @param y 长度 - * @param layout 布局 + * @param x 长度 + * @param y 长度 + * @param layout 布局 * @return 是否扩展 */ public boolean prepareForAdd(XCreator creator, int x, int y, XWParameterLayout layout) { @@ -404,9 +410,9 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 加入参数面板 */ - public void addParaComponent(){ + public void addParaComponent() { if (paraComponent != null) { - return ; + return; } paraHeight = WBorderLayout.DEFAULT_SIZE; paraComponent = new XWParameterLayout(); @@ -414,7 +420,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection paraComponent.setSize(paraComponent.initEditorSize()); XWBorderLayout formLayoutContainer = (XWBorderLayout) rootComponent.getParent(); formLayoutContainer.toData().setNorthSize(paraHeight); - formLayoutContainer.add(paraComponent,WBorderLayout.NORTH); + formLayoutContainer.add(paraComponent, WBorderLayout.NORTH); //设下northSize,增加para后,重置border大小,这时候para和root的大小会自适应调整 formLayoutContainer.setSize(formLayoutContainer.getWidth(), formLayoutContainer.getHeight() + paraHeight); selectionModel.reset(); @@ -424,30 +430,33 @@ public class FormDesigner extends TargetComponent implements TreeSelection } /** - * 返回根节点父容器 - * @return 父容器 + * 返回根节点父容器 + * + * @return 父容器 */ - public Component getTopContainer(){ - if(rootComponent != null){ + public Component getTopContainer() { + if (rootComponent != null) { // 返回root所在的父容器,非designer return LayoutUtils.getTopContainer(rootComponent); } - return XCreatorUtils.createXCreator(this.getTarget().getContainer()); + return XCreatorUtils.createXCreator(this.getTarget().getContainer()); } /** * 返回参数界面高度 - * @return para高度 + * + * @return para高度 */ - public int getParaHeight(){ + public int getParaHeight() { return paraHeight; } /** * 重置para的高度 - * @param height 高度 + * + * @param height 高度 */ - public void setParaHeight(int height){ + public void setParaHeight(int height) { XWBorderLayout container = (XWBorderLayout) getTopContainer(); container.toData().setNorthSize(height); container.setSize(container.getWidth(), container.getHeight() + height - getParaHeight()); @@ -457,7 +466,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 删除参数界面 */ - public void removeParaComponent(){ + public void removeParaComponent() { XWBorderLayout formLayoutContainer = (XWBorderLayout) getTopContainer(); formLayoutContainer.toData().removeWidget(paraComponent.toData()); paraHeight = 0; @@ -472,41 +481,42 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 切换 - * @param elementCaseContainer 容器 + * + * @param elementCaseContainer 容器 */ - public void switchTab(FormElementCaseContainerProvider elementCaseContainer){ - if(this.switchAction == null){ + public void switchTab(FormElementCaseContainerProvider elementCaseContainer) { + if (this.switchAction == null) { return; } this.elementCaseContainer = elementCaseContainer; this.switchAction.actionPerformed(null); } - public void setElementCaseContainer(FormElementCaseContainerProvider elementCaseContainer){ + public void setElementCaseContainer(FormElementCaseContainerProvider elementCaseContainer) { this.elementCaseContainer = elementCaseContainer; } - public FormElementCaseProvider getElementCase(){ + public FormElementCaseProvider getElementCase() { return this.elementCaseContainer.getElementCase(); } - public String getElementCaseContainerName(){ + public String getElementCaseContainerName() { return this.elementCaseContainer.getElementCaseContainerName(); } - public void setElementCase(FormElementCaseProvider elementCase){ + public void setElementCase(FormElementCaseProvider elementCase) { this.elementCaseContainer.setElementCase(elementCase); } - public void setElementCaseBackground(BufferedImage image){ + public void setElementCaseBackground(BufferedImage image) { this.elementCaseContainer.setBackground(image); } - public Dimension getElementCaseContainerSize(){ + public Dimension getElementCaseContainerSize() { return this.elementCaseContainer.getSize(); } - public FormElementCaseContainerProvider getElementCaseContainer(){ + public FormElementCaseContainerProvider getElementCaseContainer() { return this.elementCaseContainer; } @@ -524,6 +534,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 增加监听事件 + * * @param listener 界面组件编辑事件 */ public void addDesignerEditListener(DesignerEditListener listener) { @@ -539,15 +550,15 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 表单则判断参数面板是否为绝对布局 + * * @return 是则返回true */ public boolean hasWAbsoluteLayout() { - if (paraComponent != null && paraComponent.acceptType(XWParameterLayout.class)){ + if (paraComponent != null && paraComponent.acceptType(XWParameterLayout.class)) { return true; - } - else{ + } else { if (this.getSelectionModel().getSelection().getSelectedCreator().getParent() != null - && ((XLayoutContainer)this.getSelectionModel().getSelection().getSelectedCreator().getParent()).acceptType(XWAbsoluteLayout.class)){ + && ((XLayoutContainer) this.getSelectionModel().getSelection().getSelectedCreator().getParent()).acceptType(XWAbsoluteLayout.class)) { return true; } } @@ -555,7 +566,8 @@ public class FormDesigner extends TargetComponent implements TreeSelection } /** - * 设置是否为报表块编辑 + * 设置是否为报表块编辑 + * * @param isEditing 是否为报表块编辑 */ public void setReportBlockEditing(boolean isEditing) { @@ -564,25 +576,27 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 是否为报表块编辑 + * * @return 是否为报表块编辑 */ public boolean isReportBlockEditing() { return this.isReportBlockEditing; } - public void setWidgetsIntersect(boolean isWidgetsIntersect){ + public void setWidgetsIntersect(boolean isWidgetsIntersect) { this.isWidgetsIntersect = isWidgetsIntersect; } - public boolean isWidgetsIntersect(){ + public boolean isWidgetsIntersect() { return this.isWidgetsIntersect; } /** * 是否重命名控件 + * * @param creator 组件 * @param newName 新的组件名 - * @return 组件名有变化,且不和其他一样返回true + * @return 组件名有变化,且不和其他一样返回true */ public boolean renameCreator(XCreator creator, String newName) { if (ComparatorUtils.equals(creator.toData().getWidgetName(), newName)) { @@ -609,16 +623,17 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 更新界面布局,重绘 - * @param proxy 动态代理类 + * + * @param proxy 动态代理类 * @param method 接口方法 - * @param args 参数 + * @param args 参数 * @return 不返回任何对象 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if(rootComponent != null){ + if (rootComponent != null) { LayoutUtils.layoutRootContainer(rootComponent); } - if(paraComponent != null){ + if (paraComponent != null) { LayoutUtils.layoutRootContainer(paraComponent); } repaint(); @@ -654,6 +669,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 增加组件事件 + * * @param h 动态代理 */ public void addInvocationHandler(InvocationHandler h) { @@ -678,7 +694,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection } /** - * 设置其UI类为DesignerUI,负责渲染 + * 设置其UI类为DesignerUI,负责渲染 */ @Override public void updateUI() { @@ -741,15 +757,13 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 更新边框线状态 + * * @param e 鼠标事件 */ public void updateDrawLineMode(MouseEvent e) { - Point p = ConnectorHelper.getNearWidgetPoint(e); - if (p == null) { - XComponent comp = getComponentAt(e); - if (comp == rootComponent) { - p = new Point(e.getX() + formArea.getHorizontalValue(), e.getY() + formArea.getVerticalValue()); - } + Point p = connectorHelper.getNearWidgetPoint(e); + if (p == null && getComponentAt(e) == rootComponent) { + p = new Point(e.getX() + formArea.getHorizontalValue(), e.getY() + formArea.getVerticalValue()); } stateModel.startDrawLine(p); } @@ -761,7 +775,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection // 撤销恢复操作都会refreshRoot,这时候的target.getContainer里的widget会和之前不一样,所以不用root判断来取 XLayoutContainer formLayoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator(this.getTarget().getContainer()); // 布局默认都是1,底层的border改为0,不然没意义 - this.getTarget().getContainer().setMargin(new PaddingMargin(0,0,0,0)); + this.getTarget().getContainer().setMargin(new PaddingMargin(0, 0, 0, 0)); formLayoutContainer.setBorder(null); if (formLayoutContainer.acceptType(XWBorderLayout.class)) { WBorderLayout borderLayout = (WBorderLayout) formLayoutContainer.toData(); @@ -774,7 +788,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection refreshNorth(northWidget, formLayoutContainer); refreshCenter(centerWidget, formLayoutContainer); - } else { + } else { formLayoutContainer.setSize(LARGE_PREFERRED_SIZE); setRootComponent(formLayoutContainer); } @@ -790,9 +804,9 @@ public class FormDesigner extends TargetComponent implements TreeSelection } XLayoutContainer northContainer = (XLayoutContainer) XCreatorUtils.createXCreator(northWidget); - paraHeight = ((XWBorderLayout)formLayoutContainer).toData().getNorthSize(); + paraHeight = ((XWBorderLayout) formLayoutContainer).toData().getNorthSize(); paraComponent = northContainer; - northContainer.setSize(0,paraHeight); + northContainer.setSize(0, paraHeight); formLayoutContainer.add(northContainer, WBorderLayout.NORTH); } @@ -841,14 +855,16 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 是否是报表的参数面板 - * @return 否(表单的) + * + * @return 否(表单的) */ - public boolean isFormParaDesigner(){ + public boolean isFormParaDesigner() { return false; } /** - * 是否为底层容器 + * 是否为底层容器 + * * @param comp 组件 * @return 是则返回true */ @@ -923,10 +939,10 @@ public class FormDesigner extends TargetComponent implements TreeSelection } public SelectionModel getSelectionModel() { - if (paraComponent!=null){ - paraComponent.setSize(paraComponent.getWidth(),getParaHeight()); + if (paraComponent != null) { + paraComponent.setSize(paraComponent.getWidth(), getParaHeight()); Rectangle rec = rootComponent.getBounds(); - rootComponent.setBounds(rec.x,getParaHeight(),rec.width,rec.height); + rootComponent.setBounds(rec.x, getParaHeight(), rec.width, rec.height); } return selectionModel; } @@ -941,6 +957,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 拖拽准备 + * * @param xCreator 组件 */ public void startDraggingBean(XCreator xCreator) { @@ -953,11 +970,12 @@ public class FormDesigner extends TargetComponent implements TreeSelection } /** - * 拖拽时相关处理 - * @param xCreator 组件 + * 拖拽时相关处理 + * + * @param xCreator 组件 * @param lastPressEvent 鼠标事件 - * @param x 坐标x - * @param y 坐标y + * @param x 坐标x + * @param y 坐标y */ public void startDraggingComponent(XCreator xCreator, MouseEvent lastPressEvent, int x, int y) { // 根据所选择的组件的BeanInfo生成相应的AddingModel @@ -978,6 +996,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 改变组件值 + * * @param e 组件选择事件 */ @Override @@ -1024,6 +1043,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 是否支持权限编辑 + * * @return 是则返回true */ public boolean isSupportAuthority() { @@ -1048,7 +1068,8 @@ public class FormDesigner extends TargetComponent implements TreeSelection } /** - * 是否含有action名 + * 是否含有action名 + * * @param name action名 * @return 有则返回true */ @@ -1058,6 +1079,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 显示组件 + * * @param comp 组件 */ public void makeVisible(XCreator comp) { @@ -1088,16 +1110,16 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 返回复制粘贴删除等动作 + * 鼠标右键菜单 + * * @return 同上 */ public Action[] getActions() { - if (designer_actions == null) { - //先把复制粘贴按钮去掉,只留下删除 -// designer_actions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this), -// new FormDeleteAction(this)}; - designer_actions = new Action[]{new FormDeleteAction(this)}; + if (designerActions == null) { + designerActions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this), + new FormDeleteAction(this)}; } - return designer_actions; + return designerActions; } protected Border getOuterBorder() { @@ -1120,6 +1142,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 返回表单区域 + * * @return 表单区域 */ public FormArea getArea() { @@ -1128,6 +1151,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 设置上层区域 + * * @param formArea 表单区域 */ public void setParent(FormArea formArea) { @@ -1136,14 +1160,15 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 绘制组件根节点 + * * @param clipg 图形 */ public void paintContent(Graphics clipg) { rootComponent.paint(clipg); } - public void paintPara(Graphics clipg){ - if(paraComponent != null){ + public void paintPara(Graphics clipg) { + if (paraComponent != null) { paraComponent.paint(clipg); } } @@ -1157,14 +1182,16 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 返回连线类 + * * @return ConnectorHelper类 */ public ConnectorHelper getDrawLineHelper() { - return ConnectorHelper; + return connectorHelper; } /** - * 是否画线模式 + * 是否画线模式 + * * @return 是则返回true */ public boolean isDrawLineMode() { @@ -1173,6 +1200,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 设置DrawLineMode + * * @param mode 是or或 */ public void setDrawLineMode(boolean mode) { @@ -1199,6 +1227,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 返回表单控件权限编辑pane + * * @return 同上 */ public AuthorityEditPane createAuthorityEditPane() { @@ -1249,6 +1278,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 粘贴 + * * @return 否 */ @Override @@ -1259,6 +1289,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 剪切 + * * @return 否 */ @Override @@ -1273,6 +1304,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 工具栏菜单 + * * @return 同上 */ @Override @@ -1286,6 +1318,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 模版菜单 + * * @return 同上 */ @Override @@ -1295,6 +1328,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 权限菜单 + * * @return 同上 */ public ShortCut[] shortCuts4Authority() { @@ -1304,6 +1338,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 返回ToolBarDef + * * @return 同上 */ @Override @@ -1313,10 +1348,12 @@ public class FormDesigner extends TargetComponent implements TreeSelection /** * 返回工具栏按钮组件 + * * @return 同上 */ public JComponent[] toolBarButton4Form() { - return new JComponent[0]; + return new JComponent[]{new CutAction(this).createToolBarComponent(), new CopyAction(this).createToolBarComponent(), new PasteAction(this).createToolBarComponent(), + new FormDeleteAction(this).createToolBarComponent()}; } diff --git a/designer_form/src/com/fr/design/mainframe/FormSelection.java b/designer_form/src/com/fr/design/mainframe/FormSelection.java index c81fc5841..f30cf2e84 100644 --- a/designer_form/src/com/fr/design/mainframe/FormSelection.java +++ b/designer_form/src/com/fr/design/mainframe/FormSelection.java @@ -20,288 +20,300 @@ import com.fr.design.utils.gui.LayoutUtils; public class FormSelection { - private ArrayList selection; - private Rectangle backupBounds; - private ArrayList recs = new ArrayList(); - - public FormSelection() { - selection = new ArrayList(); - } - - /** - * 重置选中的组件 - */ - public void reset() { - selection.clear(); - } - - /** - * 是否没有选中的组件 - * @return 为空返回true - */ - public boolean isEmpty() { - return selection.isEmpty(); - } - - /** - * 选中的组件数量 - * @return 选中的组件数量 - */ - public int size() { - return selection.size(); - } - - /** - * 去除选中的组件中指定组件 - * @param creator 待去除组件 - */ - public void removeCreator(XCreator creator) { - selection.remove(creator); - } - - /** - * 是否成功删除选择的组件 - * @param comp 组件 - * @return 是则返回true - */ - public boolean removeSelectedCreator(XCreator comp) { - if (selection.size() > 1 && selection.contains(comp)) { - removeCreator(comp); - return true; - } - return false; - } - - /** - * 成功增加选中的组件 - * @param creator 组件 - * @return 成功增加返回true - */ - public boolean addSelectedCreator(XCreator creator) { - if (addedable(creator)) { - selection.add(creator); - return true; - } - return false; - } - - /** - * 是否是可以增加的 - * @param creator 组件 - * @return 是则返回true - */ - public boolean addedable(XCreator creator) { - if (selection.isEmpty()) { - return true; - } - XLayoutContainer container = XCreatorUtils.getParentXLayoutContainer(creator); - if (!(container instanceof XWAbsoluteLayout)) { - return false; - } - for (XCreator selected : selection) { - if (selected == creator || XCreatorUtils.getParentXLayoutContainer(selected) != container) { - return false; - } - } - return true; - } - - /** - * 返回选中的第一个组件,为空返回null - * @return 返回选中组件 - */ - public XCreator getSelectedCreator() { - return !selection.isEmpty() ? selection.get(0) : null; - } - - /** - * 返回选中的所有组件 - * @return 所有组件s - */ - public XCreator[] getSelectedCreators() { - return selection.toArray(new XCreator[selection.size()]); - } - - public Widget[] getSelectedWidgets() { - Widget[] selectWidget = new Widget[selection.size()]; - for (int i = 0; i < selection.size(); i++) { - selectWidget[i] = selection.get(i).toData(); - } - return selectWidget; - } - - public void setSelectedCreator(XCreator creator) { - reset(); - selection.add(creator); - } - - public void setSelectedCreators(ArrayList selections) { - reset(); - for (XCreator creator : selections) { - if (addedable(creator)) { - selection.add(creator); - } - } - } - - /** - * 是否包含当前控件 - * @param widget 控件 - * @return 是则返回true - */ - public boolean contains(Widget widget) { - for (XCreator creator : selection) { - if (creator.toData() == widget) { - return true; - } - } - return false; - } - - public int[] getDirections() { - if (this.selection.size() > 1) { - return Direction.ALL; - } else if (this.selection.size() == 1) { - return this.selection.get(0).getDirections(); - } else { - return new int[0]; - } - } - - /** - * 备份组件的bound - */ - public void backupBounds() { - backupBounds = getRelativeBounds(); - recs.clear(); - for (XComponent comp : selection) { - recs.add(comp.getBounds()); - } - } - - public Rectangle getBackupBounds() { - return backupBounds; - } - - public Rectangle getRelativeBounds() { - Rectangle bounds = getSelctionBounds(); - XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.get(0)); - if (parent == null) { - return bounds; - } - Rectangle rec = ComponentUtils.getRelativeBounds(parent); - bounds.x += rec.x; - bounds.y += rec.y; - return bounds; - } - - public Rectangle getSelctionBounds() { - if(selection.isEmpty()) { - return new Rectangle(); - } - Rectangle bounds = selection.get(0).getBounds(); - for (int i = 1, len = selection.size(); i < len; i++) { - bounds = bounds.union(selection.get(i).getBounds()); - } - return bounds; - } - - public void setSelectionBounds(Rectangle rec, FormDesigner designer) { - XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.get(0)); - Rectangle backupBounds = new Rectangle(this.backupBounds); - if (parent != null) { - Rectangle r = ComponentUtils.getRelativeBounds(parent); - rec.x -= r.x; - rec.y -= r.y; - backupBounds.x -= r.x; - backupBounds.y -= r.y; - } - - int size = selection.size(); - if (size == 1) { - XCreator creator = selection.get(0); - creator.setBounds(rec); - if(creator.acceptType(XWParameterLayout.class)){ - designer.setParaHeight((int)rec.getHeight()); + private ArrayList selection; + private Rectangle backupBounds; + private ArrayList recs = new ArrayList(); + + public FormSelection() { + selection = new ArrayList(); + } + + /** + * 重置选中的组件 + */ + public void reset() { + selection.clear(); + } + + /** + * 是否没有选中的组件 + * + * @return 为空返回true + */ + public boolean isEmpty() { + return selection.isEmpty(); + } + + /** + * 选中的组件数量 + * + * @return 选中的组件数量 + */ + public int size() { + return selection.size(); + } + + /** + * 去除选中的组件中指定组件 + * + * @param creator 待去除组件 + */ + public void removeCreator(XCreator creator) { + selection.remove(creator); + } + + /** + * 是否成功删除选择的组件 + * + * @param comp 组件 + * @return 是则返回true + */ + public boolean removeSelectedCreator(XCreator comp) { + if (selection.size() > 1 && selection.contains(comp)) { + removeCreator(comp); + return true; + } + return false; + } + + /** + * 成功增加选中的组件 + * + * @param creator 组件 + * @return 成功增加返回true + */ + public boolean addSelectedCreator(XCreator creator) { + if (addedable(creator)) { + selection.add(creator); + return true; + } + return false; + } + + /** + * 是否是可以增加的 + * + * @param creator 组件 + * @return 是则返回true + */ + public boolean addedable(XCreator creator) { + if (selection.isEmpty()) { + return true; + } + XLayoutContainer container = XCreatorUtils.getParentXLayoutContainer(creator); + if (!(container instanceof XWAbsoluteLayout)) { + return false; + } + for (XCreator selected : selection) { + if (selected == creator || XCreatorUtils.getParentXLayoutContainer(selected) != container) { + return false; + } + } + return true; + } + + /** + * 返回选中的第一个组件,为空返回null + * + * @return 返回选中组件 + */ + public XCreator getSelectedCreator() { + return !selection.isEmpty() ? selection.get(0) : null; + } + + /** + * 返回选中的所有组件 + * + * @return 所有组件s + */ + public XCreator[] getSelectedCreators() { + return selection.toArray(new XCreator[selection.size()]); + } + + public Widget[] getSelectedWidgets() { + Widget[] selectWidget = new Widget[selection.size()]; + for (int i = 0; i < selection.size(); i++) { + selectWidget[i] = selection.get(i).toData(); + } + return selectWidget; + } + + public void setSelectedCreator(XCreator creator) { + reset(); + selection.add(creator); + } + + public void setSelectedCreators(ArrayList selections) { + reset(); + for (XCreator creator : selections) { + if (addedable(creator)) { + selection.add(creator); + } + } + } + + /** + * 是否包含当前控件 + * + * @param widget 控件 + * @return 是则返回true + */ + public boolean contains(Widget widget) { + for (XCreator creator : selection) { + if (creator.toData() == widget) { + return true; + } + } + return false; + } + + public int[] getDirections() { + if (this.selection.size() > 1) { + return Direction.ALL; + } else if (this.selection.size() == 1) { + return this.selection.get(0).getDirections(); + } else { + return new int[0]; + } + } + + /** + * 备份组件的bound + */ + public void backupBounds() { + backupBounds = getRelativeBounds(); + recs.clear(); + for (XComponent comp : selection) { + recs.add(comp.getBounds()); + } + } + + public Rectangle getBackupBounds() { + return backupBounds; + } + + public Rectangle getRelativeBounds() { + Rectangle bounds = getSelctionBounds(); + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.get(0)); + if (parent == null) { + return bounds; + } + Rectangle rec = ComponentUtils.getRelativeBounds(parent); + bounds.x += rec.x; + bounds.y += rec.y; + return bounds; + } + + public Rectangle getSelctionBounds() { + if (selection.isEmpty()) { + return new Rectangle(); + } + Rectangle bounds = selection.get(0).getBounds(); + for (int i = 1, len = selection.size(); i < len; i++) { + bounds = bounds.union(selection.get(i).getBounds()); + } + return bounds; + } + + public void setSelectionBounds(Rectangle rec, FormDesigner designer) { + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.get(0)); + Rectangle backupBounds = new Rectangle(this.backupBounds); + if (parent != null) { + Rectangle r = ComponentUtils.getRelativeBounds(parent); + rec.x -= r.x; + rec.y -= r.y; + backupBounds.x -= r.x; + backupBounds.y -= r.y; + } + + int size = selection.size(); + if (size == 1) { + XCreator creator = selection.get(0); + creator.setBounds(rec); + if (creator.acceptType(XWParameterLayout.class)) { + designer.setParaHeight((int) rec.getHeight()); designer.getArea().doLayout(); } - LayoutUtils.layoutContainer(creator); - } else if (size > 1) { - for (int i = 0; i < selection.size(); i++) { - Rectangle newBounds = new Rectangle(recs.get(i)); - newBounds.x = rec.x + (newBounds.x - backupBounds.x) * rec.width / backupBounds.width; - newBounds.y = rec.y + (newBounds.y - backupBounds.y) * rec.height / backupBounds.height; - newBounds.width = rec.width * newBounds.width / backupBounds.width; - newBounds.height = rec.height * newBounds.height / backupBounds.height; - XCreator creator = selection.get(i); - creator.setBounds(newBounds); - if(creator.acceptType(XWParameterLayout.class)){ - designer.setParaHeight((int)rec.getHeight()); + LayoutUtils.layoutContainer(creator); + } else if (size > 1) { + for (int i = 0; i < selection.size(); i++) { + Rectangle newBounds = new Rectangle(recs.get(i)); + newBounds.x = rec.x + (newBounds.x - backupBounds.x) * rec.width / backupBounds.width; + newBounds.y = rec.y + (newBounds.y - backupBounds.y) * rec.height / backupBounds.height; + newBounds.width = rec.width * newBounds.width / backupBounds.width; + newBounds.height = rec.height * newBounds.height / backupBounds.height; + XCreator creator = selection.get(i); + creator.setBounds(newBounds); + if (creator.acceptType(XWParameterLayout.class)) { + designer.setParaHeight((int) rec.getHeight()); designer.getArea().doLayout(); } - } - LayoutUtils.layoutRootContainer(designer.getRootComponent()); - } - } - - /** - * 调整组件大小 - * @param designer 设计界面组件 - */ - public void fixCreator(FormDesigner designer) { - for (XCreator creator : selection) { - LayoutAdapter layoutAdapter = AdapterBus.searchLayoutAdapter(designer, creator); - if (layoutAdapter != null) { - creator.setBackupBound(backupBounds); - layoutAdapter.fix(creator); - } - } - } - - private void removeCreatorFromContainer(XCreator creator) { - XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator); - if (parent == null) { - return; - } - // 删除其根组件,同时就删除了同时被选择的叶子组件 - parent.remove(creator); - LayoutManager layout = parent.getLayout(); - - if (layout != null) { - // 刷新组件容器的布局 - LayoutUtils.layoutContainer(parent); - } - } - - /** - * 剪切选中的所有组件 - * @param clipBoard 剪切板 - */ - public void cut2ClipBoard(FormSelection clipBoard) { - clipBoard.reset(); - clipBoard.selection.addAll(selection); - - for (XCreator creator : selection) { - removeCreatorFromContainer(creator); - } - reset(); - } - - /** - * 复制选中的所有组件 - * @param clipBoard 复制板 - */ - public void copy2ClipBoard(FormSelection clipBoard) { - clipBoard.reset(); - - for (XCreator root : selection) { - try { - XCreator creator = XCreatorUtils.createXCreator((Widget) root.toData().clone()); - creator.setBounds(root.getBounds()); - clipBoard.selection.add(creator); - } catch (CloneNotSupportedException e) { - FRContext.getLogger().error(e.getMessage(), e); - } - } - } + } + LayoutUtils.layoutRootContainer(designer.getRootComponent()); + } + } + + /** + * 调整组件大小 + * + * @param designer 设计界面组件 + */ + public void fixCreator(FormDesigner designer) { + for (XCreator creator : selection) { + LayoutAdapter layoutAdapter = AdapterBus.searchLayoutAdapter(designer, creator); + if (layoutAdapter != null) { + creator.setBackupBound(backupBounds); + layoutAdapter.fix(creator); + } + } + } + + private void removeCreatorFromContainer(XCreator creator) { + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator); + if (parent == null) { + return; + } + // 删除其根组件,同时就删除了同时被选择的叶子组件 + parent.remove(creator); + LayoutManager layout = parent.getLayout(); + + if (layout != null) { + // 刷新组件容器的布局 + LayoutUtils.layoutContainer(parent); + } + } + + /** + * 剪切选中的所有组件 + * + * @param clipBoard 剪切板 + */ + public void cut2ClipBoard(FormSelection clipBoard) { + clipBoard.reset(); + clipBoard.selection.addAll(selection); + + for (XCreator creator : selection) { + removeCreatorFromContainer(creator); + } + reset(); + } + + /** + * 复制选中的所有组件 + * + * @param clipBoard 复制板 + */ + public void copy2ClipBoard(FormSelection clipBoard) { + clipBoard.reset(); + + for (XCreator root : selection) { + try { + XCreator creator = XCreatorUtils.createXCreator((Widget) root.toData().clone()); + creator.setBounds(root.getBounds()); + clipBoard.selection.add(creator); + } catch (CloneNotSupportedException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java b/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java index fc6391225..ff976ef77 100644 --- a/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java +++ b/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java @@ -1,126 +1,270 @@ -package com.fr.design.mainframe; - -import java.awt.Component; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.fr.base.FRContext; -import com.fr.general.ComparatorUtils; -import com.fr.design.designer.beans.LayoutAdapter; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWAbsoluteLayout; -import com.fr.form.main.ClonedWidgetCreator; -import com.fr.form.ui.Widget; - -public class FormSelectionUtils { - - public static void paste2Container(FormDesigner designer, XLayoutContainer parent, FormSelection selection, int x, - int y) { - LayoutAdapter adapter = parent.getLayoutAdapter(); - if (selection.size() == 1) { - try { - XCreator creator = selection.getSelectedCreator(); - Widget cloned = new ClonedWidgetCreator(designer.getTarget()).clonedWidgetWithNoRepeatName(creator - .toData()); - XCreator clondCreator = XCreatorUtils.createXCreator(cloned, creator.getSize()); - if (adapter.addBean(clondCreator, x + clondCreator.getWidth() / 2, y + clondCreator.getHeight() / 2)) { - designer.getSelectionModel().getSelection().setSelectedCreator(clondCreator); - designer.getEditListenerTable().fireCreatorModified(clondCreator, DesignerEvent.CREATOR_PASTED); - return; - } - } catch (CloneNotSupportedException e) { - FRContext.getLogger().error(e.getMessage(), e); - } - } else if (selection.size() > 1) { - if (parent instanceof XWAbsoluteLayout) { - designer.getSelectionModel().getSelection().reset(); - Rectangle rec = selection.getSelctionBounds(); - for (XCreator creator : selection.getSelectedCreators()) { - try { - Widget cloned = new ClonedWidgetCreator(designer.getTarget()) - .clonedWidgetWithNoRepeatName(creator.toData()); - XCreator clondCreator = XCreatorUtils.createXCreator(cloned, creator.getSize()); - // 设置位置,移动20x20,防止被粘帖的组件重叠,照顾表单布局情况下 - adapter.addBean(clondCreator, x + creator.getX() - rec.x + clondCreator.getWidth() / 2, y - + creator.getY() - rec.y + clondCreator.getHeight() / 2); - designer.getSelectionModel().getSelection().addSelectedCreator(clondCreator); - } catch (CloneNotSupportedException e) { - FRContext.getLogger().error(e.getMessage(), e); - } - } - designer.getEditListenerTable().fireCreatorModified( - designer.getSelectionModel().getSelection().getSelectedCreator(), DesignerEvent.CREATOR_PASTED); - return; - } - } - Toolkit.getDefaultToolkit().beep(); - } - - public static void rebuildSelection(FormDesigner designer) { - ArrayList newSelection = new ArrayList(); - List widgetList = new ArrayList(); - for (XCreator comp : designer.getSelectionModel().getSelection().getSelectedCreators()) { - widgetList.add(comp.toData()); - } - designer.getSelectionModel().setSelectedCreators( - rebuildSelection(designer.getRootComponent(), widgetList, newSelection)); - } - - public static ArrayList rebuildSelection(XCreator rootComponent, Widget[] selectWidgets) { - List selectionWidget = new ArrayList(); - if(selectWidgets != null){ - selectionWidget.addAll(Arrays.asList(selectWidgets)); - } - return FormSelectionUtils.rebuildSelection(rootComponent, selectionWidget, new ArrayList()); - } - - private static ArrayList rebuildSelection(XCreator rootComponent, List selectionWidget, - ArrayList newSelection) { - FormSelectionUtils._rebuild(rootComponent, selectionWidget, newSelection); - if (newSelection.isEmpty()) { - newSelection.add(rootComponent); - } - return newSelection; - } - - private static void _rebuild(XCreator root, List selectionWidget, List newSelection) { - if (selectionWidget.isEmpty()) { - return; - } - for (Widget x : selectionWidget) { - if (ComparatorUtils.equals(x, root.toData())) { - if (!newSelection.contains(root)) { - newSelection.add(root); - selectionWidget.remove(x); - } - break; - } - } - - int count = root.getComponentCount(); - for (int i = 0; i < count && !selectionWidget.isEmpty(); i++) { - Component c = root.getComponent(i); - if (c instanceof XCreator) { - XCreator creator = (XCreator) c; - for (Widget x : selectionWidget) { - if (ComparatorUtils.equals(x, creator.toData())) { - newSelection.add(creator); - selectionWidget.remove(x); - break; - } - } - if (c instanceof XLayoutContainer) { - _rebuild((XLayoutContainer) c, selectionWidget, newSelection); - } else { - continue; - } - } - } - } +package com.fr.design.mainframe; + +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.Widget; +import com.fr.form.ui.container.WTitleLayout; +import com.fr.general.ComparatorUtils; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FormSelectionUtils { + + //组件复制时坐标偏移 + private static final int DELAY_X = 20; + private static final int DELAY_Y = 20; + + //组件复制时是否已经向左上偏移 + private static boolean backoffset = false; + + //组件重命名后缀 + private static final String POSTFIX = "_c"; + + private FormSelectionUtils() { + + } + + /** + * @param designer 编辑器 + * @param parent 粘贴依据的组件 + * @param clipboard 剪贴板内容 + * @param x x + * @param y y + */ + public static void paste2Container(FormDesigner designer, XLayoutContainer parent, + FormSelection clipboard, int x, int y) { + LayoutAdapter adapter = parent.getLayoutAdapter(); + if (parent instanceof XWAbsoluteLayout) { + //绝对布局 + absolutePaste(designer, clipboard, adapter, x, y); + return; + } else if (parent instanceof XWFitLayout) { + //相对布局 + relativePaste(designer, clipboard, adapter, x, y); + return; + } + Toolkit.getDefaultToolkit().beep(); + } + + /** + * 绝对布局粘贴 + * + * @param designer + * @param clipboard + * @param adapter + * @param x + * @param y + */ + private static void absolutePaste(FormDesigner designer, FormSelection clipboard, LayoutAdapter adapter, int x, int y) { + + 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()); + // 获取位置 + Point point = getPasteLocation((AbstractLayoutAdapter) adapter, + copiedCreator, + x + creator.getX() - rec.x + copiedCreator.getWidth() / 2, + y + creator.getY() - rec.y + copiedCreator.getHeight() / 2); + boolean addSuccess = adapter.addBean(copiedCreator, point.x, point.y); + if (addSuccess) { + designer.getSelectionModel().getSelection().addSelectedCreator(copiedCreator); + } + } catch (CloneNotSupportedException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + rebuildSelection(designer); + designer.getEditListenerTable().fireCreatorModified( + designer.getSelectionModel().getSelection().getSelectedCreator(), DesignerEvent.CREATOR_PASTED); + + } + + /** + * 相对布局粘贴 + * + * @param designer + * @param clipboard + * @param adapter + * @param x + * @param y + */ + private static void relativePaste(FormDesigner designer, FormSelection clipboard, LayoutAdapter adapter, int x, int y) { + designer.getSelectionModel().getSelection().reset(); + for (XCreator creator : clipboard.getSelectedCreators()) { + try { + Widget copied = copyWidget(designer, creator); + XCreator copiedCreator = XCreatorUtils.createXCreator(copied, creator.getSize()); + boolean addSuccess = adapter.addBean(copiedCreator, x, y); + if (addSuccess) { + designer.getSelectionModel().getSelection().addSelectedCreator(copiedCreator); + } + } catch (CloneNotSupportedException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + rebuildSelection(designer); + designer.getEditListenerTable().fireCreatorModified( + designer.getSelectionModel().getSelection().getSelectedCreator(), DesignerEvent.CREATOR_PASTED); + } + + /** + * 组件复用绝对布局获取粘贴组件位置 + * + * @param layoutAdapter 绝对布局容器AbstractLayoutAdapter + * @param copiedCreator 复制的组件 + * @param x x=组件x + clonedCreator.getWidth() / 2 + * @param y y=组件y + clonedCreator.getHeight() / 2 + * 除2的步骤会导致当宽度或者高度为奇数是,中心点向左上各偏移一个像素 + * 由于中心点向左上各偏移一个像素,依赖中心点计算的右下点就会相应的想做上偏移一个像素,导致结果不准确 + * @return 新位置坐标 + */ + private static Point getPasteLocation(AbstractLayoutAdapter layoutAdapter, XCreator copiedCreator, int x, int y) { + //当宽度为奇数时 设置偏移 + int xoffset = (copiedCreator.getWidth() & 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 + xoffset > container.getWidth(); + boolean yOut = y < 0 || y + copiedCreator.getHeight() / 2 + yoffset > container.getHeight(); + /* + * 组件原始位置位于布局的右下角, + * 和布局右下边界线紧挨, + * 粘贴时组件在原始位置向左错开20像素。 + * x,y同时越界 + */ + if (xOut && yOut) { + 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); + } + /* + * 组件原始位置与布局边界距离小于20像素(下边界&右边界同时小于或者任意一个边界小于), + * 则粘贴时距离小于20像素一侧直接贴近布局边界, + * 距离大于20像素的一侧正常错开。 + * x,y中只有一个越界 + */ + else if ((xOut || yOut)) { + x = xOut ? container.getWidth() - copiedCreator.getWidth() / 2 - xoffset : x; + y = yOut ? container.getHeight() - copiedCreator.getHeight() / 2 - yoffset : y; + return new Point(x, y); + } + } + return new Point(x, y); + } + + + /** + * 拷贝组件 + * + * @param formDesigner + * @param xCreator + * @return + * @throws CloneNotSupportedException + */ + private static Widget copyWidget(FormDesigner formDesigner, XCreator xCreator) throws + CloneNotSupportedException { + ArrayList nameSpace = new ArrayList(); + Widget copied = (Widget) xCreator.toData().clone(); + //重命名拷贝的组件 + String name = getCopiedName(formDesigner, copied, nameSpace); + if (copied instanceof WTitleLayout) { + XWTitleLayout xwTitleLayout = new XWTitleLayout((WTitleLayout) copied, xCreator.getSize()); + xwTitleLayout.resetCreatorName(name); + } else { + copied.setWidgetName(name); + } + return copied; + } + + /** + * 组件拷贝命名规则 + * + * @param formDesigner + * @param copied + * @param nameSpace + * @return name + */ + private static String getCopiedName(FormDesigner formDesigner, Widget copied, ArrayList nameSpace) { + StringBuffer name = new StringBuffer(copied.getWidgetName()); + do { + 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) { + ArrayList newSelection = new ArrayList(); + List widgetList = new ArrayList(); + for (XCreator comp : designer.getSelectionModel().getSelection().getSelectedCreators()) { + widgetList.add(comp.toData()); + } + designer.getSelectionModel().setSelectedCreators( + rebuildSelection(designer.getRootComponent(), widgetList, newSelection)); + } + + public static ArrayList rebuildSelection(XCreator rootComponent, Widget[] selectWidgets) { + List selectionWidget = new ArrayList(); + if (selectWidgets != null) { + selectionWidget.addAll(Arrays.asList(selectWidgets)); + } + return FormSelectionUtils.rebuildSelection(rootComponent, selectionWidget, new ArrayList()); + } + + private static ArrayList rebuildSelection(XCreator rootComponent, List selectionWidget, + ArrayList newSelection) { + FormSelectionUtils.rebuild(rootComponent, selectionWidget, newSelection); + if (newSelection.isEmpty()) { + newSelection.add(rootComponent); + } + return newSelection; + } + + private static void rebuild(XCreator root, List selectionWidget, List newSelection) { + if (selectionWidget.isEmpty()) { + return; + } + for (Widget x : selectionWidget) { + if (ComparatorUtils.equals(x, root.toData())) { + if (!newSelection.contains(root)) { + newSelection.add(root); + selectionWidget.remove(x); + } + break; + } + } + + int count = root.getComponentCount(); + for (int i = 0; i < count && !selectionWidget.isEmpty(); i++) { + Component c = root.getComponent(i); + if (c instanceof XCreator) { + XCreator creator = (XCreator) c; + for (Widget x : selectionWidget) { + if (ComparatorUtils.equals(x, creator.toData())) { + newSelection.add(creator); + selectionWidget.remove(x); + break; + } + } + if (c instanceof XLayoutContainer) { + rebuild((XLayoutContainer) c, selectionWidget, newSelection); + } + } + } + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/JForm.java b/designer_form/src/com/fr/design/mainframe/JForm.java index b20f44bca..ba491e351 100644 --- a/designer_form/src/com/fr/design/mainframe/JForm.java +++ b/designer_form/src/com/fr/design/mainframe/JForm.java @@ -1,800 +1,791 @@ -package com.fr.design.mainframe; - -import com.fr.base.BaseUtils; -import com.fr.design.DesignState; -import com.fr.design.actions.core.WorkBookSupportable; -import com.fr.design.actions.file.WebPreviewUtils; -import com.fr.design.mainframe.actions.FormMobileAttrAction; -import com.fr.design.cell.FloatElementsProvider; -import com.fr.design.constants.UIConstants; -import com.fr.design.designer.beans.actions.FormDeleteAction; -import com.fr.design.designer.beans.events.DesignerEditListener; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.design.designer.creator.*; -import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; -import com.fr.design.event.TargetModifiedEvent; -import com.fr.design.event.TargetModifiedListener; -import com.fr.design.gui.frpane.HyperlinkGroupPane; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.imenu.UIMenuItem; -import com.fr.design.gui.xpane.FormHyperlinkGroupPane; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.actions.EmbeddedFormExportExportAction; -import com.fr.design.mainframe.actions.TemplateParameterAction; -import com.fr.design.mainframe.form.FormECCompositeProvider; -import com.fr.design.mainframe.form.FormECDesignerProvider; -import com.fr.design.mainframe.templateinfo.JFormProcessInfo; -import com.fr.design.mainframe.templateinfo.TemplateProcessInfo; -import com.fr.design.mainframe.toolbar.ToolBarMenuDock; -import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; -import com.fr.design.menu.KeySetUtils; -import com.fr.design.menu.MenuDef; -import com.fr.design.menu.ShortCut; -import com.fr.design.menu.ToolBarDef; -import com.fr.design.parameter.ParameterPropertyPane; -import com.fr.design.roleAuthority.RolesAlreadyEditedPane; -import com.fr.design.utils.gui.LayoutUtils; -import com.fr.file.FILE; -import com.fr.form.FormElementCaseContainerProvider; -import com.fr.form.FormElementCaseProvider; -import com.fr.form.main.Form; -import com.fr.form.ui.Widget; -import com.fr.form.ui.container.WBorderLayout; -import com.fr.form.ui.container.WFitLayout; -import com.fr.form.ui.container.WLayout; -import com.fr.general.ComparatorUtils; -import com.fr.general.FRLogger; -import com.fr.general.Inter; -import com.fr.stable.ArrayUtils; -import com.fr.stable.Constants; -import com.fr.stable.bridge.StableFactory; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.image.BufferedImage; -import java.util.HashMap; - -public class JForm extends JTemplate implements BaseJForm { - private static final String FORM_CARD = "FORM"; - private static final String ELEMENTCASE_CARD = "ELEMENTCASE"; - - private static final String[] CARDNAME = new String[]{FORM_CARD, ELEMENTCASE_CARD}; - private static final int TOOLBARPANEDIMHEIGHT_FORM = 60; - - //表单设计器 - private FormDesigner formDesign; - //格子设计器 - private FormECDesignerProvider elementCaseDesign; - - //中间编辑区域, carllayout布局 - private JPanel tabCenterPane; - private CardLayout cardLayout; - //当前编辑的组件对象 - private JComponent editingComponent; - private FormECCompositeProvider reportComposite; - - //FORM_TAB代表是否点击编辑,用于点击编辑前后菜单的显示 - protected int index = FORM_TAB; - - public JForm() { - super(new Form(new WBorderLayout("form")), "Form"); - } - - public JForm(Form form, FILE file) { - super(form, file); - } - - public int getMenuState() { - - return DesignState.JFORM; - } - - public TemplateProcessInfo getProcessInfo() { - if (processInfo == null) { - processInfo = new JFormProcessInfo(template); - } - return processInfo; - } - - @Override - protected boolean accept(Object o) { - return !(o instanceof FloatElementsProvider); - } - - /** - * 是否是报表 - * - * @return 否 - */ - public boolean isJWorkBook() { - return false; - } - - /** - * 返回当前支持的超链界面pane - * - * @return 超链连接界面 - */ - public HyperlinkGroupPane getHyperLinkPane() { - return new FormHyperlinkGroupPane(); - } - - //表单返回 FORM_TAB or ELEMENTCASE_TAB - public int getEditingReportIndex() { - return this.index; - } - - public void setAuthorityMode(boolean isUpMode) { - return; - } - - public int getToolBarHeight() { - return TOOLBARPANEDIMHEIGHT_FORM; - } - - /** - * 菜单栏上的文件按钮 - * - * @return 菜单数组 - */ - public ShortCut[] shortcut4FileMenu() { - return (ShortCut[]) ArrayUtils.addAll( - super.shortcut4FileMenu(), new ShortCut[]{this.createWorkBookExportMenu()} - ); - } - - private MenuDef createWorkBookExportMenu() { - MenuDef exportMenuDef = new MenuDef(KeySetUtils.EXPORT.getMenuName()); - exportMenuDef.setIconPath("/com/fr/design/images/m_file/export.png"); - exportMenuDef.addShortCut(new EmbeddedFormExportExportAction(this)); - - return exportMenuDef; - } - - /** - * 取消格式 - */ - public void cancelFormat() { - return; - } - - /** - * 重新计算大小 - */ - public void doResize() { - formDesign.getRootComponent().setSize(formDesign.getSize()); - LayoutUtils.layoutRootContainer(formDesign.getRootComponent()); - } - - @Override - protected JPanel createCenterPane() { - tabCenterPane = FRGUIPaneFactory.createCardLayout_S_Pane(); - cardLayout = (CardLayout) tabCenterPane.getLayout(); - - JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - centerPane.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 0, new Color(85, 85, 85))); - formDesign = new FormDesigner(this.getTarget(), new TabChangeAction(BaseJForm.ELEMENTCASE_TAB, this)); - WidgetToolBarPane.getInstance(formDesign); - FormArea area = new FormArea(formDesign); - centerPane.add(area, BorderLayout.CENTER); - tabCenterPane.add(centerPane, FORM_CARD, FORM_TAB); - - this.add(tabCenterPane, BorderLayout.CENTER); - - formDesign.addTargetModifiedListener(new TargetModifiedListener() { - - @Override - public void targetModified(TargetModifiedEvent e) { - JForm.this.fireTargetModified();// 调用保存*, 调用刷新界面, 刷新工具栏按钮 - } - }); - formDesign.addDesignerEditListener(new DesignerEditListener() { - - @Override - public void fireCreatorModified(DesignerEvent evt) { - if (evt.getCreatorEventID() == DesignerEvent.CREATOR_CUTED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED) { - setPropertyPaneChange(formDesign.getRootComponent()); - } else if (evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { - setPropertyPaneChange(evt.getAffectedCreator()); - } - } - }); - return tabCenterPane; - } - - public FormDesigner getFormDesign() { - return formDesign; - } - - public void setFormDesign(FormDesigner formDesign) { - this.formDesign = formDesign; - } - - /** - * 去除选择 - */ - public void removeTemplateSelection() { - return; - } - - public void setSheetCovered(boolean isCovered) { - - } - - /** - * 刷新容器 - */ - public void refreshContainer() { - - } - - /** - * 去除参数面板选择 - */ - public void removeParameterPaneSelection() { - return; - } - - /** - * 创建权限细粒度编辑面板 - * - * @return 权限细粒度编辑面板 - */ - public AuthorityEditPane createAuthorityEditPane() { - FormWidgetAuthorityEditPane formWidgetAuthorityEditPane = new FormWidgetAuthorityEditPane(formDesign); - formWidgetAuthorityEditPane.populateDetials(); - return formWidgetAuthorityEditPane; - } - - - private void setPropertyPaneChange(XComponent comp) { - if (comp == null) { - return; - } - editingComponent = comp.createToolPane(this, formDesign); - if (BaseUtils.isAuthorityEditing()) { - EastRegionContainerPane.getInstance().replaceUpPane( - ComparatorUtils.equals(editingComponent.getClass(), NoSupportAuthorityEdit.class) ? editingComponent : createAuthorityEditPane()); - } else { - EastRegionContainerPane.getInstance().replaceUpPane(editingComponent); - - } - } - - public JComponent getEditingPane() { - return editingComponent; - } - - - public ToolBarMenuDockPlus getToolBarMenuDockPlus() { - return this; - } - - - @Override - /** - *焦点放到JForm - */ - public void requestFocus() { - super.requestFocus(); - formDesign.requestFocus(); - } - - /** - * 焦点放到JForm - */ - public void requestGridFocus() { - super.requestFocus(); - formDesign.requestFocus(); - } - - @Override - /** - * 保存文件的后缀名 - * - * @return 返回后缀名 - */ - public String suffix() { - // daniel改成三个字 - return ".frm"; - } - - /** - * 刷新 - */ - public void refreshRoot() { - // formDesign子类的target重置 - this.formDesign.setTarget(this.getTarget()); - this.formDesign.refreshRoot(); - FormHierarchyTreePane.getInstance().refreshRoot(); - } - - /** - * 刷新s - */ - public void refreshAllNameWidgets() { - if (formDesign.getParaComponent() != null) { - XCreatorUtils.refreshAllNameWidgets(formDesign.getParaComponent()); - } - XCreatorUtils.refreshAllNameWidgets(formDesign.getRootComponent()); - } - - /** - * 刷新 - */ - public void refreshSelectedWidget() { - formDesign.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_SELECTED); - } - - @Override - /** - *复制 f - */ - public void copy() { - this.formDesign.copy(); - } - - @Override - /** - * - * 粘贴 - * @return 是否成功 - */ - public boolean paste() { - return this.formDesign.paste(); - } - - @Override - /** - * - * 剪切 - * @return 是否成功 - */ - public boolean cut() { - return this.formDesign.cut(); - } - - // //////////////////////////////////////////////////////////////////// - // ////////////////for toolbarMenuAdapter////////////////////////////// - // //////////////////////////////////////////////////////////////////// - - - @Override - /** - * 目标菜单 - * - * @return 菜单 - */ - public MenuDef[] menus4Target() { - return this.index == FORM_TAB ? - (MenuDef[]) ArrayUtils.addAll(super.menus4Target(), this.formDesign.menus4Target()) : - (MenuDef[]) ArrayUtils.addAll(super.menus4Target(), this.elementCaseDesign.menus4Target()); - } - - @Override - /** - * 模板的工具 - * - * @return 工具 - */ - public ToolBarDef[] toolbars4Target() { - return this.index == FORM_TAB ? - this.formDesign.toolbars4Target() : - this.elementCaseDesign.toolbars4Target(); - } - - @Override - /** - * 模板菜单 - * - * @return 返回菜单 - */ - public ShortCut[] shortcut4TemplateMenu() { - if (this.index == FORM_TAB) { - return (ShortCut[]) ArrayUtils.addAll(new ShortCut[]{ - new TemplateParameterAction(this), - new FormMobileAttrAction(this) - }, new ShortCut[0]); - } else { - return (ShortCut[]) ArrayUtils.addAll(new ShortCut[]{ - new TemplateParameterAction(this), - new FormMobileAttrAction(this) - }, this.elementCaseDesign.shortcut4TemplateMenu()); - } - } - - /** - * 权限细粒度模板菜单 - * 表单中去掉此菜单项 - * - * @return 菜单 - */ - public ShortCut[] shortCuts4Authority() { - return new ShortCut[0]; - } - - @Override - /** - * undo的表单state - * - * @return 表单State - */ - protected FormUndoState createUndoState() { - FormUndoState cur = new FormUndoState(this, this.formDesign.getArea()); - if (this.formDesign.isReportBlockEditing()) { - cur.setFormReportType(BaseUndoState.STATE_FORM_REPORT); - } - return cur; - } - - /** - * 应用UndoState - * - * @param o undo的状态 - */ - public void applyUndoState4Form(BaseUndoState o) { - this.applyUndoState((FormUndoState) o); - } - - /** - * 可以撤销 - * - * @return 是则返回true - */ - public boolean canUndo() { - //报表块最多撤销至编辑报表块的第一步,不能撤销表单中的操作 - boolean inECUndoForm = undoState.getFormReportType() == BaseUndoState.STATE_BEFORE_FORM_REPORT && formDesign.isReportBlockEditing(); - return !inECUndoForm && this.getUndoManager().canUndo(); - } - - // 返回当前的body, - // 假如当前body是自适应的话就沿用, - // 假如当前body是绝对布局的话就返回绝对布局body - private XLayoutContainer selectedBodyLayout() { - XLayoutContainer rootLayout = formDesign.getRootComponent(); - for (int i = 0; i < rootLayout.getComponentCount(); i++){ - if (rootLayout.getXCreator(i).acceptType(XWAbsoluteBodyLayout.class)){ - rootLayout = (XWAbsoluteBodyLayout)rootLayout.getXCreator(i); - } - } - return rootLayout; - } - @Override - /** - * 应用undoState的表单数据 - */ - protected void applyUndoState(FormUndoState u) { - try { - //JForm的target重置 - this.setTarget((Form) u.getForm().clone()); - if (this.index == FORM_TAB) { - JForm.this.refreshRoot(); - this.formDesign.getArea().setAreaSize(u.getAreaSize(), u.getHorizontalValue(), u.getVerticalValue(), u.getWidthValue(), u.getHeightValue(), u.getSlideValue()); - //撤销的时候要重新选择的body布局 - this.formDesign.getSelectionModel().setSelectedCreators(FormSelectionUtils.rebuildSelection(formDesign.getRootComponent(), - formDesign.getRootComponent() == selectedBodyLayout() ? u.getSelectWidgets() : new Widget[]{selectedBodyLayout().toData()})); - } else { - String widgetName = this.formDesign.getElementCaseContainerName(); - //这儿太坑了,u.getForm() 与 getTarget内容不一样 - FormElementCaseProvider dataTable = getTarget().getElementCaseByName(widgetName); - this.reportComposite.setSelectedWidget(dataTable); - //下面这句话是防止撤销之后直接退出编辑再编辑撤销的东西会回来,因为撤销不会保存EC - formDesign.setElementCase(dataTable); - } - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - - if (BaseUtils.isAuthorityEditing()) { - this.authorityUndoState = u; - } else { - this.undoState = u; - } - - } - - @Override - /** - * - */ - protected FormModelAdapter createDesignModel() { - return new FormModelAdapter(this); - } - - @Override - /** - * 表单的工具栏 - * - * @return 表单工具栏 - */ - public JPanel[] toolbarPanes4Form() { - return this.index == FORM_TAB ? - new JPanel[]{FormParaWidgetPane.getInstance(formDesign)} : - new JPanel[0]; - } - - /** - * 表单的工具按钮 - * - * @return 工具按钮 - */ - public JComponent[] toolBarButton4Form() { - return this.index == FORM_TAB ? - new JComponent[]{ - //自适应布局里的复制粘贴意义不大, 先屏蔽掉 -// new CutAction(formDesign).createToolBarComponent(), -// new CopyAction(formDesign).createToolBarComponent(), -// new PasteAction(formDesign).createToolBarComponent(), - new FormDeleteAction(formDesign).createToolBarComponent()} : - elementCaseDesign.toolBarButton4Form(); - } - - /** - * 权限细粒度状态下的工具面板 - * - * @return 工具面板 - */ - public JComponent toolBar4Authority() { - JPanel panel = new JPanel(new BorderLayout()) { - public Dimension getPreferredSize() { - Dimension dim = super.getPreferredSize(); - dim.height = ToolBarMenuDock.PANLE_HEIGNT; - return dim; - } - }; - UILabel uiLabel = new UILabel(Inter.getLocText(new String[]{"DashBoard-FormBook", "Privilege", "Edit"})); - uiLabel.setHorizontalAlignment(SwingConstants.CENTER); - uiLabel.setFont(new Font(Inter.getLocText("FR-Designer-All_MSBold"), 0, 14)); - uiLabel.setForeground(new Color(150, 150, 150)); - panel.add(uiLabel, BorderLayout.CENTER); - return panel; - } - - - public JPanel getEastUpPane() { - if (BaseUtils.isAuthorityEditing()) { - if (formDesign.isSupportAuthority()) { - return new AuthorityPropertyPane(this); - } else { - return new NoSupportAuthorityEdit(); - } - } else { - if (editingComponent == null) { - editingComponent = formDesign.getRootComponent().createToolPane(this, formDesign); - } - return (JPanel) editingComponent; - } - } - - public JPanel getEastDownPane() { - return formDesign.getEastDownPane(); - } - - @Override - /** - * - */ - public Icon getPreviewLargeIcon() { - return UIConstants.RUN_BIG_ICON; - } - - @Override - /** - * 创建菜单项Preview - * - * @return 菜单 - */ - public UIMenuItem[] createMenuItem4Preview() { - UIMenuItem form = new UIMenuItem(Inter.getLocText("M-Form_Preview"), UIConstants.RUN_SMALL_ICON); - form.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - WebPreviewUtils.onFormPreview(JForm.this); - } - }); - return new UIMenuItem[]{form}; - } - - /** - * 刷新参数 - */ - public void populateParameter() { - formDesign.populateParameterPropertyPane(); - } - - @Override - /** - * 刷新工具区域 - */ - public void refreshToolArea() { - populateParameter(); - DesignerContext.getDesignerFrame().resetToolkitByPlus(JForm.this); - //表单切换后拖不进去组件是因为找不到designer - WidgetToolBarPane.getInstance(formDesign); - if (BaseUtils.isAuthorityEditing()) { - if (formDesign.isSupportAuthority()) { - EastRegionContainerPane.getInstance().replaceUpPane(new AuthorityPropertyPane(this)); - } else { - EastRegionContainerPane.getInstance().replaceUpPane(new NoSupportAuthorityEdit()); - } - EastRegionContainerPane.getInstance().replaceDownPane(RolesAlreadyEditedPane.getInstance()); - return; - } - - if (formDesign.isReportBlockEditing()) { - if (elementCaseDesign != null) { - EastRegionContainerPane.getInstance().removeParameterPane(); - EastRegionContainerPane.getInstance().replaceDownPane(elementCaseDesign.getEastDownPane()); - EastRegionContainerPane.getInstance().replaceUpPane(elementCaseDesign.getEastUpPane()); - return; - } - } - - EastRegionContainerPane.getInstance().replaceUpPane(WidgetPropertyPane.getInstance(formDesign)); - EastRegionContainerPane.getInstance().addParameterPane(ParameterPropertyPane.getInstance(formDesign)); - EastRegionContainerPane.getInstance().setParameterHeight(ParameterPropertyPane.getInstance(formDesign).getPreferredSize().height); - if (EastRegionContainerPane.getInstance().getDownPane() == null) { - new Thread() { - public void run() { - try { - Thread.sleep(1500); - } catch (InterruptedException e) { - FRLogger.getLogger().error(e.getMessage(), e); - } - JPanel pane = new JPanel(); - pane.setLayout(new BorderLayout()); - pane.add(FormWidgetDetailPane.getInstance(formDesign), BorderLayout.CENTER); - EastRegionContainerPane.getInstance().replaceDownPane(pane); - } - }.start(); - } else { - JPanel pane = new JPanel(); - pane.setLayout(new BorderLayout()); - pane.add(FormWidgetDetailPane.getInstance(formDesign), BorderLayout.CENTER); - EastRegionContainerPane.getInstance().replaceDownPane(pane); - - } - } - - public String getEditingCreatorName() { - return formDesign.getSelectionModel().getSelection().getSelectedCreator().toData().getWidgetName(); - } - - public WLayout getRootLayout() { - return formDesign.getRootComponent().toData(); - } - - /** - * 选择的是否是表单主体 - * - * @return 是则返回true - */ - public boolean isSelectRootPane() { - return (formDesign.getRootComponent() == formDesign.getSelectionModel().getSelection().getSelectedCreator()) - || (formDesign.getSelectionModel().getSelection().getSelectedCreator().acceptType(XWAbsoluteBodyLayout.class)); - - } - - /** - * 只在Form和ElementCase之间切换 - * - * @param index 切换位置 - */ - public void tabChanged(int index) { - if (index == ELEMENTCASE_TAB) { - formDesign.setReportBlockEditing(true); - ecTabAction(); - } else { - formDesign.setReportBlockEditing(false); - formTabAction(); - } - this.index = index; - refreshToolArea(); - this.cardLayout.show(tabCenterPane, CARDNAME[index]); - if (elementCaseDesign != null && index == ELEMENTCASE_TAB) { - //报表块编辑失焦,进入报表块可直接编辑A1 - elementCaseDesign.requestFocus(); - //进入编辑报表块,触发一次保存,记住编辑报表块前的表单状态 - //防止报表块中撤销到表单 - JForm.this.fireTargetModified(); - } - } - - /** - * 在Form和ElementCase, 以及ElementCase和ElementCase之间切换 - * - * @param index 切换位置 - * @param ecContainer ElementCase所在container - */ - public void tabChanged(int index, FormElementCaseContainerProvider ecContainer) { - if (index == ELEMENTCASE_CHANGE_TAB) { - saveImage(); - //更新FormDesign中的控件容器 - formDesign.setElementCaseContainer(ecContainer); - //如果只是内部ElementCase之间的切换, 那么不需要下面的界面变动 - return; - } - - tabChanged(index); - } - - /** - * 格子编辑组件 - */ - private FormECDesignerProvider initElementCaseDesign() { - HashMap designerClass = new HashMap(); - designerClass.put(Constants.ARG_0, FormElementCaseProvider.class); - - Object[] designerArg = new Object[]{formDesign.getElementCase()}; - return StableFactory.getMarkedInstanceObjectFromClass(FormECDesignerProvider.XML_TAG, designerArg, designerClass, FormECDesignerProvider.class); - } - - /** - * 整个报表块编辑区域 - */ - private FormECCompositeProvider initComposite() { - Object[] compositeArg = new Object[]{this, elementCaseDesign, formDesign.getElementCaseContainer()}; - HashMap compoClass = new HashMap(); - compoClass.put(Constants.ARG_0, BaseJForm.class); - compoClass.put(Constants.ARG_2, FormElementCaseContainerProvider.class); - return StableFactory.getMarkedInstanceObjectFromClass(FormECCompositeProvider.XML_TAG, compositeArg, compoClass, FormECCompositeProvider.class); - } - - /** - * 切换格子编辑 - */ - private void ecTabAction() { - elementCaseDesign = initElementCaseDesign(); - reportComposite = initComposite(); - - tabCenterPane.add((Component) reportComposite, ELEMENTCASE_CARD, 1); - reportComposite.addTargetModifiedListener(new TargetModifiedListener() { - - @Override - public void targetModified(TargetModifiedEvent e) { - JForm.this.fireTargetModified(); - FormElementCaseProvider te = elementCaseDesign.getEditingElementCase(); - formDesign.setElementCase(te); - } - }); - } - - private void saveImage() { - //触发一次保存, 把缩略图保存起来 - JForm.this.fireTargetModified(); - //用formDesign的size是为了当报表块被拉伸时, 它对应的背景图片需要足够大才不会显示成空白 - BufferedImage image = elementCaseDesign.getElementCaseImage(formDesign.getSize()); - formDesign.setElementCaseBackground(image); - } - - /** - * 切换form编辑 - */ - private void formTabAction() { - saveImage(); - } - - /** - * 取小图标,主要用于多TAB标签栏 - * - * @return 图表 - */ - public Icon getIcon() { - return BaseUtils.readIcon("/com/fr/web/images/form/new_form3.png"); - } - - @Override - public boolean acceptToolbarItem(Class clazz) { - return WorkBookSupportable.class.isAssignableFrom(clazz); - } - - @Override - public Widget getSelectElementCase() { - FormSelection selection = formDesign.getSelectionModel().getSelection(); - XCreator creator = selection.getSelectedCreator(); - return creator.toData(); - } +package com.fr.design.mainframe; + +import com.fr.base.BaseUtils; +import com.fr.design.DesignState; +import com.fr.design.actions.core.WorkBookSupportable; +import com.fr.design.actions.file.WebPreviewUtils; +import com.fr.design.cell.FloatElementsProvider; +import com.fr.design.constants.UIConstants; +import com.fr.design.designer.beans.actions.CopyAction; +import com.fr.design.designer.beans.actions.CutAction; +import com.fr.design.designer.beans.actions.FormDeleteAction; +import com.fr.design.designer.beans.actions.PasteAction; +import com.fr.design.designer.beans.events.DesignerEditListener; +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.creator.*; +import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; +import com.fr.design.event.TargetModifiedEvent; +import com.fr.design.event.TargetModifiedListener; +import com.fr.design.gui.frpane.HyperlinkGroupPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.imenu.UIMenuItem; +import com.fr.design.gui.xpane.FormHyperlinkGroupPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.actions.EmbeddedFormExportExportAction; +import com.fr.design.mainframe.actions.FormMobileAttrAction; +import com.fr.design.mainframe.actions.TemplateParameterAction; +import com.fr.design.mainframe.form.FormECCompositeProvider; +import com.fr.design.mainframe.form.FormECDesignerProvider; +import com.fr.design.mainframe.templateinfo.JFormProcessInfo; +import com.fr.design.mainframe.templateinfo.TemplateProcessInfo; +import com.fr.design.mainframe.toolbar.ToolBarMenuDock; +import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; +import com.fr.design.menu.KeySetUtils; +import com.fr.design.menu.MenuDef; +import com.fr.design.menu.ShortCut; +import com.fr.design.menu.ToolBarDef; +import com.fr.design.parameter.ParameterPropertyPane; +import com.fr.design.roleAuthority.RolesAlreadyEditedPane; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.file.FILE; +import com.fr.form.FormElementCaseContainerProvider; +import com.fr.form.FormElementCaseProvider; +import com.fr.form.main.Form; +import com.fr.form.ui.Widget; +import com.fr.form.ui.container.WBorderLayout; +import com.fr.form.ui.container.WLayout; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; +import com.fr.stable.Constants; +import com.fr.stable.bridge.StableFactory; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +public class JForm extends JTemplate implements BaseJForm { + private static final String FORM_CARD = "FORM"; + private static final String ELEMENTCASE_CARD = "ELEMENTCASE"; + + private static final String[] CARDNAME = new String[]{FORM_CARD, ELEMENTCASE_CARD}; + private static final int TOOLBARPANEDIMHEIGHT_FORM = 60; + + //表单设计器 + private FormDesigner formDesign; + //格子设计器 + private FormECDesignerProvider elementCaseDesign; + + //中间编辑区域, carllayout布局 + private JPanel tabCenterPane; + private CardLayout cardLayout; + //当前编辑的组件对象 + private JComponent editingComponent; + private FormECCompositeProvider reportComposite; + + //FORM_TAB代表是否点击编辑,用于点击编辑前后菜单的显示 + protected int index = FORM_TAB; + + public JForm() { + super(new Form(new WBorderLayout("form")), "Form"); + } + + public JForm(Form form, FILE file) { + super(form, file); + } + + public int getMenuState() { + + return DesignState.JFORM; + } + + public TemplateProcessInfo getProcessInfo() { + if (processInfo == null) { + processInfo = new JFormProcessInfo(template); + } + return processInfo; + } + + @Override + protected boolean accept(Object o) { + return !(o instanceof FloatElementsProvider); + } + + /** + * 是否是报表 + * + * @return 否 + */ + public boolean isJWorkBook() { + return false; + } + + /** + * 返回当前支持的超链界面pane + * + * @return 超链连接界面 + */ + public HyperlinkGroupPane getHyperLinkPane() { + return new FormHyperlinkGroupPane(); + } + + //表单返回 FORM_TAB or ELEMENTCASE_TAB + public int getEditingReportIndex() { + return this.index; + } + + public void setAuthorityMode(boolean isUpMode) { + return; + } + + public int getToolBarHeight() { + return TOOLBARPANEDIMHEIGHT_FORM; + } + + /** + * 菜单栏上的文件按钮 + * + * @return 菜单数组 + */ + public ShortCut[] shortcut4FileMenu() { + return (ShortCut[]) ArrayUtils.addAll( + super.shortcut4FileMenu(), new ShortCut[]{this.createWorkBookExportMenu()} + ); + } + + private MenuDef createWorkBookExportMenu() { + MenuDef exportMenuDef = new MenuDef(KeySetUtils.EXPORT.getMenuName()); + exportMenuDef.setIconPath("/com/fr/design/images/m_file/export.png"); + exportMenuDef.addShortCut(new EmbeddedFormExportExportAction(this)); + + return exportMenuDef; + } + + /** + * 取消格式 + */ + public void cancelFormat() { + return; + } + + /** + * 重新计算大小 + */ + public void doResize() { + formDesign.getRootComponent().setSize(formDesign.getSize()); + LayoutUtils.layoutRootContainer(formDesign.getRootComponent()); + } + + @Override + protected JPanel createCenterPane() { + tabCenterPane = FRGUIPaneFactory.createCardLayout_S_Pane(); + cardLayout = (CardLayout) tabCenterPane.getLayout(); + + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + centerPane.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 0, new Color(85, 85, 85))); + formDesign = new FormDesigner(this.getTarget(), new TabChangeAction(BaseJForm.ELEMENTCASE_TAB, this)); + WidgetToolBarPane.getInstance(formDesign); + FormArea area = new FormArea(formDesign); + centerPane.add(area, BorderLayout.CENTER); + tabCenterPane.add(centerPane, FORM_CARD, FORM_TAB); + + this.add(tabCenterPane, BorderLayout.CENTER); + + formDesign.addTargetModifiedListener(new TargetModifiedListener() { + + @Override + public void targetModified(TargetModifiedEvent e) { + JForm.this.fireTargetModified();// 调用保存*, 调用刷新界面, 刷新工具栏按钮 + } + }); + formDesign.addDesignerEditListener(new DesignerEditListener() { + + @Override + public void fireCreatorModified(DesignerEvent evt) { + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_CUTED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED) { + setPropertyPaneChange(formDesign.getRootComponent()); + } else if (evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { + setPropertyPaneChange(evt.getAffectedCreator()); + } + } + }); + return tabCenterPane; + } + + public FormDesigner getFormDesign() { + return formDesign; + } + + public void setFormDesign(FormDesigner formDesign) { + this.formDesign = formDesign; + } + + /** + * 去除选择 + */ + public void removeTemplateSelection() { + return; + } + + public void setSheetCovered(boolean isCovered) { + + } + + /** + * 刷新容器 + */ + public void refreshContainer() { + + } + + /** + * 去除参数面板选择 + */ + public void removeParameterPaneSelection() { + return; + } + + /** + * 创建权限细粒度编辑面板 + * + * @return 权限细粒度编辑面板 + */ + public AuthorityEditPane createAuthorityEditPane() { + FormWidgetAuthorityEditPane formWidgetAuthorityEditPane = new FormWidgetAuthorityEditPane(formDesign); + formWidgetAuthorityEditPane.populateDetials(); + return formWidgetAuthorityEditPane; + } + + + private void setPropertyPaneChange(XComponent comp) { + if (comp == null) { + return; + } + editingComponent = comp.createToolPane(this, formDesign); + if (BaseUtils.isAuthorityEditing()) { + EastRegionContainerPane.getInstance().replaceUpPane( + ComparatorUtils.equals(editingComponent.getClass(), NoSupportAuthorityEdit.class) ? editingComponent : createAuthorityEditPane()); + } else { + EastRegionContainerPane.getInstance().replaceUpPane(editingComponent); + + } + } + + public JComponent getEditingPane() { + return editingComponent; + } + + + public ToolBarMenuDockPlus getToolBarMenuDockPlus() { + return this; + } + + + /** + * 焦点放到JForm + */ + @Override + public void requestFocus() { + super.requestFocus(); + formDesign.requestFocus(); + } + + /** + * 焦点放到JForm + */ + public void requestGridFocus() { + super.requestFocus(); + formDesign.requestFocus(); + } + + /** + * 保存文件的后缀名 + * + * @return 返回后缀名 + */ + @Override + public String suffix() { + // daniel改成三个字 + return ".frm"; + } + + /** + * 刷新 + */ + public void refreshRoot() { + // formDesign子类的target重置 + this.formDesign.setTarget(this.getTarget()); + this.formDesign.refreshRoot(); + FormHierarchyTreePane.getInstance().refreshRoot(); + } + + /** + * 刷新s + */ + public void refreshAllNameWidgets() { + if (formDesign.getParaComponent() != null) { + XCreatorUtils.refreshAllNameWidgets(formDesign.getParaComponent()); + } + XCreatorUtils.refreshAllNameWidgets(formDesign.getRootComponent()); + } + + /** + * 刷新 + */ + public void refreshSelectedWidget() { + formDesign.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_SELECTED); + } + + + /** + * 复制 + */ + @Override + public void copy() { + this.formDesign.copy(); + } + + + /** + * 粘贴 + * + * @return 是否成功 + */ + @Override + public boolean paste() { + return this.formDesign.paste(); + } + + + /** + * 剪切 + * + * @return 是否成功 + */ + @Override + public boolean cut() { + return this.formDesign.cut(); + } + + // //////////////////////////////////////////////////////////////////// + // ////////////////for toolbarMenuAdapter////////////////////////////// + // //////////////////////////////////////////////////////////////////// + + + /** + * 目标菜单 + * + * @return 菜单 + */ + @Override + public MenuDef[] menus4Target() { + return this.index == FORM_TAB ? + (MenuDef[]) ArrayUtils.addAll(super.menus4Target(), this.formDesign.menus4Target()) : + (MenuDef[]) ArrayUtils.addAll(super.menus4Target(), this.elementCaseDesign.menus4Target()); + } + + + /** + * 模板的工具 + * + * @return 工具 + */ + @Override + public ToolBarDef[] toolbars4Target() { + return this.index == FORM_TAB ? + this.formDesign.toolbars4Target() : + this.elementCaseDesign.toolbars4Target(); + } + + + /** + * 模板菜单 + * + * @return 返回菜单 + */ + @Override + public ShortCut[] shortcut4TemplateMenu() { + if (this.index == FORM_TAB) { + return (ShortCut[]) ArrayUtils.addAll(new ShortCut[]{ + new TemplateParameterAction(this), + new FormMobileAttrAction(this) + }, new ShortCut[0]); + } else { + return (ShortCut[]) ArrayUtils.addAll(new ShortCut[]{ + new TemplateParameterAction(this), + new FormMobileAttrAction(this) + }, this.elementCaseDesign.shortcut4TemplateMenu()); + } + } + + /** + * 权限细粒度模板菜单 + * 表单中去掉此菜单项 + * + * @return 菜单 + */ + public ShortCut[] shortCuts4Authority() { + return new ShortCut[0]; + } + + @Override + protected FormUndoState createUndoState() { + FormUndoState cur = new FormUndoState(this, this.formDesign.getArea()); + if (this.formDesign.isReportBlockEditing()) { + cur.setFormReportType(BaseUndoState.STATE_FORM_REPORT); + } + return cur; + } + + /** + * 应用UndoState + * + * @param o undo的状态 + */ + public void applyUndoState4Form(BaseUndoState o) { + this.applyUndoState((FormUndoState) o); + } + + /** + * 可以撤销 + * + * @return 是则返回true + */ + public boolean canUndo() { + //报表块最多撤销至编辑报表块的第一步,不能撤销表单中的操作 + boolean inECUndoForm = undoState.getFormReportType() == BaseUndoState.STATE_BEFORE_FORM_REPORT && formDesign.isReportBlockEditing(); + return !inECUndoForm && this.getUndoManager().canUndo(); + } + + // 返回当前的body, + // 假如当前body是自适应的话就沿用, + // 假如当前body是绝对布局的话就返回绝对布局body + private XLayoutContainer selectedBodyLayout() { + XLayoutContainer rootLayout = formDesign.getRootComponent(); + for (int i = 0; i < rootLayout.getComponentCount(); i++) { + if (rootLayout.getXCreator(i).acceptType(XWAbsoluteBodyLayout.class)) { + rootLayout = (XWAbsoluteBodyLayout) rootLayout.getXCreator(i); + } + } + return rootLayout; + } + + @Override + protected void applyUndoState(FormUndoState u) { + try { + //JForm的target重置 + this.setTarget((Form) u.getForm().clone()); + if (this.index == FORM_TAB) { + JForm.this.refreshRoot(); + this.formDesign.getArea().setAreaSize(u.getAreaSize(), u.getHorizontalValue(), u.getVerticalValue(), u.getWidthValue(), u.getHeightValue(), u.getSlideValue()); + //撤销的时候要重新选择的body布局 + this.formDesign.getSelectionModel().setSelectedCreators(FormSelectionUtils.rebuildSelection(formDesign.getRootComponent(), + formDesign.getRootComponent() == selectedBodyLayout() ? u.getSelectWidgets() : new Widget[]{selectedBodyLayout().toData()})); + } else { + String widgetName = this.formDesign.getElementCaseContainerName(); + //这儿太坑了,u.getForm() 与 getTarget内容不一样 + FormElementCaseProvider dataTable = getTarget().getElementCaseByName(widgetName); + this.reportComposite.setSelectedWidget(dataTable); + //下面这句话是防止撤销之后直接退出编辑再编辑撤销的东西会回来,因为撤销不会保存EC + formDesign.setElementCase(dataTable); + } + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + + if (BaseUtils.isAuthorityEditing()) { + this.authorityUndoState = u; + } else { + this.undoState = u; + } + + } + + @Override + protected FormModelAdapter createDesignModel() { + return new FormModelAdapter(this); + } + + @Override + public JPanel[] toolbarPanes4Form() { + return this.index == FORM_TAB ? + new JPanel[]{FormParaWidgetPane.getInstance(formDesign)} : + new JPanel[0]; + } + + /** + * 表单的工具按钮 + * + * @return 工具按钮 + */ + public JComponent[] toolBarButton4Form() { + return this.index == FORM_TAB ? + new JComponent[]{ + new CutAction(formDesign).createToolBarComponent(), + new CopyAction(formDesign).createToolBarComponent(), + new PasteAction(formDesign).createToolBarComponent(), + new FormDeleteAction(formDesign).createToolBarComponent()} : + elementCaseDesign.toolBarButton4Form(); + } + + /** + * 权限细粒度状态下的工具面板 + * + * @return 工具面板 + */ + public JComponent toolBar4Authority() { + JPanel panel = new JPanel(new BorderLayout()) { + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.height = ToolBarMenuDock.PANLE_HEIGNT; + return dim; + } + }; + UILabel uiLabel = new UILabel(Inter.getLocText(new String[]{"DashBoard-FormBook", "Privilege", "Edit"})); + uiLabel.setHorizontalAlignment(SwingConstants.CENTER); + uiLabel.setFont(new Font(Inter.getLocText("FR-Designer-All_MSBold"), 0, 14)); + uiLabel.setForeground(new Color(150, 150, 150)); + panel.add(uiLabel, BorderLayout.CENTER); + return panel; + } + + + public JPanel getEastUpPane() { + if (BaseUtils.isAuthorityEditing()) { + if (formDesign.isSupportAuthority()) { + return new AuthorityPropertyPane(this); + } else { + return new NoSupportAuthorityEdit(); + } + } else { + if (editingComponent == null) { + editingComponent = formDesign.getRootComponent().createToolPane(this, formDesign); + } + return (JPanel) editingComponent; + } + } + + public JPanel getEastDownPane() { + return formDesign.getEastDownPane(); + } + + @Override + /** + * + */ + public Icon getPreviewLargeIcon() { + return UIConstants.RUN_BIG_ICON; + } + + @Override + /** + * 创建菜单项Preview + * + * @return 菜单 + */ + public UIMenuItem[] createMenuItem4Preview() { + UIMenuItem form = new UIMenuItem(Inter.getLocText("M-Form_Preview"), UIConstants.RUN_SMALL_ICON); + form.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + WebPreviewUtils.onFormPreview(JForm.this); + } + }); + return new UIMenuItem[]{form}; + } + + /** + * 刷新参数 + */ + public void populateParameter() { + formDesign.populateParameterPropertyPane(); + } + + @Override + /** + * 刷新工具区域 + */ + public void refreshToolArea() { + populateParameter(); + DesignerContext.getDesignerFrame().resetToolkitByPlus(JForm.this); + //表单切换后拖不进去组件是因为找不到designer + WidgetToolBarPane.getInstance(formDesign); + if (BaseUtils.isAuthorityEditing()) { + if (formDesign.isSupportAuthority()) { + EastRegionContainerPane.getInstance().replaceUpPane(new AuthorityPropertyPane(this)); + } else { + EastRegionContainerPane.getInstance().replaceUpPane(new NoSupportAuthorityEdit()); + } + EastRegionContainerPane.getInstance().replaceDownPane(RolesAlreadyEditedPane.getInstance()); + return; + } + + if (formDesign.isReportBlockEditing()) { + if (elementCaseDesign != null) { + EastRegionContainerPane.getInstance().removeParameterPane(); + EastRegionContainerPane.getInstance().replaceDownPane(elementCaseDesign.getEastDownPane()); + EastRegionContainerPane.getInstance().replaceUpPane(elementCaseDesign.getEastUpPane()); + return; + } + } + + EastRegionContainerPane.getInstance().replaceUpPane(WidgetPropertyPane.getInstance(formDesign)); + EastRegionContainerPane.getInstance().addParameterPane(ParameterPropertyPane.getInstance(formDesign)); + EastRegionContainerPane.getInstance().setParameterHeight(ParameterPropertyPane.getInstance(formDesign).getPreferredSize().height); + if (EastRegionContainerPane.getInstance().getDownPane() == null) { + new Thread() { + public void run() { + try { + Thread.sleep(1500); + } catch (InterruptedException e) { + FRLogger.getLogger().error(e.getMessage(), e); + } + JPanel pane = new JPanel(); + pane.setLayout(new BorderLayout()); + pane.add(FormWidgetDetailPane.getInstance(formDesign), BorderLayout.CENTER); + EastRegionContainerPane.getInstance().replaceDownPane(pane); + } + }.start(); + } else { + JPanel pane = new JPanel(); + pane.setLayout(new BorderLayout()); + pane.add(FormWidgetDetailPane.getInstance(formDesign), BorderLayout.CENTER); + EastRegionContainerPane.getInstance().replaceDownPane(pane); + + } + } + + public String getEditingCreatorName() { + return formDesign.getSelectionModel().getSelection().getSelectedCreator().toData().getWidgetName(); + } + + public WLayout getRootLayout() { + return formDesign.getRootComponent().toData(); + } + + /** + * 选择的是否是表单主体 + * + * @return 是则返回true + */ + public boolean isSelectRootPane() { + return (formDesign.getRootComponent() == formDesign.getSelectionModel().getSelection().getSelectedCreator()) + || (formDesign.getSelectionModel().getSelection().getSelectedCreator().acceptType(XWAbsoluteBodyLayout.class)); + + } + + /** + * 只在Form和ElementCase之间切换 + * + * @param index 切换位置 + */ + public void tabChanged(int index) { + if (index == ELEMENTCASE_TAB) { + formDesign.setReportBlockEditing(true); + ecTabAction(); + } else { + formDesign.setReportBlockEditing(false); + formTabAction(); + } + this.index = index; + refreshToolArea(); + this.cardLayout.show(tabCenterPane, CARDNAME[index]); + if (elementCaseDesign != null && index == ELEMENTCASE_TAB) { + //报表块编辑失焦,进入报表块可直接编辑A1 + elementCaseDesign.requestFocus(); + //进入编辑报表块,触发一次保存,记住编辑报表块前的表单状态 + //防止报表块中撤销到表单 + JForm.this.fireTargetModified(); + } + } + + /** + * 在Form和ElementCase, 以及ElementCase和ElementCase之间切换 + * + * @param index 切换位置 + * @param ecContainer ElementCase所在container + */ + public void tabChanged(int index, FormElementCaseContainerProvider ecContainer) { + if (index == ELEMENTCASE_CHANGE_TAB) { + saveImage(); + //更新FormDesign中的控件容器 + formDesign.setElementCaseContainer(ecContainer); + //如果只是内部ElementCase之间的切换, 那么不需要下面的界面变动 + return; + } + + tabChanged(index); + } + + /** + * 格子编辑组件 + */ + private FormECDesignerProvider initElementCaseDesign() { + HashMap designerClass = new HashMap(); + designerClass.put(Constants.ARG_0, FormElementCaseProvider.class); + + Object[] designerArg = new Object[]{formDesign.getElementCase()}; + return StableFactory.getMarkedInstanceObjectFromClass(FormECDesignerProvider.XML_TAG, designerArg, designerClass, FormECDesignerProvider.class); + } + + /** + * 整个报表块编辑区域 + */ + private FormECCompositeProvider initComposite() { + Object[] compositeArg = new Object[]{this, elementCaseDesign, formDesign.getElementCaseContainer()}; + HashMap compoClass = new HashMap(); + compoClass.put(Constants.ARG_0, BaseJForm.class); + compoClass.put(Constants.ARG_2, FormElementCaseContainerProvider.class); + return StableFactory.getMarkedInstanceObjectFromClass(FormECCompositeProvider.XML_TAG, compositeArg, compoClass, FormECCompositeProvider.class); + } + + /** + * 切换格子编辑 + */ + private void ecTabAction() { + elementCaseDesign = initElementCaseDesign(); + reportComposite = initComposite(); + + tabCenterPane.add((Component) reportComposite, ELEMENTCASE_CARD, 1); + reportComposite.addTargetModifiedListener(new TargetModifiedListener() { + + @Override + public void targetModified(TargetModifiedEvent e) { + JForm.this.fireTargetModified(); + FormElementCaseProvider te = elementCaseDesign.getEditingElementCase(); + formDesign.setElementCase(te); + } + }); + } + + private void saveImage() { + //触发一次保存, 把缩略图保存起来 + JForm.this.fireTargetModified(); + //用formDesign的size是为了当报表块被拉伸时, 它对应的背景图片需要足够大才不会显示成空白 + BufferedImage image = elementCaseDesign.getElementCaseImage(formDesign.getSize()); + formDesign.setElementCaseBackground(image); + } + + /** + * 切换form编辑 + */ + private void formTabAction() { + saveImage(); + } + + /** + * 取小图标,主要用于多TAB标签栏 + * + * @return 图表 + */ + public Icon getIcon() { + return BaseUtils.readIcon("/com/fr/web/images/form/new_form3.png"); + } + + @Override + public boolean acceptToolbarItem(Class clazz) { + return WorkBookSupportable.class.isAssignableFrom(clazz); + } + + @Override + public Widget getSelectElementCase() { + FormSelection selection = formDesign.getSelectionModel().getSelection(); + XCreator creator = selection.getSelectedCreator(); + return creator.toData(); + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java b/designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java index f79eca1a9..c9a858797 100644 --- a/designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java +++ b/designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java @@ -1,346 +1,348 @@ -package com.fr.design.mainframe; - -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.ListSelectionModel; -import javax.swing.table.*; - -import com.fr.design.designer.creator.XCreator; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.itable.GroupRenderer; -import com.fr.form.ui.Widget; -import com.fr.form.ui.container.*; -import com.fr.general.ComparatorUtils; -import com.fr.general.Inter; -import com.fr.stable.StringUtils; - -/** - * MobileWidgetTable类主要显示各种容器的控件列表(body,tab,绝对布局快,不包括参数面板) - * Created with IntelliJ IDEA. - * User: zx - * Date: 14-9-15 - * Time: 下午4:52 - * Modified by fanglei at 2017/01/23 - */ -public class MobileWidgetTable extends JTable { - - private FormDesigner designer; - private String[][] cellData; - private String[] headers = {Inter.getLocText("Form-Widget_Name")}; - private static final int WIDGET_TABLE_ROW_HEIGHT = 22; - private UILabel moveComponent = new UILabel(); // 作为拖动时候随鼠标移动的那个半透明控件 - private int selectedRow = -1; - private int GAP = 11; - private boolean draging = false; - private boolean collapsed = false; // 控件列表是否折叠 - - @Override - public TableCellRenderer getCellRenderer(int row, int column) { - //第一行渲染成为标题的样子 - if (row == 0) { - return new GroupRenderer(); - } - return super.getCellRenderer(row, column); - } - - - public MobileWidgetTable(FormDesigner designer) { - this.designer = designer; - cellData = getData(); - this.setTableProperties(); - TableModel defaultModel = new BeanTableModel(); - this.setModel(defaultModel); - this.repaint(); - this.setDefaultRenderer(Object.class,new DefaultTableCellRenderer()); - refreshData(); - this.addMouseListener(mouseAdapter); - this.addMouseMotionListener(mouseAdapter); - add(moveComponent); - } - - private void setTableProperties() { - JTableHeader header = getTableHeader(); - header.setReorderingAllowed(false); - header.setPreferredSize(new Dimension(0, 0)); // 隐藏表头 - GroupRenderer headerRenderer = new GroupRenderer(); - headerRenderer.setPreferredSize(new Dimension(0, 0)); //这行代码隐藏表头。因为要实现折叠效果,表头不好监听事件 - headerRenderer.setHorizontalAlignment(JLabel.LEFT); - header.setDefaultRenderer(headerRenderer); - - this.setRowHeight(WIDGET_TABLE_ROW_HEIGHT); - this.setGridColor(new Color(212, 208, 200)); - this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - this.setColumnSelectionAllowed(false); - this.setRowSelectionAllowed(false); - this.setFillsViewportHeight(false); - this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); - } - - private MouseAdapter mouseAdapter = new MouseAdapter() { - /** - * 鼠标按下时处理的事件(设置当前选中的行列) - * @param e - */ - @Override - public void mousePressed(MouseEvent e) { - getInstance().setCellSelected(); - if (selectedRow == 0 && !e.isPopupTrigger() && e.getClickCount() == 1 && e.getX() < WIDGET_TABLE_ROW_HEIGHT / 2){ // 如果是点击在第一行 - toggleCollapse(); - } - } - - /** - * 鼠标放开时处理的事件(如果是正在拖动则执行换位操作,重新绘制属性表,如果不是则什么也不做) - * 所谓的换行就是简单的重新拿到一次表格数据然后重新绘制表格 - * @param e - */ - @Override - public void mouseReleased(MouseEvent e) { - if(!draging){ - return; - } - draging = false; - moveComponent.setVisible(false); - int toIndex = e.getY() < GAP ? 0 : (int)Math.rint((e.getY() - GAP)/WIDGET_TABLE_ROW_HEIGHT) + 1; - //当鼠标放开时,将选中的容器调整至新的顺序 - ((WSortLayout)designer.getSelectionModel().getSelection().getSelectedCreator().toData()).adjustOrder(selectedRow - 1, toIndex - 1); - //拿取排序后表格数据,然后重绘表格 - getInstance().refreshData(); - getInstance().repaint(); - designer.fireTargetModified(); - getInstance().setCellSelected(); - } - - /** - * 设置鼠标在属性表区域移动时候的事件 - * @param e - */ - @Override - public void mouseMoved(MouseEvent e) { - int overRow = 0; - for (int i = 0;i < getRowCount();i++) { - if (e.getY() > i * WIDGET_TABLE_ROW_HEIGHT && e.getY() <= (i + 1) * WIDGET_TABLE_ROW_HEIGHT){ - overRow = i; //判断鼠标在哪一行 - } - } - //如果鼠标移动到当前选中的行上面的时候 - if (overRow == selectedRow && selectedRow > 0) { - //把当前选中的那一行的光标改成(除了第一列)移动样式MOVE_CURSOR - setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); - } else { - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - } - - /** - * 鼠标拖动事件(如果鼠标当前是MOVE_CURSOR状态则执行开始拖动的代码, - * 绘制一个moveComponent来跟随鼠标移动) - * @param e - */ - @Override - public void mouseDragged(MouseEvent e) { - int width = getColumnModel().getColumn(0).getWidth(); - //如果当前选中的行的范围是合理的话,就可以拖动 - if (selectedRow < getRowCount() && selectedRow > 0){ - setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); - draging = true; - moveComponent.setText(getValueAt(selectedRow,0).toString()); - moveComponent.setLocation(0, e.getY() - GAP); - moveComponent.setSize(new Dimension(width, WIDGET_TABLE_ROW_HEIGHT)); - moveComponent.setVisible(true); - moveComponent.setForeground(Color.lightGray); - moveComponent.setBorder(BorderFactory.createLineBorder(Color.lightGray)); - } - } - - /** - * 设置鼠标单击时处理的事件(单击控件列表进入控件属性表) - * @param e - */ - @Override - public void mouseClicked(MouseEvent e) { - if(selectedRow > 0){ - //当前点击的控件的名字 - String widgetName = cellData[selectedRow][0]; - if (StringUtils.isNotEmpty(widgetName)){ - //当前选择的容器 - XCreator selectedContainer = designer.getSelectionModel().getSelection().getSelectedCreator(); - WLayout selectedWidget = (WLayout)selectedContainer.toData(); - //当前选择的容器中的控件数量 - int count = selectedWidget.getWidgetCount(); - for (int i = 0;i < count ;i++){ - XCreator xCreator = (XCreator) selectedContainer.getComponent(i); - Widget widget = xCreator.toData(); - if (ComparatorUtils.equals(widgetName, widget.getWidgetName())) { - getEditingDesigner().getSelectionModel().setSelectedCreator(xCreator); - } - } - } - } else if (selectedRow == 0){ // 如果是点击在第一行 - if (!e.isPopupTrigger() && e.getClickCount() > 1) { - toggleCollapse(); - } - } - } - - /** - * 鼠标离开属性表区域事件 - * @param e - */ - public void mouseExited(MouseEvent e) { - draging = false; - moveComponent.setVisible(false); - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - }; - - public MobileWidgetTable getInstance(){ - return this; - } - - public FormDesigner getEditingDesigner(){ - return designer; - } - - /** - * 设置当前get到的行列的单元格为选中状态 - */ - private void setCellSelected() { - selectedRow = getSelectedRow(); - if (selectedRow != -1) { - this.setRowSelectionInterval(selectedRow, selectedRow); - this.setColumnSelectionInterval(0, 0); - } - } - - /** - * 切换属性组折叠属性true/false - */ - private void toggleCollapse() { - this.setCollapsed(!this.isCollapsed()); - //这里获取表格的父控件是为了当表格被折叠了后,装表格的父控件也要相应的重新布局一下 - //比如折叠之后表格行数应该比原来的少,占用父容器空间应该小点,不重新布局父容器,表格大小不会改变 - Container parent = MobileWidgetTable.this.getParent(); - if (parent != null) { - parent.revalidate(); - } - repaint(); - } - - /** - * 重新get排序后的数据 - */ - public void refreshData(){ - cellData = getData(); - } - - /** - * 获取选中控件的控件列表 - * - * @return String[][] 二维数组,[0][0]widgetName - */ - private String[][] getData(){ - if(designer.isFormParaDesigner()){ - return new String[0][0]; - } - - //选择的控件 - Widget selectedModel = designer.getSelectionModel().getSelection().getSelectedCreator().toData(); - - if(selectedModel == null){ - return new String[0][0]; - } - - // 选择的控件有两种类型,一种是WLayout,代表容器,一种是Widget,代表控件 - if (selectedModel.acceptType(WSortLayout.class)) { - List mobileWidgetList = ((WSortLayout)selectedModel).getOrderedMobileWidgetList(); - String[][] widgetName = new String[mobileWidgetList.size() + 1][1]; - widgetName[0][0] = Inter.getLocText("FR-Designer_WidgetOrder"); - for (int i = 0; i < mobileWidgetList.size(); i++) { - widgetName[i + 1][0] = mobileWidgetList.get(i); - } - return widgetName; - } else { - return new String[0][0]; - } - } - - public boolean isCollapsed() { - return collapsed; - } - - public void setCollapsed(boolean collapsed) { - this.collapsed = collapsed; - } - - /** - * 自定义的tableEditor类 - */ - public class BeanTableModel extends DefaultTableModel { - public BeanTableModel() { - super(cellData,headers); - } - - @Override - public int getRowCount() { - if (isCollapsed()) { - return 1; - } - return cellData.length; - } - - @Override - public int getColumnCount() { - return 1; - } - - - @Override - public Object getValueAt(int row, int column) { - if (row >= getRowCount() || column >= getColumnCount()) { - return null; - } - if (row == 0) { - return (isCollapsed()? "+" : "-") + cellData[row][0]; - } - - return cellData[row][0]; - } - - @Override - public String getColumnName(int column) { - return headers[0]; - } - - - @Override - public void setValueAt(Object aValue, int row, int column) { - if (row >= getRowCount() || column >= getColumnCount()) { - return; - } - if (aValue == null) { - cellData[row] = null; - return; - } - cellData[row][0] = aValue.toString(); - } - - /** - * 是否可编辑 - * @param row 行号 - * @param column 列号 - * @return 是否可编辑 - */ - public boolean isCellEditable(int row, int column) { - return false; - } - - } - +package com.fr.design.mainframe; + +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.table.*; + +import com.fr.design.designer.creator.XCreator; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itable.GroupRenderer; +import com.fr.form.ui.Widget; +import com.fr.form.ui.container.*; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +/** + * MobileWidgetTable类主要显示各种容器的控件列表(body,tab,绝对布局快,不包括参数面板) + * Created with IntelliJ IDEA. + * User: zx + * Date: 14-9-15 + * Time: 下午4:52 + * Modified by fanglei at 2017/01/23 + */ +public class MobileWidgetTable extends JTable { + + private FormDesigner designer; + private String[][] cellData; + private String[] headers = {Inter.getLocText("Form-Widget_Name")}; + private static final int WIDGET_TABLE_ROW_HEIGHT = 22; + private UILabel moveComponent = new UILabel(); // 作为拖动时候随鼠标移动的那个半透明控件 + private int selectedRow = -1; + private static final int GAP = 11; + private boolean draging = false; + private boolean collapsed = false; // 控件列表是否折叠 + + @Override + public TableCellRenderer getCellRenderer(int row, int column) { + //第一行渲染成为标题的样子 + if (row == 0) { + return new GroupRenderer(); + } + return super.getCellRenderer(row, column); + } + + + public MobileWidgetTable(FormDesigner designer) { + this.designer = designer; + cellData = getData(); + this.setTableProperties(); + TableModel defaultModel = new BeanTableModel(); + this.setModel(defaultModel); + this.repaint(); + this.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()); + refreshData(); + this.addMouseListener(mouseAdapter); + this.addMouseMotionListener(mouseAdapter); + add(moveComponent); + } + + private void setTableProperties() { + JTableHeader header = getTableHeader(); + header.setReorderingAllowed(false); + header.setPreferredSize(new Dimension(0, 0)); // 隐藏表头 + GroupRenderer headerRenderer = new GroupRenderer(); + headerRenderer.setPreferredSize(new Dimension(0, 0)); //这行代码隐藏表头。因为要实现折叠效果,表头不好监听事件 + headerRenderer.setHorizontalAlignment(JLabel.LEFT); + header.setDefaultRenderer(headerRenderer); + + this.setRowHeight(WIDGET_TABLE_ROW_HEIGHT); + this.setGridColor(new Color(212, 208, 200)); + this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + this.setColumnSelectionAllowed(false); + this.setRowSelectionAllowed(false); + this.setFillsViewportHeight(false); + this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + } + + private MouseAdapter mouseAdapter = new MouseAdapter() { + /** + * 鼠标按下时处理的事件(设置当前选中的行列) + * @param e + */ + @Override + public void mousePressed(MouseEvent e) { + getInstance().setCellSelected(); + if (selectedRow == 0 && !e.isPopupTrigger() && e.getClickCount() == 1 && e.getX() < WIDGET_TABLE_ROW_HEIGHT / 2) { // 如果是点击在第一行 + toggleCollapse(); + } + } + + /** + * 鼠标放开时处理的事件(如果是正在拖动则执行换位操作,重新绘制属性表,如果不是则什么也不做) + * 所谓的换行就是简单的重新拿到一次表格数据然后重新绘制表格 + * @param e + */ + @Override + public void mouseReleased(MouseEvent e) { + if (!draging) { + return; + } + draging = false; + moveComponent.setVisible(false); + int toIndex = e.getY() < GAP ? 0 : (int) Math.rint((e.getY() - GAP) / WIDGET_TABLE_ROW_HEIGHT) + 1; + //当鼠标放开时,将选中的容器调整至新的顺序 + ((WSortLayout) designer.getSelectionModel().getSelection().getSelectedCreator().toData()).adjustOrder(selectedRow - 1, toIndex - 1); + //拿取排序后表格数据,然后重绘表格 + getInstance().refreshData(); + getInstance().repaint(); + designer.fireTargetModified(); + getInstance().setCellSelected(); + } + + /** + * 设置鼠标在属性表区域移动时候的事件 + * @param e + */ + @Override + public void mouseMoved(MouseEvent e) { + int overRow = 0; + for (int i = 0; i < getRowCount(); i++) { + if (e.getY() > i * WIDGET_TABLE_ROW_HEIGHT && e.getY() <= (i + 1) * WIDGET_TABLE_ROW_HEIGHT) { + overRow = i; //判断鼠标在哪一行 + } + } + //如果鼠标移动到当前选中的行上面的时候 + if (overRow == selectedRow && selectedRow > 0) { + //把当前选中的那一行的光标改成(除了第一列)移动样式MOVE_CURSOR + setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + } else { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + + /** + * 鼠标拖动事件(如果鼠标当前是MOVE_CURSOR状态则执行开始拖动的代码, + * 绘制一个moveComponent来跟随鼠标移动) + * @param e + */ + @Override + public void mouseDragged(MouseEvent e) { + int width = getColumnModel().getColumn(0).getWidth(); + //如果当前选中的行的范围是合理的话,就可以拖动 + if (selectedRow < getRowCount() && selectedRow > 0) { + setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + draging = true; + moveComponent.setText(getValueAt(selectedRow, 0).toString()); + moveComponent.setLocation(0, e.getY() - GAP); + moveComponent.setSize(new Dimension(width, WIDGET_TABLE_ROW_HEIGHT)); + moveComponent.setVisible(true); + moveComponent.setForeground(Color.lightGray); + moveComponent.setBorder(BorderFactory.createLineBorder(Color.lightGray)); + } + } + + /** + * 设置鼠标单击时处理的事件(单击控件列表进入控件属性表) + * @param e + */ + @Override + public void mouseClicked(MouseEvent e) { + if (selectedRow > 0) { + //当前点击的控件的名字 + String widgetName = cellData[selectedRow][0]; + if (StringUtils.isNotEmpty(widgetName)) { + //当前选择的容器 + XCreator selectedContainer = designer.getSelectionModel().getSelection().getSelectedCreator(); + WLayout selectedWidget = (WLayout) selectedContainer.toData(); + //当前选择的容器中的控件数量 + int count = selectedWidget.getWidgetCount(); + for (int i = 0; i < count; i++) { + XCreator xCreator = (XCreator) selectedContainer.getComponent(i); + Widget widget = xCreator.toData(); + if (ComparatorUtils.equals(widgetName, widget.getWidgetName())) { + getEditingDesigner().getSelectionModel().setSelectedCreator(xCreator); + } + } + } + } else if (selectedRow == 0) { // 如果是点击在第一行 + if (!e.isPopupTrigger() && e.getClickCount() > 1) { + toggleCollapse(); + } + } + } + + /** + * 鼠标离开属性表区域事件 + * @param e + */ + public void mouseExited(MouseEvent e) { + draging = false; + moveComponent.setVisible(false); + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + }; + + public MobileWidgetTable getInstance() { + return this; + } + + public FormDesigner getEditingDesigner() { + return designer; + } + + /** + * 设置当前get到的行列的单元格为选中状态 + */ + private void setCellSelected() { + selectedRow = getSelectedRow(); + if (selectedRow != -1) { + this.setRowSelectionInterval(selectedRow, selectedRow); + this.setColumnSelectionInterval(0, 0); + } + } + + /** + * 切换属性组折叠属性true/false + */ + private void toggleCollapse() { + this.setCollapsed(!this.isCollapsed()); + //这里获取表格的父控件是为了当表格被折叠了后,装表格的父控件也要相应的重新布局一下 + //比如折叠之后表格行数应该比原来的少,占用父容器空间应该小点,不重新布局父容器,表格大小不会改变 + Container parent = MobileWidgetTable.this.getParent(); + if (parent != null) { + parent.revalidate(); + } + repaint(); + } + + /** + * 重新get排序后的数据 + */ + public void refreshData() { + cellData = getData(); + } + + /** + * 获取选中控件的控件列表 + * + * @return String[][] 二维数组,[0][0]widgetName + */ + private String[][] getData() { + if (designer.isFormParaDesigner()) { + return new String[0][0]; + } + + //选择的控件 + XCreator selectedCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); + Widget selectedModel = selectedCreator != null ? selectedCreator.toData() : null; + + if (selectedModel == null) { + return new String[0][0]; + } + + // 选择的控件有两种类型,一种是WLayout,代表容器,一种是Widget,代表控件 + if (selectedModel.acceptType(WSortLayout.class)) { + List mobileWidgetList = ((WSortLayout) selectedModel).getOrderedMobileWidgetList(); + String[][] widgetName = new String[mobileWidgetList.size() + 1][1]; + widgetName[0][0] = Inter.getLocText("FR-Designer_WidgetOrder"); + for (int i = 0; i < mobileWidgetList.size(); i++) { + widgetName[i + 1][0] = mobileWidgetList.get(i); + } + return widgetName; + } else { + return new String[0][0]; + } + } + + public boolean isCollapsed() { + return collapsed; + } + + public void setCollapsed(boolean collapsed) { + this.collapsed = collapsed; + } + + /** + * 自定义的tableEditor类 + */ + public class BeanTableModel extends DefaultTableModel { + public BeanTableModel() { + super(cellData, headers); + } + + @Override + public int getRowCount() { + if (isCollapsed()) { + return 1; + } + return cellData.length; + } + + @Override + public int getColumnCount() { + return 1; + } + + + @Override + public Object getValueAt(int row, int column) { + if (row >= getRowCount() || column >= getColumnCount()) { + return null; + } + if (row == 0) { + return (isCollapsed() ? "+" : "-") + cellData[row][0]; + } + + return cellData[row][0]; + } + + @Override + public String getColumnName(int column) { + return headers[0]; + } + + + @Override + public void setValueAt(Object aValue, int row, int column) { + if (row >= getRowCount() || column >= getColumnCount()) { + return; + } + if (aValue == null) { + cellData[row] = null; + return; + } + cellData[row][0] = aValue.toString(); + } + + /** + * 是否可编辑 + * + * @param row 行号 + * @param column 列号 + * @return 是否可编辑 + */ + public boolean isCellEditable(int row, int column) { + return false; + } + + } + } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java b/designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java index 33736ac0a..6a8480206 100644 --- a/designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java +++ b/designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java @@ -1,366 +1,372 @@ -package com.fr.design.mainframe; - -import com.fr.base.BaseUtils; -import com.fr.design.ExtraDesignClassManager; -import com.fr.design.designer.beans.events.DesignerEditListener; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWParameterLayout; -import com.fr.design.designer.properties.EventPropertyTable; -import com.fr.design.designer.properties.WidgetPropertyTable; -import com.fr.design.fun.WidgetPropertyUIProvider; -import com.fr.design.gui.frpane.UITabbedPane; -import com.fr.design.gui.icontainer.UIScrollPane; -import com.fr.design.gui.itable.AbstractPropertyTable; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.form.ui.Widget; -import com.fr.general.Inter; -import com.fr.stable.ArrayUtils; - -import javax.swing.*; -import javax.swing.border.LineBorder; -import javax.swing.table.JTableHeader; -import java.awt.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -/** - * 控件属性表绘制 - * Modified by fanglei - */ -public class WidgetPropertyPane extends FormDockView implements BaseWidgetPropertyPane { - - private static final String PARA = "para"; - private static final String BODY = "body"; - private WidgetPropertyTable propertyTable; // 控件的属性表 - private EventPropertyTable eventTable; // 控件的事件表 - private List widgetPropertyTables; // 这个变量应该是保存控件拓展的属性tab - private FormDesigner designer; // 当前designer - private UIScrollPane psp; // 用来装载属性表table的容器 - private UIScrollPane esp; //用来装载事件table的容器 - private JPanel wsp; // 装载移动端tab的容器,包括移动端属性表和控件拓展的移动端属性表 - private MobileParaWidgetTable mobileParaWidgetTable; // 参数面板的移动端属性tab(和body的移动端属性tab区别是没有标签名column) - private MobileWidgetTable mobileWidgetTable; // body的移动端属性tab - private UIScrollPane downPanel; // 这个滚动容器是用于装载centerPane的 - private JPanel centerPane; // 此centerPane采用的是cardLayout布局,装载着mobileWidgetTable和mobileBodyWidgetTable - private CardLayout cardLayout; // 卡片布局,选中参数面板时显示mobileWidgetTable,选中body时显示mobileBodyWidgetTable - private JTableHeader header;//把表头单独get出来作为一个组件 - - public static WidgetPropertyPane getInstance() { - if (HOLDER.singleton == null) { - HOLDER.singleton = new WidgetPropertyPane(); - } - return HOLDER.singleton; - } - - public static WidgetPropertyPane getInstance(FormDesigner formEditor) { - HOLDER.singleton.setEditingFormDesigner(formEditor); - HOLDER.singleton.refreshDockingView(); - return HOLDER.singleton; - } - - private static class HOLDER { - private static WidgetPropertyPane singleton = new WidgetPropertyPane(); - } - - private WidgetPropertyPane() { - setLayout(FRGUIPaneFactory.createBorderLayout()); - } - - @Override - public String getViewTitle() { - return Inter.getLocText("Form-Widget_Property_Table"); - } - - @Override - public Icon getViewIcon() { - return BaseUtils.readIcon("/com/fr/design/images/m_report/attributes.png"); - } - - @Override - /** - * 绘制属性表tab - */ - public void refreshDockingView() { - designer = this.getEditingFormDesigner(); - removeAll(); - if (designer == null) { - clearDockingView(); - return; - } - widgetPropertyTables = new ArrayList(); - - //依次创建属性表、事件表、移动端表,再将它们整合到TabPane中去 - this.createPropertyTable(); - this.createEventTable(); - this.createMobileWidgetTable(); - this.createTabPane(); - - this.initTables(); - } - - /** - * 初始化属性表,事件表,移动端拓展的属性表 - */ - private void initTables() { - propertyTable.initPropertyGroups(null); - eventTable.refresh(); - for (AbstractPropertyTable propertyTable : widgetPropertyTables) { - propertyTable.initPropertyGroups(designer); - } - } - - /** - * 创建属性表table - */ - private void createPropertyTable() { - propertyTable = new WidgetPropertyTable(designer); - designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable)); - propertyTable.setBorder(null); - psp = new UIScrollPane(propertyTable); // 用来装载属性表table - psp.setBorder(null); - } - - /** - * 创建事件表(事件选项卡不是JTable) - */ - private void createEventTable() { - eventTable = new EventPropertyTable(designer); - designer.addDesignerEditListener(new EventPropertyDesignerAdapter(eventTable)); - eventTable.setBorder(null); - esp = new UIScrollPane(eventTable); //用来装载事件table - esp.setBorder(null); - } - - /** - * 创建移动端控件列表 - */ - private void createMobileWidgetTable() { - //加上表头后,这里不再使用borderLayout布局,而采用BoxLayout布局 - wsp = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); - wsp.setBorder(null); - mobileParaWidgetTable = new MobileParaWidgetTable(designer); - mobileWidgetTable = new MobileWidgetTable(designer); - designer.addDesignerEditListener(new mobileWidgetDesignerAdapter()); - centerPane = FRGUIPaneFactory.createCardLayout_S_Pane(); - cardLayout = (CardLayout) centerPane.getLayout(); - centerPane.add(mobileParaWidgetTable, PARA);// 采用卡片布局的容器必须指定卡片名字,如果没有卡片名字 - // 就会出现:Exception in thread "main" java.lang.IllegalArgumentException: - // cannot add to layout: constraint must be a string - // 第二个参数代表卡片的名字。后来show方法调用时通过名字找到要显示的卡片 - centerPane.add(mobileWidgetTable, BODY); //这两句代码,是把JTable放到一个JPanel中去了,表头不会显示, - //只有放到JScrollPanel中去表头才能正常显示,这就是MobileWidgetTable中定义了表头却没有显示的原因! - //解决方案:MobileWidgetTable实在无法直接放到JScrollPanel中去的时候,应该把表头get出来单独作为一个组件显示 - - if(hasSelectParaPane(designer)){ - cardLayout.show(centerPane,PARA); - header = mobileParaWidgetTable.getTableHeader(); - } else { - cardLayout.show(centerPane,BODY); - header = mobileWidgetTable.getTableHeader(); - } - downPanel = new UIScrollPane(centerPane); - downPanel.setBorder(new LineBorder(Color.GRAY)); - - //获取拓展移动端属性tab - WidgetPropertyUIProvider[] widgetAttrProviders = getExtraPropertyUIProviders(); - - addWidgetAttr(widgetAttrProviders); - } - - /** - * 将属性表,事件表,移动端控件列表整合到TabPane里面去 - */ - private void createTabPane() { - UITabbedPane tabbedPane = new UITabbedPane(); // tab选项卡容器 - initTabPane(tabbedPane); - add(tabbedPane, BorderLayout.CENTER); - } - - /** - * 获取当前控件扩展的属性tab - * 来源有两个: - * 1, 各个控件从各自的Xcreator里扩展(例如手机重布局的tab就是从Xcreator中扩展的); - * 2, 所有的控件从插件里扩展. - * - * @return 扩展的tab - */ - private WidgetPropertyUIProvider[] getExtraPropertyUIProviders() { - FormSelection selection = designer.getSelectionModel().getSelection(); - WidgetPropertyUIProvider[] embeddedPropertyUIProviders = null; - if (selection != null && selection.getSelectedCreator() != null) { - embeddedPropertyUIProviders = selection.getSelectedCreator().getWidgetPropertyUIProviders(); - } - Set set = ExtraDesignClassManager.getInstance().getArray(WidgetPropertyUIProvider.XML_TAG); - return ArrayUtils.addAll(embeddedPropertyUIProviders, set.toArray(new WidgetPropertyUIProvider[set.size()])); - } - - /** - * 判断是将拓展的tab放入属性表还是将原来的tab放入属性表 - * @param widgetAttrProviders 拓展的tab - */ - private void addWidgetAttr(WidgetPropertyUIProvider[] widgetAttrProviders) { - if (widgetAttrProviders.length == 0) { // 判断有没有拓展的tab,没有就使用原来的 - wsp.add(header); - wsp.add(downPanel); - } else { - for (WidgetPropertyUIProvider widgetAttrProvider : widgetAttrProviders) { - AbstractPropertyTable propertyTable = widgetAttrProvider.createWidgetAttrTable(); - widgetPropertyTables.add(propertyTable); - designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable)); - UIScrollPane uiScrollPane = new UIScrollPane(getExtraBodyTable(propertyTable)); - wsp.add(uiScrollPane); - } - } - } - - /** - * 如果是body的拓展属性表,那么要额外加上一张控件顺序表 - * @return - */ - private Component getExtraBodyTable(AbstractPropertyTable abstractPropertyTable) { - Widget selection = designer.getSelectionModel().getSelection().getSelectedCreator().toData(); - if (selection.getWidgetName().equals("body")) { - JPanel jPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); - jPanel.add(abstractPropertyTable); - MobileWidgetTable mobileWidgetTable = new MobileWidgetTable(designer); - jPanel.add(mobileWidgetTable.getTableHeader()); - jPanel.add(mobileWidgetTable); - return jPanel; - } - return abstractPropertyTable; - } - - private void initTabPane(UITabbedPane tabbedPane) { - tabbedPane.setOpaque(true); - tabbedPane.setBorder(null); - tabbedPane.setTabPlacement(SwingConstants.BOTTOM); - tabbedPane.addTab(Inter.getLocText("FR-Designer_Properties"), psp); - tabbedPane.addTab(Inter.getLocText("FR-Designer_Event"), esp); - tabbedPane.addTab(Inter.getLocText("FR-Widget_Mobile_Terminal"), wsp); - } - - // - /** - * 选中的组件是否在参数面板里 - * @param designer 设计器 - * @return 是则返回true - */ - public boolean hasSelectParaPane(FormDesigner designer){ - XCreator xCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); - if(xCreator == null){ - xCreator = designer.getRootComponent(); - } - XLayoutContainer container = XCreatorUtils.getHotspotContainer(xCreator); - return xCreator.acceptType(XWParameterLayout.class) || container.acceptType(XWParameterLayout.class); - } - - public void setEditingFormDesigner(BaseFormDesigner editor) { - FormDesigner fd = (FormDesigner) editor; - super.setEditingFormDesigner(fd); - } - - private void clearDockingView() { - propertyTable = null; - eventTable = null; - if (widgetPropertyTables != null) { - widgetPropertyTables.clear(); - } - JScrollPane psp = new JScrollPane(); - psp.setBorder(null); - this.add(psp, BorderLayout.CENTER); - } - - /** - * 属性表监听界面事件(编辑,删除,选中,改变大小) - */ - private class WidgetPropertyDesignerAdapter implements DesignerEditListener { - AbstractPropertyTable propertyTable; - - WidgetPropertyDesignerAdapter(AbstractPropertyTable propertyTable) { - this.propertyTable = propertyTable; - } - - @Override - public void fireCreatorModified(DesignerEvent evt) { - if (evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { - propertyTable.initPropertyGroups(designer); - } else if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED) { - repaint(); - } - } - - @Override - public boolean equals(Object o) { - return o instanceof WidgetPropertyDesignerAdapter && ((WidgetPropertyDesignerAdapter) o).propertyTable == this.propertyTable; - } - } - - /** - * 事件表监听界面事件(编辑,选中) - */ - private class EventPropertyDesignerAdapter implements DesignerEditListener { - EventPropertyTable propertyTable; - - EventPropertyDesignerAdapter(EventPropertyTable eventTable) { - this.propertyTable = eventTable; - } - - @Override - public void fireCreatorModified(DesignerEvent evt) { - if (evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { - propertyTable.refresh(); - } - } - - @Override - public boolean equals(Object o) { - return o instanceof EventPropertyDesignerAdapter; - } - } - - /** - * 移动端属性表监听界面事件(改变大小,编辑,选中,增加控件) - */ - private class mobileWidgetDesignerAdapter implements DesignerEditListener { - - mobileWidgetDesignerAdapter() { - } - - /** - * 响应界面改变事件 - * @param evt 事件 - */ - public void fireCreatorModified(DesignerEvent evt) { - if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_ADDED) { - int value = downPanel.getVerticalScrollBar().getValue(); - if(hasSelectParaPane(getEditingFormDesigner())){ - cardLayout.show(centerPane,PARA); - mobileParaWidgetTable.refreshData(); - } else { - cardLayout.show(centerPane,BODY); - mobileWidgetTable.refreshData(); - } - //出现滚动条 - downPanel.doLayout(); - //控件列表选中某组件,触发表单中选中控件,选中事件又触发列表刷新,滚动条回到0 - //此处设置滚动条值为刷新前 - downPanel.getVerticalScrollBar().setValue(value); - } - } - } - - @Override - public Location preferredLocation() { - return Location.WEST_BELOW; - } +package com.fr.design.mainframe; + +import com.fr.base.BaseUtils; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.designer.beans.events.DesignerEditListener; +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XCreatorUtils; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWParameterLayout; +import com.fr.design.designer.properties.EventPropertyTable; +import com.fr.design.designer.properties.WidgetPropertyTable; +import com.fr.design.fun.WidgetPropertyUIProvider; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.itable.AbstractPropertyTable; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.form.ui.Widget; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; + +import javax.swing.*; +import javax.swing.border.LineBorder; +import javax.swing.table.JTableHeader; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * 控件属性表绘制 + * Modified by fanglei + */ +public class WidgetPropertyPane extends FormDockView implements BaseWidgetPropertyPane { + + private static final String PARA = "para"; + private static final String BODY = "body"; + private WidgetPropertyTable propertyTable; // 控件的属性表 + private EventPropertyTable eventTable; // 控件的事件表 + private List widgetPropertyTables; // 这个变量应该是保存控件拓展的属性tab + private FormDesigner designer; // 当前designer + private UIScrollPane psp; // 用来装载属性表table的容器 + private UIScrollPane esp; //用来装载事件table的容器 + private JPanel wsp; // 装载移动端tab的容器,包括移动端属性表和控件拓展的移动端属性表 + private MobileParaWidgetTable mobileParaWidgetTable; // 参数面板的移动端属性tab(和body的移动端属性tab区别是没有标签名column) + private MobileWidgetTable mobileWidgetTable; // body的移动端属性tab + private UIScrollPane downPanel; // 这个滚动容器是用于装载centerPane的 + private JPanel centerPane; // 此centerPane采用的是cardLayout布局,装载着mobileWidgetTable和mobileBodyWidgetTable + private CardLayout cardLayout; // 卡片布局,选中参数面板时显示mobileWidgetTable,选中body时显示mobileBodyWidgetTable + private JTableHeader header;//把表头单独get出来作为一个组件 + + public static WidgetPropertyPane getInstance() { + if (HOLDER.singleton == null) { + HOLDER.singleton = new WidgetPropertyPane(); + } + return HOLDER.singleton; + } + + public static WidgetPropertyPane getInstance(FormDesigner formEditor) { + HOLDER.singleton.setEditingFormDesigner(formEditor); + HOLDER.singleton.refreshDockingView(); + return HOLDER.singleton; + } + + private static class HOLDER { + private static WidgetPropertyPane singleton = new WidgetPropertyPane(); + } + + private WidgetPropertyPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + } + + @Override + public String getViewTitle() { + return Inter.getLocText("Form-Widget_Property_Table"); + } + + @Override + public Icon getViewIcon() { + return BaseUtils.readIcon("/com/fr/design/images/m_report/attributes.png"); + } + + @Override + /** + * 绘制属性表tab + */ + public void refreshDockingView() { + designer = this.getEditingFormDesigner(); + removeAll(); + if (designer == null) { + clearDockingView(); + return; + } + widgetPropertyTables = new ArrayList(); + + //依次创建属性表、事件表、移动端表,再将它们整合到TabPane中去 + this.createPropertyTable(); + this.createEventTable(); + this.createMobileWidgetTable(); + this.createTabPane(); + + this.initTables(); + } + + /** + * 初始化属性表,事件表,移动端拓展的属性表 + */ + private void initTables() { + propertyTable.initPropertyGroups(null); + eventTable.refresh(); + for (AbstractPropertyTable propertyTable : widgetPropertyTables) { + propertyTable.initPropertyGroups(designer); + } + } + + /** + * 创建属性表table + */ + private void createPropertyTable() { + propertyTable = new WidgetPropertyTable(designer); + designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable)); + propertyTable.setBorder(null); + psp = new UIScrollPane(propertyTable); // 用来装载属性表table + psp.setBorder(null); + } + + /** + * 创建事件表(事件选项卡不是JTable) + */ + private void createEventTable() { + eventTable = new EventPropertyTable(designer); + designer.addDesignerEditListener(new EventPropertyDesignerAdapter(eventTable)); + eventTable.setBorder(null); + esp = new UIScrollPane(eventTable); //用来装载事件table + esp.setBorder(null); + } + + /** + * 创建移动端控件列表 + */ + private void createMobileWidgetTable() { + //加上表头后,这里不再使用borderLayout布局,而采用BoxLayout布局 + wsp = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + wsp.setBorder(null); + mobileParaWidgetTable = new MobileParaWidgetTable(designer); + mobileWidgetTable = new MobileWidgetTable(designer); + designer.addDesignerEditListener(new mobileWidgetDesignerAdapter()); + centerPane = FRGUIPaneFactory.createCardLayout_S_Pane(); + cardLayout = (CardLayout) centerPane.getLayout(); + centerPane.add(mobileParaWidgetTable, PARA); + // 采用卡片布局的容器必须指定卡片名字,如果没有卡片名字 + // 就会出现:Exception in thread "main" java.lang.IllegalArgumentException: + // cannot add to layout: constraint must be a string + // 第二个参数代表卡片的名字。后来show方法调用时通过名字找到要显示的卡片 + centerPane.add(mobileWidgetTable, BODY); //这两句代码,是把JTable放到一个JPanel中去了,表头不会显示, + //只有放到JScrollPanel中去表头才能正常显示,这就是MobileWidgetTable中定义了表头却没有显示的原因! + //解决方案:MobileWidgetTable实在无法直接放到JScrollPanel中去的时候,应该把表头get出来单独作为一个组件显示 + + if (hasSelectParaPane(designer)) { + cardLayout.show(centerPane, PARA); + header = mobileParaWidgetTable.getTableHeader(); + } else { + cardLayout.show(centerPane, BODY); + header = mobileWidgetTable.getTableHeader(); + } + downPanel = new UIScrollPane(centerPane); + downPanel.setBorder(new LineBorder(Color.GRAY)); + + //获取拓展移动端属性tab + WidgetPropertyUIProvider[] widgetAttrProviders = getExtraPropertyUIProviders(); + + addWidgetAttr(widgetAttrProviders); + } + + /** + * 将属性表,事件表,移动端控件列表整合到TabPane里面去 + */ + private void createTabPane() { + UITabbedPane tabbedPane = new UITabbedPane(); // tab选项卡容器 + initTabPane(tabbedPane); + add(tabbedPane, BorderLayout.CENTER); + } + + /** + * 获取当前控件扩展的属性tab + * 来源有两个: + * 1, 各个控件从各自的Xcreator里扩展(例如手机重布局的tab就是从Xcreator中扩展的); + * 2, 所有的控件从插件里扩展. + * + * @return 扩展的tab + */ + private WidgetPropertyUIProvider[] getExtraPropertyUIProviders() { + FormSelection selection = designer.getSelectionModel().getSelection(); + WidgetPropertyUIProvider[] embeddedPropertyUIProviders = null; + if (selection != null && selection.getSelectedCreator() != null) { + embeddedPropertyUIProviders = selection.getSelectedCreator().getWidgetPropertyUIProviders(); + } + Set set = ExtraDesignClassManager.getInstance().getArray(WidgetPropertyUIProvider.XML_TAG); + return ArrayUtils.addAll(embeddedPropertyUIProviders, set.toArray(new WidgetPropertyUIProvider[set.size()])); + } + + /** + * 判断是将拓展的tab放入属性表还是将原来的tab放入属性表 + * + * @param widgetAttrProviders 拓展的tab + */ + private void addWidgetAttr(WidgetPropertyUIProvider[] widgetAttrProviders) { + if (widgetAttrProviders.length == 0) { // 判断有没有拓展的tab,没有就使用原来的 + wsp.add(header); + wsp.add(downPanel); + } else { + for (WidgetPropertyUIProvider widgetAttrProvider : widgetAttrProviders) { + AbstractPropertyTable propertyTable = widgetAttrProvider.createWidgetAttrTable(); + widgetPropertyTables.add(propertyTable); + designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable)); + UIScrollPane uiScrollPane = new UIScrollPane(getExtraBodyTable(propertyTable)); + wsp.add(uiScrollPane); + } + } + } + + /** + * 如果是body的拓展属性表,那么要额外加上一张控件顺序表 + * + * @return + */ + private Component getExtraBodyTable(AbstractPropertyTable abstractPropertyTable) { + Widget selection = designer.getSelectionModel().getSelection().getSelectedCreator().toData(); + if (selection.getWidgetName().equals("body")) { + JPanel jPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + jPanel.add(abstractPropertyTable); + MobileWidgetTable mobileWidgetTable = new MobileWidgetTable(designer); + jPanel.add(mobileWidgetTable.getTableHeader()); + jPanel.add(mobileWidgetTable); + return jPanel; + } + return abstractPropertyTable; + } + + private void initTabPane(UITabbedPane tabbedPane) { + tabbedPane.setOpaque(true); + tabbedPane.setBorder(null); + tabbedPane.setTabPlacement(SwingConstants.BOTTOM); + tabbedPane.addTab(Inter.getLocText("FR-Designer_Properties"), psp); + tabbedPane.addTab(Inter.getLocText("FR-Designer_Event"), esp); + tabbedPane.addTab(Inter.getLocText("FR-Widget_Mobile_Terminal"), wsp); + } + + + /** + * 选中的组件是否在参数面板里 + * + * @param designer 设计器 + * @return 是则返回true + */ + public boolean hasSelectParaPane(FormDesigner designer) { + XCreator xCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); + if (xCreator == null) { + xCreator = designer.getRootComponent(); + } + XLayoutContainer container = XCreatorUtils.getHotspotContainer(xCreator); + //TODO container可能为空,引发空指针异常 + return xCreator.acceptType(XWParameterLayout.class) || container.acceptType(XWParameterLayout.class); + } + + public void setEditingFormDesigner(BaseFormDesigner editor) { + FormDesigner fd = (FormDesigner) editor; + super.setEditingFormDesigner(fd); + } + + private void clearDockingView() { + propertyTable = null; + eventTable = null; + if (widgetPropertyTables != null) { + widgetPropertyTables.clear(); + } + JScrollPane psp = new JScrollPane(); + psp.setBorder(null); + this.add(psp, BorderLayout.CENTER); + } + + /** + * 属性表监听界面事件(编辑,删除,选中,改变大小) + */ + private class WidgetPropertyDesignerAdapter implements DesignerEditListener { + AbstractPropertyTable propertyTable; + + WidgetPropertyDesignerAdapter(AbstractPropertyTable propertyTable) { + this.propertyTable = propertyTable; + } + + @Override + public void fireCreatorModified(DesignerEvent evt) { + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { + propertyTable.initPropertyGroups(designer); + } else if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED) { + repaint(); + } + } + + @Override + public boolean equals(Object o) { + return o instanceof WidgetPropertyDesignerAdapter && ((WidgetPropertyDesignerAdapter) o).propertyTable == this.propertyTable; + } + } + + /** + * 事件表监听界面事件(编辑,选中) + */ + private class EventPropertyDesignerAdapter implements DesignerEditListener { + EventPropertyTable propertyTable; + + EventPropertyDesignerAdapter(EventPropertyTable eventTable) { + this.propertyTable = eventTable; + } + + @Override + public void fireCreatorModified(DesignerEvent evt) { + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { + propertyTable.refresh(); + } + } + + @Override + public boolean equals(Object o) { + return o instanceof EventPropertyDesignerAdapter; + } + } + + /** + * 移动端属性表监听界面事件(改变大小,编辑,选中,增加控件) + */ + private class mobileWidgetDesignerAdapter implements DesignerEditListener { + + mobileWidgetDesignerAdapter() { + } + + /** + * 响应界面改变事件 + * + * @param evt 事件 + */ + public void fireCreatorModified(DesignerEvent evt) { + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_ADDED) { + int value = downPanel.getVerticalScrollBar().getValue(); + if (hasSelectParaPane(getEditingFormDesigner())) { + cardLayout.show(centerPane, PARA); + mobileParaWidgetTable.refreshData(); + } else { + cardLayout.show(centerPane, BODY); + mobileWidgetTable.refreshData(); + } + //出现滚动条 + downPanel.doLayout(); + //控件列表选中某组件,触发表单中选中控件,选中事件又触发列表刷新,滚动条回到0 + //此处设置滚动条值为刷新前 + downPanel.getVerticalScrollBar().setValue(value); + } + } + } + + @Override + public Location preferredLocation() { + return Location.WEST_BELOW; + } } \ No newline at end of file