yaoh.wu
8 years ago
3 changed files with 1197 additions and 1197 deletions
File diff suppressed because it is too large
Load Diff
@ -1,410 +1,410 @@
|
||||
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.*; |
||||
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.form.ui.container.cardlayout.WCardMainBorderLayout; |
||||
import com.fr.stable.ArrayUtils; |
||||
|
||||
/** |
||||
* 该model保存当前选择的组件和剪切版信息 |
||||
*/ |
||||
public class SelectionModel { |
||||
//被粘贴组件在所选组件位置处往下、往右各错开20像素。执行多次粘贴时,在上一次粘贴的位置处错开20像素。
|
||||
private static final int DELTA_X_Y = 20; //粘贴时候的偏移距离
|
||||
private static final int BORDER_PROPORTION = 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()) { |
||||
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(), |
||||
CLIP_BOARD, |
||||
rec.x + rec.width / 2, |
||||
rec.y + BORDER_PROPORTION); |
||||
} else { |
||||
Rectangle rec = selection.getRelativeBounds(); |
||||
//自适应布局
|
||||
FormSelectionUtils.paste2Container(designer, designer.getRootComponent(), |
||||
CLIP_BOARD, |
||||
rec.x + rec.width / 2, |
||||
rec.y + BORDER_PROPORTION); |
||||
} |
||||
} else { |
||||
//绝对布局
|
||||
//编辑器外面还有两层容器,使用designer.getRootComponent()获取到的是编辑器中层的容器,不是编辑器表层
|
||||
//当前选择的就是编辑器表层
|
||||
FormSelectionUtils.paste2Container(designer, (XLayoutContainer) selection.getSelectedCreator(), |
||||
CLIP_BOARD, |
||||
DELTA_X_Y, |
||||
DELTA_X_Y); |
||||
} |
||||
} else { |
||||
//cpt本地组件复用,编辑器就一层,是最底层,使用designer.getRootComponent()就可以获取到
|
||||
//使用selection.getSelectedCreator()也应该是可以获取到的。
|
||||
FormSelectionUtils.paste2Container(designer, designer.getRootComponent(), |
||||
CLIP_BOARD, |
||||
DELTA_X_Y, |
||||
DELTA_X_Y); |
||||
} |
||||
} |
||||
//已选
|
||||
else { |
||||
//获取到编辑器的表层容器(已选的组件的父容器就是表层容器)
|
||||
parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator()); |
||||
if (selection.getSelectedCreator().getParent() instanceof XWFitLayout) { |
||||
//自适应布局
|
||||
if (parent != null) { |
||||
Rectangle rec = selection.getRelativeBounds(); |
||||
FormSelectionUtils.paste2Container(designer, parent, CLIP_BOARD, rec.x + rec.width / 2, rec.y + |
||||
rec.height - BORDER_PROPORTION); |
||||
} |
||||
} else if (selection.getSelectedCreator().getParent() instanceof XWAbsoluteLayout) { |
||||
//绝对布局
|
||||
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 |
||||
* yaoh.wu 不应该通过判断是否是最底层容器来判断是否选择了组件 |
||||
* 而是应该判断选择的容器是否是编辑器的最表层容器,也就是点击空白地方选择的容器 |
||||
* 但是直接判断选择的容器是否是编辑器最表层类型又会引发拖动时选不上的情况, |
||||
* 因此通过判断父容器来实现 |
||||
* <p> |
||||
* 举例:frm组件复用 绝对布局情况下,不选择时有三层容器: |
||||
* 底层@see {@link com.fr.design.designer.creator.XWBorderLayout} |
||||
* 中层@see {@link XWFitLayout} |
||||
* 表层@see {@link com.fr.design.designer.creator.XWAbsoluteBodyLayout} |
||||
* <p> |
||||
* 但是编辑窗口的最外层其实是表层@see {@link com.fr.design.designer.creator.XWAbsoluteBodyLayout}, |
||||
* 其他两层不是靠添加组件就可以编辑的。 |
||||
*/ |
||||
public boolean hasSelectionComponent() { |
||||
if (designer.getClass().equals(FormDesigner.class)) { |
||||
//frm本地组件复用
|
||||
return selection.getSelectedCreator() != null |
||||
&& !( |
||||
//frm绝对布局编辑器
|
||||
selection.getSelectedCreator().getClass().equals(XWAbsoluteBodyLayout.class) |
||||
//Tab布局编辑器
|
||||
|| selection.getSelectedCreator().getClass().equals(XWCardMainBorderLayout.class) |
||||
|| selection.getSelectedCreator().getClass().equals(XWCardLayout.class) |
||||
|| selection.getSelectedCreator().getClass().equals(XWTabFitLayout.class) |
||||
//自适应布局编辑器
|
||||
|| selection.getSelectedCreator().getClass().equals(XWFitLayout.class) |
||||
); |
||||
} else { |
||||
//cpt本地组件复用,selection.getSelectedCreator().getParent()=@XWParameterLayout instanceof @XWAbsoluteLayout
|
||||
return selection.getSelectedCreator() != null && 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<XCreator> rebuildSelection) { |
||||
selection.setSelectedCreators(rebuildSelection); |
||||
fireCreatorSelected(); |
||||
} |
||||
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.*; |
||||
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.form.ui.container.cardlayout.WCardMainBorderLayout; |
||||
import com.fr.stable.ArrayUtils; |
||||
|
||||
/** |
||||
* 该model保存当前选择的组件和剪切版信息 |
||||
*/ |
||||
public class SelectionModel { |
||||
//被粘贴组件在所选组件位置处往下、往右各错开20像素。执行多次粘贴时,在上一次粘贴的位置处错开20像素。
|
||||
private static final int DELTA_X_Y = 20; //粘贴时候的偏移距离
|
||||
private static final int BORDER_PROPORTION = 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()) { |
||||
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(), |
||||
CLIP_BOARD, |
||||
rec.x + rec.width / 2, |
||||
rec.y + BORDER_PROPORTION); |
||||
} else { |
||||
Rectangle rec = selection.getRelativeBounds(); |
||||
//自适应布局
|
||||
FormSelectionUtils.paste2Container(designer, designer.getRootComponent(), |
||||
CLIP_BOARD, |
||||
rec.x + rec.width / 2, |
||||
rec.y + BORDER_PROPORTION); |
||||
} |
||||
} else { |
||||
//绝对布局
|
||||
//编辑器外面还有两层容器,使用designer.getRootComponent()获取到的是编辑器中层的容器,不是编辑器表层
|
||||
//当前选择的就是编辑器表层
|
||||
FormSelectionUtils.paste2Container(designer, (XLayoutContainer) selection.getSelectedCreator(), |
||||
CLIP_BOARD, |
||||
DELTA_X_Y, |
||||
DELTA_X_Y); |
||||
} |
||||
} else { |
||||
//cpt本地组件复用,编辑器就一层,是最底层,使用designer.getRootComponent()就可以获取到
|
||||
//使用selection.getSelectedCreator()也应该是可以获取到的。
|
||||
FormSelectionUtils.paste2Container(designer, designer.getRootComponent(), |
||||
CLIP_BOARD, |
||||
DELTA_X_Y, |
||||
DELTA_X_Y); |
||||
} |
||||
} |
||||
//已选
|
||||
else { |
||||
//获取到编辑器的表层容器(已选的组件的父容器就是表层容器)
|
||||
parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator()); |
||||
if (selection.getSelectedCreator().getParent() instanceof XWFitLayout) { |
||||
//自适应布局
|
||||
if (parent != null) { |
||||
Rectangle rec = selection.getRelativeBounds(); |
||||
FormSelectionUtils.paste2Container(designer, parent, CLIP_BOARD, rec.x + rec.width / 2, rec.y + |
||||
rec.height - BORDER_PROPORTION); |
||||
} |
||||
} else if (selection.getSelectedCreator().getParent() instanceof XWAbsoluteLayout) { |
||||
//绝对布局
|
||||
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 |
||||
* yaoh.wu 不应该通过判断是否是最底层容器来判断是否选择了组件 |
||||
* 而是应该判断选择的容器是否是编辑器的最表层容器,也就是点击空白地方选择的容器 |
||||
* 但是直接判断选择的容器是否是编辑器最表层类型又会引发拖动时选不上的情况, |
||||
* 因此通过判断父容器来实现 |
||||
* <p> |
||||
* 举例:frm组件复用 绝对布局情况下,不选择时有三层容器: |
||||
* 底层@see {@link com.fr.design.designer.creator.XWBorderLayout} |
||||
* 中层@see {@link XWFitLayout} |
||||
* 表层@see {@link com.fr.design.designer.creator.XWAbsoluteBodyLayout} |
||||
* <p> |
||||
* 但是编辑窗口的最外层其实是表层@see {@link com.fr.design.designer.creator.XWAbsoluteBodyLayout}, |
||||
* 其他两层不是靠添加组件就可以编辑的。 |
||||
*/ |
||||
public boolean hasSelectionComponent() { |
||||
if (designer.getClass().equals(FormDesigner.class)) { |
||||
//frm本地组件复用
|
||||
return selection.getSelectedCreator() != null |
||||
&& !( |
||||
//frm绝对布局编辑器
|
||||
selection.getSelectedCreator().getClass().equals(XWAbsoluteBodyLayout.class) |
||||
//Tab布局编辑器
|
||||
|| selection.getSelectedCreator().getClass().equals(XWCardMainBorderLayout.class) |
||||
|| selection.getSelectedCreator().getClass().equals(XWCardLayout.class) |
||||
|| selection.getSelectedCreator().getClass().equals(XWTabFitLayout.class) |
||||
//自适应布局编辑器
|
||||
|| selection.getSelectedCreator().getClass().equals(XWFitLayout.class) |
||||
); |
||||
} else { |
||||
//cpt本地组件复用,selection.getSelectedCreator().getParent()=@XWParameterLayout instanceof @XWAbsoluteLayout
|
||||
return selection.getSelectedCreator() != null && 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<XCreator> rebuildSelection) { |
||||
selection.setSelectedCreators(rebuildSelection); |
||||
fireCreatorSelected(); |
||||
} |
||||
} |
@ -1,246 +1,246 @@
|
||||
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) { |
||||
//绝对布局
|
||||
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); |
||||
return; |
||||
} else if (parent instanceof XWFitLayout) { |
||||
//相对布局
|
||||
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); |
||||
return; |
||||
} |
||||
Toolkit.getDefaultToolkit().beep(); |
||||
} |
||||
|
||||
/** |
||||
* 组件复用绝对布局获取粘贴组件位置 |
||||
* |
||||
* @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<String> nameSpace = new ArrayList<String>(); |
||||
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<String> 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<XCreator> newSelection = new ArrayList<XCreator>(); |
||||
List<Widget> widgetList = new ArrayList<Widget>(); |
||||
for (XCreator comp : designer.getSelectionModel().getSelection().getSelectedCreators()) { |
||||
widgetList.add(comp.toData()); |
||||
} |
||||
designer.getSelectionModel().setSelectedCreators( |
||||
rebuildSelection(designer.getRootComponent(), widgetList, newSelection)); |
||||
} |
||||
|
||||
public static ArrayList<XCreator> rebuildSelection(XCreator rootComponent, Widget[] selectWidgets) { |
||||
List<Widget> selectionWidget = new ArrayList<Widget>(); |
||||
if (selectWidgets != null) { |
||||
selectionWidget.addAll(Arrays.asList(selectWidgets)); |
||||
} |
||||
return FormSelectionUtils.rebuildSelection(rootComponent, selectionWidget, new ArrayList<XCreator>()); |
||||
} |
||||
|
||||
private static ArrayList<XCreator> rebuildSelection(XCreator rootComponent, List<Widget> selectionWidget, |
||||
ArrayList<XCreator> newSelection) { |
||||
FormSelectionUtils._rebuild(rootComponent, selectionWidget, newSelection); |
||||
if (newSelection.isEmpty()) { |
||||
newSelection.add(rootComponent); |
||||
} |
||||
return newSelection; |
||||
} |
||||
|
||||
private static void _rebuild(XCreator root, List<Widget> selectionWidget, List<XCreator> 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); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
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) { |
||||
//绝对布局
|
||||
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); |
||||
return; |
||||
} else if (parent instanceof XWFitLayout) { |
||||
//相对布局
|
||||
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); |
||||
return; |
||||
} |
||||
Toolkit.getDefaultToolkit().beep(); |
||||
} |
||||
|
||||
/** |
||||
* 组件复用绝对布局获取粘贴组件位置 |
||||
* |
||||
* @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<String> nameSpace = new ArrayList<String>(); |
||||
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<String> 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<XCreator> newSelection = new ArrayList<XCreator>(); |
||||
List<Widget> widgetList = new ArrayList<Widget>(); |
||||
for (XCreator comp : designer.getSelectionModel().getSelection().getSelectedCreators()) { |
||||
widgetList.add(comp.toData()); |
||||
} |
||||
designer.getSelectionModel().setSelectedCreators( |
||||
rebuildSelection(designer.getRootComponent(), widgetList, newSelection)); |
||||
} |
||||
|
||||
public static ArrayList<XCreator> rebuildSelection(XCreator rootComponent, Widget[] selectWidgets) { |
||||
List<Widget> selectionWidget = new ArrayList<Widget>(); |
||||
if (selectWidgets != null) { |
||||
selectionWidget.addAll(Arrays.asList(selectWidgets)); |
||||
} |
||||
return FormSelectionUtils.rebuildSelection(rootComponent, selectionWidget, new ArrayList<XCreator>()); |
||||
} |
||||
|
||||
private static ArrayList<XCreator> rebuildSelection(XCreator rootComponent, List<Widget> selectionWidget, |
||||
ArrayList<XCreator> newSelection) { |
||||
FormSelectionUtils._rebuild(rootComponent, selectionWidget, newSelection); |
||||
if (newSelection.isEmpty()) { |
||||
newSelection.add(rootComponent); |
||||
} |
||||
return newSelection; |
||||
} |
||||
|
||||
private static void _rebuild(XCreator root, List<Widget> selectionWidget, List<XCreator> 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); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue