forked from fanruan/design
Browse Source
* commit '46ff930d4b659a768a8043f00ac4676b3a521df3': 无任务 调整代码通过pmd 无任务 调整代码 无任务 代码调整 无任务,调整代码 无任务,调整代码 无任务,调整代码 无任务 调整代码 无任务代码调整 tab 间组件复用 tab 文件间复用 FRM组件复用,文件间相互复制,遗留:自适应to绝对会因大小超出而不能复制 代码调整 rename frm本地组件复用 绝对布局,遗留:重命名问题master
superman
8 years ago
25 changed files with 7112 additions and 6729 deletions
@ -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; |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -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);
} |
||||
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); |
||||
} |
@ -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<String> 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();
} |
||||
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<String> 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(); |
||||
|
||||
} |
@ -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<JComponent> dbcomponents) { |
||||
for (JComponent jcomponent : dbcomponents) { |
||||
jcomponent.setDoubleBuffered(true); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 禁止双缓冲状态,并将初始状态为启动双缓冲的组件保存到dbcomponents中 |
||||
*/ |
||||
public static void disableBuffer(Component comp, ArrayList<JComponent> 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<JComponent> dbcomponents) { |
||||
for (JComponent jcomponent : dbcomponents) { |
||||
jcomponent.setDoubleBuffered(true); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 禁止双缓冲状态,并将初始状态为启动双缓冲的组件保存到dbcomponents中 |
||||
*/ |
||||
public static void disableBuffer(Component comp, ArrayList<JComponent> 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; |
||||
} |
||||
} |
@ -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); |
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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(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(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<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); |
||||
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); |
||||
} |
||||
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); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -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); |
||||
} |
||||
} |
@ -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<XCreator> 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 不应该通过判断是否是最底层容器来判断是否选择了组件 |
||||
* 而是应该判断选择的容器是否是编辑器的最表层容器,也就是点击空白地方选择的容器 |
||||
* 但是直接判断选择的容器是否是编辑器最表层类型又会引发拖动时选不上的情况, |
||||
* 因此通过判断父容器来实现 |
||||
* <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() { |
||||
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<XCreator> rebuildSelection) { |
||||
selection.setSelectedCreators(rebuildSelection); |
||||
fireCreatorSelected(); |
||||
} |
||||
} |
@ -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<Component> 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<Component> 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; |
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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<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); |
||||
} 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<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); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -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)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 鼠标拖动事件(如果鼠标当前是<code>MOVE_CURSOR</code>状态则执行开始拖动的代码, |
||||
* 绘制一个<code>moveComponent</code>来跟随鼠标移动) |
||||
* @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<String> 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)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 鼠标拖动事件(如果鼠标当前是<code>MOVE_CURSOR</code>状态则执行开始拖动的代码, |
||||
* 绘制一个<code>moveComponent</code>来跟随鼠标移动) |
||||
* @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<String> 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; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -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<AbstractPropertyTable> 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<AbstractPropertyTable>(); |
||||
|
||||
//依次创建属性表、事件表、移动端表,再将它们整合到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<WidgetPropertyUIProvider> 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<AbstractPropertyTable> 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<AbstractPropertyTable>(); |
||||
|
||||
//依次创建属性表、事件表、移动端表,再将它们整合到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<WidgetPropertyUIProvider> 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; |
||||
} |
||||
} |
Loading…
Reference in new issue