diff --git a/designer_base/src/com/fr/design/actions/edit/CopyAction.java b/designer_base/src/com/fr/design/actions/edit/CopyAction.java index a9e6855524..d0579a5797 100644 --- a/designer_base/src/com/fr/design/actions/edit/CopyAction.java +++ b/designer_base/src/com/fr/design/actions/edit/CopyAction.java @@ -1,37 +1,35 @@ -/* - * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. - */ -package com.fr.design.actions.edit; - -import java.awt.event.KeyEvent; - -import javax.swing.KeyStroke; - -import com.fr.base.BaseUtils; -import com.fr.design.actions.TemplateComponentAction; -import com.fr.design.designer.TargetComponent; -import com.fr.general.Inter; - -/** - * Copy. - */ -public class CopyAction extends TemplateComponentAction { - public CopyAction(TargetComponent t) { - super(t); - - this.setName(Inter.getLocText("M_Edit-Copy")); - this.setMnemonic('C'); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); - this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK)); - } - - @Override - public boolean executeActionReturnUndoRecordNeeded() { - TargetComponent tc = getEditingComponent(); - if (tc != null) { - tc.copy(); - } - - return false; - } +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.edit; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.TemplateComponentAction; +import com.fr.design.designer.TargetComponent; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.event.KeyEvent; + +/** + * Copy. + */ +public class CopyAction extends TemplateComponentAction { + public CopyAction(TargetComponent t) { + super(t); + + this.setName(Inter.getLocText("M_Edit-Copy")); + this.setMnemonic('C'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); + this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK)); + } + + @Override + public boolean executeActionReturnUndoRecordNeeded() { + TargetComponent tc = getEditingComponent(); + if (tc != null) { + tc.copy(); + } + return false; + } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/beans/location/MoveUtils.java b/designer_base/src/com/fr/design/beans/location/MoveUtils.java index da5b0fa970..91a62ed5ff 100644 --- a/designer_base/src/com/fr/design/beans/location/MoveUtils.java +++ b/designer_base/src/com/fr/design/beans/location/MoveUtils.java @@ -18,7 +18,7 @@ public class MoveUtils { public static final int SORPTION_UNIT = 5; private static final int EQUIDISTANTLINE_UNIT = 4; - public static ArrayList equidistantLines = new ArrayList<>(); + private static ArrayList equidistantLines = new ArrayList<>(); private MoveUtils() { diff --git a/designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java b/designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java index a812238b72..3ba3d610da 100644 --- a/designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java +++ b/designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java @@ -1 +1,72 @@ -package com.fr.design.parameter; import com.fr.base.Parameter; import com.fr.base.parameter.ParameterUI; import com.fr.design.mainframe.AuthorityEditPane; import javax.swing.*; import java.awt.*; /** * 参数设计界面接口 */ public interface ParameterDesignerProvider { void addListener(ParaDefinitePane paraDefinitePane); Component createWrapper(); void setDesignHeight(int height); Dimension getDesignSize(); Dimension getPreferredSize(); void populate(ParameterUI p); void refreshAllNameWidgets(); void refresh4TableData(String oldName, String newName); void refreshParameter(ParaDefinitePane paraDefinitePane); boolean isWithQueryButton(); java.util.List getAllXCreatorNameList(); boolean isWithoutParaXCreator(Parameter[] ps); boolean isBlank(); ParameterUI getParaTarget(); boolean addingParameter2Editor(Parameter parameter, int index); boolean addingParameter2EditorWithQueryButton(Parameter parameter, int index); void addingAllParameter2Editor(Parameter[] parameterArray, int currentIndex); JPanel[] toolbarPanes4Form(); JComponent[] toolBarButton4Form(); void initBeforeUpEdit(); void populateParameterPropertyPane(ParaDefinitePane p); void initWidgetToolbarPane(); AuthorityEditPane getAuthorityEditPane(); JPanel getEastUpPane(); JPanel getEastDownPane(); boolean isSupportAuthority(); void removeSelection(); ParameterBridge getParaComponent(); } \ No newline at end of file +package com.fr.design.parameter; + +import com.fr.base.Parameter; +import com.fr.base.parameter.ParameterUI; +import com.fr.design.mainframe.AuthorityEditPane; + +import javax.swing.*; +import java.awt.*; + + +/** + * 参数设计界面接口 + */ +public interface ParameterDesignerProvider { + + void addListener(ParaDefinitePane paraDefinitePane); + + Component createWrapper(); + + void setDesignHeight(int height); + + Dimension getDesignSize(); + + Dimension getPreferredSize(); + + void populate(ParameterUI p); + + void refreshAllNameWidgets(); + + void refresh4TableData(String oldName, String newName); + + void refreshParameter(ParaDefinitePane paraDefinitePane); + + boolean isWithQueryButton(); + + java.util.List getAllXCreatorNameList(); + + boolean isWithoutParaXCreator(Parameter[] ps); + + boolean isBlank(); + + ParameterUI getParaTarget(); + + boolean addingParameter2Editor(Parameter parameter, int index); + + boolean addingParameter2EditorWithQueryButton(Parameter parameter, int index); + + void addingAllParameter2Editor(Parameter[] parameterArray, int currentIndex); + + JPanel[] toolbarPanes4Form(); + + JComponent[] toolBarButton4Form(); + + void initBeforeUpEdit(); + + void populateParameterPropertyPane(ParaDefinitePane p); + + void initWidgetToolbarPane(); + + AuthorityEditPane getAuthorityEditPane(); + + JPanel getEastUpPane(); + + JPanel getEastDownPane(); + + boolean isSupportAuthority(); + + void removeSelection(); + + ParameterBridge getParaComponent(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/utils/ComponentUtils.java b/designer_base/src/com/fr/design/utils/ComponentUtils.java index 4f15323f78..1d93611386 100644 --- a/designer_base/src/com/fr/design/utils/ComponentUtils.java +++ b/designer_base/src/com/fr/design/utils/ComponentUtils.java @@ -1,151 +1,154 @@ -package com.fr.design.utils; - -import com.fr.general.ComparatorUtils; - -import javax.swing.*; -import java.awt.*; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; - -/** - * 工具类,提供常用的工具方法 - */ -public class ComponentUtils { - - public static boolean isComponentVisible(Component comp) { - if (!comp.isVisible() && !isRootComponent(comp)) { - return false; - } - Component parent = comp.getParent(); - - return parent == null || isComponentVisible(parent); - - } - - /** - * 获取component所在的容器的绝对位置 - */ - public static Rectangle getRelativeBounds(Component component) { - Rectangle bounds = new Rectangle(0, 0, component.getWidth(), component.getHeight()); - Container parent = component.getParent(); - - while (parent != null) { - bounds.x += component.getX(); - bounds.y += component.getY(); - component = parent; - parent = component.getParent(); - } - - return bounds; - } - - /** - * 恢复双缓冲状态,dbcomponents保存着初始状态为启动双缓冲的组件 - */ - public static void resetBuffer(ArrayList dbcomponents) { - for (JComponent jcomponent : dbcomponents) { - jcomponent.setDoubleBuffered(true); - } - } - - /** - * 禁止双缓冲状态,并将初始状态为启动双缓冲的组件保存到dbcomponents中 - */ - public static void disableBuffer(Component comp, ArrayList dbcomponents) { - if ((comp instanceof JComponent) && comp.isDoubleBuffered()) { - JComponent jcomponent = (JComponent) comp; - - dbcomponents.add(jcomponent); - jcomponent.setDoubleBuffered(false); - } - - if (comp instanceof Container) { - Container container = (Container) comp; - int count = container.getComponentCount(); - - if (count > 0) { - for (int i = 0; i < count; i++) { - Component component = container.getComponent(i); - - disableBuffer(component, dbcomponents); - } - } - } - } - - public static int indexOfComponent(Container container, Component target) { - int count = container.getComponentCount(); - - for (int i = 0; i < count; i++) { - Component child = container.getComponent(i); - - if (child == target) { - return i; - } - } - - return -1; - } - - /** - * 计算组件root相对于其顶层容器的可见区域 - */ - public static Rectangle computeVisibleRectRel2Root(Component root) { - Container container = findAncestorScrollPane(root); - - if (container == null) { - return getRelativeBounds(root); - } else { - // 如果是JScrollPane的子组件,需要计算其viewport与改组件的交叉的可见区域 - return getBoundsRel2Parent(root, container); - } - } - - /** - * 计算组件root相对于其顶层容器的可见区域 - */ - public static Rectangle computeVisibleRect(JComponent root) { - Rectangle root_bounds = ComponentUtils.getRelativeBounds(root); - Rectangle rect = computeVisibleRectRel2Root(root); - rect.x -= root_bounds.x; - rect.y -= root_bounds.y; - - return rect; - } - - private static Rectangle getBoundsRel2Parent(Component child, Container parent) { - Rectangle cRect = getRelativeBounds(child); - Rectangle pRect = getRelativeBounds(parent); - Rectangle bounds = new Rectangle(); - Rectangle2D.intersect(cRect, pRect, bounds); - - return bounds; - } - - public static Container findAncestorScrollPane(Component p) { - if ((p == null) || !(p instanceof Container)) { - return null; - } - - Container c = p.getParent(); - - return findAncestorScrollPane(c); - } - - public static boolean isRootComponent(Component root) { - Container parent = root.getParent(); - return parent == null; - } - - public static boolean isChildOf(Component component, Class parent) { - Container container = component.getParent(); - if (container != null) { - if (ComparatorUtils.equals(container.getClass(), parent)) { - return true; - } else { - return isChildOf(container, parent); - } - } - return false; - } +package com.fr.design.utils; + +import com.fr.general.ComparatorUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; + +/** + * 工具类,提供常用的工具方法 + */ +public class ComponentUtils { + + private ComponentUtils() { + } + + public static boolean isComponentVisible(Component comp) { + if (!comp.isVisible() && !isRootComponent(comp)) { + return false; + } + Component parent = comp.getParent(); + + return parent == null || isComponentVisible(parent); + + } + + /** + * 获取component所在的容器的绝对位置 + */ + public static Rectangle getRelativeBounds(Component component) { + Rectangle bounds = new Rectangle(0, 0, component.getWidth(), component.getHeight()); + Container parent = component.getParent(); + + while (parent != null) { + bounds.x += component.getX(); + bounds.y += component.getY(); + component = parent; + parent = component.getParent(); + } + + return bounds; + } + + /** + * 恢复双缓冲状态,dbcomponents保存着初始状态为启动双缓冲的组件 + */ + public static void resetBuffer(ArrayList dbcomponents) { + for (JComponent jcomponent : dbcomponents) { + jcomponent.setDoubleBuffered(true); + } + } + + /** + * 禁止双缓冲状态,并将初始状态为启动双缓冲的组件保存到dbcomponents中 + */ + public static void disableBuffer(Component comp, ArrayList dbcomponents) { + if ((comp instanceof JComponent) && comp.isDoubleBuffered()) { + JComponent jcomponent = (JComponent) comp; + + dbcomponents.add(jcomponent); + jcomponent.setDoubleBuffered(false); + } + + if (comp instanceof Container) { + Container container = (Container) comp; + int count = container.getComponentCount(); + + if (count > 0) { + for (int i = 0; i < count; i++) { + Component component = container.getComponent(i); + + disableBuffer(component, dbcomponents); + } + } + } + } + + public static int indexOfComponent(Container container, Component target) { + int count = container.getComponentCount(); + + for (int i = 0; i < count; i++) { + Component child = container.getComponent(i); + + if (child.equals(target)) { + return i; + } + } + + return -1; + } + + /** + * 计算组件root相对于其顶层容器的可见区域 + */ + public static Rectangle computeVisibleRectRel2Root(Component root) { + Container container = findAncestorScrollPane(root); + + if (container == null) { + return getRelativeBounds(root); + } else { + // 如果是JScrollPane的子组件,需要计算其viewport与改组件的交叉的可见区域 + return getBoundsRel2Parent(root, container); + } + } + + /** + * 计算组件root相对于其顶层容器的可见区域 + */ + public static Rectangle computeVisibleRect(JComponent root) { + Rectangle rootBounds = ComponentUtils.getRelativeBounds(root); + Rectangle rect = computeVisibleRectRel2Root(root); + rect.x -= rootBounds.x; + rect.y -= rootBounds.y; + + return rect; + } + + private static Rectangle getBoundsRel2Parent(Component child, Container parent) { + Rectangle cRect = getRelativeBounds(child); + Rectangle pRect = getRelativeBounds(parent); + Rectangle bounds = new Rectangle(); + Rectangle2D.intersect(cRect, pRect, bounds); + + return bounds; + } + + public static Container findAncestorScrollPane(Component p) { + if ((p == null) || !(p instanceof Container)) { + return null; + } + + Container c = p.getParent(); + + return findAncestorScrollPane(c); + } + + public static boolean isRootComponent(Component root) { + Container parent = root.getParent(); + return parent == null; + } + + public static boolean isChildOf(Component component, Class parent) { + Container container = component.getParent(); + if (container != null) { + if (ComparatorUtils.equals(container.getClass(), parent)) { + return true; + } else { + return isChildOf(container, parent); + } + } + return false; + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java index e814c7892e..c087d78fef 100644 --- a/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java +++ b/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java @@ -1,94 +1,94 @@ -package com.fr.design.designer.beans; - -import com.fr.design.beans.GroupModel; -import com.fr.design.designer.creator.XCreator; - -/** - * 该接口是LayoutManager的BeanInfo类。标准Java平台没有提供布局管理器的BeanInfo类, - * 对于界面设计工具来说还需一些特殊的行为。 - * - * @since 6.5.3 - */ -public interface LayoutAdapter { - - /** - * 在添加组件状态时,当鼠标移动到某个容器上方时,如果该容器有布局管理器,则会调用该布局 - * 管理适配器的accept来决定当前位置是否可以放置,并提供特殊的标识,比如红色区域标识。比 - * 如在BorderLayout中,如果某个方位已经放置了组件,则此时应该返回false标识该区域不可以 - * 放置。 - * - * @param creator 组件 - * @param x 添加的位置x,该位置是相对于container的 - * @param y 添加的位置y,该位置是相对于container的 - * @return 是否可以放置 - */ - boolean accept(XCreator creator, int x, int y); - - /** - * 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适,如果不合适,就需要重新fix一下 - * - * @param creator 组件 - */ - void fix(XCreator creator); - - /** - * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 - * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 - * - * @param creator 被添加的新组件 - * @param x 添加的位置x,该位置是相对于container的 - * @param y 添加的位置y,该位置是相对于container的 - * @return 是否添加成功,成功返回true,否则false - */ - boolean addBean(XCreator creator, int x, int y); - - /** - * 返回该布局管理适配器的Painter,为容器提供放置位置的标识。 - */ - HoverPainter getPainter(); - - /** - * 显示parent的字组件child,解决CardLayout中显示某个非显示组件的特殊情况 - * - * @param child 组件 - */ - void showComponent(XCreator child); - - void addNextComponent(XCreator dragged); - - /** - * 组件叠放顺序前插入 - * - * @param target 目标组件 - * @param added 插入组件 - */ - void addBefore(XCreator target, XCreator added); - - /** - * 组件叠放顺序后插入 - * - * @param target 目标组件 - * @param added 放置组件 - */ - void addAfter(XCreator target, XCreator added); - - /** - * 能否放置更多组件 - * - * @return 能则返回true - */ - boolean canAcceptMoreComponent(); - - ConstraintsGroupModel getLayoutConstraints(XCreator creator); - - GroupModel getLayoutProperties(); - - /** - * 删除组件 - * - * @param creator 组件 - * @param initWidth 组件之前宽度 - * @param initHeight 组件之前高度 - */ - void removeBean(XCreator creator, int initWidth, int initHeight); +package com.fr.design.designer.beans; + +import com.fr.design.beans.GroupModel; +import com.fr.design.designer.creator.XCreator; + +/** + * 该接口是LayoutManager的BeanInfo类。标准Java平台没有提供布局管理器的BeanInfo类, + * 对于界面设计工具来说还需一些特殊的行为。 + * + * @since 6.5.3 + */ +public interface LayoutAdapter { + + /** + * 在添加组件状态时,当鼠标移动到某个容器上方时,如果该容器有布局管理器,则会调用该布局 + * 管理适配器的accept来决定当前位置是否可以放置,并提供特殊的标识,比如红色区域标识。比 + * 如在BorderLayout中,如果某个方位已经放置了组件,则此时应该返回false标识该区域不可以 + * 放置。 + * + * @param creator 组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否可以放置 + */ + boolean accept(XCreator creator, int x, int y); + + /** + * 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适,如果不合适,就需要重新fix一下 + * + * @param creator 组件 + */ + void fix(XCreator creator); + + /** + * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 + * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 + * + * @param creator 被添加的新组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否添加成功,成功返回true,否则false + */ + boolean addBean(XCreator creator, int x, int y); + + /** + * 返回该布局管理适配器的Painter,为容器提供放置位置的标识。 + */ + HoverPainter getPainter(); + + /** + * 显示parent的字组件child,解决CardLayout中显示某个非显示组件的特殊情况 + * + * @param child 组件 + */ + void showComponent(XCreator child); + + void addNextComponent(XCreator dragged); + + /** + * 组件叠放顺序前插入 + * + * @param target 目标组件 + * @param added 插入组件 + */ + void addBefore(XCreator target, XCreator added); + + /** + * 组件叠放顺序后插入 + * + * @param target 目标组件 + * @param added 放置组件 + */ + void addAfter(XCreator target, XCreator added); + + /** + * 能否放置更多组件 + * + * @return 能则返回true + */ + boolean canAcceptMoreComponent(); + + ConstraintsGroupModel getLayoutConstraints(XCreator creator); + + GroupModel getLayoutProperties(); + + /** + * 删除组件 + * + * @param creator 组件 + * @param initWidth 组件之前宽度 + * @param initHeight 组件之前高度 + */ + void removeBean(XCreator creator, int initWidth, int initHeight); } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java b/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java index de36cde9b0..23686f651a 100644 --- a/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java +++ b/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java @@ -1,31 +1,30 @@ -package com.fr.design.designer.beans.actions; - -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; - -import javax.swing.KeyStroke; - -import com.fr.base.BaseUtils; -import com.fr.general.Inter; -import com.fr.design.mainframe.FormDesigner; - -public class CopyAction extends FormEditAction { - - public CopyAction(FormDesigner t) { - super(t); - this.setName(Inter.getLocText("M_Edit-Copy")); - this.setMnemonic('C'); - this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); - this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK)); - } - - @Override - public boolean executeActionReturnUndoRecordNeeded() { - FormDesigner tc = getEditingComponent(); - if (tc != null) { - tc.copy(); - } - return false; - } - +package com.fr.design.designer.beans.actions; + +import com.fr.base.BaseUtils; +import com.fr.design.mainframe.FormDesigner; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +public class CopyAction extends FormEditAction { + + public CopyAction(FormDesigner t) { + super(t); + this.setName(Inter.getLocText("M_Edit-Copy")); + this.setMnemonic('C'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); + this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK)); + } + + @Override + public boolean executeActionReturnUndoRecordNeeded() { + FormDesigner tc = getEditingComponent(); + if (tc != null) { + tc.copy(); + } + return false; + } + } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java index 54d6abab42..493dd02aa2 100644 --- a/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java +++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java @@ -1,189 +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 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; - } +package com.fr.design.designer.beans.adapters.layout; + +import com.fr.design.beans.GroupModel; +import com.fr.design.designer.beans.ConstraintsGroupModel; +import com.fr.design.designer.beans.HoverPainter; +import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.beans.painters.NullPainter; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWidgetCreator; +import com.fr.design.utils.ComponentUtils; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.general.ComparatorUtils; + +import java.awt.*; + +public abstract class AbstractLayoutAdapter implements LayoutAdapter { + + protected XLayoutContainer container; + protected LayoutManager layout; + + public AbstractLayoutAdapter(XLayoutContainer container) { + this.container = container; + this.layout = container.getLayout(); + } + + /** + * 是否使用控件备份大小 + * + * @param xCreator 控件 + * @return 所在容器相同,且支持备份的话返回true + */ + public boolean whetherUseBackupSize(XCreator xCreator) { + Class clazz = container.getClass(); + Class bkClazz = null; + if (xCreator.getBackupParent() != null) { + bkClazz = xCreator.getBackupParent().getClass(); + } + return ComparatorUtils.equals(bkClazz, clazz) + && supportBackupSize(); + } + + /** + * 是否支持用备份大小 + * + * @return 否 + */ + public boolean supportBackupSize() { + return false; + } + + /** + * 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适,如果不合适,就需要重新fix一下 + * + * @param creator 组件 + */ + public void fix(XCreator creator) { + } + + /** + * 显示parent的字组件child,解决CardLayout中显示某个非显示组件的特殊情况 + * + * @param child 组件 + */ + @Override + public void showComponent(XCreator child) { + child.setVisible(true); + } + + /** + * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 + * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 + * + * @param creator 被添加的新组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否添加成功,成功返回true,否则false + */ + @Override + public boolean addBean(XCreator creator, int x, int y) { + if (!accept(creator, x, y)) { + return false; + } + addComp(creator, x, y); + ((XWidgetCreator) creator).recalculateChildrenSize(); + return true; + } + + /** + * 删除组件 + * + * @param creator 组件 + * @param creatorWidth + * @param creatorHeight + */ + public void removeBean(XCreator creator, int creatorWidth, int creatorHeight) { + delete(creator, creatorWidth, creatorHeight); + } + + protected void delete(XCreator creator, int creatorWidth, int creatorHeight) { + } + + protected abstract void addComp(XCreator creator, int x, int y); + + /** + * 增加下一个组件 + * + * @param dragged 组件 + */ + @Override + public void addNextComponent(XCreator dragged) { + container.add(dragged); + LayoutUtils.layoutRootContainer(container); + } + + /** + * 目标控件位置插入组件 + * + * @param target 目标 + * @param added 增加组件 + */ + @Override + public void addBefore(XCreator target, XCreator added) { + int index = ComponentUtils.indexOfComponent(container, target); + + if (index == -1) { + container.add(added, 0); + } else { + container.add(added, index); + } + + LayoutUtils.layoutRootContainer(container); + } + + /** + * 插在目标组件后面 + * + * @param target 目标 + * @param added 增加组件 + */ + @Override + public void addAfter(XCreator target, XCreator added) { + int index = ComponentUtils.indexOfComponent(container, target); + + if (index == -1) { + container.add(added); + } else { + index++; + + if (index >= container.getComponentCount()) { + container.add(added); + } else { + container.add(added, index); + } + } + + LayoutUtils.layoutRootContainer(container); + } + + @Override + public HoverPainter getPainter() { + return new NullPainter(container); + } + + /** + * 是否能接收更多的组件 + * + * @return 能则返回true + */ + @Override + public boolean canAcceptMoreComponent() { + return true; + } + + @Override + public ConstraintsGroupModel getLayoutConstraints(XCreator creator) { + return null; + } + + @Override + public GroupModel getLayoutProperties() { + return null; + } + + + public XLayoutContainer getContainer() { + return this.container; + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java index 58c07b045d..b8a8e8ad19 100644 --- a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java +++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java @@ -1,363 +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 { - //这边计算得到的组件其实位置是正确的, - //因为传入的x和y已经加上了宽度或者高度的一半,再减去相同的宽度和高度的一半是没区别的, - // 例如高度为21,那么就是+10-10; - // 高度为20,那么就是+10-10; 没区别 - int w = creator.getWidth() / 2; - int h = creator.getHeight() / 2; - creatorX = x - w; - creatorY = y - h; - } - //frm 组件复用允许组件重叠 - //无须再判断和布局中其他控件重叠 - //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); - //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); - } +package com.fr.design.designer.beans.adapters.layout; + +import com.fr.design.beans.GroupModel; +import com.fr.design.designer.beans.ConstraintsGroupModel; +import com.fr.design.designer.beans.HoverPainter; +import com.fr.design.designer.beans.painters.FRAbsoluteLayoutPainter; +import com.fr.design.designer.creator.*; +import com.fr.design.designer.properties.BoundsGroupModel; +import com.fr.design.designer.properties.FRAbsoluteLayoutPropertiesGroupModel; +import com.fr.design.utils.ComponentUtils; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.form.ui.container.WAbsoluteLayout; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; + +import java.awt.*; + +public class FRAbsoluteLayoutAdapter extends FRBodyLayoutAdapter { + //是不是添加到父容器上 + private boolean isAdd2ParentLayout = false; + private HoverPainter painter; + + public FRAbsoluteLayoutAdapter(XLayoutContainer container) { + super(container); + painter = new FRAbsoluteLayoutPainter(container); + initMinSize(); + } + + private void initMinSize() { + XWAbsoluteLayout layout = (XWAbsoluteLayout) container; + minWidth = layout.getActualMinWidth(); + minHeight = layout.getActualMinHeight(); + actualVal = layout.getAcualInterval(); + margin = layout.toData().getMargin(); + } + + @Override + public HoverPainter getPainter() { + return painter; + } + + /** + * 是否能在指定位置添加组件 + * + * @param creator 组件 + * @param x 坐标x + * @param y 坐标y + * @return 能则返回true + */ + //这个地方的逻辑非常复杂, + // 1.当前绝对布局是不可编辑且是最外层,那么其他控件添加在它周围, + // 2.当前绝对布局是不可编辑且不是最外层,那么控件不可添加,(嵌套) + // 3.当前绝对布局可编辑,那么控件添加 + @Override + public boolean accept(XCreator creator, int x, int y) { + Component comp = container.getComponentAt(x, y); + //布局控件要先判断是不是可编辑 + //可以编辑,按原有逻辑判断 + //不可编辑,当成一整个控件处理 + if (comp == null) { + return false; + } + //参数面板内的组件不允许拖往绝对布局中 + if (creator.getParent() != null && ((XCreator) creator.getParent()).acceptType(XWParameterLayout.class)) { + Rectangle rec = creator.getBounds(); + rec.y = creator.getParent().getHeight() - rec.height; + creator.setBounds(rec); + return false; + } + //判断组件能不能拖入绝对布局 + if (!creator.canEnterIntoAbsolutePane()) { + return false; + } + XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator) comp).getTopLayout(); + if (topLayout != null) { + if (topLayout.isEditable()) { + return topLayoutAccept(creator, x, y); + } + //绝对布局嵌套,处于内层,不可编辑,不添加,topLayout只能获取到最外层可编辑的布局 + else if (((XLayoutContainer) topLayout.getParent()).acceptType(XWAbsoluteLayout.class)) { + return false; + } else { + return acceptWidget(x, y); + } + } else { + FRLogger.getLogger().error("top layout is null!"); + } + + return false; + } + + //topLayout假如可以编辑的话就往里面添加组件 + private boolean topLayoutAccept(XCreator creator, int x, int y) { + //允许组件重叠,可以不判断有没有和当前控件重叠 + //先计算当前控件的位置 + int creatorX, creatorY; + if (XCreatorUtils.getParentXLayoutContainer(creator) != null) { + Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator); + creatorX = creatorRectangle.x; + creatorY = creatorRectangle.y; + } else { + //这边计算得到的组件其实位置是正确的, + //因为传入的x和y已经加上了宽度或者高度的一半,再减去相同的宽度和高度的一半是没区别的, + // 例如高度为21,那么就是+10-10; + // 高度为20,那么就是+10-10; 没区别 + int w = creator.getWidth() / 2; + int h = creator.getHeight() / 2; + creatorX = x - w; + creatorY = y - h; + } + if (creatorX < 0 || creatorX + creator.getWidth() > container.getWidth()) { + return false; + } + if (creatorY < 0 || creatorY + creator.getHeight() > container.getHeight()) { + return false; + } + return x >= 0 && y >= 0 && creator.getHeight() <= container.getHeight() + && creator.getWidth() <= container.getWidth(); + } + + /** + * 判断是否鼠标在组件的三等分区域,如果组件在布局管理器中间,上下左右都可能会三等分 + * + * @param parentComp 鼠标所在区域的组件 + * @param x 坐标x + * @param y 坐标y + * @return 是则返回true + */ + public boolean isTrisectionArea(Component parentComp, int x, int y) { + XCreator creator = (XCreator) parentComp; + trisectAreaDirect = 0; + if (container.getComponentCount() <= 1) { + return false; + } + int maxWidth = parentComp.getWidth(); + int maxHeight = parentComp.getHeight(); + int xL = parentComp.getX(); + int yL = parentComp.getY(); + // 组件宽高的十分之一和默认值取大 + int minRangeWidth = Math.max(maxWidth / BORDER_PROPORTION, DEFAULT_AREA_LENGTH); + int minRangeHeight = Math.max(maxHeight / BORDER_PROPORTION, DEFAULT_AREA_LENGTH); + if (y < yL + minRangeHeight) { + // 在组件上侧三等分 + trisectAreaDirect = COMP_TOP; + } else if (y > yL + maxHeight - minRangeHeight) { + // 在组件下侧三等分 + trisectAreaDirect = COMP_BOTTOM; + } else if (x < xL + minRangeWidth) { + // 在组件左侧三等分 + trisectAreaDirect = COMP_LEFT; + } else if (x > xL + maxWidth - minRangeWidth) { + // 在组件右侧三等分 + trisectAreaDirect = COMP_RIGHT; + } + // tab布局的边界特殊处理,不进行三等分 + if (!creator.getTargetChildrenList().isEmpty()) { + return false; + } + + return !ComparatorUtils.equals(trisectAreaDirect, 0); + } + + //当前绝对布局不可编辑,就当成一个控件,组件添加在周围 + private boolean acceptWidget(int x, int y) { + isFindRelatedComps = false; + //拖入组件判断时,先判断是否为交叉点区域,其次三等分区域,再次平分区域 + Component comp = container.getComponentAt(x, y); + //如果当前处于边缘地带, 那么就把他贴到父容器上 + XLayoutContainer parent = container.findNearestFit(); + container = parent != null ? parent : container; + isAdd2ParentLayout = true; + + int componentHeight = comp.getHeight(); + int componentWidth = comp.getWidth(); + //上半部分高度 + int upHeight = (int) (componentHeight * TOP_HALF) + comp.getY(); + //下半部分高度 + int downHeight = (int) (componentHeight * BOTTOM_HALF) + comp.getY(); + + if (isCrossPointArea(comp, x, y)) { + return canAcceptWhileCrossPoint(comp, x, y); + } + + if (isTrisectionArea(comp, x, y)) { + return canAcceptWhileTrisection(comp, x, y); + } + + boolean horizonValid = componentWidth >= minWidth * 2 + actualVal; + boolean verticalValid = componentHeight >= minHeight * 2 + actualVal; + return y > upHeight && y < downHeight ? horizonValid : verticalValid; + } + + /** + * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 + * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 + * + * @param creator 被添加的新组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否添加成功,成功返回true,否则false + */ + @Override + public boolean addBean(XCreator creator, int x, int y) { + Rectangle rect = ComponentUtils.getRelativeBounds(container); + + int posX = x + rect.x; + int posY = y + rect.y; + if (!accept(creator, x, y)) { + return false; + } + addComp(creator, posX, posY); + ((XWidgetCreator) creator).recalculateChildrenSize(); + return true; + } + + @Override + protected void addComp(XCreator creator, int x, int y) { + if (!isAdd2ParentLayout) { + Rectangle r = ComponentUtils.getRelativeBounds(container); + x = x - r.x; + y = y - r.y; + if (XCreatorUtils.getParentXLayoutContainer(creator) != null) { + + Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator); + x = creatorRectangle.x - r.x; + y = creatorRectangle.y - r.y; + } else { + int w = creator.getWidth() / 2; + int h = creator.getHeight() / 2; + x = x - w; + y = y - h; + } + fix(creator, x, y); + + if (creator.hasTitleStyle()) { + addParentCreator(creator); + } else { + container.add(creator, creator.toData().getWidgetName()); + } + XWAbsoluteLayout layout = (XWAbsoluteLayout) container; + layout.updateBoundsWidget(creator); + updateCreatorBackBound(); + LayoutUtils.layoutRootContainer(container); + } else { + fixAbsolute(creator, x, y); + if (creator.shouldScaleCreator() || creator.hasTitleStyle()) { + addParentCreator(creator); + } else { + container.add(creator, creator.toData().getWidgetName()); + } + XWFitLayout layout = (XWFitLayout) container; + // 更新对应的BoundsWidget + layout.updateBoundsWidget(); + updateCreatorBackBound(); + } + } + + private void updateCreatorBackBound() { + for (int i = 0, size = container.getComponentCount(); i < size; i++) { + XCreator creator = (XCreator) container.getComponent(i); + creator.updateChildBound(minHeight); + creator.setBackupBound(creator.getBounds()); + } + } + + private void addParentCreator(XCreator child) { + XLayoutContainer parentPanel = child.initCreatorWrapper(child.getHeight()); + container.add(parentPanel, child.toData().getWidgetName()); + } + + /** + * 新拖入组件时,计算调整其他关联组件位置大小 + * + * @param child 新拖入的组件 + * @param x 鼠标所在x坐标 + * @param y 鼠标所在y坐标 + */ + private void fixAbsolute(XCreator child, int x, int y) { + Component parentComp = container.getComponentAt(x, y); + if (container.getComponentCount() == 0) { + child.setLocation(0, 0); + child.setSize(parentComp.getWidth(), parentComp.getHeight()); + } else if (isCrossPointArea(parentComp, x, y)) { + //交叉区域插入组件时,根据具体位置进行上下或者左右或者相邻三个组件的位置大小插入 + fixCrossPointArea(parentComp, child, x, y); + //TODO 尽量不要出现这种写法吧?if else条件要么互斥,要么多个if判断return,不要在一条if else语句里面return吧? + return; + } else if (isTrisectionArea(parentComp, x, y)) { + // 在边界三等分区域,就不再和组件二等分了 + fixTrisect(parentComp, child, x, y); + return; + } else { + fixHalve(parentComp, child, x, y); + } + } + + /** + * 组件拖拽后调整大小 + * + * @param creator 组件 + */ + @Override + public void fix(XCreator creator) { + WAbsoluteLayout wabs = (WAbsoluteLayout) container.toData(); + fix(creator, creator.getX(), creator.getY()); + wabs.setBounds(creator.toData(), creator.getBounds()); + + XWAbsoluteLayout layout = (XWAbsoluteLayout) container; + layout.updateBoundsWidget(creator); + } + + /** + * 调整组件大小到合适尺寸位置 + * + * @param creator 组件 + * @param x 坐标x + * @param y 坐标y + */ + public void fix(XCreator creator, int x, int y) { + int height = creator.getHeight(); + int width = creator.getWidth(); + if (x < 0) { + width += x; + x = 0; + } else if (x + creator.getWidth() > container.getWidth()) { + width = container.getWidth() - x; + } + + if (y < 0) { + height += y; + y = 0; + } else if (y + creator.getHeight() > container.getHeight()) { + height = container.getHeight() - y; + } + + creator.setBounds(x, y, width, height); + } + + @Override + public ConstraintsGroupModel getLayoutConstraints(XCreator creator) { + return new BoundsGroupModel((XWAbsoluteLayout) container, creator); + } + + @Override + public GroupModel getLayoutProperties() { + XWAbsoluteLayout xwAbsoluteLayout = (XWAbsoluteLayout) container; + return new FRAbsoluteLayoutPropertiesGroupModel(xwAbsoluteLayout); + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java index 417e95c35c..e31ee6a5d3 100644 --- a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java +++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java @@ -1,1199 +1,1189 @@ -/** - * - */ -package com.fr.design.designer.beans.adapters.layout; - -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; - -import com.fr.design.beans.GroupModel; -import com.fr.design.designer.beans.ConstraintsGroupModel; -import com.fr.design.designer.beans.HoverPainter; -import com.fr.design.designer.beans.painters.FRFitLayoutPainter; -import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWFitLayout; -import com.fr.design.designer.creator.cardlayout.XWCardLayout; -import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; -import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; -import com.fr.design.designer.properties.FRFitLayoutConstraints; -import com.fr.design.designer.properties.FRFitLayoutPropertiesGroupModel; -import com.fr.design.file.HistoryTemplateListPane; -import com.fr.design.mainframe.JForm; -import com.fr.design.utils.ComponentUtils; -import com.fr.form.ui.LayoutBorderStyle; -import com.fr.form.ui.container.WLayout; -import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; -import com.fr.form.ui.widget.BoundsWidget; -import com.fr.general.ComparatorUtils; - -/** - * 自适应布局的容器适配器 - * - * @author jim - * @date 2014-6-24 - */ -public class FRFitLayoutAdapter extends FRBodyLayoutAdapter { - - public static final String WIDGETPANEICONPATH = "/com/fr/web/images/form/resources/layout_absolute.png"; - private static final int DEPENDING_SCOPE = 3; - private HoverPainter painter; - //区分拖拽和编辑宽高 - private boolean isEdit; - - public boolean isEdit() { - return isEdit; - } - - public void setEdit(boolean edit) { - isEdit = edit; - } - - /** - * 构造函数 - * - * @param container XWFitLayout容器 - */ - public FRFitLayoutAdapter(XLayoutContainer container) { - super(container); - painter = new FRFitLayoutPainter(container); - initMinSize(); - } - - private void initMinSize() { - XWFitLayout layout = (XWFitLayout) container; - minWidth = layout.getActualMinWidth(); - minHeight = layout.getActualMinHeight(); - actualVal = layout.getAcualInterval(); - margin = layout.toData().getMargin(); - } - - @Override - public HoverPainter getPainter() { - return painter; - } - - /** - * 返回布局自身属性,方便一些特有设置在layout刷新时处理 - */ - @Override - public GroupModel getLayoutProperties() { - XWFitLayout xfl = (XWFitLayout) container; - return new FRFitLayoutPropertiesGroupModel(xfl); - } - - /** - * 添加组件 - * - * @param child 待添加的组件 - * @param x 坐标x - * @param y 坐标y - */ - @Override - public void addComp(XCreator child, int x, int y) { - fix(child, x, y); - if (child.shouldScaleCreator() || child.hasTitleStyle()) { - addParentCreator(child); - } else { - container.add(child, child.toData().getWidgetName()); - } - XWFitLayout layout = (XWFitLayout) container; - // 更新对应的BoundsWidget - layout.updateBoundsWidget(); - updateCreatorBackBound(); - } - - public void updateCreatorBackBound() { - for (int i = 0, size = container.getComponentCount(); i < size; i++) { - XCreator creator = (XCreator) container.getComponent(i); - creator.updateChildBound(minHeight); - creator.setBackupBound(creator.getBounds()); - } - } - - - private void addParentCreator(XCreator child) { - XLayoutContainer parentPanel = child.initCreatorWrapper(minHeight); - container.add(parentPanel, child.toData().getWidgetName()); - } - - /** - * 能否对应位置放置当前组件 - * - * @param creator 组件 - * @param x 添加的位置x,该位置是相对于container的 - * @param y 添加的位置y,该位置是相对于container的 - * @return 是否可以放置 - */ - @Override - public boolean accept(XCreator creator, int x, int y) { - // 计算是否能拖入鼠标区域时,会用到fix 的方法 - isFindRelatedComps = false; - //拖入组件判断时,先判断是否为交叉点区域,其次三等分区域,再次平分区域 - Component comp = container.getComponentAt(x, y); - if (checkInterval(comp)) { - return false; - } - //如果当前处于边缘地带, 那么就把他贴到父容器上 - boolean isMatchEdge = matchEdge(x, y); - - int componentHeight = comp.getHeight(); - int componentWidth = comp.getWidth(); - //上半部分高度 - int upHeight = (int) (componentHeight * TOP_HALF) + comp.getY(); - //下半部分高度 - int downHeight = (int) (componentHeight * BOTTOM_HALF) + comp.getY(); - - //布局控件要先判断是不是可编辑 - XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator) comp).getTopLayout(); - if (topLayout != null && !isMatchEdge && !topLayout.isEditable()) { - return false; - } - - if (isCrossPointArea(comp, x, y)) { - return canAcceptWhileCrossPoint(comp, x, y); - } - - if (isTrisectionArea(comp, x, y)) { - return canAcceptWhileTrisection(comp, x, y); - } - - boolean horizonValid = componentWidth >= minWidth * 2 + actualVal; - boolean verticalValid = componentHeight >= minHeight * 2 + actualVal; - return y > upHeight && y < downHeight ? horizonValid : verticalValid; - } - - // 间隔区域 - private boolean checkInterval(Component comp) { - return container.getComponentCount() > 0 && comp == container; - } - - /** - * 是否在组件边缘 - * - * @param x 横坐标 - * @param y 纵坐标 - * @return 是否在组件边缘 - */ - public boolean matchEdge(int x, int y) { - if (intersectsEdge(x, y, container)) { - //寻找最近的fit, 在边缘地段添加的控件, 将其送给该fit - XLayoutContainer parent = container.findNearestFit(); - container = parent != null ? parent : container; - return true; - } - return false; - } - - /** - * 是否在组件边缘 - * - * @param x 横坐标 - * @param y 纵坐标 - * @param container 参照组件 - * @return 是否在组件边缘 - */ - //是否包含于边缘地段, 按顺序上, 下, 左, 右检测 - public boolean intersectsEdge(int x, int y, XLayoutContainer container) { - int containerX = container.getX(); - int containerY = container.getY(); - int containerWidth = container.getWidth(); - int containerHeight = container.getHeight(); - - // 当前坐标点 - Rectangle currentXY = new Rectangle(x, y, 1, 1); - // 上边缘 - Rectangle upEdge = new Rectangle(containerX, containerY, containerWidth, BORDER_PROPORTION); - if (upEdge.intersects(currentXY)) { - return true; - } - - int bottomY = containerY + containerHeight - BORDER_PROPORTION; - // 下边缘 - Rectangle bottomEdge = new Rectangle(containerX, bottomY, containerWidth, BORDER_PROPORTION); - if (bottomEdge.intersects(currentXY)) { - return true; - } - - //左右边缘的高度 -10*2 是为了不和上下边缘重合 - int verticalHeight = containerHeight - BORDER_PROPORTION * 2; - int leftY = containerY + BORDER_PROPORTION; - // 左边缘 - Rectangle leftEdge = new Rectangle(containerX, leftY, BORDER_PROPORTION, verticalHeight); - if (leftEdge.intersects(currentXY)) { - return true; - } - - int rightY = containerY + BORDER_PROPORTION; - int rightX = containerX + containerWidth - BORDER_PROPORTION; - // 右边缘 - Rectangle rightEdge = new Rectangle(rightX, rightY, BORDER_PROPORTION, verticalHeight); - return rightEdge.intersects(currentXY); - } - - /** - * 交叉点区域时,能否对应位置放入组件 - */ - protected boolean canAcceptWhileCrossPoint(Component comp, int x, int y) { - return super.canAcceptWhileCrossPoint(comp, x, y); - } - - protected boolean canAcceptWhileTrisection(Component comp, int x, int y) { - return super.canAcceptWhileTrisection(comp, x, y); - } - - /** - * 判断是否鼠标在组件的三等分区域,如果组件在布局管理器中间,上下左右都可能会三等分 - * - * @param parentComp 鼠标所在区域的组件 - * @param x 坐标x - * @param y 坐标y - * @return 是则返回true - */ - public boolean isTrisectionArea(Component parentComp, int x, int y) { - return super.isTrisectionArea(parentComp, x, y); - } - - /** - * 是否为组件交叉点区域 或者是相邻三组建中间点 - * - * @param currentComp 当前组件 - * @param x 坐标x - * @param y 坐标y - * @return 是则返回true - */ - public boolean isCrossPointArea(Component currentComp, int x, int y) { - return super.isCrossPointArea(currentComp, x, y); - } - - protected void initCompsList() { - super.initCompsList(); - } - - protected void clearCompsList() { - super.clearCompsList(); - } - - protected Rectangle getLayoutBound(XWCardMainBorderLayout mainLayout) { - return mainLayout.getBounds(); - } - - private Rectangle adjustBackupBound(Rectangle backupBound, XWCardMainBorderLayout mainLayout) { - // 参数界面高度对纵坐标产生的影响 - JForm jform = (JForm) (HistoryTemplateListPane.getInstance().getCurrentEditingTemplate()); - if (jform.getFormDesign().getParaComponent() != null) { - backupBound.y -= jform.getFormDesign().getParaHeight(); - } - - Rectangle rec = getLayoutBound(mainLayout); - // XWTabLayout里面的横纵坐标收到外层XWCardMainBorderLayout的横纵坐标影响 - // 减掉之后可以按照它原来的逻辑执行 - backupBound.x -= rec.x; - backupBound.y -= rec.y; - XWCardLayout cardLayout = mainLayout.getCardPart(); - LayoutBorderStyle style = cardLayout.toData().getBorderStyle(); - // 当tab布局为标题样式时,才需要处理标题栏高度产生的影响 - if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) { - backupBound.y -= WCardMainBorderLayout.TAB_HEIGHT; - } - return backupBound; - } - - /** - * 拖拽控件边框后,根据控件的大小尺寸,进行相关组件的调整 - * - * @param creator 组件 - */ - @Override - public void fix(XCreator creator) { - //拖拽组件原大小、位置 - Rectangle backupBound = creator.getBackupBound(); - backupBound.x -= container.getX(); - backupBound.y -= container.getY(); - //当前拖拽组件的位置 - int x = creator.getX(); - int y = creator.getY(); - - // 获取容器所有内部组件横坐标 - int[] posXs = container.getHors(); - // 获取容器所有内部组件纵坐标 - int[] posYs = container.getVeris(); - - XLayoutContainer outerLayout = container.getOuterLayout(); - if (!ComparatorUtils.equals(outerLayout, container.getBackupParent())) { - XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout) outerLayout; - backupBound = adjustBackupBound(backupBound, mainLayout); - } - - //拖拽组件拖拽以后的大小 - int w = creator.getWidth(); - int h = creator.getHeight(); - initCompsList(); - creator.setBounds(backupBound); - int difference = 0; - if (x != backupBound.x) { - dealLeft(backupBound, x, posXs, difference, creator); - } else if (w != backupBound.width) { - dealRight(backupBound, x, w, posXs, difference, creator); - } else if (y != backupBound.y) { - dealTop(backupBound, y, posYs, difference, creator); - } else if (h != backupBound.height) { - dealButtom(backupBound, y, h, posYs, difference, creator); - } - clearCompsList(); - XWFitLayout layout = (XWFitLayout) container; - layout.updateBoundsWidget(); // 更新对应的BoundsWidget - updateCreatorBackBound(); - } - - /** - * 拖拽控件边框后,根据控件的大小尺寸,进行相关组件的调整 - * - * @param backupBound 边界备份 - * @param bounds 组件边界 - * @param xCreator 组件 - * @param row 选中的行 - * @param difference 偏移量 - */ - public void calculateBounds(Rectangle backupBound, Rectangle bounds, XCreator xCreator, int row, int difference) { - Rectangle rc = new Rectangle(0, 0, 0, 0); - XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xCreator); - if (parent != null) { - Rectangle rec = ComponentUtils.getRelativeBounds(parent); - rc.x = rec.x; - rc.y = rec.y; - } - int x = backupBound.x - rc.x, y = backupBound.y - rc.y; - //处理左右延伸 - switch (row) { - case 0: - if (backupBound.width + backupBound.x == container.getWidth() - margin.getRight() + rc.x) { - x += difference; - } - break; - case 1: - if (backupBound.y + backupBound.height == container.getHeight() - margin.getBottom() + rc.y) { - y += difference; - } - break; - } - bounds.setLocation(x, y); - xCreator.setBackupBound(backupBound); - xCreator.setBounds(bounds); - this.fix(xCreator); - } - - private void dealLeft(Rectangle backupBound, int x, int[] posXs, int difference, XCreator creator) { - if (backupBound.x == margin.getLeft()) { - return; - } - x = adjustCoordinateByDependingLine(x, posXs); - difference = x - backupBound.x; - dealDirectionAtLeft(backupBound, difference, creator); - } - - private void dealRight(Rectangle backupBound, int x, int w, int[] posXs, int difference, XCreator creator) { - if (backupBound.width + backupBound.x == container.getWidth() - margin.getRight()) { - return; - } - w = adjustDiffByDependingLine(x, posXs, w); - difference = w - backupBound.width; //拖拽长度 - dealDirectionAtRight(backupBound, difference, creator); - } - - private void dealTop(Rectangle backupBound, int y, int[] posYs, int difference, XCreator creator) { - if (backupBound.y == margin.getTop()) { - return; - } - y = adjustCoordinateByDependingLine(y, posYs); - difference = y - backupBound.y; - dealDirectionAtTop(backupBound, difference, creator); - } - - private void dealButtom(Rectangle backupBound, int y, int h, int[] posYs, int difference, XCreator creator) { - if (backupBound.y + backupBound.height == container.getHeight() - margin.getBottom()) { - return; - } - h = adjustDiffByDependingLine(y, posYs, h); - difference = h - backupBound.height; - dealDirectionABottom(backupBound, difference, creator); - } - - // 根据需要依附的位置调整拖拽的坐标值 - private int adjustCoordinateByDependingLine(int coordinate, int[] coordinates) { - if (!isEdit) { - for (int i = 0; i < coordinates.length; i++) { - if (coordinate == coordinates[i]) { - continue; - } - if (coordinate > coordinates[i] - DEPENDING_SCOPE && coordinate < coordinates[i] + DEPENDING_SCOPE) { - coordinate = coordinates[i]; - break; - } - } - } - return coordinate; - } - - // 根据需要依附的位置调整拖拽的距离 - private int adjustDiffByDependingLine(int coordinate, int[] coordinates, int diff) { - if (!isEdit) { - for (int i = 0; i < coordinates.length; i++) { - if (coordinate + diff > coordinates[i] - DEPENDING_SCOPE && coordinate + diff < coordinates[i] + DEPENDING_SCOPE) { - diff = coordinates[i] - coordinate; - break; - } - } - } - return diff; - } - - // 左侧边框拉伸,循环找出对齐的两侧控件 - private void dealDirectionAtLeft(Rectangle backupBound, int difference, Component creator) { - rightComps.add(creator); - Component rightComp = null; - int leftx = backupBound.x - DEFAULT_AREA_LENGTH - actualVal; - // 取左侧边框右面的组件x值 - int rightx = backupBound.x + DEFAULT_AREA_LENGTH; - Component leftComp = container.getLeftComp(backupBound.x, backupBound.y); - leftComps.add(leftComp); - //先找上侧对齐时(y相等)的左右两边组件 - int ry = backupBound.y; - int ly = leftComp.getY(); - int min = margin.getTop(); - int max = container.getHeight() - margin.getBottom(); - while (ry >= min && ly >= min) { - if (ry == ly) { - break; - } else { - if (ry > ly) { - rightComp = container.getTopComp(rightx, ry); - ry = rightComp.getY(); - rightComps.add(rightComp); - } else { - leftComp = container.getTopComp(leftx, ly); - ly = leftComp.getY(); - leftComps.add(leftComp); - } - } - } - // 下侧对齐时(y+h相等)两边组件 - ry = backupBound.y + backupBound.height; - ly = leftComps.get(0).getY() + leftComps.get(0).getHeight(); - while (ry <= max && ly <= max) { - if (ry == ly) { - break; - } else { - if (ry > ly) { - leftComp = container.getComponentAt(leftx, ly + DEFAULT_AREA_LENGTH + actualVal); - ly = leftComp.getY() + leftComp.getHeight(); - leftComps.add(leftComp); - } else { - rightComp = container.getComponentAt(rightx, ry + DEFAULT_AREA_LENGTH + actualVal); - ry = rightComp.getY() + rightComp.getHeight(); - rightComps.add(rightComp); - } - } - } - dealHorDirection(backupBound.x, difference); - } - - // 右侧边框拉伸,循环找出对齐的两侧控件 - private void dealDirectionAtRight(Rectangle backupBound, int difference, Component creator) { - leftComps.add(creator); - Component leftComp = null; - int leftx = backupBound.x + backupBound.width - DEFAULT_AREA_LENGTH; - // 取右侧边框右面的组件x值 - int rightx = backupBound.x + backupBound.width + DEFAULT_AREA_LENGTH + actualVal; - Component rightComp = container.getRightComp(backupBound.x, backupBound.y, backupBound.width); - rightComps.add(rightComp); - int ly = backupBound.y, ry = rightComp.getY(); - int min = margin.getTop(); - int max = container.getHeight() - margin.getBottom(); - while (ry >= min && ly >= min) { - if (ry == ly) { - break; - } else { - if (ry > ly) { - rightComp = container.getTopComp(rightx, ry); - ry = rightComp.getY(); - rightComps.add(rightComp); - } else { - leftComp = container.getTopComp(leftx, ly); - ly = leftComp.getY(); - leftComps.add(leftComp); - } - } - } - ly = backupBound.y + backupBound.height; - ry = rightComps.get(0).getY() + rightComps.get(0).getHeight(); - while (ry <= max && ly <= max) { - if (ry == ly) { - break; - } else { - if (ry > ly) { - leftComp = container.getComponentAt(leftx, ly + DEFAULT_AREA_LENGTH + actualVal); - ly = leftComp.getY() + leftComp.getHeight(); - leftComps.add(leftComp); - } else { - rightComp = container.getComponentAt(rightx, ry + DEFAULT_AREA_LENGTH + actualVal); - ry = rightComp.getY() + rightComp.getHeight(); - rightComps.add(rightComp); - } - } - } - dealHorDirection(backupBound.x + backupBound.width + actualVal, difference); - } - - /** - * 水平方向上拉伸边框的处理 - */ - private void dealHorDirection(int objx, int difference) { - if (difference > 0) { - difference = Math.min(getMinWidth(rightComps) - minWidth, difference); - } else { - difference = Math.max(difference, minWidth - getMinWidth(leftComps)); - } - //重新计算左右两侧组件size、point - if (CalculateLefttRelatComponent(difference)) { - CalculateRightRelatComponent(objx + difference, -difference); - } - } - - // 上侧边框拉伸,循环找出对齐的两侧控件 - private void dealDirectionAtTop(Rectangle backupBound, int difference, Component creator) { - downComps.add(creator); - // 取上侧边框上面的组件用的y值 - int topy = backupBound.y - DEFAULT_AREA_LENGTH - actualVal; - // 上侧边框下面的组件y值 - int bottomy = backupBound.y + DEFAULT_AREA_LENGTH; - Component topComp = container.getTopComp(backupBound.x, backupBound.y); - upComps.add(topComp); - Component bottomComp = null; - int min = margin.getLeft(); - int max = container.getWidth() - margin.getRight(); - //先找左侧侧对齐时(x相等)的上下两边组件 - int ux = topComp.getX(); - int dx = backupBound.x; - while (ux >= min && dx >= min) { - if (ux == dx) { - break; - } else { - if (ux < dx) { - bottomComp = container.getLeftComp(dx, bottomy); - dx = bottomComp.getX(); - downComps.add(bottomComp); - } else { - topComp = container.getLeftComp(ux, topy); - ux = topComp.getX(); - upComps.add(topComp); - } - } - } - // 右侧对齐时(x+w相等)两边组件 - ux = upComps.get(0).getX() + upComps.get(0).getWidth(); - dx = backupBound.x + backupBound.width; - while (ux <= max && dx <= max) { - if (ux == dx) { - break; - } else { - if (ux < dx) { - topComp = container.getComponentAt(ux + DEFAULT_AREA_LENGTH + actualVal, topy); - ux = topComp.getX() + topComp.getWidth(); - upComps.add(topComp); - } else { - bottomComp = container.getComponentAt(dx + DEFAULT_AREA_LENGTH + actualVal, bottomy); - dx = bottomComp.getX() + bottomComp.getWidth(); - downComps.add(bottomComp); - } - } - } - - dealVertiDirection(backupBound.y, difference); - } - - // 下侧边框拉伸,循环找出对齐的两侧控件 - private void dealDirectionABottom(Rectangle backupBound, int difference, Component creator) { - upComps.add(creator); - Component topComp = null; - Component bottomComp = container.getBottomComp(backupBound.x, backupBound.y, backupBound.height); - // 下侧边框下面的组件y坐标 - int bottomy = backupBound.y + backupBound.height + DEFAULT_AREA_LENGTH + actualVal; - // 取下侧边框上面的组件用的y值 - int topy = backupBound.y + backupBound.height - DEFAULT_AREA_LENGTH; - downComps.add(bottomComp); - int dx = bottomComp.getX(); - int ux = backupBound.x; - int min = margin.getLeft(); - int max = container.getWidth() - margin.getRight(); - while (ux >= min && dx >= min) { - if (ux == dx) { - break; - } else { - if (ux < dx) { - bottomComp = container.getLeftComp(dx, bottomy); - dx = bottomComp.getX(); - downComps.add(bottomComp); - } else { - topComp = container.getLeftComp(ux, topy); - ux = topComp.getX(); - upComps.add(topComp); - } - } - } - dx = downComps.get(0).getX() + downComps.get(0).getWidth(); - ux = backupBound.x + backupBound.width; - while (ux <= max && dx <= max) { - if (ux == dx) { - break; - } else { - if (ux < dx) { - topComp = container.getComponentAt(ux + DEFAULT_AREA_LENGTH + actualVal, topy); - ux = topComp.getX() + topComp.getWidth(); - upComps.add(topComp); - } else { - bottomComp = container.getComponentAt(dx + DEFAULT_AREA_LENGTH + actualVal, bottomy); - dx = bottomComp.getX() + bottomComp.getWidth(); - downComps.add(bottomComp); - } - } - } - dealVertiDirection(backupBound.y + backupBound.height + actualVal, difference); - } - - /** - * 垂直方向上拉伸边框的处理 - */ - private void dealVertiDirection(int objY, int difference) { - if (difference > 0) { - difference = Math.min(getMinHeight(downComps) - minHeight, difference); - } else { - difference = Math.max(difference, minHeight - getMinHeight(upComps)); - } - //重新计算上下两侧组件size、point - if (CalculateUpRelatComponent(difference)) { - CalculateDownRelatComponent(objY + difference, -difference); - } - ; - } - - /** - * 新拖入组件时,计算调整其他关联组件位置大小 - * - * @param child 新拖入的组件 - * @param x 鼠标所在x坐标 - * @param y 鼠标所在y坐标 - */ - public void fix(XCreator child, int x, int y) { - Component parentComp = container.getComponentAt(x, y); - if (container.getComponentCount() == 0) { - child.setLocation(0, 0); - child.setSize(parentComp.getWidth(), parentComp.getHeight()); - } else if (isCrossPointArea(parentComp, x, y)) { - //交叉区域插入组件时,根据具体位置进行上下或者左右或者相邻三个组件的位置大小插入 - fixCrossPointArea(parentComp, child, x, y); - return; - } else if (isTrisectionArea(parentComp, x, y)) { - // 在边界三等分区域,就不再和组件二等分了 - fixTrisect(parentComp, child, x, y); - return; - } else { - fixHalve(parentComp, child, x, y); - } - } - - /** - * 平分,正常情况拖入组件时,按照上1/4区域、下1/4区域为上下平分,中左侧1/2区域、中右侧1/2区域为左右平分 - */ - protected void fixHalve(Component currentComp, XCreator child, int x, int y) { - super.fixHalve(currentComp, child, x, y); - } - - /** - * 组件交叉区域进行插入时,调整受到变动的其他组件,之前是交叉区域插入也按照三等分逻辑,后面测试中发现有bug,改为和bi一样的鼠标所在侧平分 - * 默认左上角、右下角区域是垂直方向插入组件 - * 右上角和左下角是水平方向插入组件,这样避免田字块时重复 - */ - protected void fixCrossPointArea(Component currentComp, XCreator child, int x, int y) { - super.fixCrossPointArea(currentComp, child, x, y); - } - - /** - * 三等分区域时,调整相关联的组件 - * - * @param currentComp 鼠标所在组件 - * @param child 待插入组件 - */ - protected void fixTrisect(Component currentComp, XCreator child, int x, int y) { - super.fixTrisect(currentComp, child, x, y); - } - - /** - * 删除组件或者重新拖动时,其它组件重新计算位置大小 - */ - protected void delete(XCreator creator, int creatorWidth, int creatorHeight) { - int x = creator.getX(); - int y = creator.getY(); - recalculateChildrenSize(x, y, creatorWidth, creatorHeight); - } - - /** - * 重新计算内部组件大小 - * - * @param x 坐标x - * @param y 坐标y - * @param creatorWidth 删除的组件之前所在布局的宽度 - * @param creatorHeight 删除的组件之前所在布局的高度 - */ - public void recalculateChildrenSize(int x, int y, int creatorWidth, int creatorHeight) { - if (container.getComponentCount() == 0) { - return; - } else { - initCompsList(); - int width = creatorWidth; - int height = creatorHeight; - calculateRelatedComponent(x, y, width, height); - if (!rightComps.isEmpty() && getAllHeight(rightComps) == height) { - CalculateRightRelatComponent(x, width + actualVal); - } else if (!leftComps.isEmpty() && getAllHeight(leftComps) == height) { - CalculateLefttRelatComponent(width + actualVal); - } else if (!downComps.isEmpty() && getAllWidth(downComps) == width) { - CalculateDownRelatComponent(y, height + actualVal); - } else if (!upComps.isEmpty() && getAllWidth(upComps) == width) { - CalculateUpRelatComponent(height + actualVal); - } else { - // 由于布局三等分的存在,可能会出现删除组件时,找不到关联的组件填充,此时特殊处理 - calculateNoRelatedComponent(x, y, width, height); - } - } - clearCompsList(); - } - - /** - * 四侧边框都没有对齐的,此时每侧有且只有一个方向不对齐 - * 比如右侧不对齐,那么必然右上或右下没对齐,不会同时不对齐,否则不会出现此情况 - * 正常删除是右左下上优先原则,这边目前只调整右侧以至填充完整, - * 右侧不对齐时的组件先上下微调,再向左侧填充。 - */ - private void calculateNoRelatedComponent(int x, int y, int width, int height) { - // 只有最后一个组件了,直接删除 - if (container.getComponentCount() <= 1) { - return; - } - // 删除当前组件时,由于没有刚好边框对齐的其他组件,这时候需要调整的组件 - Component rightComp = container.getRightComp(x, y, width); - if (rightComp == null) { - return; - } - - int ry = rightComp.getY(); - clearCompsList(); - initCompsList(); - Rectangle rec = new Rectangle(x, y, width, height); - if (ry != y) { - calculateNoRelatedWhileRightTop(rec, rightComp); - } else { - calculateNoRelatedWhileRightBott(rec, rightComp); - } - - } - - private void calculateNoRelatedWhileRightTop(Rectangle bound, Component rcomp) { - if (rcomp == null) { - return; - } - - int ry = rcomp.getY(); - int rh = rcomp.getHeight(); - int rw = rcomp.getWidth(); - int dh = bound.y - ry - actualVal; - // 没法缩小高度 - if (dh < minHeight) { - // 没法缩小时则拉伸rcomp的上边框 - dealDirectionAtTop(rcomp.getBounds(), dh + actualVal, rcomp); - //调整的时候可能有组件达到最小高度,判断下 - if (rcomp.getY() != bound.y) { - clearCompsList(); - initCompsList(); - dealDirectionAtTop(rcomp.getBounds(), bound.y - rcomp.getY() - minHeight - actualVal, rcomp); - ry = rcomp.getY(); - int rx = rcomp.getX(); - rcomp.setBounds(rx, ry, rw, minHeight); - recalculateChildrenSize(rx, bound.y, rw, rh - dh - actualVal); - recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); - return; - } - } else { - // 右侧控件底部对齐 - if (rh + ry == bound.y + bound.height) { - rcomp.setSize(rw, dh); - bound.width += rw; - bound.width += actualVal; - } else { - recalculateChildrenSize(bound.x, ry + rh + actualVal, bound.width, bound.height + bound.y - rh - ry - actualVal); - recalculateChildrenSize(bound.x, bound.y, bound.width, ry + rh - bound.y); - return; - } - } - recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); - } - - private void calculateNoRelatedWhileRightBott(Rectangle bound, Component rcomp) { - rcomp = container.getBottomRightComp(bound.x, bound.y, bound.height, bound.width); - int ry = rcomp.getY(); - int rh = rcomp.getHeight(); - int rw = rcomp.getWidth(); - int dh = ry + rh - bound.y - bound.height - actualVal; - if (dh < minHeight) { - dealDirectionABottom(rcomp.getBounds(), -dh - actualVal, rcomp); - //调整的时候可能有组件达到最小高度,判断下 - if (rcomp.getHeight() + ry != bound.y + bound.height) { - clearCompsList(); - initCompsList(); - dh = ry + rcomp.getHeight() - bound.y - bound.height - actualVal; - dealDirectionABottom(rcomp.getBounds(), minHeight - dh, rcomp); - rh = rcomp.getHeight(); - int rx = rcomp.getX(); - rcomp.setBounds(rx, bound.y + bound.height + actualVal, rw, minHeight); - recalculateChildrenSize(rx, ry, rw, rh - minHeight - actualVal); - recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); - return; - } - } else { - if (ry == bound.y) { - rcomp.setBounds(rcomp.getX(), bound.y + bound.height + actualVal, rw, dh); - bound.width += rw; - bound.width += actualVal; - } else { - recalculateChildrenSize(bound.x, bound.y, bound.width, ry - bound.y - actualVal); - recalculateChildrenSize(bound.x, ry, bound.width, bound.height - ry + bound.y); - return; - } - } - recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); - } - - private int getMinWidth(List comps) { - if (comps.isEmpty()) { - return 0; - } - int minWidth = container.getWidth() - margin.getLeft() - margin.getRight(); - for (int i = 0, size = comps.size(); i < size; i++) { - minWidth = minWidth > comps.get(i).getWidth() ? comps.get(i).getWidth() : minWidth; - } - return minWidth; - } - - private int getMinHeight(List comps) { - if (comps.isEmpty()) { - return 0; - } - int minH = container.getHeight() - margin.getTop() - margin.getBottom(); - for (int i = 0, size = comps.size(); i < size; i++) { - minH = minH > comps.get(i).getHeight() ? comps.get(i).getHeight() : minH; - } - return minH; - } - - // 删除时计算待删除组件上下侧的组件是否何其对齐 - private int getAllHeight(List comps) { - int allHeight = 0; - if (comps.isEmpty()) { - return allHeight; - } - int n = comps.size(); - for (int i = 0; i < n; i++) { - allHeight += comps.get(i).getHeight(); - } - allHeight += (n - 1) * actualVal; - return allHeight; - } - - private int getAllWidth(List comps) { - int allWidth = 0; - if (comps.isEmpty()) { - return allWidth; - } - int n = comps.size(); - for (int i = 0; i < n; i++) { - allWidth += comps.get(i).getWidth(); - } - allWidth += (n - 1) * actualVal; - return allWidth; - } - - /** - * 获取有哪些相关联的组件 - */ - protected void calculateRelatedComponent(int objX, int objY, int objWidth, int objHeight) { - int count = container.getComponentCount(); - for (int i = 0; i < count; i++) { - Component relatComp = container.getComponent(i); - int rx = relatComp.getX(); - int ry = relatComp.getY(); - int rwidth = relatComp.getWidth(); - int rheight = relatComp.getHeight(); - int verti = ry - objY; - int hori = rx - objX; - boolean isHori = verti >= 0 && objHeight >= (rheight + verti); - boolean isVerti = hori >= 0 && objWidth >= (rwidth + hori); - if (isHori && (objX + objWidth + actualVal) == rx) { - rightComps.add(relatComp); - } else if (isHori && objX == (rx + rwidth + actualVal)) { - leftComps.add(relatComp); - } else if (isVerti && (objY + objHeight + actualVal) == ry) { - downComps.add(relatComp); - } else if (isVerti && objY == (ry + rheight + actualVal)) { - upComps.add(relatComp); - } - } - } - - /** - * 拖拽组件时遍历某一侧组件得到该侧组件能够缩放的最小宽度,tab布局最小宽度 = 内部组件数 * 单个组件最小宽度 - * - * @param list 某一侧组件的集合 如:leftComps - * @return int 最小宽度 - */ - private int getCompsMinWidth(List list) { - return getMaxCompsNum(list, true) * WLayout.MIN_WIDTH; - } - - /** - * 拖拽组件遍历某一侧得到该侧组件能够缩放的最小高度,tab布局最小高度 = 内部组件数 * 单个组件最小高度 + 标题高度 - * - * @param list 某一侧组件集合 - * @return int 最小高度 - */ - private int getCompsMinHeight(List list) { - for (int i = 0; i < list.size(); i++) { - XCreator creator = (XCreator) list.get(i); - ArrayList childrenList = creator.getTargetChildrenList(); - if (!childrenList.isEmpty()) { - return getMaxCompsNum(list, false) * WLayout.MIN_HEIGHT + WCardMainBorderLayout.TAB_HEIGHT; - } - } - return WLayout.MIN_HEIGHT; - } - - /** - * 根据子组件的横(纵)坐标获取某一侧组件的最大内部组件数 - * - * @param list 某一侧组件集合 - * @param isHor 是否以横坐标为准 - * @return int 最大内部组件数 - */ - private int getMaxCompsNum(List list, boolean isHor) { - int maxCompNums = 1; - for (int i = 0, size = list.size(); i < size; i++) { - XCreator creator = (XCreator) list.get(i); - ArrayList childrenList = creator.getTargetChildrenList(); - int count = childrenList.size(); - if (count > 0) { - for (int j = 0; j < count; j++) { - XWTabFitLayout tabLayout = (XWTabFitLayout) childrenList.get(j); - int[] positions = isHor ? tabLayout.getHors(true) : tabLayout.getVeris(true); - int compNums = positions.length - 1; - maxCompNums = Math.max(compNums, maxCompNums); - } - } - } - return maxCompNums; - } - - /** - * 根据偏移量缩放内部组件大小,(tab布局用到) - * - * @param creator tab布局 - * @param offset 偏移量 - * @param isHor 是否为横向拖拽 - */ - private void adjustCompsSize(XCreator creator, int offset, boolean isHor) { - ArrayList childrenList = creator.getTargetChildrenList(); - int size = childrenList.size(); - if (size > 0) { - for (int j = 0; j < size; j++) { - XWTabFitLayout tabLayout = (XWTabFitLayout) childrenList.get(j); - tabLayout.setBackupBound(tabLayout.getBounds()); - int refSize = isHor ? tabLayout.getWidth() : tabLayout.getHeight(); - double percent = (double) offset / refSize; - if (percent < 0 && !tabLayout.canReduce(percent)) { - return; - } - setAdjustedSize(tabLayout, offset, isHor); - for (int m = 0; m < tabLayout.getComponentCount(); m++) { - XCreator childCreator = tabLayout.getXCreator(m); - BoundsWidget wgt = tabLayout.toData().getBoundsWidget(childCreator.toData()); - wgt.setBounds(tabLayout.getComponent(m).getBounds()); - } - adjustCreatorsSize(percent, tabLayout, isHor); - } - - } - } - - // 纵向拖拽,先将tab布局的高度设置为拖拽后的实际高度 - private void setAdjustedHeight(XWTabFitLayout tabLayout, int offset) { - tabLayout.setSize(tabLayout.getWidth(), tabLayout.getHeight() + offset); - } - - // 横向拖拽,先将tab布局的宽度设置为拖拽后的实际宽度 - private void setAdjustedSize(XWTabFitLayout tabLayout, int offset, boolean isHor) { - if (offset < 0) { - // 缩放时需要备份原tab布局宽高 - tabLayout.setReferDim(new Dimension(tabLayout.getWidth(), tabLayout.getHeight())); - } - if (isHor) { - tabLayout.setSize(tabLayout.getWidth() + offset, tabLayout.getHeight()); - return; - } - setAdjustedHeight(tabLayout, offset); - } - - // 按照拖拽偏移量,对tab布局进行缩放 - private void adjustCreatorsSize(double percent, XWTabFitLayout tabLayout, boolean isHor) { - if (isHor) { - tabLayout.adjustCreatorsWidth(percent); - return; - } - tabLayout.adjustCreatorsHeight(percent); - } - - - /** - * 删除或拉伸控件右边框 调整右侧组件位置大小 - * - * @param objX 调整后的坐标x - * @param objWidth 调整后的宽度 - */ - protected void CalculateRightRelatComponent(int objX, int objWidth) { - int count = rightComps.size(); - for (int i = 0; i < count; i++) { - XCreator creator = (XCreator) rightComps.get(i); - adjustCompsSize(creator, objWidth, true); - int ry = creator.getY(); - int rwidth = creator.getWidth(); - int rheight = creator.getHeight(); - creator.setLocation(objX, ry); - creator.setSize(rwidth + objWidth, rheight); - } - } - - /** - * 实际拖拽偏移量是否超出了可调整的宽度范围 - * - * @param offset 实际偏移量 - * @return boolean 是否超出调整范围 - */ - private boolean isBeyondAdjustWidthScope(int offset) { - boolean isBeyondScope = false; - isBeyondScope = offset < 0 ? isBeyondWidthScope(offset, leftComps) : isBeyondWidthScope(offset, rightComps); - return isBeyondScope; - } - - // 实际拖拽偏移量是否超出某一侧的可调整宽度 - private boolean isBeyondWidthScope(int offset, List compsList) { - int compMinWidth = getCompsMinWidth(compsList); - for (int i = 0; i < compsList.size(); i++) { - XCreator creator = (XCreator) compsList.get(i); - if (Math.abs(offset) > (creator.getWidth() - compMinWidth)) { - return true; - } - } - return false; - } - - /** - * 删除或拉伸控件左边框时 调整左侧的组件位置大小; - */ - protected boolean CalculateLefttRelatComponent(int objWidth) { - if (isBeyondAdjustWidthScope(objWidth)) { - return false; - } - int count = leftComps.size(); - for (int i = 0; i < count; i++) { - XCreator creator = (XCreator) leftComps.get(i); - adjustCompsSize(creator, objWidth, true); - int rwidth = creator.getWidth(); - int rheight = creator.getHeight(); - creator.setSize(rwidth + objWidth, rheight); - } - return true; - } - - /** - * 删除或拉伸下边框 调整下方的组件位置大小 - */ - protected void CalculateDownRelatComponent(int objY, int objHeight) { - int count = downComps.size(); - for (int i = 0; i < count; i++) { - XCreator creator = (XCreator) downComps.get(i); - adjustCompsSize(creator, objHeight, false); - int rx = creator.getX(); - int rwidth = creator.getWidth(); - int rheight = creator.getHeight(); - creator.setLocation(rx, objY); - creator.setSize(rwidth, rheight + objHeight); - } - } - - /** - * 实际拖拽偏移量是否超出了可调整的高度范围 - * - * @param offset 实际偏移量 - * @return boolean 是否超出调整范围 - */ - private boolean isBeyondAdjustHeightScope(int offset) { - boolean isBeyondScope = false; - isBeyondScope = offset < 0 ? isBeyondHeightScope(offset, upComps) : isBeyondHeightScope(offset, downComps); - return isBeyondScope; - } - - // 实际拖拽偏移量是否超出某一侧的可调整高度 - private boolean isBeyondHeightScope(int offset, List compsList) { - int minHeight = getCompsMinHeight(compsList); - for (int i = 0; i < compsList.size(); i++) { - XCreator creator = (XCreator) compsList.get(i); - if (Math.abs(offset) > (creator.getHeight() - minHeight)) { - return true; - } - } - return false; - } - - /** - * 删除或拉伸上边框 调整上方的组件位置大小 - */ - protected boolean CalculateUpRelatComponent(int objHeight) { - if (isBeyondAdjustHeightScope(objHeight)) { - return false; - } - int count = upComps.size(); - for (int i = 0; i < count; i++) { - XCreator creator = (XCreator) upComps.get(i); - adjustCompsSize(creator, objHeight, false); - int rwidth = creator.getWidth(); - int rheight = creator.getHeight(); - creator.setSize(rwidth, rheight + objHeight); - } - return true; - } - - /** - * 不调整,只计算位置 - * - * @return child的位置 - */ - public int[] getChildPosition(Component currentComp, XCreator child, int x, int y) { - return super.getChildPosition(currentComp, child, x, y); - } - - @Override - public ConstraintsGroupModel getLayoutConstraints(XCreator creator) { - return new FRFitLayoutConstraints((XWFitLayout) container, creator); - } +/** + * + */ +package com.fr.design.designer.beans.adapters.layout; + +import com.fr.design.beans.GroupModel; +import com.fr.design.designer.beans.ConstraintsGroupModel; +import com.fr.design.designer.beans.HoverPainter; +import com.fr.design.designer.beans.painters.FRFitLayoutPainter; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XCreatorUtils; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWFitLayout; +import com.fr.design.designer.creator.cardlayout.XWCardLayout; +import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; +import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; +import com.fr.design.designer.properties.FRFitLayoutConstraints; +import com.fr.design.designer.properties.FRFitLayoutPropertiesGroupModel; +import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.mainframe.JForm; +import com.fr.design.utils.ComponentUtils; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.container.WLayout; +import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; +import com.fr.form.ui.widget.BoundsWidget; +import com.fr.general.ComparatorUtils; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + * 自适应布局的容器适配器 + * + * @author jim + * @date 2014-6-24 + */ +public class FRFitLayoutAdapter extends FRBodyLayoutAdapter { + + public static final String WIDGETPANEICONPATH = "/com/fr/web/images/form/resources/layout_absolute.png"; + private static final int DEPENDING_SCOPE = 3; + private HoverPainter painter; + //区分拖拽和编辑宽高 + private boolean isEdit; + + public boolean isEdit() { + return isEdit; + } + + public void setEdit(boolean edit) { + isEdit = edit; + } + + /** + * 构造函数 + * + * @param container XWFitLayout容器 + */ + public FRFitLayoutAdapter(XLayoutContainer container) { + super(container); + painter = new FRFitLayoutPainter(container); + initMinSize(); + } + + private void initMinSize() { + XWFitLayout layout = (XWFitLayout) container; + minWidth = layout.getActualMinWidth(); + minHeight = layout.getActualMinHeight(); + actualVal = layout.getAcualInterval(); + margin = layout.toData().getMargin(); + } + + @Override + public HoverPainter getPainter() { + return painter; + } + + /** + * 返回布局自身属性,方便一些特有设置在layout刷新时处理 + */ + @Override + public GroupModel getLayoutProperties() { + XWFitLayout xfl = (XWFitLayout) container; + return new FRFitLayoutPropertiesGroupModel(xfl); + } + + /** + * 添加组件 + * + * @param child 待添加的组件 + * @param x 坐标x + * @param y 坐标y + */ + @Override + public void addComp(XCreator child, int x, int y) { + fix(child, x, y); + if (child.shouldScaleCreator() || child.hasTitleStyle()) { + addParentCreator(child); + } else { + container.add(child, child.toData().getWidgetName()); + } + XWFitLayout layout = (XWFitLayout) container; + // 更新对应的BoundsWidget + layout.updateBoundsWidget(); + updateCreatorBackBound(); + } + + public void updateCreatorBackBound() { + for (int i = 0, size = container.getComponentCount(); i < size; i++) { + XCreator creator = (XCreator) container.getComponent(i); + creator.updateChildBound(minHeight); + creator.setBackupBound(creator.getBounds()); + } + } + + + private void addParentCreator(XCreator child) { + XLayoutContainer parentPanel = child.initCreatorWrapper(minHeight); + container.add(parentPanel, child.toData().getWidgetName()); + } + + /** + * 能否对应位置放置当前组件 + * + * @param creator 组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否可以放置 + */ + @Override + public boolean accept(XCreator creator, int x, int y) { + // 计算是否能拖入鼠标区域时,会用到fix 的方法 + isFindRelatedComps = false; + //拖入组件判断时,先判断是否为交叉点区域,其次三等分区域,再次平分区域 + Component comp = container.getComponentAt(x, y); + if (checkInterval(comp)) { + return false; + } + //如果当前处于边缘地带, 那么就把他贴到父容器上 + boolean isMatchEdge = matchEdge(x, y); + + int componentHeight = comp.getHeight(); + int componentWidth = comp.getWidth(); + //上半部分高度 + int upHeight = (int) (componentHeight * TOP_HALF) + comp.getY(); + //下半部分高度 + int downHeight = (int) (componentHeight * BOTTOM_HALF) + comp.getY(); + + //布局控件要先判断是不是可编辑 + XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator) comp).getTopLayout(); + if (topLayout != null && !isMatchEdge && !topLayout.isEditable()) { + return false; + } + + if (isCrossPointArea(comp, x, y)) { + return canAcceptWhileCrossPoint(comp, x, y); + } + + if (isTrisectionArea(comp, x, y)) { + return canAcceptWhileTrisection(comp, x, y); + } + + boolean horizonValid = componentWidth >= minWidth * 2 + actualVal; + boolean verticalValid = componentHeight >= minHeight * 2 + actualVal; + return y > upHeight && y < downHeight ? horizonValid : verticalValid; + } + + // 间隔区域 + private boolean checkInterval(Component comp) { + return container.getComponentCount() > 0 && comp == container; + } + + /** + * 是否在组件边缘 + * + * @param x 横坐标 + * @param y 纵坐标 + * @return 是否在组件边缘 + */ + public boolean matchEdge(int x, int y) { + if (intersectsEdge(x, y, container)) { + //寻找最近的fit, 在边缘地段添加的控件, 将其送给该fit + XLayoutContainer parent = container.findNearestFit(); + container = parent != null ? parent : container; + return true; + } + return false; + } + + /** + * 是否在组件边缘 + * + * @param x 横坐标 + * @param y 纵坐标 + * @param container 参照组件 + * @return 是否在组件边缘 + */ + //是否包含于边缘地段, 按顺序上, 下, 左, 右检测 + public boolean intersectsEdge(int x, int y, XLayoutContainer container) { + int containerX = container.getX(); + int containerY = container.getY(); + int containerWidth = container.getWidth(); + int containerHeight = container.getHeight(); + + // 当前坐标点 + Rectangle currentXY = new Rectangle(x, y, 1, 1); + // 上边缘 + Rectangle upEdge = new Rectangle(containerX, containerY, containerWidth, BORDER_PROPORTION); + if (upEdge.intersects(currentXY)) { + return true; + } + + int bottomY = containerY + containerHeight - BORDER_PROPORTION; + // 下边缘 + Rectangle bottomEdge = new Rectangle(containerX, bottomY, containerWidth, BORDER_PROPORTION); + if (bottomEdge.intersects(currentXY)) { + return true; + } + + //左右边缘的高度 -10*2 是为了不和上下边缘重合 + int verticalHeight = containerHeight - BORDER_PROPORTION * 2; + int leftY = containerY + BORDER_PROPORTION; + // 左边缘 + Rectangle leftEdge = new Rectangle(containerX, leftY, BORDER_PROPORTION, verticalHeight); + if (leftEdge.intersects(currentXY)) { + return true; + } + + int rightY = containerY + BORDER_PROPORTION; + int rightX = containerX + containerWidth - BORDER_PROPORTION; + // 右边缘 + Rectangle rightEdge = new Rectangle(rightX, rightY, BORDER_PROPORTION, verticalHeight); + return rightEdge.intersects(currentXY); + } + + /** + * 交叉点区域时,能否对应位置放入组件 + */ + protected boolean canAcceptWhileCrossPoint(Component comp, int x, int y) { + return super.canAcceptWhileCrossPoint(comp, x, y); + } + + protected boolean canAcceptWhileTrisection(Component comp, int x, int y) { + return super.canAcceptWhileTrisection(comp, x, y); + } + + /** + * 判断是否鼠标在组件的三等分区域,如果组件在布局管理器中间,上下左右都可能会三等分 + * + * @param parentComp 鼠标所在区域的组件 + * @param x 坐标x + * @param y 坐标y + * @return 是则返回true + */ + public boolean isTrisectionArea(Component parentComp, int x, int y) { + return super.isTrisectionArea(parentComp, x, y); + } + + /** + * 是否为组件交叉点区域 或者是相邻三组建中间点 + * + * @param currentComp 当前组件 + * @param x 坐标x + * @param y 坐标y + * @return 是则返回true + */ + public boolean isCrossPointArea(Component currentComp, int x, int y) { + return super.isCrossPointArea(currentComp, x, y); + } + + + protected Rectangle getLayoutBound(XWCardMainBorderLayout mainLayout) { + return mainLayout.getBounds(); + } + + private Rectangle adjustBackupBound(Rectangle backupBound, XWCardMainBorderLayout mainLayout) { + // 参数界面高度对纵坐标产生的影响 + JForm jform = (JForm) (HistoryTemplateListPane.getInstance().getCurrentEditingTemplate()); + if (jform.getFormDesign().getParaComponent() != null) { + backupBound.y -= jform.getFormDesign().getParaHeight(); + } + + Rectangle rec = getLayoutBound(mainLayout); + // XWTabLayout里面的横纵坐标收到外层XWCardMainBorderLayout的横纵坐标影响 + // 减掉之后可以按照它原来的逻辑执行 + backupBound.x -= rec.x; + backupBound.y -= rec.y; + XWCardLayout cardLayout = mainLayout.getCardPart(); + LayoutBorderStyle style = cardLayout.toData().getBorderStyle(); + // 当tab布局为标题样式时,才需要处理标题栏高度产生的影响 + if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) { + backupBound.y -= WCardMainBorderLayout.TAB_HEIGHT; + } + return backupBound; + } + + /** + * 拖拽控件边框后,根据控件的大小尺寸,进行相关组件的调整 + * + * @param creator 组件 + */ + @Override + public void fix(XCreator creator) { + //拖拽组件原大小、位置 + Rectangle backupBound = creator.getBackupBound(); + backupBound.x -= container.getX(); + backupBound.y -= container.getY(); + //当前拖拽组件的位置 + int x = creator.getX(); + int y = creator.getY(); + + // 获取容器所有内部组件横坐标 + int[] posXs = container.getHors(); + // 获取容器所有内部组件纵坐标 + int[] posYs = container.getVeris(); + + XLayoutContainer outerLayout = container.getOuterLayout(); + if (!ComparatorUtils.equals(outerLayout, container.getBackupParent())) { + XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout) outerLayout; + backupBound = adjustBackupBound(backupBound, mainLayout); + } + + //拖拽组件拖拽以后的大小 + int w = creator.getWidth(); + int h = creator.getHeight(); + initCompsList(); + creator.setBounds(backupBound); + int difference = 0; + if (x != backupBound.x) { + dealLeft(backupBound, x, posXs, difference, creator); + } else if (w != backupBound.width) { + dealRight(backupBound, x, w, posXs, difference, creator); + } else if (y != backupBound.y) { + dealTop(backupBound, y, posYs, difference, creator); + } else if (h != backupBound.height) { + dealButtom(backupBound, y, h, posYs, difference, creator); + } + clearCompsList(); + XWFitLayout layout = (XWFitLayout) container; + layout.updateBoundsWidget(); // 更新对应的BoundsWidget + updateCreatorBackBound(); + } + + /** + * 拖拽控件边框后,根据控件的大小尺寸,进行相关组件的调整 + * + * @param backupBound 边界备份 + * @param bounds 组件边界 + * @param xCreator 组件 + * @param row 选中的行 + * @param difference 偏移量 + */ + public void calculateBounds(Rectangle backupBound, Rectangle bounds, XCreator xCreator, int row, int difference) { + Rectangle rc = new Rectangle(0, 0, 0, 0); + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xCreator); + if (parent != null) { + Rectangle rec = ComponentUtils.getRelativeBounds(parent); + rc.x = rec.x; + rc.y = rec.y; + } + int x = backupBound.x - rc.x, y = backupBound.y - rc.y; + //处理左右延伸 + switch (row) { + case 0: + if (backupBound.width + backupBound.x == container.getWidth() - margin.getRight() + rc.x) { + x += difference; + } + break; + case 1: + if (backupBound.y + backupBound.height == container.getHeight() - margin.getBottom() + rc.y) { + y += difference; + } + break; + } + bounds.setLocation(x, y); + xCreator.setBackupBound(backupBound); + xCreator.setBounds(bounds); + this.fix(xCreator); + } + + private void dealLeft(Rectangle backupBound, int x, int[] posXs, int difference, XCreator creator) { + if (backupBound.x == margin.getLeft()) { + return; + } + x = adjustCoordinateByDependingLine(x, posXs); + difference = x - backupBound.x; + dealDirectionAtLeft(backupBound, difference, creator); + } + + private void dealRight(Rectangle backupBound, int x, int w, int[] posXs, int difference, XCreator creator) { + if (backupBound.width + backupBound.x == container.getWidth() - margin.getRight()) { + return; + } + w = adjustDiffByDependingLine(x, posXs, w); + difference = w - backupBound.width; //拖拽长度 + dealDirectionAtRight(backupBound, difference, creator); + } + + private void dealTop(Rectangle backupBound, int y, int[] posYs, int difference, XCreator creator) { + if (backupBound.y == margin.getTop()) { + return; + } + y = adjustCoordinateByDependingLine(y, posYs); + difference = y - backupBound.y; + dealDirectionAtTop(backupBound, difference, creator); + } + + private void dealButtom(Rectangle backupBound, int y, int h, int[] posYs, int difference, XCreator creator) { + if (backupBound.y + backupBound.height == container.getHeight() - margin.getBottom()) { + return; + } + h = adjustDiffByDependingLine(y, posYs, h); + difference = h - backupBound.height; + dealDirectionABottom(backupBound, difference, creator); + } + + // 根据需要依附的位置调整拖拽的坐标值 + private int adjustCoordinateByDependingLine(int coordinate, int[] coordinates) { + if (!isEdit) { + for (int i = 0; i < coordinates.length; i++) { + if (coordinate == coordinates[i]) { + continue; + } + if (coordinate > coordinates[i] - DEPENDING_SCOPE && coordinate < coordinates[i] + DEPENDING_SCOPE) { + coordinate = coordinates[i]; + break; + } + } + } + return coordinate; + } + + // 根据需要依附的位置调整拖拽的距离 + private int adjustDiffByDependingLine(int coordinate, int[] coordinates, int diff) { + if (!isEdit) { + for (int i = 0; i < coordinates.length; i++) { + if (coordinate + diff > coordinates[i] - DEPENDING_SCOPE && coordinate + diff < coordinates[i] + DEPENDING_SCOPE) { + diff = coordinates[i] - coordinate; + break; + } + } + } + return diff; + } + + // 左侧边框拉伸,循环找出对齐的两侧控件 + private void dealDirectionAtLeft(Rectangle backupBound, int difference, Component creator) { + rightComps.add(creator); + Component rightComp = null; + int leftx = backupBound.x - DEFAULT_AREA_LENGTH - actualVal; + // 取左侧边框右面的组件x值 + int rightx = backupBound.x + DEFAULT_AREA_LENGTH; + Component leftComp = container.getLeftComp(backupBound.x, backupBound.y); + leftComps.add(leftComp); + //先找上侧对齐时(y相等)的左右两边组件 + int ry = backupBound.y; + int ly = leftComp.getY(); + int min = margin.getTop(); + int max = container.getHeight() - margin.getBottom(); + while (ry >= min && ly >= min) { + if (ry == ly) { + break; + } else { + if (ry > ly) { + rightComp = container.getTopComp(rightx, ry); + ry = rightComp.getY(); + rightComps.add(rightComp); + } else { + leftComp = container.getTopComp(leftx, ly); + ly = leftComp.getY(); + leftComps.add(leftComp); + } + } + } + // 下侧对齐时(y+h相等)两边组件 + ry = backupBound.y + backupBound.height; + ly = leftComps.get(0).getY() + leftComps.get(0).getHeight(); + while (ry <= max && ly <= max) { + if (ry == ly) { + break; + } else { + if (ry > ly) { + leftComp = container.getComponentAt(leftx, ly + DEFAULT_AREA_LENGTH + actualVal); + ly = leftComp.getY() + leftComp.getHeight(); + leftComps.add(leftComp); + } else { + rightComp = container.getComponentAt(rightx, ry + DEFAULT_AREA_LENGTH + actualVal); + ry = rightComp.getY() + rightComp.getHeight(); + rightComps.add(rightComp); + } + } + } + dealHorDirection(backupBound.x, difference); + } + + // 右侧边框拉伸,循环找出对齐的两侧控件 + private void dealDirectionAtRight(Rectangle backupBound, int difference, Component creator) { + leftComps.add(creator); + Component leftComp = null; + int leftx = backupBound.x + backupBound.width - DEFAULT_AREA_LENGTH; + // 取右侧边框右面的组件x值 + int rightx = backupBound.x + backupBound.width + DEFAULT_AREA_LENGTH + actualVal; + Component rightComp = container.getRightComp(backupBound.x, backupBound.y, backupBound.width); + rightComps.add(rightComp); + int ly = backupBound.y, ry = rightComp.getY(); + int min = margin.getTop(); + int max = container.getHeight() - margin.getBottom(); + while (ry >= min && ly >= min) { + if (ry == ly) { + break; + } else { + if (ry > ly) { + rightComp = container.getTopComp(rightx, ry); + ry = rightComp.getY(); + rightComps.add(rightComp); + } else { + leftComp = container.getTopComp(leftx, ly); + ly = leftComp.getY(); + leftComps.add(leftComp); + } + } + } + ly = backupBound.y + backupBound.height; + ry = rightComps.get(0).getY() + rightComps.get(0).getHeight(); + while (ry <= max && ly <= max) { + if (ry == ly) { + break; + } else { + if (ry > ly) { + leftComp = container.getComponentAt(leftx, ly + DEFAULT_AREA_LENGTH + actualVal); + ly = leftComp.getY() + leftComp.getHeight(); + leftComps.add(leftComp); + } else { + rightComp = container.getComponentAt(rightx, ry + DEFAULT_AREA_LENGTH + actualVal); + ry = rightComp.getY() + rightComp.getHeight(); + rightComps.add(rightComp); + } + } + } + dealHorDirection(backupBound.x + backupBound.width + actualVal, difference); + } + + /** + * 水平方向上拉伸边框的处理 + */ + private void dealHorDirection(int objx, int difference) { + if (difference > 0) { + difference = Math.min(getMinWidth(rightComps) - minWidth, difference); + } else { + difference = Math.max(difference, minWidth - getMinWidth(leftComps)); + } + //重新计算左右两侧组件size、point + if (calculateLefttRelatComponent(difference)) { + calculateRightRelatComponent(objx + difference, -difference); + } + } + + // 上侧边框拉伸,循环找出对齐的两侧控件 + private void dealDirectionAtTop(Rectangle backupBound, int difference, Component creator) { + downComps.add(creator); + // 取上侧边框上面的组件用的y值 + int topy = backupBound.y - DEFAULT_AREA_LENGTH - actualVal; + // 上侧边框下面的组件y值 + int bottomy = backupBound.y + DEFAULT_AREA_LENGTH; + Component topComp = container.getTopComp(backupBound.x, backupBound.y); + upComps.add(topComp); + Component bottomComp = null; + int min = margin.getLeft(); + int max = container.getWidth() - margin.getRight(); + //先找左侧侧对齐时(x相等)的上下两边组件 + int ux = topComp.getX(); + int dx = backupBound.x; + while (ux >= min && dx >= min) { + if (ux == dx) { + break; + } else { + if (ux < dx) { + bottomComp = container.getLeftComp(dx, bottomy); + dx = bottomComp.getX(); + downComps.add(bottomComp); + } else { + topComp = container.getLeftComp(ux, topy); + ux = topComp.getX(); + upComps.add(topComp); + } + } + } + // 右侧对齐时(x+w相等)两边组件 + ux = upComps.get(0).getX() + upComps.get(0).getWidth(); + dx = backupBound.x + backupBound.width; + while (ux <= max && dx <= max) { + if (ux == dx) { + break; + } else { + if (ux < dx) { + topComp = container.getComponentAt(ux + DEFAULT_AREA_LENGTH + actualVal, topy); + ux = topComp.getX() + topComp.getWidth(); + upComps.add(topComp); + } else { + bottomComp = container.getComponentAt(dx + DEFAULT_AREA_LENGTH + actualVal, bottomy); + dx = bottomComp.getX() + bottomComp.getWidth(); + downComps.add(bottomComp); + } + } + } + + dealVertiDirection(backupBound.y, difference); + } + + // 下侧边框拉伸,循环找出对齐的两侧控件 + private void dealDirectionABottom(Rectangle backupBound, int difference, Component creator) { + upComps.add(creator); + Component topComp = null; + Component bottomComp = container.getBottomComp(backupBound.x, backupBound.y, backupBound.height); + // 下侧边框下面的组件y坐标 + int bottomy = backupBound.y + backupBound.height + DEFAULT_AREA_LENGTH + actualVal; + // 取下侧边框上面的组件用的y值 + int topy = backupBound.y + backupBound.height - DEFAULT_AREA_LENGTH; + downComps.add(bottomComp); + int dx = bottomComp.getX(); + int ux = backupBound.x; + int min = margin.getLeft(); + int max = container.getWidth() - margin.getRight(); + while (ux >= min && dx >= min) { + if (ux == dx) { + break; + } else { + if (ux < dx) { + bottomComp = container.getLeftComp(dx, bottomy); + dx = bottomComp.getX(); + downComps.add(bottomComp); + } else { + topComp = container.getLeftComp(ux, topy); + ux = topComp.getX(); + upComps.add(topComp); + } + } + } + dx = downComps.get(0).getX() + downComps.get(0).getWidth(); + ux = backupBound.x + backupBound.width; + while (ux <= max && dx <= max) { + if (ux == dx) { + break; + } else { + if (ux < dx) { + topComp = container.getComponentAt(ux + DEFAULT_AREA_LENGTH + actualVal, topy); + ux = topComp.getX() + topComp.getWidth(); + upComps.add(topComp); + } else { + bottomComp = container.getComponentAt(dx + DEFAULT_AREA_LENGTH + actualVal, bottomy); + dx = bottomComp.getX() + bottomComp.getWidth(); + downComps.add(bottomComp); + } + } + } + dealVertiDirection(backupBound.y + backupBound.height + actualVal, difference); + } + + /** + * 垂直方向上拉伸边框的处理 + */ + private void dealVertiDirection(int objY, int difference) { + if (difference > 0) { + difference = Math.min(getMinHeight(downComps) - minHeight, difference); + } else { + difference = Math.max(difference, minHeight - getMinHeight(upComps)); + } + //重新计算上下两侧组件size、point + if (calculateUpRelatComponent(difference)) { + calculateDownRelatComponent(objY + difference, -difference); + } + } + + /** + * 新拖入组件时,计算调整其他关联组件位置大小 + * + * @param child 新拖入的组件 + * @param x 鼠标所在x坐标 + * @param y 鼠标所在y坐标 + */ + public void fix(XCreator child, int x, int y) { + Component parentComp = container.getComponentAt(x, y); + if (container.getComponentCount() == 0) { + child.setLocation(0, 0); + child.setSize(parentComp.getWidth(), parentComp.getHeight()); + } else if (isCrossPointArea(parentComp, x, y)) { + //交叉区域插入组件时,根据具体位置进行上下或者左右或者相邻三个组件的位置大小插入 + fixCrossPointArea(parentComp, child, x, y); + return; + } else if (isTrisectionArea(parentComp, x, y)) { + // 在边界三等分区域,就不再和组件二等分了 + fixTrisect(parentComp, child, x, y); + return; + } else { + fixHalve(parentComp, child, x, y); + } + } + + /** + * 平分,正常情况拖入组件时,按照上1/4区域、下1/4区域为上下平分,中左侧1/2区域、中右侧1/2区域为左右平分 + */ + protected void fixHalve(Component currentComp, XCreator child, int x, int y) { + super.fixHalve(currentComp, child, x, y); + } + + /** + * 组件交叉区域进行插入时,调整受到变动的其他组件,之前是交叉区域插入也按照三等分逻辑,后面测试中发现有bug,改为和bi一样的鼠标所在侧平分 + * 默认左上角、右下角区域是垂直方向插入组件 + * 右上角和左下角是水平方向插入组件,这样避免田字块时重复 + */ + protected void fixCrossPointArea(Component currentComp, XCreator child, int x, int y) { + super.fixCrossPointArea(currentComp, child, x, y); + } + + /** + * 三等分区域时,调整相关联的组件 + * + * @param currentComp 鼠标所在组件 + * @param child 待插入组件 + */ + protected void fixTrisect(Component currentComp, XCreator child, int x, int y) { + super.fixTrisect(currentComp, child, x, y); + } + + /** + * 删除组件或者重新拖动时,其它组件重新计算位置大小 + */ + protected void delete(XCreator creator, int creatorWidth, int creatorHeight) { + int x = creator.getX(); + int y = creator.getY(); + recalculateChildrenSize(x, y, creatorWidth, creatorHeight); + } + + /** + * 重新计算内部组件大小 + * + * @param x 坐标x + * @param y 坐标y + * @param creatorWidth 删除的组件之前所在布局的宽度 + * @param creatorHeight 删除的组件之前所在布局的高度 + */ + public void recalculateChildrenSize(int x, int y, int creatorWidth, int creatorHeight) { + if (container.getComponentCount() == 0) { + return; + } else { + initCompsList(); + int width = creatorWidth; + int height = creatorHeight; + calculateRelatedComponent(x, y, width, height); + if (!rightComps.isEmpty() && getAllHeight(rightComps) == height) { + calculateRightRelatComponent(x, width + actualVal); + } else if (!leftComps.isEmpty() && getAllHeight(leftComps) == height) { + calculateLefttRelatComponent(width + actualVal); + } else if (!downComps.isEmpty() && getAllWidth(downComps) == width) { + calculateDownRelatComponent(y, height + actualVal); + } else if (!upComps.isEmpty() && getAllWidth(upComps) == width) { + calculateUpRelatComponent(height + actualVal); + } else { + // 由于布局三等分的存在,可能会出现删除组件时,找不到关联的组件填充,此时特殊处理 + calculateNoRelatedComponent(x, y, width, height); + } + } + clearCompsList(); + } + + /** + * 四侧边框都没有对齐的,此时每侧有且只有一个方向不对齐 + * 比如右侧不对齐,那么必然右上或右下没对齐,不会同时不对齐,否则不会出现此情况 + * 正常删除是右左下上优先原则,这边目前只调整右侧以至填充完整, + * 右侧不对齐时的组件先上下微调,再向左侧填充。 + */ + private void calculateNoRelatedComponent(int x, int y, int width, int height) { + // 只有最后一个组件了,直接删除 + if (container.getComponentCount() <= 1) { + return; + } + // 删除当前组件时,由于没有刚好边框对齐的其他组件,这时候需要调整的组件 + Component rightComp = container.getRightComp(x, y, width); + if (rightComp == null) { + return; + } + + int ry = rightComp.getY(); + clearCompsList(); + initCompsList(); + Rectangle rec = new Rectangle(x, y, width, height); + if (ry != y) { + calculateNoRelatedWhileRightTop(rec, rightComp); + } else { + calculateNoRelatedWhileRightBott(rec, rightComp); + } + + } + + private void calculateNoRelatedWhileRightTop(Rectangle bound, Component rcomp) { + if (rcomp == null) { + return; + } + + int ry = rcomp.getY(); + int rh = rcomp.getHeight(); + int rw = rcomp.getWidth(); + int dh = bound.y - ry - actualVal; + // 没法缩小高度 + if (dh < minHeight) { + // 没法缩小时则拉伸rcomp的上边框 + dealDirectionAtTop(rcomp.getBounds(), dh + actualVal, rcomp); + //调整的时候可能有组件达到最小高度,判断下 + if (rcomp.getY() != bound.y) { + clearCompsList(); + initCompsList(); + dealDirectionAtTop(rcomp.getBounds(), bound.y - rcomp.getY() - minHeight - actualVal, rcomp); + ry = rcomp.getY(); + int rx = rcomp.getX(); + rcomp.setBounds(rx, ry, rw, minHeight); + recalculateChildrenSize(rx, bound.y, rw, rh - dh - actualVal); + recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); + return; + } + } else { + // 右侧控件底部对齐 + if (rh + ry == bound.y + bound.height) { + rcomp.setSize(rw, dh); + bound.width += rw; + bound.width += actualVal; + } else { + recalculateChildrenSize(bound.x, ry + rh + actualVal, bound.width, bound.height + bound.y - rh - ry - actualVal); + recalculateChildrenSize(bound.x, bound.y, bound.width, ry + rh - bound.y); + return; + } + } + recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); + } + + private void calculateNoRelatedWhileRightBott(Rectangle bound, Component rcomp) { + rcomp = container.getBottomRightComp(bound.x, bound.y, bound.height, bound.width); + int ry = rcomp.getY(); + int rh = rcomp.getHeight(); + int rw = rcomp.getWidth(); + int dh = ry + rh - bound.y - bound.height - actualVal; + if (dh < minHeight) { + dealDirectionABottom(rcomp.getBounds(), -dh - actualVal, rcomp); + //调整的时候可能有组件达到最小高度,判断下 + if (rcomp.getHeight() + ry != bound.y + bound.height) { + clearCompsList(); + initCompsList(); + dh = ry + rcomp.getHeight() - bound.y - bound.height - actualVal; + dealDirectionABottom(rcomp.getBounds(), minHeight - dh, rcomp); + rh = rcomp.getHeight(); + int rx = rcomp.getX(); + rcomp.setBounds(rx, bound.y + bound.height + actualVal, rw, minHeight); + recalculateChildrenSize(rx, ry, rw, rh - minHeight - actualVal); + recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); + return; + } + } else { + if (ry == bound.y) { + rcomp.setBounds(rcomp.getX(), bound.y + bound.height + actualVal, rw, dh); + bound.width += rw; + bound.width += actualVal; + } else { + recalculateChildrenSize(bound.x, bound.y, bound.width, ry - bound.y - actualVal); + recalculateChildrenSize(bound.x, ry, bound.width, bound.height - ry + bound.y); + return; + } + } + recalculateChildrenSize(bound.x, bound.y, bound.width, bound.height); + } + + private int getMinWidth(List comps) { + if (comps.isEmpty()) { + return 0; + } + int minWidth = container.getWidth() - margin.getLeft() - margin.getRight(); + for (int i = 0, size = comps.size(); i < size; i++) { + minWidth = minWidth > comps.get(i).getWidth() ? comps.get(i).getWidth() : minWidth; + } + return minWidth; + } + + private int getMinHeight(List comps) { + if (comps.isEmpty()) { + return 0; + } + int minH = container.getHeight() - margin.getTop() - margin.getBottom(); + for (int i = 0, size = comps.size(); i < size; i++) { + minH = minH > comps.get(i).getHeight() ? comps.get(i).getHeight() : minH; + } + return minH; + } + + // 删除时计算待删除组件上下侧的组件是否何其对齐 + private int getAllHeight(List comps) { + int allHeight = 0; + if (comps.isEmpty()) { + return allHeight; + } + int n = comps.size(); + for (int i = 0; i < n; i++) { + allHeight += comps.get(i).getHeight(); + } + allHeight += (n - 1) * actualVal; + return allHeight; + } + + private int getAllWidth(List comps) { + int allWidth = 0; + if (comps.isEmpty()) { + return allWidth; + } + int n = comps.size(); + for (int i = 0; i < n; i++) { + allWidth += comps.get(i).getWidth(); + } + allWidth += (n - 1) * actualVal; + return allWidth; + } + + /** + * 获取有哪些相关联的组件 + */ + protected void calculateRelatedComponent(int objX, int objY, int objWidth, int objHeight) { + int count = container.getComponentCount(); + for (int i = 0; i < count; i++) { + Component relatComp = container.getComponent(i); + int rx = relatComp.getX(); + int ry = relatComp.getY(); + int rwidth = relatComp.getWidth(); + int rheight = relatComp.getHeight(); + int verti = ry - objY; + int hori = rx - objX; + boolean isHori = verti >= 0 && objHeight >= (rheight + verti); + boolean isVerti = hori >= 0 && objWidth >= (rwidth + hori); + if (isHori && (objX + objWidth + actualVal) == rx) { + rightComps.add(relatComp); + } else if (isHori && objX == (rx + rwidth + actualVal)) { + leftComps.add(relatComp); + } else if (isVerti && (objY + objHeight + actualVal) == ry) { + downComps.add(relatComp); + } else if (isVerti && objY == (ry + rheight + actualVal)) { + upComps.add(relatComp); + } + } + } + + /** + * 拖拽组件时遍历某一侧组件得到该侧组件能够缩放的最小宽度,tab布局最小宽度 = 内部组件数 * 单个组件最小宽度 + * + * @param list 某一侧组件的集合 如:leftComps + * @return int 最小宽度 + */ + private int getCompsMinWidth(List list) { + return getMaxCompsNum(list, true) * WLayout.MIN_WIDTH; + } + + /** + * 拖拽组件遍历某一侧得到该侧组件能够缩放的最小高度,tab布局最小高度 = 内部组件数 * 单个组件最小高度 + 标题高度 + * + * @param list 某一侧组件集合 + * @return int 最小高度 + */ + private int getCompsMinHeight(List list) { + for (int i = 0; i < list.size(); i++) { + XCreator creator = (XCreator) list.get(i); + ArrayList childrenList = creator.getTargetChildrenList(); + if (!childrenList.isEmpty()) { + return getMaxCompsNum(list, false) * WLayout.MIN_HEIGHT + WCardMainBorderLayout.TAB_HEIGHT; + } + } + return WLayout.MIN_HEIGHT; + } + + /** + * 根据子组件的横(纵)坐标获取某一侧组件的最大内部组件数 + * + * @param list 某一侧组件集合 + * @param isHor 是否以横坐标为准 + * @return int 最大内部组件数 + */ + private int getMaxCompsNum(List list, boolean isHor) { + int maxCompNums = 1; + for (int i = 0, size = list.size(); i < size; i++) { + XCreator creator = (XCreator) list.get(i); + ArrayList childrenList = creator.getTargetChildrenList(); + int count = childrenList.size(); + if (count > 0) { + for (int j = 0; j < count; j++) { + XWTabFitLayout tabLayout = (XWTabFitLayout) childrenList.get(j); + int[] positions = isHor ? tabLayout.getHors(true) : tabLayout.getVeris(true); + int compNums = positions.length - 1; + maxCompNums = Math.max(compNums, maxCompNums); + } + } + } + return maxCompNums; + } + + /** + * 根据偏移量缩放内部组件大小,(tab布局用到) + * + * @param creator tab布局 + * @param offset 偏移量 + * @param isHor 是否为横向拖拽 + */ + private void adjustCompsSize(XCreator creator, int offset, boolean isHor) { + ArrayList childrenList = creator.getTargetChildrenList(); + int size = childrenList.size(); + if (size > 0) { + for (int j = 0; j < size; j++) { + XWTabFitLayout tabLayout = (XWTabFitLayout) childrenList.get(j); + tabLayout.setBackupBound(tabLayout.getBounds()); + int refSize = isHor ? tabLayout.getWidth() : tabLayout.getHeight(); + double percent = (double) offset / refSize; + if (percent < 0 && !tabLayout.canReduce(percent)) { + return; + } + setAdjustedSize(tabLayout, offset, isHor); + for (int m = 0; m < tabLayout.getComponentCount(); m++) { + XCreator childCreator = tabLayout.getXCreator(m); + BoundsWidget wgt = tabLayout.toData().getBoundsWidget(childCreator.toData()); + wgt.setBounds(tabLayout.getComponent(m).getBounds()); + } + adjustCreatorsSize(percent, tabLayout, isHor); + } + + } + } + + // 纵向拖拽,先将tab布局的高度设置为拖拽后的实际高度 + private void setAdjustedHeight(XWTabFitLayout tabLayout, int offset) { + tabLayout.setSize(tabLayout.getWidth(), tabLayout.getHeight() + offset); + } + + // 横向拖拽,先将tab布局的宽度设置为拖拽后的实际宽度 + private void setAdjustedSize(XWTabFitLayout tabLayout, int offset, boolean isHor) { + if (offset < 0) { + // 缩放时需要备份原tab布局宽高 + tabLayout.setReferDim(new Dimension(tabLayout.getWidth(), tabLayout.getHeight())); + } + if (isHor) { + tabLayout.setSize(tabLayout.getWidth() + offset, tabLayout.getHeight()); + return; + } + setAdjustedHeight(tabLayout, offset); + } + + // 按照拖拽偏移量,对tab布局进行缩放 + private void adjustCreatorsSize(double percent, XWTabFitLayout tabLayout, boolean isHor) { + if (isHor) { + tabLayout.adjustCreatorsWidth(percent); + return; + } + tabLayout.adjustCreatorsHeight(percent); + } + + + /** + * 删除或拉伸控件右边框 调整右侧组件位置大小 + * + * @param objX 调整后的坐标x + * @param objWidth 调整后的宽度 + */ + protected void calculateRightRelatComponent(int objX, int objWidth) { + int count = rightComps.size(); + for (int i = 0; i < count; i++) { + XCreator creator = (XCreator) rightComps.get(i); + adjustCompsSize(creator, objWidth, true); + int ry = creator.getY(); + int rwidth = creator.getWidth(); + int rheight = creator.getHeight(); + creator.setLocation(objX, ry); + creator.setSize(rwidth + objWidth, rheight); + } + } + + /** + * 实际拖拽偏移量是否超出了可调整的宽度范围 + * + * @param offset 实际偏移量 + * @return boolean 是否超出调整范围 + */ + private boolean isBeyondAdjustWidthScope(int offset) { + boolean isBeyondScope = false; + isBeyondScope = offset < 0 ? isBeyondWidthScope(offset, leftComps) : isBeyondWidthScope(offset, rightComps); + return isBeyondScope; + } + + // 实际拖拽偏移量是否超出某一侧的可调整宽度 + private boolean isBeyondWidthScope(int offset, List compsList) { + int compMinWidth = getCompsMinWidth(compsList); + for (int i = 0; i < compsList.size(); i++) { + XCreator creator = (XCreator) compsList.get(i); + if (Math.abs(offset) > (creator.getWidth() - compMinWidth)) { + return true; + } + } + return false; + } + + /** + * 删除或拉伸控件左边框时 调整左侧的组件位置大小; + */ + protected boolean calculateLefttRelatComponent(int objWidth) { + if (isBeyondAdjustWidthScope(objWidth)) { + return false; + } + int count = leftComps.size(); + for (int i = 0; i < count; i++) { + XCreator creator = (XCreator) leftComps.get(i); + adjustCompsSize(creator, objWidth, true); + int rwidth = creator.getWidth(); + int rheight = creator.getHeight(); + creator.setSize(rwidth + objWidth, rheight); + } + return true; + } + + /** + * 删除或拉伸下边框 调整下方的组件位置大小 + */ + protected void calculateDownRelatComponent(int objY, int objHeight) { + int count = downComps.size(); + for (int i = 0; i < count; i++) { + XCreator creator = (XCreator) downComps.get(i); + adjustCompsSize(creator, objHeight, false); + int rx = creator.getX(); + int rwidth = creator.getWidth(); + int rheight = creator.getHeight(); + creator.setLocation(rx, objY); + creator.setSize(rwidth, rheight + objHeight); + } + } + + /** + * 实际拖拽偏移量是否超出了可调整的高度范围 + * + * @param offset 实际偏移量 + * @return boolean 是否超出调整范围 + */ + private boolean isBeyondAdjustHeightScope(int offset) { + boolean isBeyondScope = false; + isBeyondScope = offset < 0 ? isBeyondHeightScope(offset, upComps) : isBeyondHeightScope(offset, downComps); + return isBeyondScope; + } + + // 实际拖拽偏移量是否超出某一侧的可调整高度 + private boolean isBeyondHeightScope(int offset, List compsList) { + int minHeight = getCompsMinHeight(compsList); + for (int i = 0; i < compsList.size(); i++) { + XCreator creator = (XCreator) compsList.get(i); + if (Math.abs(offset) > (creator.getHeight() - minHeight)) { + return true; + } + } + return false; + } + + /** + * 删除或拉伸上边框 调整上方的组件位置大小 + */ + protected boolean calculateUpRelatComponent(int objHeight) { + if (isBeyondAdjustHeightScope(objHeight)) { + return false; + } + int count = upComps.size(); + for (int i = 0; i < count; i++) { + XCreator creator = (XCreator) upComps.get(i); + adjustCompsSize(creator, objHeight, false); + int rwidth = creator.getWidth(); + int rheight = creator.getHeight(); + creator.setSize(rwidth, rheight + objHeight); + } + return true; + } + + /** + * 不调整,只计算位置 + * + * @return child的位置 + */ + public int[] getChildPosition(Component currentComp, XCreator child, int x, int y) { + return super.getChildPosition(currentComp, child, x, y); + } + + @Override + public ConstraintsGroupModel getLayoutConstraints(XCreator creator) { + return new FRFitLayoutConstraints((XWFitLayout) container, creator); + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java index 12a5ad55b7..352a3ba7a6 100644 --- a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java +++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java @@ -1,107 +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布局的边缘,则需要把新组件添加到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); - } +/** + * + */ +package com.fr.design.designer.beans.adapters.layout; + + +import com.fr.design.beans.GroupModel; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWidgetCreator; +import com.fr.design.designer.creator.cardlayout.XWCardLayout; +import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; +import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; +import com.fr.design.designer.properties.FRTabFitLayoutPropertiesGroupModel; +import com.fr.design.utils.ComponentUtils; +import com.fr.form.ui.LayoutBorderStyle; +import com.fr.form.ui.container.WBorderLayout; +import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; +import com.fr.general.ComparatorUtils; + +import java.awt.*; + +/** + * tab布局tabFit适配器 + * + * @author focus + * @date 2014-6-24 + */ +public class FRTabFitLayoutAdapter extends FRFitLayoutAdapter { + + /** + * 构造函数 + * + * @param container XWTabFitLayout容器 + */ + public FRTabFitLayoutAdapter(XLayoutContainer container) { + super(container); + } + + /** + * 返回布局自身属性,方便一些特有设置在layout刷新时处理 + */ + @Override + public GroupModel getLayoutProperties() { + XWTabFitLayout xfl = (XWTabFitLayout) container; + return new FRTabFitLayoutPropertiesGroupModel(xfl); + } + + /** + * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的 + * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。 + * + * @param creator 被添加的新组件 + * @param x 添加的位置x,该位置是相对于container的 + * @param y 添加的位置y,该位置是相对于container的 + * @return 是否添加成功,成功返回true,否则false + */ + @Override + public boolean addBean(XCreator creator, int x, int y) { + // 经过accept判断后,container会被改变,先备份 + XLayoutContainer backUpContainer = container; + Rectangle rect = ComponentUtils.getRelativeBounds(container); + int posX = x - rect.x; + int posY = y - rect.y; + if (!accept(creator, posX, posY)) { + return false; + } + // posX,posY是新拖入组件相对于容器的位置,若在tab布局的边缘,则需要把新组件添加到l + // 父层自适应布局中,这时候的添加位置就是tab布局所在的位置 + if (this.intersectsEdge(posX, posY, backUpContainer)) { + if (!ComparatorUtils.equals(backUpContainer.getOuterLayout(), backUpContainer.getBackupParent())) { + XWTabFitLayout tabLayout = (XWTabFitLayout) backUpContainer; + y = adjustY(y, tabLayout); + } + addComp(creator, x, y); + ((XWidgetCreator) creator).recalculateChildrenSize(); + return true; + } + // 如果不在边缘,容器为本自适应布局,增加组件的位置就是相对于容器的位置 + addComp(creator, posX, posY); + ((XWidgetCreator) creator).recalculateChildrenSize(); + return true; + } + + // tab布局的纵坐标受到tab高度的影响,判断的上边界取得是里面XWTabFitLayout的上边界, + // 实际计算的时候的纵坐标用了外层的CardMainBorerLayout,需要将tab高度减掉 + //将y值变为相对坐标以实现获取到鼠标drop位置的控件 + //TODO 可以直接在这边将x,y都变成相对坐标,这样在后面判断拖进来的新控件放置方式的时候就不用再判断了 + private int adjustY(int y, XWTabFitLayout tabLayout) { + XWCardLayout cardLayout = (XWCardLayout) tabLayout.getBackupParent(); + LayoutBorderStyle style = cardLayout.toData().getBorderStyle(); + if (container.getLocation().y == WBorderLayout.DEFAULT_SIZE) { + y = y - WBorderLayout.DEFAULT_SIZE; + } + if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) { + y = y - WCardMainBorderLayout.TAB_HEIGHT; + } + return y; + } + + protected Rectangle getLayoutBound(XWCardMainBorderLayout mainLayout) { + return ComponentUtils.getRelativeBounds(mainLayout); + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java b/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java index 161fe6bd5f..088f29a0a0 100644 --- a/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java +++ b/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java @@ -3,19 +3,17 @@ */ package com.fr.design.designer.beans.location; -import java.awt.*; - import com.fr.design.beans.location.Absorptionline; import com.fr.design.beans.location.MoveUtils; import com.fr.design.designer.creator.*; import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.FormSelection; import com.fr.design.utils.ComponentUtils; -import com.fr.form.main.Form; import com.fr.form.ui.container.WAbsoluteLayout; -import com.fr.form.ui.container.WParameterLayout; import com.fr.form.ui.widget.BoundsWidget; +import java.awt.*; + /** * @author richer * @since 6.5.3 @@ -26,197 +24,184 @@ public abstract class AccessDirection implements Direction { private int ymin; private int xmin; - abstract int getCursor(); - - protected abstract Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer, - Rectangle oldbounds); - - protected int[] sorption(int x, int y,Rectangle current_bounds, FormDesigner designer) { - // 自适应布局不需要吸附线,但需要对齐线,对齐线后面处理 - if (!designer.hasWAbsoluteLayout()) { - designer.getStateModel().setEquidistantLine(null); - designer.getStateModel().setXAbsorptionline(null); - designer.getStateModel().setYAbsorptionline(null); - return new int[] { x, y }; - } else { - int posy = current_bounds.y; - - Point relativePoint = getRelativePoint(x, y, current_bounds,designer); - sorptionPoint(relativePoint,current_bounds, designer); - return new int[] { relativePoint.x, relativePoint.y }; - } - - } - - protected Point getRelativePoint(int x, int y, Rectangle current_bounds,FormDesigner designer) { - if (x < 0) { - x = 0; - } else if (x > designer.getRootComponent().getWidth() && designer.getSelectionModel().hasSelectionComponent()) { - x = designer.getRootComponent().getWidth(); - } + abstract int getCursor(); + + protected abstract Rectangle getDraggedBounds(int dx, int dy, Rectangle currentBounds, FormDesigner designer, + Rectangle oldBounds); + + protected int[] sorption(int x, int y, Rectangle currentBounds, FormDesigner designer) { + // 自适应布局不需要吸附线,但需要对齐线,对齐线后面处理 + if (!designer.hasWAbsoluteLayout()) { + designer.getStateModel().setEquidistantLine(null); + designer.getStateModel().setXAbsorptionline(null); + designer.getStateModel().setYAbsorptionline(null); + return new int[]{x, y}; + } else { + Point relativePoint = getRelativePoint(x, y, currentBounds, designer); + sorptionPoint(relativePoint, currentBounds, designer); + return new int[]{relativePoint.x, relativePoint.y}; + } + + } + + protected Point getRelativePoint(int x, int y, Rectangle currentBounds, FormDesigner designer) { + if (x < 0) { + x = 0; + } else if (x > designer.getRootComponent().getWidth() && designer.getSelectionModel().hasSelectionComponent()) { + x = designer.getRootComponent().getWidth(); + } //参数面板可以无下限拉长 - if (y < 0) { - y = 0; - } else if (y > designer.getRootComponent().getHeight() + designer.getParaHeight() && designer.getSelectionModel().hasSelectionComponent() + if (y < 0) { + y = 0; + } else if (y > designer.getRootComponent().getHeight() + designer.getParaHeight() && designer.getSelectionModel().hasSelectionComponent() && !designer.getSelectionModel().getSelection().getSelectedCreator().acceptType(XWParameterLayout.class)) { - y = designer.getRootComponent().getHeight() + designer.getParaHeight(); - } - return new Point(x, y); - } - - protected void sorptionPoint(Point point, Rectangle current_bounds,FormDesigner designer) { - boolean findInX = current_bounds.getWidth() <= MoveUtils.SORPTION_UNIT ? true : false; - boolean findInY = current_bounds.getHeight() <= MoveUtils.SORPTION_UNIT ? true : false; - WAbsoluteLayout layout =getLayout(designer); - FormSelection selection = designer.getSelectionModel().getSelection(); -// boolean isWidgetsIntersect = false; - for (int i = 0, count = layout.getWidgetCount(); i < count; i++) { - BoundsWidget temp = (BoundsWidget) layout.getWidget(i); - if (!temp.isVisible() || selection.contains(temp.getWidget())) { - continue; - } - Rectangle bounds = getWidgetRelativeBounds(temp.getBounds(), selection); - if (!findInX) { - int x1 = bounds.x; - if (Math.abs(x1 - point.x) <= MoveUtils.SORPTION_UNIT) { - point.x = x1; - findInX = true; - } - int x2 = bounds.x + bounds.width; - if (Math.abs(x2 - point.x) <= MoveUtils.SORPTION_UNIT) { - point.x = x2; - findInX = true; - } - } - if (!findInY) { - int y1 = bounds.y; - if (Math.abs(y1 - point.y) <= MoveUtils.SORPTION_UNIT) { - point.y = y1; - findInY = true; - } - int y2 = bounds.y + bounds.height; - if (Math.abs(y2 - point.y) <= MoveUtils.SORPTION_UNIT) { - point.y = y2; - findInY = true; - } - - } - if (findInX && findInY) { - break; - } - -// if (current_bounds.intersects(bounds) && !(layout instanceof WParameterLayout)) { -// isWidgetsIntersect = true; -// } + y = designer.getRootComponent().getHeight() + designer.getParaHeight(); } -// processRectangleIntersects(designer, point.x, point.y, isWidgetsIntersect); - setDesignerStateModelProperties(designer, findInX, findInY, current_bounds, point); + return new Point(x, y); + } + + protected void sorptionPoint(Point point, Rectangle currentBounds, FormDesigner designer) { + boolean findInX = currentBounds.getWidth() <= MoveUtils.SORPTION_UNIT; + boolean findInY = currentBounds.getHeight() <= MoveUtils.SORPTION_UNIT; + WAbsoluteLayout layout = getLayout(designer); + FormSelection selection = designer.getSelectionModel().getSelection(); + for (int i = 0, count = layout.getWidgetCount(); i < count; i++) { + BoundsWidget temp = (BoundsWidget) layout.getWidget(i); + if (!temp.isVisible() || selection.contains(temp.getWidget())) { + continue; + } + Rectangle bounds = getWidgetRelativeBounds(temp.getBounds(), selection); + if (!findInX) { + int x1 = bounds.x; + if (Math.abs(x1 - point.x) <= MoveUtils.SORPTION_UNIT) { + point.x = x1; + findInX = true; + } + int x2 = bounds.x + bounds.width; + if (Math.abs(x2 - point.x) <= MoveUtils.SORPTION_UNIT) { + point.x = x2; + findInX = true; + } + } + if (!findInY) { + int y1 = bounds.y; + if (Math.abs(y1 - point.y) <= MoveUtils.SORPTION_UNIT) { + point.y = y1; + findInY = true; + } + int y2 = bounds.y + bounds.height; + if (Math.abs(y2 - point.y) <= MoveUtils.SORPTION_UNIT) { + point.y = y2; + findInY = true; + } + + } + if (findInX && findInY) { + break; + } + + } + setDesignerStateModelProperties(designer, findInX, findInY, currentBounds, point); + } + + private void setDesignerStateModelProperties(FormDesigner designer, boolean findInX, boolean findInY, Rectangle + currentBounds, Point point) { + designer.getStateModel().setXAbsorptionline(findInX && currentBounds.getWidth() > MoveUtils.SORPTION_UNIT ? Absorptionline.createXAbsorptionline(point.x) : null); + designer.getStateModel().setYAbsorptionline(findInY && currentBounds.getHeight() > MoveUtils.SORPTION_UNIT ? Absorptionline.createYAbsorptionline(point.y) : null); + designer.getStateModel().setEquidistantLine(null); } - private void setDesignerStateModelProperties (FormDesigner designer, boolean findInX, boolean findInY, Rectangle current_bounds, Point point) { - designer.getStateModel().setXAbsorptionline(findInX && current_bounds.getWidth() > MoveUtils.SORPTION_UNIT ? Absorptionline.createXAbsorptionline(point.x) : null); - designer.getStateModel().setYAbsorptionline(findInY && current_bounds.getHeight() > MoveUtils.SORPTION_UNIT ? Absorptionline.createYAbsorptionline(point.y) : null); - designer.getStateModel().setEquidistantLine(null); - } - - private Rectangle getWidgetRelativeBounds(Rectangle bounds, FormSelection selection){ - Rectangle relativeRec = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); - XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator()); - if (parent == null) { - return relativeRec; - } - Rectangle rec = ComponentUtils.getRelativeBounds(parent); - relativeRec.x += rec.x; - relativeRec.y += rec.y; - return relativeRec; - } - -// private void processRectangleIntersects(FormDesigner designer, int x, int y, boolean isIntersects){ -// if(isIntersects){ -// if(designer.getLocationOnScreen() != null) { -// MoveUtils.displayForbidWindow(x + designer.getLocationOnScreen().x, y + designer.getLocationOnScreen().y); -// } -// designer.setWidgetsIntersect(true); -// } -// else{ -// MoveUtils.hideForbidWindow(); -// designer.setWidgetsIntersect(false); -// } -// } - - private WAbsoluteLayout getLayout(final FormDesigner designer){ + private Rectangle getWidgetRelativeBounds(Rectangle bounds, FormSelection selection) { + Rectangle relativeRec = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator()); + if (parent == null) { + return relativeRec; + } + Rectangle rec = ComponentUtils.getRelativeBounds(parent); + relativeRec.x += rec.x; + relativeRec.y += rec.y; + return relativeRec; + } + + + private WAbsoluteLayout getLayout(final FormDesigner designer) { XLayoutContainer formLayoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator( designer.getTarget().getContainer()); WAbsoluteLayout layout; - if (formLayoutContainer.acceptType(XWBorderLayout.class)){//看起来这边的作用应该是为了区别cpt(得到XWParameterLayout)还是frm(得到XWBorderLayout)的参数界面 - Container container = designer.getSelectionModel().getSelection().getSelectedCreator().getParent(); - if(container instanceof XWAbsoluteLayout){ - layout = ((XWAbsoluteLayout)container).toData(); - } - else { - layout = (WAbsoluteLayout) designer.getParaComponent().toData(); - } - } else{ + if (formLayoutContainer.acceptType(XWBorderLayout.class)) {//看起来这边的作用应该是为了区别cpt(得到XWParameterLayout)还是frm(得到XWBorderLayout)的参数界面 + Container container = designer.getSelectionModel().getSelection().getSelectedCreator().getParent(); + if (container instanceof XWAbsoluteLayout) { + layout = ((XWAbsoluteLayout) container).toData(); + } else { + layout = (WAbsoluteLayout) designer.getParaComponent().toData(); + } + } else { layout = (WAbsoluteLayout) designer.getTarget().getContainer(); } - return layout; + return layout; } - /** - * 拖拽 - * @param dx 坐标x - * @param dy 坐标y - * @param designer 设计界面 - */ - public void drag(int dx, int dy, FormDesigner designer) { - Rectangle rec = getDraggedBounds(dx, dy, designer.getSelectionModel().getSelection().getRelativeBounds(), designer, designer.getSelectionModel().getSelection().getBackupBounds()); + /** + * 拖拽 + * + * @param dx 坐标x + * @param dy 坐标y + * @param designer 设计界面 + */ + public void drag(int dx, int dy, FormDesigner designer) { + Rectangle rec = getDraggedBounds(dx, dy, designer.getSelectionModel().getSelection().getRelativeBounds(), designer, designer.getSelectionModel().getSelection().getBackupBounds()); + if (rec != null) { + designer.getSelectionModel().getSelection().setSelectionBounds(rec, designer); + } else { + return; + } //设定控件最小高度21,因每次拖曳至少移动1,防止控件高度等于21时,拖曳导致rec.y的变化使得控件不停的向上或向下移动。 - if(rec.height == MINHEIGHT){ + if (rec.height == MINHEIGHT) { ymin = rec.y; } - if(rec.height == MINHEIGHT - 1){ + if (rec.height == MINHEIGHT - 1) { ymin = ymin == rec.y ? rec.y : rec.y - 1; } - if(rec.height < MINHEIGHT){ + if (rec.height < MINHEIGHT) { rec.height = MINHEIGHT; rec.y = ymin; } // 增加下宽度也设最小为21 if (rec.width == MINWIDTH) { - xmin = rec.x; + xmin = rec.x; } - if(rec.width == MINWIDTH - 1){ - xmin = xmin == rec.x ? rec.x : rec.x - 1; + if (rec.width == MINWIDTH - 1) { + xmin = xmin == rec.x ? rec.x : rec.x - 1; } if (rec.width < MINWIDTH) { - rec.width = MINWIDTH; - rec.x = xmin; + rec.width = MINWIDTH; + rec.x = xmin; + } + + } + + /** + * 更新鼠标指针形状 + * + * @param formEditor 设计界面组件 + */ + public void updateCursor(FormDesigner formEditor) { + + // 调用位置枚举的多态方法getCursor获取鼠标形状 + int type = getCursor(); + + if (type != formEditor.getCursor().getType()) { + // 设置当前形状 + formEditor.setCursor(Cursor.getPredefinedCursor(type)); } - if(rec != null) { - designer.getSelectionModel().getSelection().setSelectionBounds(rec, designer); - } - } - - /** - * 更新鼠标指针形状 - * @param formEditor 设计界面组件 - */ - public void updateCursor(FormDesigner formEditor) { - - // 调用位置枚举的多态方法getCursor获取鼠标形状 - int type = getCursor(); - - if (type != formEditor.getCursor().getType()) { - // 设置当前形状 - formEditor.setCursor(Cursor.getPredefinedCursor(type)); - } - } - - /** - * 生成组件备用的bound - * @param formEditor 设计界面组件 - */ - public void backupBounds(FormDesigner formEditor) { - formEditor.getSelectionModel().getSelection().backupBounds(); - } + } + + /** + * 生成组件备用的bound + * + * @param formEditor 设计界面组件 + */ + public void backupBounds(FormDesigner formEditor) { + formEditor.getSelectionModel().getSelection().backupBounds(); + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java b/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java index 6105813576..171ec465ff 100644 --- a/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java +++ b/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java @@ -1,11 +1,5 @@ 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; @@ -20,9 +14,12 @@ import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.FormSelection; import com.fr.design.mainframe.FormSelectionUtils; import com.fr.design.utils.gui.LayoutUtils; -import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; import com.fr.stable.ArrayUtils; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + /** * 该model保存当前选择的组件和剪切版信息 */ @@ -30,10 +27,10 @@ public class SelectionModel { //被粘贴组件在所选组件位置处往下、往右各错开20像素。执行多次粘贴时,在上一次粘贴的位置处错开20像素。 private static final int DELTA_X_Y = 20; //粘贴时候的偏移距离 private static final int BORDER_PROPORTION = 20; - private static FormSelection CLIP_BOARD = new FormSelection(); + private static FormSelection clipboard = new FormSelection(); private FormDesigner designer; private FormSelection selection; - private Rectangle hotspot_bounds; + private Rectangle hotspotBounds; public SelectionModel(FormDesigner designer) { this.designer = designer; @@ -45,7 +42,7 @@ public class SelectionModel { */ public void reset() { selection.reset(); - hotspot_bounds = null; + hotspotBounds = null; } /** @@ -54,7 +51,7 @@ public class SelectionModel { * @return 是否为空 */ public static boolean isEmpty() { - return CLIP_BOARD.isEmpty(); + return clipboard.isEmpty(); } /** @@ -67,7 +64,6 @@ public class SelectionModel { // 如果Ctrl或者Shift键盘没有按下,则清除已经选择的组件 selection.reset(); } - // 获取e所在的组件 XCreator comp = designer.getComponentAt(e); @@ -93,7 +89,7 @@ public class SelectionModel { */ public void cutSelectedCreator2ClipBoard() { if (hasSelectionComponent()) { - selection.cut2ClipBoard(CLIP_BOARD); + selection.cut2ClipBoard(clipboard); designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED); designer.repaint(); } @@ -104,7 +100,7 @@ public class SelectionModel { */ public void copySelectedCreator2ClipBoard() { if (!selection.isEmpty()) { - selection.copy2ClipBoard(CLIP_BOARD); + selection.copy2ClipBoard(clipboard); } } @@ -114,7 +110,7 @@ public class SelectionModel { * @return 否 */ public boolean pasteFromClipBoard() { - if (!CLIP_BOARD.isEmpty()) { + if (!clipboard.isEmpty()) { XLayoutContainer parent = null; //未选 if (!hasSelectionComponent()) { @@ -124,14 +120,14 @@ public class SelectionModel { Rectangle rec = selection.getRelativeBounds(); //Tab布局 FormSelectionUtils.paste2Container(designer, (XLayoutContainer) selection.getSelectedCreator(), - CLIP_BOARD, + clipboard, rec.x + rec.width / 2, rec.y + BORDER_PROPORTION); } else { Rectangle rec = selection.getRelativeBounds(); //自适应布局 FormSelectionUtils.paste2Container(designer, designer.getRootComponent(), - CLIP_BOARD, + clipboard, rec.x + rec.width / 2, rec.y + BORDER_PROPORTION); } @@ -140,7 +136,7 @@ public class SelectionModel { //编辑器外面还有两层容器,使用designer.getRootComponent()获取到的是编辑器中层的容器,不是编辑器表层 //当前选择的就是编辑器表层 FormSelectionUtils.paste2Container(designer, (XLayoutContainer) selection.getSelectedCreator(), - CLIP_BOARD, + clipboard, DELTA_X_Y, DELTA_X_Y); } @@ -148,7 +144,7 @@ public class SelectionModel { //cpt本地组件复用,编辑器就一层,是最底层,使用designer.getRootComponent()就可以获取到 //使用selection.getSelectedCreator()也应该是可以获取到的。 FormSelectionUtils.paste2Container(designer, designer.getRootComponent(), - CLIP_BOARD, + clipboard, DELTA_X_Y, DELTA_X_Y); } @@ -157,19 +153,16 @@ public class SelectionModel { else { //获取到编辑器的表层容器(已选的组件的父容器就是表层容器) parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator()); - if (selection.getSelectedCreator().getParent() instanceof XWFitLayout) { + if (parent != null && selection.getSelectedCreator().getParent() instanceof XWFitLayout) { //自适应布局 - if (parent != null) { - Rectangle rec = selection.getRelativeBounds(); - FormSelectionUtils.paste2Container(designer, parent, CLIP_BOARD, rec.x + rec.width / 2, rec.y + - rec.height - BORDER_PROPORTION); - } - } else if (selection.getSelectedCreator().getParent() instanceof XWAbsoluteLayout) { + 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) { //绝对布局 - if (parent != null) { - Rectangle rec = selection.getSelctionBounds(); - FormSelectionUtils.paste2Container(designer, parent, CLIP_BOARD, rec.x + DELTA_X_Y, rec.y + DELTA_X_Y); - } + Rectangle rec = selection.getSelctionBounds(); + FormSelectionUtils.paste2Container(designer, parent, clipboard, rec.x + DELTA_X_Y, rec.y + DELTA_X_Y); } } } else { @@ -223,14 +216,14 @@ public class SelectionModel { * 设置选择区域 */ public void setHotspotBounds(Rectangle rect) { - hotspot_bounds = rect; + hotspotBounds = rect; } /** * 获得当前选择区域 */ public Rectangle getHotspotBounds() { - return hotspot_bounds; + return hotspotBounds; } private void removeCreatorFromContainer(XCreator creator, int creatorWidth, int creatorHeight) { @@ -271,22 +264,28 @@ public class SelectionModel { * 其他两层不是靠添加组件就可以编辑的。 */ public boolean hasSelectionComponent() { + XCreator selectionXCreator = selection.getSelectedCreator(); if (designer.getClass().equals(FormDesigner.class)) { //frm本地组件复用 - return selection.getSelectedCreator() != null - && !( + if (selectionXCreator != null) { + if (selectionXCreator.getClass().equals(XWAbsoluteBodyLayout.class)) { //frm绝对布局编辑器 - selection.getSelectedCreator().getClass().equals(XWAbsoluteBodyLayout.class) - //Tab布局编辑器 - || selection.getSelectedCreator().getClass().equals(XWCardMainBorderLayout.class) - || selection.getSelectedCreator().getClass().equals(XWCardLayout.class) - || selection.getSelectedCreator().getClass().equals(XWTabFitLayout.class) - //自适应布局编辑器 - || selection.getSelectedCreator().getClass().equals(XWFitLayout.class) - ); + return false; + } else if (selectionXCreator.getClass().equals(XWCardMainBorderLayout.class) + || selectionXCreator.getClass().equals(XWCardLayout.class) + || selectionXCreator.getClass().equals(XWTabFitLayout.class)) { + //Tab布局编辑器 + return false; + } else { + //自适应布局编辑器 + return !selectionXCreator.getClass().equals(XWFitLayout.class); + } + } else { + return false; + } } else { //cpt本地组件复用,selection.getSelectedCreator().getParent()=@XWParameterLayout instanceof @XWAbsoluteLayout - return selection.getSelectedCreator() != null && selection.getSelectedCreator().getParent() != null; + return selectionXCreator != null && selectionXCreator.getParent() != null; } } @@ -330,10 +329,9 @@ public class SelectionModel { 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; - } + if (selection.size() == 1 && !ArrayUtils.contains(selection.getSelectedCreator().getDirections(), dir + .getActual())) { + dir = Location.outer; } } else { dir = Location.outer; diff --git a/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java b/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java index d929399d4a..f223e5d8f2 100644 --- a/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java +++ b/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java @@ -1,96 +1,96 @@ -/** - * - */ -package com.fr.design.designer.creator; - -import com.fr.form.ui.container.WLayout; - -import java.awt.*; -import java.beans.IntrospectionException; -import java.util.ArrayList; - -/** - * 一些控件专属的容器,如标题容器,sclae容器 - * - * @author jim - * @date 2014-11-7 - */ -public abstract class DedicateLayoutContainer extends XLayoutContainer { - - public DedicateLayoutContainer(WLayout widget, Dimension initSize) { - super(widget, initSize); - } - - /** - * 得到属性名 - * - * @return 属性名 - * @throws IntrospectionException - */ - public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException { - return new CRPropertyDescriptor[0]; - } - - /** - * 返回容器图标 - * - * @return - */ - @Override - public String getIconPath() { - if (this.getXCreator(XWScaleLayout.INDEX) != null) { - return this.getXCreator(XWScaleLayout.INDEX).getIconPath(); - } - return "/com/fr/web/images/form/resources/text_field_16.png"; - } - - - /** - * 控件树不显示此组件 - * - * @param path 控件树list - */ - public void notShowInComponentTree(ArrayList path) { - path.remove(path.size() - 1); - } - - /** - * 重置组件的名称 - * - * @param name 名称 - */ - public void resetCreatorName(String name) { - super.resetCreatorName(name); - XCreator child = getXCreator(XWScaleLayout.INDEX); - //实现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; - } - +/** + * + */ +package com.fr.design.designer.creator; + +import com.fr.form.ui.container.WLayout; + +import java.awt.*; +import java.beans.IntrospectionException; +import java.util.ArrayList; + +/** + * 一些控件专属的容器,如标题容器,sclae容器 + * + * @author jim + * @date 2014-11-7 + */ +public abstract class DedicateLayoutContainer extends XLayoutContainer { + + public DedicateLayoutContainer(WLayout widget, Dimension initSize) { + super(widget, initSize); + } + + /** + * 得到属性名 + * + * @return 属性名 + * @throws IntrospectionException + */ + public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException { + return new CRPropertyDescriptor[0]; + } + + /** + * 返回容器图标 + * + * @return + */ + @Override + public String getIconPath() { + if (this.getXCreator(XWScaleLayout.INDEX) != null) { + return this.getXCreator(XWScaleLayout.INDEX).getIconPath(); + } + return "/com/fr/web/images/form/resources/text_field_16.png"; + } + + + /** + * 控件树不显示此组件 + * + * @param path 控件树list + */ + public void notShowInComponentTree(ArrayList path) { + path.remove(path.size() - 1); + } + + /** + * 重置组件的名称 + * + * @param name 名称 + */ + public void resetCreatorName(String name) { + super.resetCreatorName(name); + XCreator child = getXCreator(XWScaleLayout.INDEX); + //实现WTitleLayout的SetWidgetName + child.toData().setWidgetName(name); + } + + /** + * 返回对应属性表的组件,scale和title返回其子组件 + * + * @return 组件 + */ + public XCreator getPropertyDescriptorCreator() { + return getXCreator(XWScaleLayout.INDEX); + } + + /** + * 是否作为控件树的叶子节点 + * + * @return 是则返回true + */ + public boolean isComponentTreeLeaf() { + return true; + } + + /** + * 是否为sclae和title专属容器 + * + * @return 是则返回true + */ + public boolean isDedicateContainer() { + return true; + } + } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java b/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java index fcda0c684f..589be7e83d 100644 --- a/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java +++ b/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java @@ -313,7 +313,7 @@ public class FormParaDesigner extends FormDesigner implements ParameterDesignerP */ public boolean isWithQueryButton() { XLayoutContainer rootContainer = this.getRootComponent(); - return SearchQueryCreators(rootContainer); + return searchQueryCreators(rootContainer); } /** @@ -322,18 +322,18 @@ public class FormParaDesigner extends FormDesigner implements ParameterDesignerP * @return 同上 */ public Action[] getActions() { - if (designer_actions == null) { - designer_actions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this), + if (designerActions == null) { + designerActions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this), new FormDeleteAction(this)}; } - return designer_actions; + return designerActions; } - private boolean SearchQueryCreators(XLayoutContainer rootContainer) { + private boolean searchQueryCreators(XLayoutContainer rootContainer) { boolean b = false; for (int i = 0; i < rootContainer.getXCreatorCount(); i++) { if (rootContainer.getXCreator(i) instanceof XLayoutContainer) { - b = SearchQueryCreators((XLayoutContainer) rootContainer.getXCreator(i)); + b = searchQueryCreators((XLayoutContainer) rootContainer.getXCreator(i)); } else if (rootContainer.getXCreator(i) instanceof XFormSubmit) { b = true; } diff --git a/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java b/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java index 2bc38699e2..a640058123 100644 --- a/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java +++ b/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java @@ -15,96 +15,96 @@ import com.fr.design.designer.creator.XWAbsoluteLayout; import com.fr.form.ui.Connector; public class ConnectorHelper { - //这个类是用来画连接线的,暂时用不到 - - public static final int NEAR = 5; - private static double ratio = 0.5; - private final static int ADSORPTION = 15; // 吸附距离 - private ArrayList drawingPoint; - private FormDesigner designer; - private boolean drawing; + //这个类是用来画连接线的,暂时用不到 - public ConnectorHelper(FormDesigner formEditor) { - this.designer = formEditor; - } - - public void resetConnector(Connector connector) { - ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(),connector.getStartPoint(),connector.getEndPoint()); - connector.addAll(cc.createPointList()); - } - - public boolean drawLining() { - return this.drawing; - } + public static final int NEAR = 5; + private static double ratio = 0.5; + private final static int ADSORPTION = 15; // 吸附距离 + private ArrayList drawingPoint; + private FormDesigner designer; + private boolean drawing; - public void setDrawLine(boolean d) { - this.drawing = d; - } - - private boolean near(Point p1, Point p2) { - return p1.x - p2.x < NEAR && p2.x - p1.x < NEAR && p1.y - p2.y < NEAR && p2.y - p1.y < NEAR; - } + public ConnectorHelper(FormDesigner formEditor) { + this.designer = formEditor; + } - private Point getNearPoint(MouseEvent e, Rectangle r) { - Point p1 = new Point((int) (r.x + r.getWidth() * ratio), r.y); - Point p2 = new Point((int) (r.x + r.getWidth()), (int) (r.y + r.getHeight() * ratio)); - Point p3 = new Point((int) (r.x + r.getWidth() * (1 - ratio)), (int) (r.y + r.getHeight())); - Point p4 = new Point(r.x, (int) (r.y + r.getHeight() * (1 - ratio))); - Point p = new Point(e.getX() + designer.getArea().getHorizontalValue(), e.getY() + designer.getArea().getVerticalValue()); - if (near(p, p1)) { - return p1; - } else if (near(p, p2)) { - return p2; - } else if (near(p, p3)) { - return p3; - } else if (near(p, p4)) { - return p4; - } - return null; - } - - private ArrayList createDefalutNode(Point startPoint, Point endPoint) { - long s = System.currentTimeMillis(); - ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(), new Point(startPoint), new Point(endPoint)); - ArrayList p = cc.createPointList(); - long e = System.currentTimeMillis(); - return p; - } + public void resetConnector(Connector connector) { + ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(), connector.getStartPoint(), connector.getEndPoint()); + connector.addAll(cc.createPointList()); + } - public void drawAuxiliaryLine(Graphics g) { - Point startPoint = designer.getStateModel().getStartPoint(); - Point endPoint = designer.getStateModel().getEndPoint(); - drawingPoint = createDefalutNode(startPoint, endPoint); - Point[] p = drawingPoint.toArray(new Point[drawingPoint.size()]); - g.setColor(Color.green); - for (int i = 0; i < p.length - 1; i++) { - GraphHelper.drawLine(g, p[i].x - designer.getArea().getHorizontalValue(), p[i].y - - designer.getArea().getVerticalValue(), p[i + 1].x - designer.getArea().getHorizontalValue(), - p[i + 1].y - designer.getArea().getVerticalValue(), Constants.LINE_HAIR); - } - } + public boolean drawLining() { + return this.drawing; + } - public void createDefalutLine() { - if (drawingPoint != null - && drawingPoint.size() > 1 - && ConnectorCreator.getMinimumDistance(drawingPoint.get(0), drawingPoint.get(drawingPoint.size() - 1)) > ADSORPTION) { - ((XWAbsoluteLayout) designer.getRootComponent()).addConnector(new Connector().addAll(drawingPoint)); - } - drawingPoint = null; - } + public void setDrawLine(boolean d) { + this.drawing = d; + } - public Point getNearWidgetPoint(MouseEvent e) { - BoundsWidget widget; - Point p = null; - for (int i = 0, size = designer.getTarget().getContainer().getWidgetCount(); i < size; i++) { - widget = ((BoundsWidget) designer.getTarget().getContainer().getWidget(i)); - if (widget.isVisible()) { - if ((p = getNearPoint(e, widget.getBounds())) != null) { - break; - } - } - } - return p; - } + private boolean near(Point p1, Point p2) { + return p1.x - p2.x < NEAR && p2.x - p1.x < NEAR && p1.y - p2.y < NEAR && p2.y - p1.y < NEAR; + } + + private Point getNearPoint(MouseEvent e, Rectangle r) { + Point p1 = new Point((int) (r.x + r.getWidth() * ratio), r.y); + Point p2 = new Point((int) (r.x + r.getWidth()), (int) (r.y + r.getHeight() * ratio)); + Point p3 = new Point((int) (r.x + r.getWidth() * (1 - ratio)), (int) (r.y + r.getHeight())); + Point p4 = new Point(r.x, (int) (r.y + r.getHeight() * (1 - ratio))); + Point p = new Point(e.getX() + designer.getArea().getHorizontalValue(), e.getY() + designer.getArea().getVerticalValue()); + if (near(p, p1)) { + return p1; + } else if (near(p, p2)) { + return p2; + } else if (near(p, p3)) { + return p3; + } else if (near(p, p4)) { + return p4; + } + return null; + } + + private ArrayList createDefalutNode(Point startPoint, Point endPoint) { + long s = System.currentTimeMillis(); + ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(), new Point(startPoint), new Point(endPoint)); + ArrayList p = cc.createPointList(); + long e = System.currentTimeMillis(); + return p; + } + + public void drawAuxiliaryLine(Graphics g) { + Point startPoint = designer.getStateModel().getStartPoint(); + Point endPoint = designer.getStateModel().getEndPoint(); + drawingPoint = createDefalutNode(startPoint, endPoint); + Point[] p = drawingPoint.toArray(new Point[drawingPoint.size()]); + g.setColor(Color.green); + for (int i = 0; i < p.length - 1; i++) { + GraphHelper.drawLine(g, p[i].x - designer.getArea().getHorizontalValue(), p[i].y + - designer.getArea().getVerticalValue(), p[i + 1].x - designer.getArea().getHorizontalValue(), + p[i + 1].y - designer.getArea().getVerticalValue(), Constants.LINE_HAIR); + } + } + + public void createDefalutLine() { + if (drawingPoint != null + && drawingPoint.size() > 1 + && ConnectorCreator.getMinimumDistance(drawingPoint.get(0), drawingPoint.get(drawingPoint.size() - 1)) > ADSORPTION) { + ((XWAbsoluteLayout) designer.getRootComponent()).addConnector(new Connector().addAll(drawingPoint)); + } + drawingPoint = null; + } + + public Point getNearWidgetPoint(MouseEvent e) { + BoundsWidget widget; + Point p = null; + for (int i = 0, size = designer.getTarget().getContainer().getWidgetCount(); i < size; i++) { + widget = ((BoundsWidget) designer.getTarget().getContainer().getWidget(i)); + if (widget.isVisible()) { + if ((p = getNearPoint(e, widget.getBounds())) != null) { + break; + } + } + } + return p; + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java b/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java index 9b4ccfeeb3..61323f4b7e 100644 --- a/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java +++ b/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java @@ -1,620 +1,621 @@ -package com.fr.design.mainframe; - -import com.fr.base.BaseUtils; -import com.fr.design.beans.location.MoveUtils; -import com.fr.design.designer.beans.AdapterBus; -import com.fr.design.designer.beans.ComponentAdapter; -import com.fr.design.designer.beans.events.DesignerEditor; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.design.designer.beans.location.Direction; -import com.fr.design.designer.beans.location.Location; -import com.fr.design.designer.beans.models.SelectionModel; -import com.fr.design.designer.beans.models.StateModel; -import com.fr.design.designer.creator.*; -import com.fr.design.designer.creator.cardlayout.XCardSwitchButton; -import com.fr.design.form.util.XCreatorConstants; -import com.fr.design.gui.ibutton.UIButton; -import com.fr.design.gui.xpane.ToolTipEditor; -import com.fr.design.icon.IconPathConstants; -import com.fr.design.utils.ComponentUtils; -import com.fr.design.utils.gui.LayoutUtils; -import com.fr.general.Inter; -import com.fr.stable.Constants; - -import javax.swing.*; -import javax.swing.event.MouseInputAdapter; -import java.awt.*; -import java.awt.event.MouseEvent; - -/** - * 普通模式下的鼠标点击、位置处理器 - */ -public class EditingMouseListener extends MouseInputAdapter { - - private static final int INDEX = 0; - private FormDesigner designer; - - /** - * 普通模式下对应的model - */ - private StateModel stateModel; - - - private XLayoutContainer xTopLayoutContainer; - private XLayoutContainer clickTopLayout; - - /** - * 获取表单设计器 - * - * @return 表单设计器 - */ - public FormDesigner getDesigner() { - return designer; - } - - /** - * 选择模型,存储当前选择的组件和剪切板 - */ - private SelectionModel selectionModel; - /** - * 获取选择模型 - * - * @return 选择 - */ - public SelectionModel getSelectionModel() { - return selectionModel; - } - - private XCreator last_creator; - private MouseEvent lastPressEvent; - private DesignerEditor current_editor; - private XCreator current_creator; - - //备份开始拖动的位置和大小 - private Rectangle dragBackupBounds; - - /** - * 获取最小移动距离 - * - * @return 最小移动距离 - */ - public int getMinMoveSize() { - return minMoveSize; - } - - private int minDragSize = 5; - private int minMoveSize = 8; - - private static final int EDIT_BTN_WIDTH = 60; - private static final int EDIT_BTN_HEIGHT = 24; - //报表块的编辑按钮不灵敏,范围扩大一点 - private static final int GAP = 10; - - private XElementCase xElementCase; - private XChartEditor xChartEditor; - - private JWindow promptWindow = new JWindow(); - - public EditingMouseListener(FormDesigner designer) { - this.designer = designer; - stateModel = designer.getStateModel(); - selectionModel = designer.getSelectionModel(); - UIButton promptButton = new UIButton(Inter.getLocText("FR-Designer_Forbid_Drag_into_Adapt_Pane"), BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); - this.promptWindow.add(promptButton); - } - - private void promptUser(int x, int y, XLayoutContainer container){ - if (!selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)){ - promptWidgetForbidEnter(x ,y , container); - } else { - cancelPromptWidgetForbidEnter(); - } - } - - private void promptWidgetForbidEnter(int x,int y, XLayoutContainer container){ - container.setBorder(BorderFactory.createLineBorder(Color.RED, Constants.LINE_MEDIUM)); - int screen_X = (int)designer.getArea().getLocationOnScreen().getX(); - int screen_Y = (int)designer.getArea().getLocationOnScreen().getY(); - this.promptWindow.setSize(promptWindow.getPreferredSize()); - this.promptWindow.setPreferredSize(promptWindow.getPreferredSize()); - promptWindow.setLocation(screen_X + x + GAP, screen_Y + y + GAP); - promptWindow.setVisible(true); - } - - private void cancelPromptWidgetForbidEnter(){ - designer.getRootComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN)); - promptWindow.setVisible(false); - } - - - /** - * 按下 - * @param e 鼠标事件 - */ - public void mousePressed(MouseEvent e) { - if (!stopEditing()) { - return; - } - if (!designer.isFocusOwner()) { - // 获取焦点,以便获取热键 - designer.requestFocus(); - } - if (e.isPopupTrigger()) { - // 为触发上下文菜单预留 - } else if (e.getButton() == MouseEvent.BUTTON1) { - - Direction dir = selectionModel.getDirectionAt(e); - if (!BaseUtils.isAuthorityEditing()) { - stateModel.setDirection(dir); - } - - if (dir == Location.outer) { - if (designer.isDrawLineMode()) { - designer.updateDrawLineMode(e); - } else { - if (selectionModel.hasSelectionComponent() - && selectionModel.getSelection().getRelativeBounds().contains( - designer.getArea().getHorizontalValue() + e.getX(), - designer.getArea().getVerticalValue() + e.getY())) { - lastPressEvent = e; - last_creator = selectionModel.getSelection().getSelectedCreator(); - } else { - stateModel.startSelecting(e); - } - } - } else { - stateModel.startResizing(e); - } - } - } - - /** - * 释放 - * @param e 鼠标事件 - */ - public void mouseReleased(MouseEvent e) { - if (e.isPopupTrigger()) { - if (stateModel.isDragging()) { - stateModel.draggingCancel(); - } - } else { - if (designer.isDrawLineMode()) { - if (stateModel.prepareForDrawLining()) { - designer.getDrawLineHelper().setDrawLine(false); - designer.getDrawLineHelper().createDefalutLine(); - } - } else if (stateModel.isSelecting()) { - // 如果当前是区域选择状态,则选择该区域所含的组件 - designer.selectComponents(e); - } - if (stateModel.isDragging()) { - mouseDraggingRelease(e); - } - } - lastPressEvent = null; - last_creator = null; - } - - private void mouseDraggingRelease(MouseEvent e) { - // 当前鼠标所在的组件 - XCreator hoveredComponent = designer.getComponentAt(e.getX(), e.getY()); - if(designer.isWidgetsIntersect() && dragBackupBounds != null && hoveredComponent != null){ - XCreator selectionXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); - if(selectionXCreator != null){ - selectionXCreator.setBounds(dragBackupBounds.x, dragBackupBounds.y, dragBackupBounds.width, dragBackupBounds.height); -// MoveUtils.hideForbidWindow(); - } - } - dragBackupBounds = null; - // 拉伸时鼠标拖动过快,导致所在组件获取会为空 - if (hoveredComponent == null && e.getY() < 0) { - // bug63538 - // 不是拖动过快导致的,而是纵坐标为负值导致的,这时参照横坐标为负值时的做法,取边界位置的组件,为鼠标所在点的组件 - // 如果直接return,界面上已经进行了拖拽不能恢复 - hoveredComponent = designer.getComponentAt(0, 0); - } - // 获取该组件所在的焦点容器 - XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent); - - if (container != null) { - boolean formSubmit2Adapt = !selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() - && container.acceptType(XWFitLayout.class); - if ( !formSubmit2Adapt) { - // 如果是处于拖拽状态,则释放组件 - stateModel.releaseDragging(e); - } else { - selectionModel.deleteSelection(); - designer.setPainter(null); - } - cancelPromptWidgetForbidEnter(); - } - } - - /** - * 激活上下文菜单,待完善 - * 6.56暂时不支持右键 bugid 8777 - */ - private void trigger_popup(MouseEvent e) { - - XCreator creator = selectionModel.getSelection().getSelectedCreator(); - - if (creator == null) { - return; - } - - JPopupMenu popupMenu = null; - ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, creator); - popupMenu = adapter.getContextPopupMenu(e); - - if (popupMenu != null) { - popupMenu.show(designer, e.getX(), e.getY()); - } - // 通知组件已经被选择了 - designer.getEditListenerTable().fireCreatorModified(creator, DesignerEvent.CREATOR_SELECTED); - } - - /** - * 移动 - * @param e 鼠标事件 - */ - public void mouseMoved(MouseEvent e) { - XCreator component = designer.getComponentAt(e); - - setCoverPaneNotDisplay(e, false); - - if(processTopLayoutMouseMove(component, e)){ - return; - } - if (component instanceof XEditorHolder) { - XEditorHolder xcreator = (XEditorHolder) component; - Rectangle rect = xcreator.getBounds(); - int min = rect.x + rect.width / 2 - minMoveSize; - int max = rect.x + rect.width / 2 + minMoveSize; - if (e.getX() > min && e.getX() < max) { - if (designer.getCursor().getType() != Cursor.HAND_CURSOR) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - return; - } else { - if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - } - } - Direction dir = selectionModel.getDirectionAt(e); - if (designer.isDrawLineMode() && stateModel.getDirection() == Location.outer) { - designer.updateDrawLineMode(e); - } - if (!BaseUtils.isAuthorityEditing()) { - stateModel.setDirection(dir); - } - - if (component.isReport()) { - elementCaseMouseMoved(e, component); - designer.repaint(); - return; - } - - processChartEditorMouseMove(component, e); - - designer.repaint(); - } - - private void elementCaseMouseMoved(MouseEvent e, XCreator component) { - xElementCase = (XElementCase)component; - UIButton button = (UIButton)xElementCase.getCoverPane().getComponent(0); - if(designer.getCursor().getType() == Cursor.HAND_CURSOR) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } // component.getParent() 是报表块所在的XWTitleLayout - int minX = button.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); - int minY = button.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); - if (e.getX() + GAP - xElementCase.getInsets().left > minX && e.getX() - GAP - xElementCase.getInsets().left < minX + button.getWidth()) { - if (e.getY() + GAP - xElementCase.getInsets().top > minY && e.getY() - GAP - xElementCase.getInsets().top < minY + button.getHeight()) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - } - xElementCase.setHelpBtnOnFocus(false); - if (xElementCase.getCoverPane().getComponentCount() > 1) { - JComponent button1 = (JComponent) xElementCase.getCoverPane().getComponent(1); - int minX1 = button1.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); - int minY1 = button1.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); - if (e.getX() + GAP - xElementCase.getInsets().left > minX1 && e.getX() - GAP - xElementCase.getInsets().left < minX1 + button1.getWidth()) { - if (e.getY() + GAP - xElementCase.getInsets().top > minY1 && e.getY() - GAP - xElementCase.getInsets().top < minY1 + button1.getHeight()) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - xElementCase.setHelpBtnOnFocus(true); - } - } - } - xElementCase.displayCoverPane(true); - xElementCase.setDirections(Direction.TOP_BOTTOM_LEFT_RIGHT); - } - - private void setCoverPaneNotDisplay(MouseEvent e, boolean isLinkedHelpDialog) { - if (xElementCase != null) { - int x = getParentPositionX(xElementCase, 0) - designer.getArea().getHorizontalValue(); - int y = getParentPositionY(xElementCase, 0) - designer.getArea().getVerticalValue(); - Rectangle rect = new Rectangle(x, y, xElementCase.getWidth(), xElementCase.getHeight()); - if (rect.contains(e.getPoint())) { - return; - } - if(isLinkedHelpDialog){ - xElementCase.destroyHelpDialog(); - } - xElementCase.displayCoverPane(false); - } - if (xChartEditor != null){ - xChartEditor.displayCoverPane(false); - } - - if (xTopLayoutContainer != null) { - xTopLayoutContainer.setMouseEnter(false); - } - designer.repaint(); - } - - private boolean processTopLayoutMouseMove(XCreator component, MouseEvent e){ - XLayoutContainer parent = XCreatorUtils.getHotspotContainer(component).getTopLayout(); - if (parent != null){ - xTopLayoutContainer = parent; - xTopLayoutContainer.setMouseEnter(true); - designer.repaint(); - if(!xTopLayoutContainer.isEditable()) { - if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - int minX = getParentPositionX(parent, parent.getX()) + parent.getWidth() / 2; - int minY = getParentPositionY(parent, parent.getY()) + parent.getHeight() / 2; - int offsetX = EDIT_BTN_WIDTH / 2 + GAP; - int offsetY = EDIT_BTN_HEIGHT / 2 + GAP; - if (e.getX() > (minX - offsetX) && e.getX() < (minX + offsetX)) { - if (e.getY() > (minY - offsetY) && e.getY() < (minY + offsetY + designer.getParaHeight())) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - } - return true; - } - } - return false; - } - - private void processChartEditorMouseMove(XCreator component, MouseEvent e){ - if (component instanceof XChartEditor) { - xChartEditor = (XChartEditor)component; - UIButton button = (UIButton)xChartEditor.getCoverPane().getComponent(0); - if(designer.getCursor().getType() ==Cursor.HAND_CURSOR) { - designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - int minX = button.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); - int minY = button.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); - if(e.getX() + GAP > minX && e.getX() - GAP < minX + button.getWidth()){ - if( e.getY() + GAP > minY && e.getY() - GAP < minY + button.getHeight()){ - designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - } - xChartEditor.displayCoverPane(true); - xChartEditor.setDirections(Direction.TOP_BOTTOM_LEFT_RIGHT); - designer.repaint(); - } - } - - private int getParentPositionX(XCreator comp, int x){ - return comp.getParent() == null ? - x : getParentPositionX((XCreator)comp.getParent(), comp.getParent().getX() + x); - } - - private int getParentPositionY(XCreator comp, int y) { - return comp.getParent() == null ? - y : getParentPositionY((XCreator) comp.getParent(), comp.getParent().getY() + y); - } - - /** - * 拖拽 - * @param e 鼠标事件 - */ - public void mouseDragged(MouseEvent e) { - if (BaseUtils.isAuthorityEditing()) { - return; - } - // 如果当前是左键拖拽状态,拖拽组件 - if (stateModel.dragable()) { - if (SwingUtilities.isRightMouseButton(e)) { - return; - } else { - stateModel.dragging(e); - // 获取e所在的焦点组件 - XCreator hotspot = designer.getComponentAt(e.getX(), e.getY()); - if(dragBackupBounds == null) { - XCreator selectingXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); - if(selectingXCreator != null){ - dragBackupBounds = new Rectangle(selectingXCreator.getX(), selectingXCreator.getY(), selectingXCreator.getWidth(), selectingXCreator.getHeight()); - } - } - // 拉伸时鼠标拖动过快,导致所在组件获取会为空 - if (hotspot == null) { - return; - } - // 获取焦点组件所在的焦点容器 - XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot); - //提示组件是否可以拖入 - promptUser(e.getX(), e.getY(), container); - } - } else if (designer.isDrawLineMode()) { - if (stateModel.prepareForDrawLining()) { - stateModel.drawLine(e); - } - } else if (stateModel.isSelecting() && (selectionModel.getHotspotBounds() != null)) { - // 如果是拖拽选择区域状态,则更新选择区域 - stateModel.changeSelection(e); - } else { - if ((lastPressEvent == null) || (last_creator == null)) { - return; - } - if (e.getPoint().distance(lastPressEvent.getPoint()) > minDragSize) { - //参数面板和自适应布局不支持拖拽 - if (last_creator.isSupportDrag()){ - designer.startDraggingComponent(last_creator, lastPressEvent, e.getX(), e.getY()); - } - e.consume(); - lastPressEvent = null; - } - } - designer.repaint(); - } - - //当前编辑的组件是在布局中,鼠标点击布局外部,需要一次性将布局及其父布局都置为不可编辑 - private void setTopLayoutUnEditable(XLayoutContainer clickedTopLayout, XLayoutContainer clickingTopLayout){ - //双击的前后点击click为相同对象,过滤掉 - if (clickedTopLayout == null || clickedTopLayout == clickingTopLayout){ - return; - } - //位于同一层级的控件,父布局相同,过滤掉 - if (clickingTopLayout != null && clickedTopLayout.getParent() == clickingTopLayout.getParent()){ - return; - } - //前后点击的位于不同层级,要置为不可编辑 - XLayoutContainer xLayoutContainer = (XLayoutContainer)clickedTopLayout.getParent(); - if (xLayoutContainer == clickingTopLayout){ - return; - } - if (xLayoutContainer != null){ - xLayoutContainer.setEditable(false); - setTopLayoutUnEditable((XLayoutContainer) clickedTopLayout.getParent(), clickingTopLayout); - } - } - - private boolean isCreatorInLayout(XCreator creator, XCreator layout){ - if (creator == layout){ - return true; - } - if(layout.getParent() != null){ - return isCreatorInLayout(creator, (XCreator)layout.getParent()); - } - return false; - } - - private XCreator processTopLayoutMouseClick(XCreator creator){ - XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(creator).getTopLayout(); - if(topLayout != null){ - if (clickTopLayout != null && clickTopLayout != topLayout && !isCreatorInLayout(clickTopLayout, topLayout)){ - clickTopLayout.setEditable(false); - setTopLayoutUnEditable(clickTopLayout, topLayout); - } - clickTopLayout = topLayout; - if(!topLayout.isEditable()) { - creator = topLayout; - } - } - else{ - if(clickTopLayout != null){ - clickTopLayout.setEditable(false); - setTopLayoutUnEditable(clickTopLayout, null); - } - } - - return creator; - } - /** - * 点击 - * @param e 鼠标事件 - */ - public void mouseClicked(MouseEvent e) { - XCreator creator = designer.getComponentAt(e); - - if (e.getButton() != MouseEvent.BUTTON1 && !creator.acceptType(XCardSwitchButton.class)) { - return; - } - - creator = processTopLayoutMouseClick(creator); - - if(creator != null){ - creator.respondClick(this, e); - } - creator.doLayout(); - LayoutUtils.layoutRootContainer(designer.getRootComponent()); - } - - - - /** - * 离开 - * @param e 鼠标事件 - */ - public void mouseExited(MouseEvent e) { - if (designer.getCursor().getType() != Cursor.DEFAULT_CURSOR) { - designer.setCursor(Cursor.getDefaultCursor()); - } - - setCoverPaneNotDisplay(e, true); - - cancelPromptWidgetForbidEnter(); - } - - /** - * 开始编辑 - * @param creator 容器 - * @param designerEditor 设计器 - * @param adapter 适配器 - */ - public void startEditing(XCreator creator, DesignerEditor designerEditor, ComponentAdapter adapter) { - if (designerEditor != null) { - Rectangle rect = ComponentUtils.getRelativeBounds(creator); - current_editor = designerEditor; - current_creator = creator; - Rectangle bounds = new Rectangle(1, 1, creator.getWidth() - 2, creator.getHeight() - 2); - bounds.x += (rect.x - designer.getArea().getHorizontalValue()); - bounds.y += (rect.y - designer.getArea().getVerticalValue()); - designerEditor.getEditorTarget().setBounds(bounds); - designer.add(designerEditor.getEditorTarget()); - designer.invalidate(); - designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - designerEditor.getEditorTarget().requestFocus(); - designer.repaint(); - } - } - - /** - * 停止编辑 - * @return 是否编辑成功 - */ - public boolean stopEditing() { - if (current_editor != null) { - designer.remove(current_editor.getEditorTarget()); - current_editor.fireEditStoped(); - - Container container = current_creator.getParent(); - - if (container != null) { - LayoutUtils.layoutRootContainer(container); - } - designer.invalidate(); - designer.repaint(); - current_creator = null; - current_editor = null; - return true; - } - return true; - } - - /** - * 重置编辑控件大小 - */ - public void resetEditorComponentBounds() { - if (current_editor == null) { - return; - } - - if (current_creator.getParent() == null) { - stopEditing(); - return; - } - - Rectangle rect = ComponentUtils.getRelativeBounds(current_creator); - Rectangle bounds = new Rectangle(1, 1, current_creator.getWidth() - 2, current_creator.getHeight() - 2); - bounds.x += (rect.x - designer.getArea().getHorizontalValue()); - bounds.y += (rect.y - designer.getArea().getVerticalValue()); - if (current_creator instanceof XEditorHolder) { - ToolTipEditor.getInstance().resetBounds((XEditorHolder) current_creator, bounds, current_editor.getEditorTarget().getBounds()); - } - current_editor.getEditorTarget().setBounds(bounds); - } +package com.fr.design.mainframe; + +import com.fr.base.BaseUtils; +import com.fr.design.designer.beans.AdapterBus; +import com.fr.design.designer.beans.ComponentAdapter; +import com.fr.design.designer.beans.events.DesignerEditor; +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.beans.location.Direction; +import com.fr.design.designer.beans.location.Location; +import com.fr.design.designer.beans.models.SelectionModel; +import com.fr.design.designer.beans.models.StateModel; +import com.fr.design.designer.creator.*; +import com.fr.design.designer.creator.cardlayout.XCardSwitchButton; +import com.fr.design.form.util.XCreatorConstants; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.xpane.ToolTipEditor; +import com.fr.design.icon.IconPathConstants; +import com.fr.design.utils.ComponentUtils; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.general.Inter; +import com.fr.stable.Constants; + +import javax.swing.*; +import javax.swing.event.MouseInputAdapter; +import java.awt.*; +import java.awt.event.MouseEvent; + +/** + * 普通模式下的鼠标点击、位置处理器 + */ +public class EditingMouseListener extends MouseInputAdapter { + + private FormDesigner designer; + + /** + * 普通模式下对应的model + */ + private StateModel stateModel; + + + private XLayoutContainer xTopLayoutContainer; + private XLayoutContainer clickTopLayout; + + /** + * 获取表单设计器 + * + * @return 表单设计器 + */ + public FormDesigner getDesigner() { + return designer; + } + + /** + * 选择模型,存储当前选择的组件和剪切板 + */ + private SelectionModel selectionModel; + + /** + * 获取选择模型 + * + * @return 选择 + */ + public SelectionModel getSelectionModel() { + return selectionModel; + } + + private XCreator lastXCreator; + private MouseEvent lastPressEvent; + private DesignerEditor currentEditor; + private XCreator currentXCreator; + + //备份开始拖动的位置和大小 + private Rectangle dragBackupBounds; + + /** + * 获取最小移动距离 + * + * @return 最小移动距离 + */ + public int getMinMoveSize() { + return minMoveSize; + } + + private int minDragSize = 5; + private int minMoveSize = 8; + + private static final int EDIT_BTN_WIDTH = 60; + private static final int EDIT_BTN_HEIGHT = 24; + //报表块的编辑按钮不灵敏,范围扩大一点 + private static final int GAP = 10; + + private XElementCase xElementCase; + private XChartEditor xChartEditor; + + private JWindow promptWindow = new JWindow(); + + public EditingMouseListener(FormDesigner designer) { + this.designer = designer; + stateModel = designer.getStateModel(); + selectionModel = designer.getSelectionModel(); + UIButton promptButton = new UIButton(Inter.getLocText("FR-Designer_Forbid_Drag_into_Adapt_Pane"), BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); + this.promptWindow.add(promptButton); + } + + private void promptUser(int x, int y, XLayoutContainer container) { + if (!selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)) { + promptWidgetForbidEnter(x, y, container); + } else { + cancelPromptWidgetForbidEnter(); + } + } + + private void promptWidgetForbidEnter(int x, int y, XLayoutContainer container) { + container.setBorder(BorderFactory.createLineBorder(Color.RED, Constants.LINE_MEDIUM)); + int screenX = (int) designer.getArea().getLocationOnScreen().getX(); + int screenY = (int) designer.getArea().getLocationOnScreen().getY(); + this.promptWindow.setSize(promptWindow.getPreferredSize()); + this.promptWindow.setPreferredSize(promptWindow.getPreferredSize()); + promptWindow.setLocation(screenX + x + GAP, screenY + y + GAP); + promptWindow.setVisible(true); + } + + private void cancelPromptWidgetForbidEnter() { + designer.getRootComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN)); + promptWindow.setVisible(false); + } + + + /** + * 按下 + * + * @param e 鼠标事件 + */ + public void mousePressed(MouseEvent e) { + if (!stopEditing()) { + return; + } + if (!designer.isFocusOwner()) { + // 获取焦点,以便获取热键 + designer.requestFocus(); + } + if (e.getButton() == MouseEvent.BUTTON1) { + + Direction dir = selectionModel.getDirectionAt(e); + if (!BaseUtils.isAuthorityEditing()) { + stateModel.setDirection(dir); + } + + if (dir == Location.outer) { + if (designer.isDrawLineMode()) { + designer.updateDrawLineMode(e); + } else { + if (selectionModel.hasSelectionComponent() + && selectionModel.getSelection().getRelativeBounds().contains( + designer.getArea().getHorizontalValue() + e.getX(), + designer.getArea().getVerticalValue() + e.getY())) { + lastPressEvent = e; + lastXCreator = selectionModel.getSelection().getSelectedCreator(); + } else { + stateModel.startSelecting(e); + } + } + } else { + stateModel.startResizing(e); + } + } + } + + /** + * 释放 + * + * @param e 鼠标事件 + */ + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) { + if (stateModel.isDragging()) { + stateModel.draggingCancel(); + } + } else { + if (designer.isDrawLineMode()) { + if (stateModel.prepareForDrawLining()) { + designer.getDrawLineHelper().setDrawLine(false); + designer.getDrawLineHelper().createDefalutLine(); + } + } else if (stateModel.isSelecting()) { + // 如果当前是区域选择状态,则选择该区域所含的组件 + designer.selectComponents(e); + } + if (stateModel.isDragging()) { + mouseDraggingRelease(e); + } + } + lastPressEvent = null; + lastXCreator = null; + } + + private void mouseDraggingRelease(MouseEvent e) { + // 当前鼠标所在的组件 + XCreator hoveredComponent = designer.getComponentAt(e.getX(), e.getY()); + if (designer.isWidgetsIntersect() && dragBackupBounds != null && hoveredComponent != null) { + XCreator selectionXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); + if (selectionXCreator != null) { + selectionXCreator.setBounds(dragBackupBounds.x, dragBackupBounds.y, dragBackupBounds.width, dragBackupBounds.height); + } + } + dragBackupBounds = null; + // 拉伸时鼠标拖动过快,导致所在组件获取会为空 + if (hoveredComponent == null && e.getY() < 0) { + // bug63538 + // 不是拖动过快导致的,而是纵坐标为负值导致的,这时参照横坐标为负值时的做法,取边界位置的组件,为鼠标所在点的组件 + // 如果直接return,界面上已经进行了拖拽不能恢复 + hoveredComponent = designer.getComponentAt(0, 0); + } + // 获取该组件所在的焦点容器 + XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent); + + if (container != null) { + boolean formSubmit2Adapt = !selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() + && container.acceptType(XWFitLayout.class); + if (!formSubmit2Adapt) { + // 如果是处于拖拽状态,则释放组件 + stateModel.releaseDragging(e); + } else { + selectionModel.deleteSelection(); + designer.setPainter(null); + } + cancelPromptWidgetForbidEnter(); + } + } + + /** + * TODO 激活上下文菜单,待完善 + * 6.56暂时不支持右键 bugid 8777 + */ + private void triggerPopup(MouseEvent e) { + XCreator creator = selectionModel.getSelection().getSelectedCreator(); + if (creator == null) { + return; + } + JPopupMenu popupMenu = null; + ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, creator); + popupMenu = adapter.getContextPopupMenu(e); + + if (popupMenu != null) { + popupMenu.show(designer, e.getX(), e.getY()); + } + // 通知组件已经被选择了 + designer.getEditListenerTable().fireCreatorModified(creator, DesignerEvent.CREATOR_SELECTED); + } + + /** + * 移动 + * + * @param e 鼠标事件 + */ + public void mouseMoved(MouseEvent e) { + XCreator component = designer.getComponentAt(e); + + setCoverPaneNotDisplay(e, false); + + if (processTopLayoutMouseMove(component, e)) { + return; + } + if (component instanceof XEditorHolder) { + XEditorHolder xcreator = (XEditorHolder) component; + Rectangle rect = xcreator.getBounds(); + int min = rect.x + rect.width / 2 - minMoveSize; + int max = rect.x + rect.width / 2 + minMoveSize; + if (e.getX() > min && e.getX() < max) { + if (designer.getCursor().getType() != Cursor.HAND_CURSOR) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + return; + } else { + if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + } + Direction dir = selectionModel.getDirectionAt(e); + if (designer.isDrawLineMode() && stateModel.getDirection() == Location.outer) { + designer.updateDrawLineMode(e); + } + if (!BaseUtils.isAuthorityEditing()) { + stateModel.setDirection(dir); + } + + if (component.isReport()) { + elementCaseMouseMoved(e, component); + designer.repaint(); + return; + } + + processChartEditorMouseMove(component, e); + + designer.repaint(); + } + + private void elementCaseMouseMoved(MouseEvent e, XCreator component) { + xElementCase = (XElementCase) component; + UIButton button = (UIButton) xElementCase.getCoverPane().getComponent(0); + if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } // component.getParent() 是报表块所在的XWTitleLayout + int minX = button.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); + int minY = button.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); + if (e.getX() + GAP - xElementCase.getInsets().left > minX && e.getX() - GAP - xElementCase.getInsets().left < minX + button.getWidth()) { + if (e.getY() + GAP - xElementCase.getInsets().top > minY && e.getY() - GAP - xElementCase.getInsets().top < minY + button.getHeight()) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + } + xElementCase.setHelpBtnOnFocus(false); + if (xElementCase.getCoverPane().getComponentCount() > 1) { + JComponent button1 = (JComponent) xElementCase.getCoverPane().getComponent(1); + int minX1 = button1.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); + int minY1 = button1.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); + if (e.getX() + GAP - xElementCase.getInsets().left > minX1 && e.getX() - GAP - xElementCase.getInsets().left < minX1 + button1.getWidth()) { + if (e.getY() + GAP - xElementCase.getInsets().top > minY1 && e.getY() - GAP - xElementCase.getInsets().top < minY1 + button1.getHeight()) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + xElementCase.setHelpBtnOnFocus(true); + } + } + } + xElementCase.displayCoverPane(true); + xElementCase.setDirections(Direction.TOP_BOTTOM_LEFT_RIGHT); + } + + private void setCoverPaneNotDisplay(MouseEvent e, boolean isLinkedHelpDialog) { + if (xElementCase != null) { + int x = getParentPositionX(xElementCase, 0) - designer.getArea().getHorizontalValue(); + int y = getParentPositionY(xElementCase, 0) - designer.getArea().getVerticalValue(); + Rectangle rect = new Rectangle(x, y, xElementCase.getWidth(), xElementCase.getHeight()); + if (rect.contains(e.getPoint())) { + return; + } + if (isLinkedHelpDialog) { + xElementCase.destroyHelpDialog(); + } + xElementCase.displayCoverPane(false); + } + if (xChartEditor != null) { + xChartEditor.displayCoverPane(false); + } + + if (xTopLayoutContainer != null) { + xTopLayoutContainer.setMouseEnter(false); + } + designer.repaint(); + } + + private boolean processTopLayoutMouseMove(XCreator component, MouseEvent e) { + XLayoutContainer parent = XCreatorUtils.getHotspotContainer(component).getTopLayout(); + if (parent != null) { + xTopLayoutContainer = parent; + xTopLayoutContainer.setMouseEnter(true); + designer.repaint(); + if (!xTopLayoutContainer.isEditable()) { + if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + int minX = getParentPositionX(parent, parent.getX()) + parent.getWidth() / 2; + int minY = getParentPositionY(parent, parent.getY()) + parent.getHeight() / 2; + int offsetX = EDIT_BTN_WIDTH / 2 + GAP; + int offsetY = EDIT_BTN_HEIGHT / 2 + GAP; + if (e.getX() > (minX - offsetX) && e.getX() < (minX + offsetX)) { + if (e.getY() > (minY - offsetY) && e.getY() < (minY + offsetY + designer.getParaHeight())) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + } + return true; + } + } + return false; + } + + private void processChartEditorMouseMove(XCreator component, MouseEvent e) { + if (component instanceof XChartEditor) { + xChartEditor = (XChartEditor) component; + UIButton button = (UIButton) xChartEditor.getCoverPane().getComponent(0); + if (designer.getCursor().getType() == Cursor.HAND_CURSOR) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + int minX = button.getX() + getParentPositionX(component, 0) - designer.getArea().getHorizontalValue(); + int minY = button.getY() + getParentPositionY(component, 0) - designer.getArea().getVerticalValue(); + if (e.getX() + GAP > minX && e.getX() - GAP < minX + button.getWidth()) { + if (e.getY() + GAP > minY && e.getY() - GAP < minY + button.getHeight()) { + designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + } + xChartEditor.displayCoverPane(true); + xChartEditor.setDirections(Direction.TOP_BOTTOM_LEFT_RIGHT); + designer.repaint(); + } + } + + private int getParentPositionX(XCreator comp, int x) { + return comp.getParent() == null ? + x : getParentPositionX((XCreator) comp.getParent(), comp.getParent().getX() + x); + } + + private int getParentPositionY(XCreator comp, int y) { + return comp.getParent() == null ? + y : getParentPositionY((XCreator) comp.getParent(), comp.getParent().getY() + y); + } + + /** + * 拖拽 + * + * @param e 鼠标事件 + */ + public void mouseDragged(MouseEvent e) { + if (BaseUtils.isAuthorityEditing()) { + return; + } + // 如果当前是左键拖拽状态,拖拽组件 + if (stateModel.dragable()) { + if (SwingUtilities.isRightMouseButton(e)) { + return; + } else { + stateModel.dragging(e); + // 获取e所在的焦点组件 + XCreator hotspot = designer.getComponentAt(e.getX(), e.getY()); + if (dragBackupBounds == null) { + XCreator selectingXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); + if (selectingXCreator != null) { + dragBackupBounds = new Rectangle(selectingXCreator.getX(), selectingXCreator.getY(), selectingXCreator.getWidth(), selectingXCreator.getHeight()); + } + } + // 拉伸时鼠标拖动过快,导致所在组件获取会为空 + if (hotspot == null) { + return; + } + // 获取焦点组件所在的焦点容器 + XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot); + //提示组件是否可以拖入 + promptUser(e.getX(), e.getY(), container); + } + } else if (designer.isDrawLineMode()) { + if (stateModel.prepareForDrawLining()) { + stateModel.drawLine(e); + } + } else if (stateModel.isSelecting() && (selectionModel.getHotspotBounds() != null)) { + // 如果是拖拽选择区域状态,则更新选择区域 + stateModel.changeSelection(e); + } else { + if ((lastPressEvent == null) || (lastXCreator == null)) { + return; + } + if (e.getPoint().distance(lastPressEvent.getPoint()) > minDragSize) { + //参数面板和自适应布局不支持拖拽 + if (lastXCreator.isSupportDrag()) { + designer.startDraggingComponent(lastXCreator, lastPressEvent, e.getX(), e.getY()); + } + e.consume(); + lastPressEvent = null; + } + } + designer.repaint(); + } + + //当前编辑的组件是在布局中,鼠标点击布局外部,需要一次性将布局及其父布局都置为不可编辑 + private void setTopLayoutUnEditable(XLayoutContainer clickedTopLayout, XLayoutContainer clickingTopLayout) { + //双击的前后点击click为相同对象,过滤掉 + if (clickedTopLayout == null || clickedTopLayout == clickingTopLayout) { + return; + } + //位于同一层级的控件,父布局相同,过滤掉 + if (clickingTopLayout != null && clickedTopLayout.getParent() == clickingTopLayout.getParent()) { + return; + } + //前后点击的位于不同层级,要置为不可编辑 + XLayoutContainer xLayoutContainer = (XLayoutContainer) clickedTopLayout.getParent(); + if (xLayoutContainer == clickingTopLayout) { + return; + } + if (xLayoutContainer != null) { + xLayoutContainer.setEditable(false); + setTopLayoutUnEditable((XLayoutContainer) clickedTopLayout.getParent(), clickingTopLayout); + } + } + + private boolean isCreatorInLayout(XCreator creator, XCreator layout) { + if (creator.equals(layout)) { + return true; + } + if (layout.getParent() != null) { + return isCreatorInLayout(creator, (XCreator) layout.getParent()); + } + return false; + } + + private XCreator processTopLayoutMouseClick(XCreator creator) { + XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(creator).getTopLayout(); + if (topLayout != null) { + if (clickTopLayout != null && !clickTopLayout.equals(topLayout) && !isCreatorInLayout(clickTopLayout, + topLayout)) { + clickTopLayout.setEditable(false); + setTopLayoutUnEditable(clickTopLayout, topLayout); + } + clickTopLayout = topLayout; + if (!topLayout.isEditable()) { + creator = topLayout; + } + } else { + if (clickTopLayout != null) { + clickTopLayout.setEditable(false); + setTopLayoutUnEditable(clickTopLayout, null); + } + } + + return creator; + } + + /** + * 点击 + * + * @param e 鼠标事件 + */ + public void mouseClicked(MouseEvent e) { + XCreator creator = designer.getComponentAt(e); + + if (e.getButton() != MouseEvent.BUTTON1 && !creator.acceptType(XCardSwitchButton.class)) { + return; + } + + creator = processTopLayoutMouseClick(creator); + + if (creator != null) { + creator.respondClick(this, e); + } + creator.doLayout(); + LayoutUtils.layoutRootContainer(designer.getRootComponent()); + } + + + /** + * 离开 + * + * @param e 鼠标事件 + */ + public void mouseExited(MouseEvent e) { + if (designer.getCursor().getType() != Cursor.DEFAULT_CURSOR) { + designer.setCursor(Cursor.getDefaultCursor()); + } + + setCoverPaneNotDisplay(e, true); + + cancelPromptWidgetForbidEnter(); + } + + /** + * 开始编辑 + * + * @param creator 容器 + * @param designerEditor 设计器 + * @param adapter 适配器 + */ + public void startEditing(XCreator creator, DesignerEditor designerEditor, ComponentAdapter adapter) { + if (designerEditor != null) { + Rectangle rect = ComponentUtils.getRelativeBounds(creator); + currentEditor = designerEditor; + currentXCreator = creator; + Rectangle bounds = new Rectangle(1, 1, creator.getWidth() - 2, creator.getHeight() - 2); + bounds.x += (rect.x - designer.getArea().getHorizontalValue()); + bounds.y += (rect.y - designer.getArea().getVerticalValue()); + designerEditor.getEditorTarget().setBounds(bounds); + designer.add(designerEditor.getEditorTarget()); + designer.invalidate(); + designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + designerEditor.getEditorTarget().requestFocus(); + designer.repaint(); + } + } + + /** + * 停止编辑 + * + * @return 是否编辑成功 + */ + public boolean stopEditing() { + if (currentEditor != null) { + designer.remove(currentEditor.getEditorTarget()); + currentEditor.fireEditStoped(); + + Container container = currentXCreator.getParent(); + + if (container != null) { + LayoutUtils.layoutRootContainer(container); + } + designer.invalidate(); + designer.repaint(); + currentXCreator = null; + currentEditor = null; + return true; + } + return true; + } + + /** + * 重置编辑控件大小 + */ + public void resetEditorComponentBounds() { + if (currentEditor == null) { + return; + } + + if (currentXCreator.getParent() == null) { + stopEditing(); + return; + } + + Rectangle rect = ComponentUtils.getRelativeBounds(currentXCreator); + Rectangle bounds = new Rectangle(1, 1, currentXCreator.getWidth() - 2, currentXCreator.getHeight() - 2); + bounds.x += (rect.x - designer.getArea().getHorizontalValue()); + bounds.y += (rect.y - designer.getArea().getVerticalValue()); + if (currentXCreator instanceof XEditorHolder) { + ToolTipEditor.getInstance().resetBounds((XEditorHolder) currentXCreator, bounds, currentEditor.getEditorTarget().getBounds()); + } + currentEditor.getEditorTarget().setBounds(bounds); + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/FormDesigner.java b/designer_form/src/com/fr/design/mainframe/FormDesigner.java index d78cb5557e..1dd61c5597 100644 --- a/designer_form/src/com/fr/design/mainframe/FormDesigner.java +++ b/designer_form/src/com/fr/design/mainframe/FormDesigner.java @@ -46,7 +46,6 @@ import com.fr.form.ui.container.WFitLayout; import com.fr.general.ComparatorUtils; import com.fr.general.FRLogger; import com.fr.general.Inter; -import com.fr.plugin.ExtraClassManager; import com.fr.stable.ArrayUtils; import com.fr.stable.bridge.StableFactory; @@ -72,7 +71,6 @@ public class FormDesigner extends TargetComponent
implements TreeSelection protected static final ArrayList NAME_ARRAY_LIST = new ArrayList( Arrays.asList(new String[]{Inter.getLocText("M_Edit-Cut"), Inter.getLocText("M_Edit-Copy"), Inter.getLocText("M_Edit-Delete")}) ); - private static final int BORDER_WIDTH = 6; //底层容器的默认大小 protected static final Dimension LARGE_PREFERRED_SIZE = new Dimension(WBorderLayout.DEFAULT_WIDTH, WBorderLayout.DEFAULT_HEIGHT); private int paraHeight = 0; @@ -84,7 +82,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection private XLayoutContainer paraComponent; private boolean drawLineMode; private FormArea formArea; - private ConnectorHelper ConnectorHelper; + private ConnectorHelper connectorHelper; private boolean isReportBlockEditing = false; //组件重叠 @@ -107,7 +105,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection // 编辑状态的事件表 private CreatorEventListenerTable edit; - protected Action[] designer_actions; + protected Action[] designerActions; private FormDesignerModeForSpecial desigerMode; private Action switchAction; private FormElementCaseContainerProvider elementCaseContainer; @@ -763,12 +761,9 @@ public class FormDesigner extends TargetComponent implements TreeSelection * @param e 鼠标事件 */ public void updateDrawLineMode(MouseEvent e) { - Point p = ConnectorHelper.getNearWidgetPoint(e); - if (p == null) { - XComponent comp = getComponentAt(e); - if (comp == rootComponent) { - p = new Point(e.getX() + formArea.getHorizontalValue(), e.getY() + formArea.getVerticalValue()); - } + Point p = connectorHelper.getNearWidgetPoint(e); + if (p == null && getComponentAt(e) == rootComponent) { + p = new Point(e.getX() + formArea.getHorizontalValue(), e.getY() + formArea.getVerticalValue()); } stateModel.startDrawLine(p); } @@ -1120,11 +1115,11 @@ public class FormDesigner extends TargetComponent implements TreeSelection * @return 同上 */ public Action[] getActions() { - if (designer_actions == null) { - designer_actions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this), + if (designerActions == null) { + designerActions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this), new FormDeleteAction(this)}; } - return designer_actions; + return designerActions; } protected Border getOuterBorder() { @@ -1191,7 +1186,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection * @return ConnectorHelper类 */ public ConnectorHelper getDrawLineHelper() { - return ConnectorHelper; + return connectorHelper; } /** diff --git a/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java b/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java index dc40b0e181..4f6c937bc7 100644 --- a/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java +++ b/designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java @@ -204,14 +204,14 @@ public class FormSelectionUtils { private static ArrayList rebuildSelection(XCreator rootComponent, List selectionWidget, ArrayList newSelection) { - FormSelectionUtils._rebuild(rootComponent, selectionWidget, newSelection); + FormSelectionUtils.rebuild(rootComponent, selectionWidget, newSelection); if (newSelection.isEmpty()) { newSelection.add(rootComponent); } return newSelection; } - private static void _rebuild(XCreator root, List selectionWidget, List newSelection) { + private static void rebuild(XCreator root, List selectionWidget, List newSelection) { if (selectionWidget.isEmpty()) { return; } @@ -238,7 +238,7 @@ public class FormSelectionUtils { } } if (c instanceof XLayoutContainer) { - _rebuild((XLayoutContainer) c, selectionWidget, newSelection); + rebuild((XLayoutContainer) c, selectionWidget, newSelection); } } } diff --git a/designer_form/src/com/fr/design/mainframe/JForm.java b/designer_form/src/com/fr/design/mainframe/JForm.java index eb8c90f3aa..ba491e3519 100644 --- a/designer_form/src/com/fr/design/mainframe/JForm.java +++ b/designer_form/src/com/fr/design/mainframe/JForm.java @@ -1,792 +1,791 @@ -package com.fr.design.mainframe; - -import com.fr.base.BaseUtils; -import com.fr.design.DesignState; -import com.fr.design.actions.core.WorkBookSupportable; -import com.fr.design.actions.file.WebPreviewUtils; -import com.fr.design.cell.FloatElementsProvider; -import com.fr.design.constants.UIConstants; -import com.fr.design.designer.beans.actions.CopyAction; -import com.fr.design.designer.beans.actions.CutAction; -import com.fr.design.designer.beans.actions.FormDeleteAction; -import com.fr.design.designer.beans.actions.PasteAction; -import com.fr.design.designer.beans.events.DesignerEditListener; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.design.designer.creator.*; -import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; -import com.fr.design.event.TargetModifiedEvent; -import com.fr.design.event.TargetModifiedListener; -import com.fr.design.gui.frpane.HyperlinkGroupPane; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.imenu.UIMenuItem; -import com.fr.design.gui.xpane.FormHyperlinkGroupPane; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.mainframe.actions.EmbeddedFormExportExportAction; -import com.fr.design.mainframe.actions.FormMobileAttrAction; -import com.fr.design.mainframe.actions.TemplateParameterAction; -import com.fr.design.mainframe.form.FormECCompositeProvider; -import com.fr.design.mainframe.form.FormECDesignerProvider; -import com.fr.design.mainframe.templateinfo.JFormProcessInfo; -import com.fr.design.mainframe.templateinfo.TemplateProcessInfo; -import com.fr.design.mainframe.toolbar.ToolBarMenuDock; -import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; -import com.fr.design.menu.KeySetUtils; -import com.fr.design.menu.MenuDef; -import com.fr.design.menu.ShortCut; -import com.fr.design.menu.ToolBarDef; -import com.fr.design.parameter.ParameterPropertyPane; -import com.fr.design.roleAuthority.RolesAlreadyEditedPane; -import com.fr.design.utils.gui.LayoutUtils; -import com.fr.file.FILE; -import com.fr.form.FormElementCaseContainerProvider; -import com.fr.form.FormElementCaseProvider; -import com.fr.form.main.Form; -import com.fr.form.ui.Widget; -import com.fr.form.ui.container.WBorderLayout; -import com.fr.form.ui.container.WFitLayout; -import com.fr.form.ui.container.WLayout; -import com.fr.general.ComparatorUtils; -import com.fr.general.FRLogger; -import com.fr.general.Inter; -import com.fr.stable.ArrayUtils; -import com.fr.stable.Constants; -import com.fr.stable.bridge.StableFactory; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.image.BufferedImage; -import java.util.HashMap; - -public class JForm extends JTemplate implements BaseJForm { - private static final String FORM_CARD = "FORM"; - private static final String ELEMENTCASE_CARD = "ELEMENTCASE"; - - private static final String[] CARDNAME = new String[]{FORM_CARD, ELEMENTCASE_CARD}; - private static final int TOOLBARPANEDIMHEIGHT_FORM = 60; - - //表单设计器 - private FormDesigner formDesign; - //格子设计器 - private FormECDesignerProvider elementCaseDesign; - - //中间编辑区域, carllayout布局 - private JPanel tabCenterPane; - private CardLayout cardLayout; - //当前编辑的组件对象 - private JComponent editingComponent; - private FormECCompositeProvider reportComposite; - - //FORM_TAB代表是否点击编辑,用于点击编辑前后菜单的显示 - protected int index = FORM_TAB; - - public JForm() { - super(new Form(new WBorderLayout("form")), "Form"); - } - - public JForm(Form form, FILE file) { - super(form, file); - } - - public int getMenuState() { - - return DesignState.JFORM; - } - - public TemplateProcessInfo getProcessInfo() { - if (processInfo == null) { - processInfo = new JFormProcessInfo(template); - } - return processInfo; - } - - @Override - protected boolean accept(Object o) { - return !(o instanceof FloatElementsProvider); - } - - /** - * 是否是报表 - * - * @return 否 - */ - public boolean isJWorkBook() { - return false; - } - - /** - * 返回当前支持的超链界面pane - * - * @return 超链连接界面 - */ - public HyperlinkGroupPane getHyperLinkPane() { - return new FormHyperlinkGroupPane(); - } - - //表单返回 FORM_TAB or ELEMENTCASE_TAB - public int getEditingReportIndex() { - return this.index; - } - - public void setAuthorityMode(boolean isUpMode) { - return; - } - - public int getToolBarHeight() { - return TOOLBARPANEDIMHEIGHT_FORM; - } - - /** - * 菜单栏上的文件按钮 - * - * @return 菜单数组 - */ - public ShortCut[] shortcut4FileMenu() { - return (ShortCut[]) ArrayUtils.addAll( - super.shortcut4FileMenu(), new ShortCut[]{this.createWorkBookExportMenu()} - ); - } - - private MenuDef createWorkBookExportMenu() { - MenuDef exportMenuDef = new MenuDef(KeySetUtils.EXPORT.getMenuName()); - exportMenuDef.setIconPath("/com/fr/design/images/m_file/export.png"); - exportMenuDef.addShortCut(new EmbeddedFormExportExportAction(this)); - - return exportMenuDef; - } - - /** - * 取消格式 - */ - public void cancelFormat() { - return; - } - - /** - * 重新计算大小 - */ - public void doResize() { - formDesign.getRootComponent().setSize(formDesign.getSize()); - LayoutUtils.layoutRootContainer(formDesign.getRootComponent()); - } - - @Override - protected JPanel createCenterPane() { - tabCenterPane = FRGUIPaneFactory.createCardLayout_S_Pane(); - cardLayout = (CardLayout) tabCenterPane.getLayout(); - - JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); - centerPane.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 0, new Color(85, 85, 85))); - formDesign = new FormDesigner(this.getTarget(), new TabChangeAction(BaseJForm.ELEMENTCASE_TAB, this)); - WidgetToolBarPane.getInstance(formDesign); - FormArea area = new FormArea(formDesign); - centerPane.add(area, BorderLayout.CENTER); - tabCenterPane.add(centerPane, FORM_CARD, FORM_TAB); - - this.add(tabCenterPane, BorderLayout.CENTER); - - formDesign.addTargetModifiedListener(new TargetModifiedListener() { - - @Override - public void targetModified(TargetModifiedEvent e) { - JForm.this.fireTargetModified();// 调用保存*, 调用刷新界面, 刷新工具栏按钮 - } - }); - formDesign.addDesignerEditListener(new DesignerEditListener() { - - @Override - public void fireCreatorModified(DesignerEvent evt) { - if (evt.getCreatorEventID() == DesignerEvent.CREATOR_CUTED - || evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED) { - setPropertyPaneChange(formDesign.getRootComponent()); - } else if (evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { - setPropertyPaneChange(evt.getAffectedCreator()); - } - } - }); - return tabCenterPane; - } - - public FormDesigner getFormDesign() { - return formDesign; - } - - public void setFormDesign(FormDesigner formDesign) { - this.formDesign = formDesign; - } - - /** - * 去除选择 - */ - public void removeTemplateSelection() { - return; - } - - public void setSheetCovered(boolean isCovered) { - - } - - /** - * 刷新容器 - */ - public void refreshContainer() { - - } - - /** - * 去除参数面板选择 - */ - public void removeParameterPaneSelection() { - return; - } - - /** - * 创建权限细粒度编辑面板 - * - * @return 权限细粒度编辑面板 - */ - public AuthorityEditPane createAuthorityEditPane() { - FormWidgetAuthorityEditPane formWidgetAuthorityEditPane = new FormWidgetAuthorityEditPane(formDesign); - formWidgetAuthorityEditPane.populateDetials(); - return formWidgetAuthorityEditPane; - } - - - private void setPropertyPaneChange(XComponent comp) { - if (comp == null) { - return; - } - editingComponent = comp.createToolPane(this, formDesign); - if (BaseUtils.isAuthorityEditing()) { - EastRegionContainerPane.getInstance().replaceUpPane( - ComparatorUtils.equals(editingComponent.getClass(), NoSupportAuthorityEdit.class) ? editingComponent : createAuthorityEditPane()); - } else { - EastRegionContainerPane.getInstance().replaceUpPane(editingComponent); - - } - } - - public JComponent getEditingPane() { - return editingComponent; - } - - - public ToolBarMenuDockPlus getToolBarMenuDockPlus() { - return this; - } - - - /** - * 焦点放到JForm - */ - @Override - public void requestFocus() { - super.requestFocus(); - formDesign.requestFocus(); - } - - /** - * 焦点放到JForm - */ - public void requestGridFocus() { - super.requestFocus(); - formDesign.requestFocus(); - } - - /** - * 保存文件的后缀名 - * - * @return 返回后缀名 - */ - @Override - public String suffix() { - // daniel改成三个字 - return ".frm"; - } - - /** - * 刷新 - */ - public void refreshRoot() { - // formDesign子类的target重置 - this.formDesign.setTarget(this.getTarget()); - this.formDesign.refreshRoot(); - FormHierarchyTreePane.getInstance().refreshRoot(); - } - - /** - * 刷新s - */ - public void refreshAllNameWidgets() { - if (formDesign.getParaComponent() != null) { - XCreatorUtils.refreshAllNameWidgets(formDesign.getParaComponent()); - } - XCreatorUtils.refreshAllNameWidgets(formDesign.getRootComponent()); - } - - /** - * 刷新 - */ - public void refreshSelectedWidget() { - formDesign.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_SELECTED); - } - - - /** - * 复制 - */ - @Override - public void copy() { - this.formDesign.copy(); - } - - - /** - * 粘贴 - * - * @return 是否成功 - */ - @Override - public boolean paste() { - return this.formDesign.paste(); - } - - - /** - * 剪切 - * - * @return 是否成功 - */ - @Override - public boolean cut() { - return this.formDesign.cut(); - } - - // //////////////////////////////////////////////////////////////////// - // ////////////////for toolbarMenuAdapter////////////////////////////// - // //////////////////////////////////////////////////////////////////// - - - /** - * 目标菜单 - * - * @return 菜单 - */ - @Override - public MenuDef[] menus4Target() { - return this.index == FORM_TAB ? - (MenuDef[]) ArrayUtils.addAll(super.menus4Target(), this.formDesign.menus4Target()) : - (MenuDef[]) ArrayUtils.addAll(super.menus4Target(), this.elementCaseDesign.menus4Target()); - } - - - /** - * 模板的工具 - * - * @return 工具 - */ - @Override - public ToolBarDef[] toolbars4Target() { - return this.index == FORM_TAB ? - this.formDesign.toolbars4Target() : - this.elementCaseDesign.toolbars4Target(); - } - - - /** - * 模板菜单 - * - * @return 返回菜单 - */ - @Override - public ShortCut[] shortcut4TemplateMenu() { - if (this.index == FORM_TAB) { - return (ShortCut[]) ArrayUtils.addAll(new ShortCut[]{ - new TemplateParameterAction(this), - new FormMobileAttrAction(this) - }, new ShortCut[0]); - } else { - return (ShortCut[]) ArrayUtils.addAll(new ShortCut[]{ - new TemplateParameterAction(this), - new FormMobileAttrAction(this) - }, this.elementCaseDesign.shortcut4TemplateMenu()); - } - } - - /** - * 权限细粒度模板菜单 - * 表单中去掉此菜单项 - * - * @return 菜单 - */ - public ShortCut[] shortCuts4Authority() { - return new ShortCut[0]; - } - - @Override - protected FormUndoState createUndoState() { - FormUndoState cur = new FormUndoState(this, this.formDesign.getArea()); - if (this.formDesign.isReportBlockEditing()) { - cur.setFormReportType(BaseUndoState.STATE_FORM_REPORT); - } - return cur; - } - - /** - * 应用UndoState - * - * @param o undo的状态 - */ - public void applyUndoState4Form(BaseUndoState o) { - this.applyUndoState((FormUndoState) o); - } - - /** - * 可以撤销 - * - * @return 是则返回true - */ - public boolean canUndo() { - //报表块最多撤销至编辑报表块的第一步,不能撤销表单中的操作 - boolean inECUndoForm = undoState.getFormReportType() == BaseUndoState.STATE_BEFORE_FORM_REPORT && formDesign.isReportBlockEditing(); - return !inECUndoForm && this.getUndoManager().canUndo(); - } - - // 返回当前的body, - // 假如当前body是自适应的话就沿用, - // 假如当前body是绝对布局的话就返回绝对布局body - private XLayoutContainer selectedBodyLayout() { - XLayoutContainer rootLayout = formDesign.getRootComponent(); - for (int i = 0; i < rootLayout.getComponentCount(); i++) { - if (rootLayout.getXCreator(i).acceptType(XWAbsoluteBodyLayout.class)) { - rootLayout = (XWAbsoluteBodyLayout) rootLayout.getXCreator(i); - } - } - return rootLayout; - } - - @Override - protected void applyUndoState(FormUndoState u) { - try { - //JForm的target重置 - this.setTarget((Form) u.getForm().clone()); - if (this.index == FORM_TAB) { - JForm.this.refreshRoot(); - this.formDesign.getArea().setAreaSize(u.getAreaSize(), u.getHorizontalValue(), u.getVerticalValue(), u.getWidthValue(), u.getHeightValue(), u.getSlideValue()); - //撤销的时候要重新选择的body布局 - this.formDesign.getSelectionModel().setSelectedCreators(FormSelectionUtils.rebuildSelection(formDesign.getRootComponent(), - formDesign.getRootComponent() == selectedBodyLayout() ? u.getSelectWidgets() : new Widget[]{selectedBodyLayout().toData()})); - } else { - String widgetName = this.formDesign.getElementCaseContainerName(); - //这儿太坑了,u.getForm() 与 getTarget内容不一样 - FormElementCaseProvider dataTable = getTarget().getElementCaseByName(widgetName); - this.reportComposite.setSelectedWidget(dataTable); - //下面这句话是防止撤销之后直接退出编辑再编辑撤销的东西会回来,因为撤销不会保存EC - formDesign.setElementCase(dataTable); - } - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - - if (BaseUtils.isAuthorityEditing()) { - this.authorityUndoState = u; - } else { - this.undoState = u; - } - - } - - @Override - protected FormModelAdapter createDesignModel() { - return new FormModelAdapter(this); - } - - @Override - public JPanel[] toolbarPanes4Form() { - return this.index == FORM_TAB ? - new JPanel[]{FormParaWidgetPane.getInstance(formDesign)} : - new JPanel[0]; - } - - /** - * 表单的工具按钮 - * - * @return 工具按钮 - */ - public JComponent[] toolBarButton4Form() { - return this.index == FORM_TAB ? - new JComponent[]{ - new CutAction(formDesign).createToolBarComponent(), - new CopyAction(formDesign).createToolBarComponent(), - new PasteAction(formDesign).createToolBarComponent(), - new FormDeleteAction(formDesign).createToolBarComponent()} : - elementCaseDesign.toolBarButton4Form(); - } - - /** - * 权限细粒度状态下的工具面板 - * - * @return 工具面板 - */ - public JComponent toolBar4Authority() { - JPanel panel = new JPanel(new BorderLayout()) { - public Dimension getPreferredSize() { - Dimension dim = super.getPreferredSize(); - dim.height = ToolBarMenuDock.PANLE_HEIGNT; - return dim; - } - }; - UILabel uiLabel = new UILabel(Inter.getLocText(new String[]{"DashBoard-FormBook", "Privilege", "Edit"})); - uiLabel.setHorizontalAlignment(SwingConstants.CENTER); - uiLabel.setFont(new Font(Inter.getLocText("FR-Designer-All_MSBold"), 0, 14)); - uiLabel.setForeground(new Color(150, 150, 150)); - panel.add(uiLabel, BorderLayout.CENTER); - return panel; - } - - - public JPanel getEastUpPane() { - if (BaseUtils.isAuthorityEditing()) { - if (formDesign.isSupportAuthority()) { - return new AuthorityPropertyPane(this); - } else { - return new NoSupportAuthorityEdit(); - } - } else { - if (editingComponent == null) { - editingComponent = formDesign.getRootComponent().createToolPane(this, formDesign); - } - return (JPanel) editingComponent; - } - } - - public JPanel getEastDownPane() { - return formDesign.getEastDownPane(); - } - - @Override - /** - * - */ - public Icon getPreviewLargeIcon() { - return UIConstants.RUN_BIG_ICON; - } - - @Override - /** - * 创建菜单项Preview - * - * @return 菜单 - */ - public UIMenuItem[] createMenuItem4Preview() { - UIMenuItem form = new UIMenuItem(Inter.getLocText("M-Form_Preview"), UIConstants.RUN_SMALL_ICON); - form.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - WebPreviewUtils.onFormPreview(JForm.this); - } - }); - return new UIMenuItem[]{form}; - } - - /** - * 刷新参数 - */ - public void populateParameter() { - formDesign.populateParameterPropertyPane(); - } - - @Override - /** - * 刷新工具区域 - */ - public void refreshToolArea() { - populateParameter(); - DesignerContext.getDesignerFrame().resetToolkitByPlus(JForm.this); - //表单切换后拖不进去组件是因为找不到designer - WidgetToolBarPane.getInstance(formDesign); - if (BaseUtils.isAuthorityEditing()) { - if (formDesign.isSupportAuthority()) { - EastRegionContainerPane.getInstance().replaceUpPane(new AuthorityPropertyPane(this)); - } else { - EastRegionContainerPane.getInstance().replaceUpPane(new NoSupportAuthorityEdit()); - } - EastRegionContainerPane.getInstance().replaceDownPane(RolesAlreadyEditedPane.getInstance()); - return; - } - - if (formDesign.isReportBlockEditing()) { - if (elementCaseDesign != null) { - EastRegionContainerPane.getInstance().removeParameterPane(); - EastRegionContainerPane.getInstance().replaceDownPane(elementCaseDesign.getEastDownPane()); - EastRegionContainerPane.getInstance().replaceUpPane(elementCaseDesign.getEastUpPane()); - return; - } - } - - EastRegionContainerPane.getInstance().replaceUpPane(WidgetPropertyPane.getInstance(formDesign)); - EastRegionContainerPane.getInstance().addParameterPane(ParameterPropertyPane.getInstance(formDesign)); - EastRegionContainerPane.getInstance().setParameterHeight(ParameterPropertyPane.getInstance(formDesign).getPreferredSize().height); - if (EastRegionContainerPane.getInstance().getDownPane() == null) { - new Thread() { - public void run() { - try { - Thread.sleep(1500); - } catch (InterruptedException e) { - FRLogger.getLogger().error(e.getMessage(), e); - } - JPanel pane = new JPanel(); - pane.setLayout(new BorderLayout()); - pane.add(FormWidgetDetailPane.getInstance(formDesign), BorderLayout.CENTER); - EastRegionContainerPane.getInstance().replaceDownPane(pane); - } - }.start(); - } else { - JPanel pane = new JPanel(); - pane.setLayout(new BorderLayout()); - pane.add(FormWidgetDetailPane.getInstance(formDesign), BorderLayout.CENTER); - EastRegionContainerPane.getInstance().replaceDownPane(pane); - - } - } - - public String getEditingCreatorName() { - return formDesign.getSelectionModel().getSelection().getSelectedCreator().toData().getWidgetName(); - } - - public WLayout getRootLayout() { - return formDesign.getRootComponent().toData(); - } - - /** - * 选择的是否是表单主体 - * - * @return 是则返回true - */ - public boolean isSelectRootPane() { - return (formDesign.getRootComponent() == formDesign.getSelectionModel().getSelection().getSelectedCreator()) - || (formDesign.getSelectionModel().getSelection().getSelectedCreator().acceptType(XWAbsoluteBodyLayout.class)); - - } - - /** - * 只在Form和ElementCase之间切换 - * - * @param index 切换位置 - */ - public void tabChanged(int index) { - if (index == ELEMENTCASE_TAB) { - formDesign.setReportBlockEditing(true); - ecTabAction(); - } else { - formDesign.setReportBlockEditing(false); - formTabAction(); - } - this.index = index; - refreshToolArea(); - this.cardLayout.show(tabCenterPane, CARDNAME[index]); - if (elementCaseDesign != null && index == ELEMENTCASE_TAB) { - //报表块编辑失焦,进入报表块可直接编辑A1 - elementCaseDesign.requestFocus(); - //进入编辑报表块,触发一次保存,记住编辑报表块前的表单状态 - //防止报表块中撤销到表单 - JForm.this.fireTargetModified(); - } - } - - /** - * 在Form和ElementCase, 以及ElementCase和ElementCase之间切换 - * - * @param index 切换位置 - * @param ecContainer ElementCase所在container - */ - public void tabChanged(int index, FormElementCaseContainerProvider ecContainer) { - if (index == ELEMENTCASE_CHANGE_TAB) { - saveImage(); - //更新FormDesign中的控件容器 - formDesign.setElementCaseContainer(ecContainer); - //如果只是内部ElementCase之间的切换, 那么不需要下面的界面变动 - return; - } - - tabChanged(index); - } - - /** - * 格子编辑组件 - */ - private FormECDesignerProvider initElementCaseDesign() { - HashMap designerClass = new HashMap(); - designerClass.put(Constants.ARG_0, FormElementCaseProvider.class); - - Object[] designerArg = new Object[]{formDesign.getElementCase()}; - return StableFactory.getMarkedInstanceObjectFromClass(FormECDesignerProvider.XML_TAG, designerArg, designerClass, FormECDesignerProvider.class); - } - - /** - * 整个报表块编辑区域 - */ - private FormECCompositeProvider initComposite() { - Object[] compositeArg = new Object[]{this, elementCaseDesign, formDesign.getElementCaseContainer()}; - HashMap compoClass = new HashMap(); - compoClass.put(Constants.ARG_0, BaseJForm.class); - compoClass.put(Constants.ARG_2, FormElementCaseContainerProvider.class); - return StableFactory.getMarkedInstanceObjectFromClass(FormECCompositeProvider.XML_TAG, compositeArg, compoClass, FormECCompositeProvider.class); - } - - /** - * 切换格子编辑 - */ - private void ecTabAction() { - elementCaseDesign = initElementCaseDesign(); - reportComposite = initComposite(); - - tabCenterPane.add((Component) reportComposite, ELEMENTCASE_CARD, 1); - reportComposite.addTargetModifiedListener(new TargetModifiedListener() { - - @Override - public void targetModified(TargetModifiedEvent e) { - JForm.this.fireTargetModified(); - FormElementCaseProvider te = elementCaseDesign.getEditingElementCase(); - formDesign.setElementCase(te); - } - }); - } - - private void saveImage() { - //触发一次保存, 把缩略图保存起来 - JForm.this.fireTargetModified(); - //用formDesign的size是为了当报表块被拉伸时, 它对应的背景图片需要足够大才不会显示成空白 - BufferedImage image = elementCaseDesign.getElementCaseImage(formDesign.getSize()); - formDesign.setElementCaseBackground(image); - } - - /** - * 切换form编辑 - */ - private void formTabAction() { - saveImage(); - } - - /** - * 取小图标,主要用于多TAB标签栏 - * - * @return 图表 - */ - public Icon getIcon() { - return BaseUtils.readIcon("/com/fr/web/images/form/new_form3.png"); - } - - @Override - public boolean acceptToolbarItem(Class clazz) { - return WorkBookSupportable.class.isAssignableFrom(clazz); - } - - @Override - public Widget getSelectElementCase() { - FormSelection selection = formDesign.getSelectionModel().getSelection(); - XCreator creator = selection.getSelectedCreator(); - return creator.toData(); - } +package com.fr.design.mainframe; + +import com.fr.base.BaseUtils; +import com.fr.design.DesignState; +import com.fr.design.actions.core.WorkBookSupportable; +import com.fr.design.actions.file.WebPreviewUtils; +import com.fr.design.cell.FloatElementsProvider; +import com.fr.design.constants.UIConstants; +import com.fr.design.designer.beans.actions.CopyAction; +import com.fr.design.designer.beans.actions.CutAction; +import com.fr.design.designer.beans.actions.FormDeleteAction; +import com.fr.design.designer.beans.actions.PasteAction; +import com.fr.design.designer.beans.events.DesignerEditListener; +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.creator.*; +import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; +import com.fr.design.event.TargetModifiedEvent; +import com.fr.design.event.TargetModifiedListener; +import com.fr.design.gui.frpane.HyperlinkGroupPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.imenu.UIMenuItem; +import com.fr.design.gui.xpane.FormHyperlinkGroupPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.actions.EmbeddedFormExportExportAction; +import com.fr.design.mainframe.actions.FormMobileAttrAction; +import com.fr.design.mainframe.actions.TemplateParameterAction; +import com.fr.design.mainframe.form.FormECCompositeProvider; +import com.fr.design.mainframe.form.FormECDesignerProvider; +import com.fr.design.mainframe.templateinfo.JFormProcessInfo; +import com.fr.design.mainframe.templateinfo.TemplateProcessInfo; +import com.fr.design.mainframe.toolbar.ToolBarMenuDock; +import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; +import com.fr.design.menu.KeySetUtils; +import com.fr.design.menu.MenuDef; +import com.fr.design.menu.ShortCut; +import com.fr.design.menu.ToolBarDef; +import com.fr.design.parameter.ParameterPropertyPane; +import com.fr.design.roleAuthority.RolesAlreadyEditedPane; +import com.fr.design.utils.gui.LayoutUtils; +import com.fr.file.FILE; +import com.fr.form.FormElementCaseContainerProvider; +import com.fr.form.FormElementCaseProvider; +import com.fr.form.main.Form; +import com.fr.form.ui.Widget; +import com.fr.form.ui.container.WBorderLayout; +import com.fr.form.ui.container.WLayout; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; +import com.fr.stable.Constants; +import com.fr.stable.bridge.StableFactory; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +public class JForm extends JTemplate implements BaseJForm { + private static final String FORM_CARD = "FORM"; + private static final String ELEMENTCASE_CARD = "ELEMENTCASE"; + + private static final String[] CARDNAME = new String[]{FORM_CARD, ELEMENTCASE_CARD}; + private static final int TOOLBARPANEDIMHEIGHT_FORM = 60; + + //表单设计器 + private FormDesigner formDesign; + //格子设计器 + private FormECDesignerProvider elementCaseDesign; + + //中间编辑区域, carllayout布局 + private JPanel tabCenterPane; + private CardLayout cardLayout; + //当前编辑的组件对象 + private JComponent editingComponent; + private FormECCompositeProvider reportComposite; + + //FORM_TAB代表是否点击编辑,用于点击编辑前后菜单的显示 + protected int index = FORM_TAB; + + public JForm() { + super(new Form(new WBorderLayout("form")), "Form"); + } + + public JForm(Form form, FILE file) { + super(form, file); + } + + public int getMenuState() { + + return DesignState.JFORM; + } + + public TemplateProcessInfo getProcessInfo() { + if (processInfo == null) { + processInfo = new JFormProcessInfo(template); + } + return processInfo; + } + + @Override + protected boolean accept(Object o) { + return !(o instanceof FloatElementsProvider); + } + + /** + * 是否是报表 + * + * @return 否 + */ + public boolean isJWorkBook() { + return false; + } + + /** + * 返回当前支持的超链界面pane + * + * @return 超链连接界面 + */ + public HyperlinkGroupPane getHyperLinkPane() { + return new FormHyperlinkGroupPane(); + } + + //表单返回 FORM_TAB or ELEMENTCASE_TAB + public int getEditingReportIndex() { + return this.index; + } + + public void setAuthorityMode(boolean isUpMode) { + return; + } + + public int getToolBarHeight() { + return TOOLBARPANEDIMHEIGHT_FORM; + } + + /** + * 菜单栏上的文件按钮 + * + * @return 菜单数组 + */ + public ShortCut[] shortcut4FileMenu() { + return (ShortCut[]) ArrayUtils.addAll( + super.shortcut4FileMenu(), new ShortCut[]{this.createWorkBookExportMenu()} + ); + } + + private MenuDef createWorkBookExportMenu() { + MenuDef exportMenuDef = new MenuDef(KeySetUtils.EXPORT.getMenuName()); + exportMenuDef.setIconPath("/com/fr/design/images/m_file/export.png"); + exportMenuDef.addShortCut(new EmbeddedFormExportExportAction(this)); + + return exportMenuDef; + } + + /** + * 取消格式 + */ + public void cancelFormat() { + return; + } + + /** + * 重新计算大小 + */ + public void doResize() { + formDesign.getRootComponent().setSize(formDesign.getSize()); + LayoutUtils.layoutRootContainer(formDesign.getRootComponent()); + } + + @Override + protected JPanel createCenterPane() { + tabCenterPane = FRGUIPaneFactory.createCardLayout_S_Pane(); + cardLayout = (CardLayout) tabCenterPane.getLayout(); + + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + centerPane.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 0, new Color(85, 85, 85))); + formDesign = new FormDesigner(this.getTarget(), new TabChangeAction(BaseJForm.ELEMENTCASE_TAB, this)); + WidgetToolBarPane.getInstance(formDesign); + FormArea area = new FormArea(formDesign); + centerPane.add(area, BorderLayout.CENTER); + tabCenterPane.add(centerPane, FORM_CARD, FORM_TAB); + + this.add(tabCenterPane, BorderLayout.CENTER); + + formDesign.addTargetModifiedListener(new TargetModifiedListener() { + + @Override + public void targetModified(TargetModifiedEvent e) { + JForm.this.fireTargetModified();// 调用保存*, 调用刷新界面, 刷新工具栏按钮 + } + }); + formDesign.addDesignerEditListener(new DesignerEditListener() { + + @Override + public void fireCreatorModified(DesignerEvent evt) { + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_CUTED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED) { + setPropertyPaneChange(formDesign.getRootComponent()); + } else if (evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { + setPropertyPaneChange(evt.getAffectedCreator()); + } + } + }); + return tabCenterPane; + } + + public FormDesigner getFormDesign() { + return formDesign; + } + + public void setFormDesign(FormDesigner formDesign) { + this.formDesign = formDesign; + } + + /** + * 去除选择 + */ + public void removeTemplateSelection() { + return; + } + + public void setSheetCovered(boolean isCovered) { + + } + + /** + * 刷新容器 + */ + public void refreshContainer() { + + } + + /** + * 去除参数面板选择 + */ + public void removeParameterPaneSelection() { + return; + } + + /** + * 创建权限细粒度编辑面板 + * + * @return 权限细粒度编辑面板 + */ + public AuthorityEditPane createAuthorityEditPane() { + FormWidgetAuthorityEditPane formWidgetAuthorityEditPane = new FormWidgetAuthorityEditPane(formDesign); + formWidgetAuthorityEditPane.populateDetials(); + return formWidgetAuthorityEditPane; + } + + + private void setPropertyPaneChange(XComponent comp) { + if (comp == null) { + return; + } + editingComponent = comp.createToolPane(this, formDesign); + if (BaseUtils.isAuthorityEditing()) { + EastRegionContainerPane.getInstance().replaceUpPane( + ComparatorUtils.equals(editingComponent.getClass(), NoSupportAuthorityEdit.class) ? editingComponent : createAuthorityEditPane()); + } else { + EastRegionContainerPane.getInstance().replaceUpPane(editingComponent); + + } + } + + public JComponent getEditingPane() { + return editingComponent; + } + + + public ToolBarMenuDockPlus getToolBarMenuDockPlus() { + return this; + } + + + /** + * 焦点放到JForm + */ + @Override + public void requestFocus() { + super.requestFocus(); + formDesign.requestFocus(); + } + + /** + * 焦点放到JForm + */ + public void requestGridFocus() { + super.requestFocus(); + formDesign.requestFocus(); + } + + /** + * 保存文件的后缀名 + * + * @return 返回后缀名 + */ + @Override + public String suffix() { + // daniel改成三个字 + return ".frm"; + } + + /** + * 刷新 + */ + public void refreshRoot() { + // formDesign子类的target重置 + this.formDesign.setTarget(this.getTarget()); + this.formDesign.refreshRoot(); + FormHierarchyTreePane.getInstance().refreshRoot(); + } + + /** + * 刷新s + */ + public void refreshAllNameWidgets() { + if (formDesign.getParaComponent() != null) { + XCreatorUtils.refreshAllNameWidgets(formDesign.getParaComponent()); + } + XCreatorUtils.refreshAllNameWidgets(formDesign.getRootComponent()); + } + + /** + * 刷新 + */ + public void refreshSelectedWidget() { + formDesign.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_SELECTED); + } + + + /** + * 复制 + */ + @Override + public void copy() { + this.formDesign.copy(); + } + + + /** + * 粘贴 + * + * @return 是否成功 + */ + @Override + public boolean paste() { + return this.formDesign.paste(); + } + + + /** + * 剪切 + * + * @return 是否成功 + */ + @Override + public boolean cut() { + return this.formDesign.cut(); + } + + // //////////////////////////////////////////////////////////////////// + // ////////////////for toolbarMenuAdapter////////////////////////////// + // //////////////////////////////////////////////////////////////////// + + + /** + * 目标菜单 + * + * @return 菜单 + */ + @Override + public MenuDef[] menus4Target() { + return this.index == FORM_TAB ? + (MenuDef[]) ArrayUtils.addAll(super.menus4Target(), this.formDesign.menus4Target()) : + (MenuDef[]) ArrayUtils.addAll(super.menus4Target(), this.elementCaseDesign.menus4Target()); + } + + + /** + * 模板的工具 + * + * @return 工具 + */ + @Override + public ToolBarDef[] toolbars4Target() { + return this.index == FORM_TAB ? + this.formDesign.toolbars4Target() : + this.elementCaseDesign.toolbars4Target(); + } + + + /** + * 模板菜单 + * + * @return 返回菜单 + */ + @Override + public ShortCut[] shortcut4TemplateMenu() { + if (this.index == FORM_TAB) { + return (ShortCut[]) ArrayUtils.addAll(new ShortCut[]{ + new TemplateParameterAction(this), + new FormMobileAttrAction(this) + }, new ShortCut[0]); + } else { + return (ShortCut[]) ArrayUtils.addAll(new ShortCut[]{ + new TemplateParameterAction(this), + new FormMobileAttrAction(this) + }, this.elementCaseDesign.shortcut4TemplateMenu()); + } + } + + /** + * 权限细粒度模板菜单 + * 表单中去掉此菜单项 + * + * @return 菜单 + */ + public ShortCut[] shortCuts4Authority() { + return new ShortCut[0]; + } + + @Override + protected FormUndoState createUndoState() { + FormUndoState cur = new FormUndoState(this, this.formDesign.getArea()); + if (this.formDesign.isReportBlockEditing()) { + cur.setFormReportType(BaseUndoState.STATE_FORM_REPORT); + } + return cur; + } + + /** + * 应用UndoState + * + * @param o undo的状态 + */ + public void applyUndoState4Form(BaseUndoState o) { + this.applyUndoState((FormUndoState) o); + } + + /** + * 可以撤销 + * + * @return 是则返回true + */ + public boolean canUndo() { + //报表块最多撤销至编辑报表块的第一步,不能撤销表单中的操作 + boolean inECUndoForm = undoState.getFormReportType() == BaseUndoState.STATE_BEFORE_FORM_REPORT && formDesign.isReportBlockEditing(); + return !inECUndoForm && this.getUndoManager().canUndo(); + } + + // 返回当前的body, + // 假如当前body是自适应的话就沿用, + // 假如当前body是绝对布局的话就返回绝对布局body + private XLayoutContainer selectedBodyLayout() { + XLayoutContainer rootLayout = formDesign.getRootComponent(); + for (int i = 0; i < rootLayout.getComponentCount(); i++) { + if (rootLayout.getXCreator(i).acceptType(XWAbsoluteBodyLayout.class)) { + rootLayout = (XWAbsoluteBodyLayout) rootLayout.getXCreator(i); + } + } + return rootLayout; + } + + @Override + protected void applyUndoState(FormUndoState u) { + try { + //JForm的target重置 + this.setTarget((Form) u.getForm().clone()); + if (this.index == FORM_TAB) { + JForm.this.refreshRoot(); + this.formDesign.getArea().setAreaSize(u.getAreaSize(), u.getHorizontalValue(), u.getVerticalValue(), u.getWidthValue(), u.getHeightValue(), u.getSlideValue()); + //撤销的时候要重新选择的body布局 + this.formDesign.getSelectionModel().setSelectedCreators(FormSelectionUtils.rebuildSelection(formDesign.getRootComponent(), + formDesign.getRootComponent() == selectedBodyLayout() ? u.getSelectWidgets() : new Widget[]{selectedBodyLayout().toData()})); + } else { + String widgetName = this.formDesign.getElementCaseContainerName(); + //这儿太坑了,u.getForm() 与 getTarget内容不一样 + FormElementCaseProvider dataTable = getTarget().getElementCaseByName(widgetName); + this.reportComposite.setSelectedWidget(dataTable); + //下面这句话是防止撤销之后直接退出编辑再编辑撤销的东西会回来,因为撤销不会保存EC + formDesign.setElementCase(dataTable); + } + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + + if (BaseUtils.isAuthorityEditing()) { + this.authorityUndoState = u; + } else { + this.undoState = u; + } + + } + + @Override + protected FormModelAdapter createDesignModel() { + return new FormModelAdapter(this); + } + + @Override + public JPanel[] toolbarPanes4Form() { + return this.index == FORM_TAB ? + new JPanel[]{FormParaWidgetPane.getInstance(formDesign)} : + new JPanel[0]; + } + + /** + * 表单的工具按钮 + * + * @return 工具按钮 + */ + public JComponent[] toolBarButton4Form() { + return this.index == FORM_TAB ? + new JComponent[]{ + new CutAction(formDesign).createToolBarComponent(), + new CopyAction(formDesign).createToolBarComponent(), + new PasteAction(formDesign).createToolBarComponent(), + new FormDeleteAction(formDesign).createToolBarComponent()} : + elementCaseDesign.toolBarButton4Form(); + } + + /** + * 权限细粒度状态下的工具面板 + * + * @return 工具面板 + */ + public JComponent toolBar4Authority() { + JPanel panel = new JPanel(new BorderLayout()) { + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.height = ToolBarMenuDock.PANLE_HEIGNT; + return dim; + } + }; + UILabel uiLabel = new UILabel(Inter.getLocText(new String[]{"DashBoard-FormBook", "Privilege", "Edit"})); + uiLabel.setHorizontalAlignment(SwingConstants.CENTER); + uiLabel.setFont(new Font(Inter.getLocText("FR-Designer-All_MSBold"), 0, 14)); + uiLabel.setForeground(new Color(150, 150, 150)); + panel.add(uiLabel, BorderLayout.CENTER); + return panel; + } + + + public JPanel getEastUpPane() { + if (BaseUtils.isAuthorityEditing()) { + if (formDesign.isSupportAuthority()) { + return new AuthorityPropertyPane(this); + } else { + return new NoSupportAuthorityEdit(); + } + } else { + if (editingComponent == null) { + editingComponent = formDesign.getRootComponent().createToolPane(this, formDesign); + } + return (JPanel) editingComponent; + } + } + + public JPanel getEastDownPane() { + return formDesign.getEastDownPane(); + } + + @Override + /** + * + */ + public Icon getPreviewLargeIcon() { + return UIConstants.RUN_BIG_ICON; + } + + @Override + /** + * 创建菜单项Preview + * + * @return 菜单 + */ + public UIMenuItem[] createMenuItem4Preview() { + UIMenuItem form = new UIMenuItem(Inter.getLocText("M-Form_Preview"), UIConstants.RUN_SMALL_ICON); + form.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + WebPreviewUtils.onFormPreview(JForm.this); + } + }); + return new UIMenuItem[]{form}; + } + + /** + * 刷新参数 + */ + public void populateParameter() { + formDesign.populateParameterPropertyPane(); + } + + @Override + /** + * 刷新工具区域 + */ + public void refreshToolArea() { + populateParameter(); + DesignerContext.getDesignerFrame().resetToolkitByPlus(JForm.this); + //表单切换后拖不进去组件是因为找不到designer + WidgetToolBarPane.getInstance(formDesign); + if (BaseUtils.isAuthorityEditing()) { + if (formDesign.isSupportAuthority()) { + EastRegionContainerPane.getInstance().replaceUpPane(new AuthorityPropertyPane(this)); + } else { + EastRegionContainerPane.getInstance().replaceUpPane(new NoSupportAuthorityEdit()); + } + EastRegionContainerPane.getInstance().replaceDownPane(RolesAlreadyEditedPane.getInstance()); + return; + } + + if (formDesign.isReportBlockEditing()) { + if (elementCaseDesign != null) { + EastRegionContainerPane.getInstance().removeParameterPane(); + EastRegionContainerPane.getInstance().replaceDownPane(elementCaseDesign.getEastDownPane()); + EastRegionContainerPane.getInstance().replaceUpPane(elementCaseDesign.getEastUpPane()); + return; + } + } + + EastRegionContainerPane.getInstance().replaceUpPane(WidgetPropertyPane.getInstance(formDesign)); + EastRegionContainerPane.getInstance().addParameterPane(ParameterPropertyPane.getInstance(formDesign)); + EastRegionContainerPane.getInstance().setParameterHeight(ParameterPropertyPane.getInstance(formDesign).getPreferredSize().height); + if (EastRegionContainerPane.getInstance().getDownPane() == null) { + new Thread() { + public void run() { + try { + Thread.sleep(1500); + } catch (InterruptedException e) { + FRLogger.getLogger().error(e.getMessage(), e); + } + JPanel pane = new JPanel(); + pane.setLayout(new BorderLayout()); + pane.add(FormWidgetDetailPane.getInstance(formDesign), BorderLayout.CENTER); + EastRegionContainerPane.getInstance().replaceDownPane(pane); + } + }.start(); + } else { + JPanel pane = new JPanel(); + pane.setLayout(new BorderLayout()); + pane.add(FormWidgetDetailPane.getInstance(formDesign), BorderLayout.CENTER); + EastRegionContainerPane.getInstance().replaceDownPane(pane); + + } + } + + public String getEditingCreatorName() { + return formDesign.getSelectionModel().getSelection().getSelectedCreator().toData().getWidgetName(); + } + + public WLayout getRootLayout() { + return formDesign.getRootComponent().toData(); + } + + /** + * 选择的是否是表单主体 + * + * @return 是则返回true + */ + public boolean isSelectRootPane() { + return (formDesign.getRootComponent() == formDesign.getSelectionModel().getSelection().getSelectedCreator()) + || (formDesign.getSelectionModel().getSelection().getSelectedCreator().acceptType(XWAbsoluteBodyLayout.class)); + + } + + /** + * 只在Form和ElementCase之间切换 + * + * @param index 切换位置 + */ + public void tabChanged(int index) { + if (index == ELEMENTCASE_TAB) { + formDesign.setReportBlockEditing(true); + ecTabAction(); + } else { + formDesign.setReportBlockEditing(false); + formTabAction(); + } + this.index = index; + refreshToolArea(); + this.cardLayout.show(tabCenterPane, CARDNAME[index]); + if (elementCaseDesign != null && index == ELEMENTCASE_TAB) { + //报表块编辑失焦,进入报表块可直接编辑A1 + elementCaseDesign.requestFocus(); + //进入编辑报表块,触发一次保存,记住编辑报表块前的表单状态 + //防止报表块中撤销到表单 + JForm.this.fireTargetModified(); + } + } + + /** + * 在Form和ElementCase, 以及ElementCase和ElementCase之间切换 + * + * @param index 切换位置 + * @param ecContainer ElementCase所在container + */ + public void tabChanged(int index, FormElementCaseContainerProvider ecContainer) { + if (index == ELEMENTCASE_CHANGE_TAB) { + saveImage(); + //更新FormDesign中的控件容器 + formDesign.setElementCaseContainer(ecContainer); + //如果只是内部ElementCase之间的切换, 那么不需要下面的界面变动 + return; + } + + tabChanged(index); + } + + /** + * 格子编辑组件 + */ + private FormECDesignerProvider initElementCaseDesign() { + HashMap designerClass = new HashMap(); + designerClass.put(Constants.ARG_0, FormElementCaseProvider.class); + + Object[] designerArg = new Object[]{formDesign.getElementCase()}; + return StableFactory.getMarkedInstanceObjectFromClass(FormECDesignerProvider.XML_TAG, designerArg, designerClass, FormECDesignerProvider.class); + } + + /** + * 整个报表块编辑区域 + */ + private FormECCompositeProvider initComposite() { + Object[] compositeArg = new Object[]{this, elementCaseDesign, formDesign.getElementCaseContainer()}; + HashMap compoClass = new HashMap(); + compoClass.put(Constants.ARG_0, BaseJForm.class); + compoClass.put(Constants.ARG_2, FormElementCaseContainerProvider.class); + return StableFactory.getMarkedInstanceObjectFromClass(FormECCompositeProvider.XML_TAG, compositeArg, compoClass, FormECCompositeProvider.class); + } + + /** + * 切换格子编辑 + */ + private void ecTabAction() { + elementCaseDesign = initElementCaseDesign(); + reportComposite = initComposite(); + + tabCenterPane.add((Component) reportComposite, ELEMENTCASE_CARD, 1); + reportComposite.addTargetModifiedListener(new TargetModifiedListener() { + + @Override + public void targetModified(TargetModifiedEvent e) { + JForm.this.fireTargetModified(); + FormElementCaseProvider te = elementCaseDesign.getEditingElementCase(); + formDesign.setElementCase(te); + } + }); + } + + private void saveImage() { + //触发一次保存, 把缩略图保存起来 + JForm.this.fireTargetModified(); + //用formDesign的size是为了当报表块被拉伸时, 它对应的背景图片需要足够大才不会显示成空白 + BufferedImage image = elementCaseDesign.getElementCaseImage(formDesign.getSize()); + formDesign.setElementCaseBackground(image); + } + + /** + * 切换form编辑 + */ + private void formTabAction() { + saveImage(); + } + + /** + * 取小图标,主要用于多TAB标签栏 + * + * @return 图表 + */ + public Icon getIcon() { + return BaseUtils.readIcon("/com/fr/web/images/form/new_form3.png"); + } + + @Override + public boolean acceptToolbarItem(Class clazz) { + return WorkBookSupportable.class.isAssignableFrom(clazz); + } + + @Override + public Widget getSelectElementCase() { + FormSelection selection = formDesign.getSelectionModel().getSelection(); + XCreator creator = selection.getSelectedCreator(); + return creator.toData(); + } } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java b/designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java index ac46da031f..c9a8587972 100644 --- a/designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java +++ b/designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java @@ -1,347 +1,348 @@ -package com.fr.design.mainframe; - -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.ListSelectionModel; -import javax.swing.table.*; - -import com.fr.design.designer.creator.XCreator; -import com.fr.design.gui.ilable.UILabel; -import com.fr.design.gui.itable.GroupRenderer; -import com.fr.form.ui.Widget; -import com.fr.form.ui.container.*; -import com.fr.general.ComparatorUtils; -import com.fr.general.Inter; -import com.fr.stable.StringUtils; - -/** - * MobileWidgetTable类主要显示各种容器的控件列表(body,tab,绝对布局快,不包括参数面板) - * Created with IntelliJ IDEA. - * User: zx - * Date: 14-9-15 - * Time: 下午4:52 - * Modified by fanglei at 2017/01/23 - */ -public class MobileWidgetTable extends JTable { - - private FormDesigner designer; - private String[][] cellData; - private String[] headers = {Inter.getLocText("Form-Widget_Name")}; - private static final int WIDGET_TABLE_ROW_HEIGHT = 22; - private UILabel moveComponent = new UILabel(); // 作为拖动时候随鼠标移动的那个半透明控件 - private int selectedRow = -1; - private int GAP = 11; - private boolean draging = false; - private boolean collapsed = false; // 控件列表是否折叠 - - @Override - public TableCellRenderer getCellRenderer(int row, int column) { - //第一行渲染成为标题的样子 - if (row == 0) { - return new GroupRenderer(); - } - return super.getCellRenderer(row, column); - } - - - public MobileWidgetTable(FormDesigner designer) { - this.designer = designer; - cellData = getData(); - this.setTableProperties(); - TableModel defaultModel = new BeanTableModel(); - this.setModel(defaultModel); - this.repaint(); - this.setDefaultRenderer(Object.class,new DefaultTableCellRenderer()); - refreshData(); - this.addMouseListener(mouseAdapter); - this.addMouseMotionListener(mouseAdapter); - add(moveComponent); - } - - private void setTableProperties() { - JTableHeader header = getTableHeader(); - header.setReorderingAllowed(false); - header.setPreferredSize(new Dimension(0, 0)); // 隐藏表头 - GroupRenderer headerRenderer = new GroupRenderer(); - headerRenderer.setPreferredSize(new Dimension(0, 0)); //这行代码隐藏表头。因为要实现折叠效果,表头不好监听事件 - headerRenderer.setHorizontalAlignment(JLabel.LEFT); - header.setDefaultRenderer(headerRenderer); - - this.setRowHeight(WIDGET_TABLE_ROW_HEIGHT); - this.setGridColor(new Color(212, 208, 200)); - this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - this.setColumnSelectionAllowed(false); - this.setRowSelectionAllowed(false); - this.setFillsViewportHeight(false); - this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); - } - - private MouseAdapter mouseAdapter = new MouseAdapter() { - /** - * 鼠标按下时处理的事件(设置当前选中的行列) - * @param e - */ - @Override - public void mousePressed(MouseEvent e) { - getInstance().setCellSelected(); - if (selectedRow == 0 && !e.isPopupTrigger() && e.getClickCount() == 1 && e.getX() < WIDGET_TABLE_ROW_HEIGHT / 2){ // 如果是点击在第一行 - toggleCollapse(); - } - } - - /** - * 鼠标放开时处理的事件(如果是正在拖动则执行换位操作,重新绘制属性表,如果不是则什么也不做) - * 所谓的换行就是简单的重新拿到一次表格数据然后重新绘制表格 - * @param e - */ - @Override - public void mouseReleased(MouseEvent e) { - if(!draging){ - return; - } - draging = false; - moveComponent.setVisible(false); - int toIndex = e.getY() < GAP ? 0 : (int)Math.rint((e.getY() - GAP)/WIDGET_TABLE_ROW_HEIGHT) + 1; - //当鼠标放开时,将选中的容器调整至新的顺序 - ((WSortLayout)designer.getSelectionModel().getSelection().getSelectedCreator().toData()).adjustOrder(selectedRow - 1, toIndex - 1); - //拿取排序后表格数据,然后重绘表格 - getInstance().refreshData(); - getInstance().repaint(); - designer.fireTargetModified(); - getInstance().setCellSelected(); - } - - /** - * 设置鼠标在属性表区域移动时候的事件 - * @param e - */ - @Override - public void mouseMoved(MouseEvent e) { - int overRow = 0; - for (int i = 0;i < getRowCount();i++) { - if (e.getY() > i * WIDGET_TABLE_ROW_HEIGHT && e.getY() <= (i + 1) * WIDGET_TABLE_ROW_HEIGHT){ - overRow = i; //判断鼠标在哪一行 - } - } - //如果鼠标移动到当前选中的行上面的时候 - if (overRow == selectedRow && selectedRow > 0) { - //把当前选中的那一行的光标改成(除了第一列)移动样式MOVE_CURSOR - setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); - } else { - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - } - - /** - * 鼠标拖动事件(如果鼠标当前是MOVE_CURSOR状态则执行开始拖动的代码, - * 绘制一个moveComponent来跟随鼠标移动) - * @param e - */ - @Override - public void mouseDragged(MouseEvent e) { - int width = getColumnModel().getColumn(0).getWidth(); - //如果当前选中的行的范围是合理的话,就可以拖动 - if (selectedRow < getRowCount() && selectedRow > 0){ - setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); - draging = true; - moveComponent.setText(getValueAt(selectedRow,0).toString()); - moveComponent.setLocation(0, e.getY() - GAP); - moveComponent.setSize(new Dimension(width, WIDGET_TABLE_ROW_HEIGHT)); - moveComponent.setVisible(true); - moveComponent.setForeground(Color.lightGray); - moveComponent.setBorder(BorderFactory.createLineBorder(Color.lightGray)); - } - } - - /** - * 设置鼠标单击时处理的事件(单击控件列表进入控件属性表) - * @param e - */ - @Override - public void mouseClicked(MouseEvent e) { - if(selectedRow > 0){ - //当前点击的控件的名字 - String widgetName = cellData[selectedRow][0]; - if (StringUtils.isNotEmpty(widgetName)){ - //当前选择的容器 - XCreator selectedContainer = designer.getSelectionModel().getSelection().getSelectedCreator(); - WLayout selectedWidget = (WLayout)selectedContainer.toData(); - //当前选择的容器中的控件数量 - int count = selectedWidget.getWidgetCount(); - for (int i = 0;i < count ;i++){ - XCreator xCreator = (XCreator) selectedContainer.getComponent(i); - Widget widget = xCreator.toData(); - if (ComparatorUtils.equals(widgetName, widget.getWidgetName())) { - getEditingDesigner().getSelectionModel().setSelectedCreator(xCreator); - } - } - } - } else if (selectedRow == 0){ // 如果是点击在第一行 - if (!e.isPopupTrigger() && e.getClickCount() > 1) { - toggleCollapse(); - } - } - } - - /** - * 鼠标离开属性表区域事件 - * @param e - */ - public void mouseExited(MouseEvent e) { - draging = false; - moveComponent.setVisible(false); - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - }; - - public MobileWidgetTable getInstance(){ - return this; - } - - public FormDesigner getEditingDesigner(){ - return designer; - } - - /** - * 设置当前get到的行列的单元格为选中状态 - */ - private void setCellSelected() { - selectedRow = getSelectedRow(); - if (selectedRow != -1) { - this.setRowSelectionInterval(selectedRow, selectedRow); - this.setColumnSelectionInterval(0, 0); - } - } - - /** - * 切换属性组折叠属性true/false - */ - private void toggleCollapse() { - this.setCollapsed(!this.isCollapsed()); - //这里获取表格的父控件是为了当表格被折叠了后,装表格的父控件也要相应的重新布局一下 - //比如折叠之后表格行数应该比原来的少,占用父容器空间应该小点,不重新布局父容器,表格大小不会改变 - Container parent = MobileWidgetTable.this.getParent(); - if (parent != null) { - parent.revalidate(); - } - repaint(); - } - - /** - * 重新get排序后的数据 - */ - public void refreshData(){ - cellData = getData(); - } - - /** - * 获取选中控件的控件列表 - * - * @return String[][] 二维数组,[0][0]widgetName - */ - private String[][] getData(){ - if(designer.isFormParaDesigner()){ - return new String[0][0]; - } - - //选择的控件 - XCreator selectedCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); - Widget selectedModel = selectedCreator != null ? selectedCreator.toData() : null; - - if(selectedModel == null){ - return new String[0][0]; - } - - // 选择的控件有两种类型,一种是WLayout,代表容器,一种是Widget,代表控件 - if (selectedModel.acceptType(WSortLayout.class)) { - List mobileWidgetList = ((WSortLayout)selectedModel).getOrderedMobileWidgetList(); - String[][] widgetName = new String[mobileWidgetList.size() + 1][1]; - widgetName[0][0] = Inter.getLocText("FR-Designer_WidgetOrder"); - for (int i = 0; i < mobileWidgetList.size(); i++) { - widgetName[i + 1][0] = mobileWidgetList.get(i); - } - return widgetName; - } else { - return new String[0][0]; - } - } - - public boolean isCollapsed() { - return collapsed; - } - - public void setCollapsed(boolean collapsed) { - this.collapsed = collapsed; - } - - /** - * 自定义的tableEditor类 - */ - public class BeanTableModel extends DefaultTableModel { - public BeanTableModel() { - super(cellData,headers); - } - - @Override - public int getRowCount() { - if (isCollapsed()) { - return 1; - } - return cellData.length; - } - - @Override - public int getColumnCount() { - return 1; - } - - - @Override - public Object getValueAt(int row, int column) { - if (row >= getRowCount() || column >= getColumnCount()) { - return null; - } - if (row == 0) { - return (isCollapsed()? "+" : "-") + cellData[row][0]; - } - - return cellData[row][0]; - } - - @Override - public String getColumnName(int column) { - return headers[0]; - } - - - @Override - public void setValueAt(Object aValue, int row, int column) { - if (row >= getRowCount() || column >= getColumnCount()) { - return; - } - if (aValue == null) { - cellData[row] = null; - return; - } - cellData[row][0] = aValue.toString(); - } - - /** - * 是否可编辑 - * @param row 行号 - * @param column 列号 - * @return 是否可编辑 - */ - public boolean isCellEditable(int row, int column) { - return false; - } - - } - +package com.fr.design.mainframe; + +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.table.*; + +import com.fr.design.designer.creator.XCreator; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itable.GroupRenderer; +import com.fr.form.ui.Widget; +import com.fr.form.ui.container.*; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +/** + * MobileWidgetTable类主要显示各种容器的控件列表(body,tab,绝对布局快,不包括参数面板) + * Created with IntelliJ IDEA. + * User: zx + * Date: 14-9-15 + * Time: 下午4:52 + * Modified by fanglei at 2017/01/23 + */ +public class MobileWidgetTable extends JTable { + + private FormDesigner designer; + private String[][] cellData; + private String[] headers = {Inter.getLocText("Form-Widget_Name")}; + private static final int WIDGET_TABLE_ROW_HEIGHT = 22; + private UILabel moveComponent = new UILabel(); // 作为拖动时候随鼠标移动的那个半透明控件 + private int selectedRow = -1; + private static final int GAP = 11; + private boolean draging = false; + private boolean collapsed = false; // 控件列表是否折叠 + + @Override + public TableCellRenderer getCellRenderer(int row, int column) { + //第一行渲染成为标题的样子 + if (row == 0) { + return new GroupRenderer(); + } + return super.getCellRenderer(row, column); + } + + + public MobileWidgetTable(FormDesigner designer) { + this.designer = designer; + cellData = getData(); + this.setTableProperties(); + TableModel defaultModel = new BeanTableModel(); + this.setModel(defaultModel); + this.repaint(); + this.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()); + refreshData(); + this.addMouseListener(mouseAdapter); + this.addMouseMotionListener(mouseAdapter); + add(moveComponent); + } + + private void setTableProperties() { + JTableHeader header = getTableHeader(); + header.setReorderingAllowed(false); + header.setPreferredSize(new Dimension(0, 0)); // 隐藏表头 + GroupRenderer headerRenderer = new GroupRenderer(); + headerRenderer.setPreferredSize(new Dimension(0, 0)); //这行代码隐藏表头。因为要实现折叠效果,表头不好监听事件 + headerRenderer.setHorizontalAlignment(JLabel.LEFT); + header.setDefaultRenderer(headerRenderer); + + this.setRowHeight(WIDGET_TABLE_ROW_HEIGHT); + this.setGridColor(new Color(212, 208, 200)); + this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + this.setColumnSelectionAllowed(false); + this.setRowSelectionAllowed(false); + this.setFillsViewportHeight(false); + this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + } + + private MouseAdapter mouseAdapter = new MouseAdapter() { + /** + * 鼠标按下时处理的事件(设置当前选中的行列) + * @param e + */ + @Override + public void mousePressed(MouseEvent e) { + getInstance().setCellSelected(); + if (selectedRow == 0 && !e.isPopupTrigger() && e.getClickCount() == 1 && e.getX() < WIDGET_TABLE_ROW_HEIGHT / 2) { // 如果是点击在第一行 + toggleCollapse(); + } + } + + /** + * 鼠标放开时处理的事件(如果是正在拖动则执行换位操作,重新绘制属性表,如果不是则什么也不做) + * 所谓的换行就是简单的重新拿到一次表格数据然后重新绘制表格 + * @param e + */ + @Override + public void mouseReleased(MouseEvent e) { + if (!draging) { + return; + } + draging = false; + moveComponent.setVisible(false); + int toIndex = e.getY() < GAP ? 0 : (int) Math.rint((e.getY() - GAP) / WIDGET_TABLE_ROW_HEIGHT) + 1; + //当鼠标放开时,将选中的容器调整至新的顺序 + ((WSortLayout) designer.getSelectionModel().getSelection().getSelectedCreator().toData()).adjustOrder(selectedRow - 1, toIndex - 1); + //拿取排序后表格数据,然后重绘表格 + getInstance().refreshData(); + getInstance().repaint(); + designer.fireTargetModified(); + getInstance().setCellSelected(); + } + + /** + * 设置鼠标在属性表区域移动时候的事件 + * @param e + */ + @Override + public void mouseMoved(MouseEvent e) { + int overRow = 0; + for (int i = 0; i < getRowCount(); i++) { + if (e.getY() > i * WIDGET_TABLE_ROW_HEIGHT && e.getY() <= (i + 1) * WIDGET_TABLE_ROW_HEIGHT) { + overRow = i; //判断鼠标在哪一行 + } + } + //如果鼠标移动到当前选中的行上面的时候 + if (overRow == selectedRow && selectedRow > 0) { + //把当前选中的那一行的光标改成(除了第一列)移动样式MOVE_CURSOR + setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + } else { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + + /** + * 鼠标拖动事件(如果鼠标当前是MOVE_CURSOR状态则执行开始拖动的代码, + * 绘制一个moveComponent来跟随鼠标移动) + * @param e + */ + @Override + public void mouseDragged(MouseEvent e) { + int width = getColumnModel().getColumn(0).getWidth(); + //如果当前选中的行的范围是合理的话,就可以拖动 + if (selectedRow < getRowCount() && selectedRow > 0) { + setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + draging = true; + moveComponent.setText(getValueAt(selectedRow, 0).toString()); + moveComponent.setLocation(0, e.getY() - GAP); + moveComponent.setSize(new Dimension(width, WIDGET_TABLE_ROW_HEIGHT)); + moveComponent.setVisible(true); + moveComponent.setForeground(Color.lightGray); + moveComponent.setBorder(BorderFactory.createLineBorder(Color.lightGray)); + } + } + + /** + * 设置鼠标单击时处理的事件(单击控件列表进入控件属性表) + * @param e + */ + @Override + public void mouseClicked(MouseEvent e) { + if (selectedRow > 0) { + //当前点击的控件的名字 + String widgetName = cellData[selectedRow][0]; + if (StringUtils.isNotEmpty(widgetName)) { + //当前选择的容器 + XCreator selectedContainer = designer.getSelectionModel().getSelection().getSelectedCreator(); + WLayout selectedWidget = (WLayout) selectedContainer.toData(); + //当前选择的容器中的控件数量 + int count = selectedWidget.getWidgetCount(); + for (int i = 0; i < count; i++) { + XCreator xCreator = (XCreator) selectedContainer.getComponent(i); + Widget widget = xCreator.toData(); + if (ComparatorUtils.equals(widgetName, widget.getWidgetName())) { + getEditingDesigner().getSelectionModel().setSelectedCreator(xCreator); + } + } + } + } else if (selectedRow == 0) { // 如果是点击在第一行 + if (!e.isPopupTrigger() && e.getClickCount() > 1) { + toggleCollapse(); + } + } + } + + /** + * 鼠标离开属性表区域事件 + * @param e + */ + public void mouseExited(MouseEvent e) { + draging = false; + moveComponent.setVisible(false); + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + }; + + public MobileWidgetTable getInstance() { + return this; + } + + public FormDesigner getEditingDesigner() { + return designer; + } + + /** + * 设置当前get到的行列的单元格为选中状态 + */ + private void setCellSelected() { + selectedRow = getSelectedRow(); + if (selectedRow != -1) { + this.setRowSelectionInterval(selectedRow, selectedRow); + this.setColumnSelectionInterval(0, 0); + } + } + + /** + * 切换属性组折叠属性true/false + */ + private void toggleCollapse() { + this.setCollapsed(!this.isCollapsed()); + //这里获取表格的父控件是为了当表格被折叠了后,装表格的父控件也要相应的重新布局一下 + //比如折叠之后表格行数应该比原来的少,占用父容器空间应该小点,不重新布局父容器,表格大小不会改变 + Container parent = MobileWidgetTable.this.getParent(); + if (parent != null) { + parent.revalidate(); + } + repaint(); + } + + /** + * 重新get排序后的数据 + */ + public void refreshData() { + cellData = getData(); + } + + /** + * 获取选中控件的控件列表 + * + * @return String[][] 二维数组,[0][0]widgetName + */ + private String[][] getData() { + if (designer.isFormParaDesigner()) { + return new String[0][0]; + } + + //选择的控件 + XCreator selectedCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); + Widget selectedModel = selectedCreator != null ? selectedCreator.toData() : null; + + if (selectedModel == null) { + return new String[0][0]; + } + + // 选择的控件有两种类型,一种是WLayout,代表容器,一种是Widget,代表控件 + if (selectedModel.acceptType(WSortLayout.class)) { + List mobileWidgetList = ((WSortLayout) selectedModel).getOrderedMobileWidgetList(); + String[][] widgetName = new String[mobileWidgetList.size() + 1][1]; + widgetName[0][0] = Inter.getLocText("FR-Designer_WidgetOrder"); + for (int i = 0; i < mobileWidgetList.size(); i++) { + widgetName[i + 1][0] = mobileWidgetList.get(i); + } + return widgetName; + } else { + return new String[0][0]; + } + } + + public boolean isCollapsed() { + return collapsed; + } + + public void setCollapsed(boolean collapsed) { + this.collapsed = collapsed; + } + + /** + * 自定义的tableEditor类 + */ + public class BeanTableModel extends DefaultTableModel { + public BeanTableModel() { + super(cellData, headers); + } + + @Override + public int getRowCount() { + if (isCollapsed()) { + return 1; + } + return cellData.length; + } + + @Override + public int getColumnCount() { + return 1; + } + + + @Override + public Object getValueAt(int row, int column) { + if (row >= getRowCount() || column >= getColumnCount()) { + return null; + } + if (row == 0) { + return (isCollapsed() ? "+" : "-") + cellData[row][0]; + } + + return cellData[row][0]; + } + + @Override + public String getColumnName(int column) { + return headers[0]; + } + + + @Override + public void setValueAt(Object aValue, int row, int column) { + if (row >= getRowCount() || column >= getColumnCount()) { + return; + } + if (aValue == null) { + cellData[row] = null; + return; + } + cellData[row][0] = aValue.toString(); + } + + /** + * 是否可编辑 + * + * @param row 行号 + * @param column 列号 + * @return 是否可编辑 + */ + public boolean isCellEditable(int row, int column) { + return false; + } + + } + } \ No newline at end of file diff --git a/designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java b/designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java index 533ca9dc0f..6a8480206d 100644 --- a/designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java +++ b/designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java @@ -1,372 +1,372 @@ -package com.fr.design.mainframe; - -import com.fr.base.BaseUtils; -import com.fr.design.ExtraDesignClassManager; -import com.fr.design.designer.beans.events.DesignerEditListener; -import com.fr.design.designer.beans.events.DesignerEvent; -import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XCreatorUtils; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWParameterLayout; -import com.fr.design.designer.properties.EventPropertyTable; -import com.fr.design.designer.properties.WidgetPropertyTable; -import com.fr.design.fun.WidgetPropertyUIProvider; -import com.fr.design.gui.frpane.UITabbedPane; -import com.fr.design.gui.icontainer.UIScrollPane; -import com.fr.design.gui.itable.AbstractPropertyTable; -import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.form.ui.Widget; -import com.fr.general.Inter; -import com.fr.stable.ArrayUtils; - -import javax.swing.*; -import javax.swing.border.LineBorder; -import javax.swing.table.JTableHeader; -import java.awt.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -/** - * 控件属性表绘制 - * Modified by fanglei - */ -public class WidgetPropertyPane extends FormDockView implements BaseWidgetPropertyPane { - - private static final String PARA = "para"; - private static final String BODY = "body"; - private WidgetPropertyTable propertyTable; // 控件的属性表 - private EventPropertyTable eventTable; // 控件的事件表 - private List widgetPropertyTables; // 这个变量应该是保存控件拓展的属性tab - private FormDesigner designer; // 当前designer - private UIScrollPane psp; // 用来装载属性表table的容器 - private UIScrollPane esp; //用来装载事件table的容器 - private JPanel wsp; // 装载移动端tab的容器,包括移动端属性表和控件拓展的移动端属性表 - private MobileParaWidgetTable mobileParaWidgetTable; // 参数面板的移动端属性tab(和body的移动端属性tab区别是没有标签名column) - private MobileWidgetTable mobileWidgetTable; // body的移动端属性tab - private UIScrollPane downPanel; // 这个滚动容器是用于装载centerPane的 - private JPanel centerPane; // 此centerPane采用的是cardLayout布局,装载着mobileWidgetTable和mobileBodyWidgetTable - private CardLayout cardLayout; // 卡片布局,选中参数面板时显示mobileWidgetTable,选中body时显示mobileBodyWidgetTable - private JTableHeader header;//把表头单独get出来作为一个组件 - - public static WidgetPropertyPane getInstance() { - if (HOLDER.singleton == null) { - HOLDER.singleton = new WidgetPropertyPane(); - } - return HOLDER.singleton; - } - - public static WidgetPropertyPane getInstance(FormDesigner formEditor) { - HOLDER.singleton.setEditingFormDesigner(formEditor); - HOLDER.singleton.refreshDockingView(); - return HOLDER.singleton; - } - - private static class HOLDER { - private static WidgetPropertyPane singleton = new WidgetPropertyPane(); - } - - private WidgetPropertyPane() { - setLayout(FRGUIPaneFactory.createBorderLayout()); - } - - @Override - public String getViewTitle() { - return Inter.getLocText("Form-Widget_Property_Table"); - } - - @Override - public Icon getViewIcon() { - return BaseUtils.readIcon("/com/fr/design/images/m_report/attributes.png"); - } - - @Override - /** - * 绘制属性表tab - */ - public void refreshDockingView() { - designer = this.getEditingFormDesigner(); - removeAll(); - if (designer == null) { - clearDockingView(); - return; - } - widgetPropertyTables = new ArrayList(); - - //依次创建属性表、事件表、移动端表,再将它们整合到TabPane中去 - this.createPropertyTable(); - this.createEventTable(); - this.createMobileWidgetTable(); - this.createTabPane(); - - this.initTables(); - } - - /** - * 初始化属性表,事件表,移动端拓展的属性表 - */ - private void initTables() { - propertyTable.initPropertyGroups(null); - eventTable.refresh(); - for (AbstractPropertyTable propertyTable : widgetPropertyTables) { - propertyTable.initPropertyGroups(designer); - } - } - - /** - * 创建属性表table - */ - private void createPropertyTable() { - propertyTable = new WidgetPropertyTable(designer); - designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable)); - propertyTable.setBorder(null); - psp = new UIScrollPane(propertyTable); // 用来装载属性表table - psp.setBorder(null); - } - - /** - * 创建事件表(事件选项卡不是JTable) - */ - private void createEventTable() { - eventTable = new EventPropertyTable(designer); - designer.addDesignerEditListener(new EventPropertyDesignerAdapter(eventTable)); - eventTable.setBorder(null); - esp = new UIScrollPane(eventTable); //用来装载事件table - esp.setBorder(null); - } - - /** - * 创建移动端控件列表 - */ - private void createMobileWidgetTable() { - //加上表头后,这里不再使用borderLayout布局,而采用BoxLayout布局 - wsp = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); - wsp.setBorder(null); - mobileParaWidgetTable = new MobileParaWidgetTable(designer); - mobileWidgetTable = new MobileWidgetTable(designer); - designer.addDesignerEditListener(new mobileWidgetDesignerAdapter()); - centerPane = FRGUIPaneFactory.createCardLayout_S_Pane(); - cardLayout = (CardLayout) centerPane.getLayout(); - centerPane.add(mobileParaWidgetTable, PARA); - // 采用卡片布局的容器必须指定卡片名字,如果没有卡片名字 - // 就会出现:Exception in thread "main" java.lang.IllegalArgumentException: - // cannot add to layout: constraint must be a string - // 第二个参数代表卡片的名字。后来show方法调用时通过名字找到要显示的卡片 - centerPane.add(mobileWidgetTable, BODY); //这两句代码,是把JTable放到一个JPanel中去了,表头不会显示, - //只有放到JScrollPanel中去表头才能正常显示,这就是MobileWidgetTable中定义了表头却没有显示的原因! - //解决方案:MobileWidgetTable实在无法直接放到JScrollPanel中去的时候,应该把表头get出来单独作为一个组件显示 - - if (hasSelectParaPane(designer)) { - cardLayout.show(centerPane, PARA); - header = mobileParaWidgetTable.getTableHeader(); - } else { - cardLayout.show(centerPane, BODY); - header = mobileWidgetTable.getTableHeader(); - } - downPanel = new UIScrollPane(centerPane); - downPanel.setBorder(new LineBorder(Color.GRAY)); - - //获取拓展移动端属性tab - WidgetPropertyUIProvider[] widgetAttrProviders = getExtraPropertyUIProviders(); - - addWidgetAttr(widgetAttrProviders); - } - - /** - * 将属性表,事件表,移动端控件列表整合到TabPane里面去 - */ - private void createTabPane() { - UITabbedPane tabbedPane = new UITabbedPane(); // tab选项卡容器 - initTabPane(tabbedPane); - add(tabbedPane, BorderLayout.CENTER); - } - - /** - * 获取当前控件扩展的属性tab - * 来源有两个: - * 1, 各个控件从各自的Xcreator里扩展(例如手机重布局的tab就是从Xcreator中扩展的); - * 2, 所有的控件从插件里扩展. - * - * @return 扩展的tab - */ - private WidgetPropertyUIProvider[] getExtraPropertyUIProviders() { - FormSelection selection = designer.getSelectionModel().getSelection(); - WidgetPropertyUIProvider[] embeddedPropertyUIProviders = null; - if (selection != null && selection.getSelectedCreator() != null) { - embeddedPropertyUIProviders = selection.getSelectedCreator().getWidgetPropertyUIProviders(); - } - Set set = ExtraDesignClassManager.getInstance().getArray(WidgetPropertyUIProvider.XML_TAG); - return ArrayUtils.addAll(embeddedPropertyUIProviders, set.toArray(new WidgetPropertyUIProvider[set.size()])); - } - - /** - * 判断是将拓展的tab放入属性表还是将原来的tab放入属性表 - * - * @param widgetAttrProviders 拓展的tab - */ - private void addWidgetAttr(WidgetPropertyUIProvider[] widgetAttrProviders) { - if (widgetAttrProviders.length == 0) { // 判断有没有拓展的tab,没有就使用原来的 - wsp.add(header); - wsp.add(downPanel); - } else { - for (WidgetPropertyUIProvider widgetAttrProvider : widgetAttrProviders) { - AbstractPropertyTable propertyTable = widgetAttrProvider.createWidgetAttrTable(); - widgetPropertyTables.add(propertyTable); - designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable)); - UIScrollPane uiScrollPane = new UIScrollPane(getExtraBodyTable(propertyTable)); - wsp.add(uiScrollPane); - } - } - } - - /** - * 如果是body的拓展属性表,那么要额外加上一张控件顺序表 - * - * @return - */ - private Component getExtraBodyTable(AbstractPropertyTable abstractPropertyTable) { - Widget selection = designer.getSelectionModel().getSelection().getSelectedCreator().toData(); - if (selection.getWidgetName().equals("body")) { - JPanel jPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); - jPanel.add(abstractPropertyTable); - MobileWidgetTable mobileWidgetTable = new MobileWidgetTable(designer); - jPanel.add(mobileWidgetTable.getTableHeader()); - jPanel.add(mobileWidgetTable); - return jPanel; - } - return abstractPropertyTable; - } - - private void initTabPane(UITabbedPane tabbedPane) { - tabbedPane.setOpaque(true); - tabbedPane.setBorder(null); - tabbedPane.setTabPlacement(SwingConstants.BOTTOM); - tabbedPane.addTab(Inter.getLocText("FR-Designer_Properties"), psp); - tabbedPane.addTab(Inter.getLocText("FR-Designer_Event"), esp); - tabbedPane.addTab(Inter.getLocText("FR-Widget_Mobile_Terminal"), wsp); - } - - - /** - * 选中的组件是否在参数面板里 - * - * @param designer 设计器 - * @return 是则返回true - */ - public boolean hasSelectParaPane(FormDesigner designer) { - XCreator xCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); - if (xCreator == null) { - xCreator = designer.getRootComponent(); - } - XLayoutContainer container = XCreatorUtils.getHotspotContainer(xCreator); - //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; - } +package com.fr.design.mainframe; + +import com.fr.base.BaseUtils; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.designer.beans.events.DesignerEditListener; +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XCreatorUtils; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWParameterLayout; +import com.fr.design.designer.properties.EventPropertyTable; +import com.fr.design.designer.properties.WidgetPropertyTable; +import com.fr.design.fun.WidgetPropertyUIProvider; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.itable.AbstractPropertyTable; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.form.ui.Widget; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; + +import javax.swing.*; +import javax.swing.border.LineBorder; +import javax.swing.table.JTableHeader; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * 控件属性表绘制 + * Modified by fanglei + */ +public class WidgetPropertyPane extends FormDockView implements BaseWidgetPropertyPane { + + private static final String PARA = "para"; + private static final String BODY = "body"; + private WidgetPropertyTable propertyTable; // 控件的属性表 + private EventPropertyTable eventTable; // 控件的事件表 + private List widgetPropertyTables; // 这个变量应该是保存控件拓展的属性tab + private FormDesigner designer; // 当前designer + private UIScrollPane psp; // 用来装载属性表table的容器 + private UIScrollPane esp; //用来装载事件table的容器 + private JPanel wsp; // 装载移动端tab的容器,包括移动端属性表和控件拓展的移动端属性表 + private MobileParaWidgetTable mobileParaWidgetTable; // 参数面板的移动端属性tab(和body的移动端属性tab区别是没有标签名column) + private MobileWidgetTable mobileWidgetTable; // body的移动端属性tab + private UIScrollPane downPanel; // 这个滚动容器是用于装载centerPane的 + private JPanel centerPane; // 此centerPane采用的是cardLayout布局,装载着mobileWidgetTable和mobileBodyWidgetTable + private CardLayout cardLayout; // 卡片布局,选中参数面板时显示mobileWidgetTable,选中body时显示mobileBodyWidgetTable + private JTableHeader header;//把表头单独get出来作为一个组件 + + public static WidgetPropertyPane getInstance() { + if (HOLDER.singleton == null) { + HOLDER.singleton = new WidgetPropertyPane(); + } + return HOLDER.singleton; + } + + public static WidgetPropertyPane getInstance(FormDesigner formEditor) { + HOLDER.singleton.setEditingFormDesigner(formEditor); + HOLDER.singleton.refreshDockingView(); + return HOLDER.singleton; + } + + private static class HOLDER { + private static WidgetPropertyPane singleton = new WidgetPropertyPane(); + } + + private WidgetPropertyPane() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + } + + @Override + public String getViewTitle() { + return Inter.getLocText("Form-Widget_Property_Table"); + } + + @Override + public Icon getViewIcon() { + return BaseUtils.readIcon("/com/fr/design/images/m_report/attributes.png"); + } + + @Override + /** + * 绘制属性表tab + */ + public void refreshDockingView() { + designer = this.getEditingFormDesigner(); + removeAll(); + if (designer == null) { + clearDockingView(); + return; + } + widgetPropertyTables = new ArrayList(); + + //依次创建属性表、事件表、移动端表,再将它们整合到TabPane中去 + this.createPropertyTable(); + this.createEventTable(); + this.createMobileWidgetTable(); + this.createTabPane(); + + this.initTables(); + } + + /** + * 初始化属性表,事件表,移动端拓展的属性表 + */ + private void initTables() { + propertyTable.initPropertyGroups(null); + eventTable.refresh(); + for (AbstractPropertyTable propertyTable : widgetPropertyTables) { + propertyTable.initPropertyGroups(designer); + } + } + + /** + * 创建属性表table + */ + private void createPropertyTable() { + propertyTable = new WidgetPropertyTable(designer); + designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable)); + propertyTable.setBorder(null); + psp = new UIScrollPane(propertyTable); // 用来装载属性表table + psp.setBorder(null); + } + + /** + * 创建事件表(事件选项卡不是JTable) + */ + private void createEventTable() { + eventTable = new EventPropertyTable(designer); + designer.addDesignerEditListener(new EventPropertyDesignerAdapter(eventTable)); + eventTable.setBorder(null); + esp = new UIScrollPane(eventTable); //用来装载事件table + esp.setBorder(null); + } + + /** + * 创建移动端控件列表 + */ + private void createMobileWidgetTable() { + //加上表头后,这里不再使用borderLayout布局,而采用BoxLayout布局 + wsp = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + wsp.setBorder(null); + mobileParaWidgetTable = new MobileParaWidgetTable(designer); + mobileWidgetTable = new MobileWidgetTable(designer); + designer.addDesignerEditListener(new mobileWidgetDesignerAdapter()); + centerPane = FRGUIPaneFactory.createCardLayout_S_Pane(); + cardLayout = (CardLayout) centerPane.getLayout(); + centerPane.add(mobileParaWidgetTable, PARA); + // 采用卡片布局的容器必须指定卡片名字,如果没有卡片名字 + // 就会出现:Exception in thread "main" java.lang.IllegalArgumentException: + // cannot add to layout: constraint must be a string + // 第二个参数代表卡片的名字。后来show方法调用时通过名字找到要显示的卡片 + centerPane.add(mobileWidgetTable, BODY); //这两句代码,是把JTable放到一个JPanel中去了,表头不会显示, + //只有放到JScrollPanel中去表头才能正常显示,这就是MobileWidgetTable中定义了表头却没有显示的原因! + //解决方案:MobileWidgetTable实在无法直接放到JScrollPanel中去的时候,应该把表头get出来单独作为一个组件显示 + + if (hasSelectParaPane(designer)) { + cardLayout.show(centerPane, PARA); + header = mobileParaWidgetTable.getTableHeader(); + } else { + cardLayout.show(centerPane, BODY); + header = mobileWidgetTable.getTableHeader(); + } + downPanel = new UIScrollPane(centerPane); + downPanel.setBorder(new LineBorder(Color.GRAY)); + + //获取拓展移动端属性tab + WidgetPropertyUIProvider[] widgetAttrProviders = getExtraPropertyUIProviders(); + + addWidgetAttr(widgetAttrProviders); + } + + /** + * 将属性表,事件表,移动端控件列表整合到TabPane里面去 + */ + private void createTabPane() { + UITabbedPane tabbedPane = new UITabbedPane(); // tab选项卡容器 + initTabPane(tabbedPane); + add(tabbedPane, BorderLayout.CENTER); + } + + /** + * 获取当前控件扩展的属性tab + * 来源有两个: + * 1, 各个控件从各自的Xcreator里扩展(例如手机重布局的tab就是从Xcreator中扩展的); + * 2, 所有的控件从插件里扩展. + * + * @return 扩展的tab + */ + private WidgetPropertyUIProvider[] getExtraPropertyUIProviders() { + FormSelection selection = designer.getSelectionModel().getSelection(); + WidgetPropertyUIProvider[] embeddedPropertyUIProviders = null; + if (selection != null && selection.getSelectedCreator() != null) { + embeddedPropertyUIProviders = selection.getSelectedCreator().getWidgetPropertyUIProviders(); + } + Set set = ExtraDesignClassManager.getInstance().getArray(WidgetPropertyUIProvider.XML_TAG); + return ArrayUtils.addAll(embeddedPropertyUIProviders, set.toArray(new WidgetPropertyUIProvider[set.size()])); + } + + /** + * 判断是将拓展的tab放入属性表还是将原来的tab放入属性表 + * + * @param widgetAttrProviders 拓展的tab + */ + private void addWidgetAttr(WidgetPropertyUIProvider[] widgetAttrProviders) { + if (widgetAttrProviders.length == 0) { // 判断有没有拓展的tab,没有就使用原来的 + wsp.add(header); + wsp.add(downPanel); + } else { + for (WidgetPropertyUIProvider widgetAttrProvider : widgetAttrProviders) { + AbstractPropertyTable propertyTable = widgetAttrProvider.createWidgetAttrTable(); + widgetPropertyTables.add(propertyTable); + designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable)); + UIScrollPane uiScrollPane = new UIScrollPane(getExtraBodyTable(propertyTable)); + wsp.add(uiScrollPane); + } + } + } + + /** + * 如果是body的拓展属性表,那么要额外加上一张控件顺序表 + * + * @return + */ + private Component getExtraBodyTable(AbstractPropertyTable abstractPropertyTable) { + Widget selection = designer.getSelectionModel().getSelection().getSelectedCreator().toData(); + if (selection.getWidgetName().equals("body")) { + JPanel jPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + jPanel.add(abstractPropertyTable); + MobileWidgetTable mobileWidgetTable = new MobileWidgetTable(designer); + jPanel.add(mobileWidgetTable.getTableHeader()); + jPanel.add(mobileWidgetTable); + return jPanel; + } + return abstractPropertyTable; + } + + private void initTabPane(UITabbedPane tabbedPane) { + tabbedPane.setOpaque(true); + tabbedPane.setBorder(null); + tabbedPane.setTabPlacement(SwingConstants.BOTTOM); + tabbedPane.addTab(Inter.getLocText("FR-Designer_Properties"), psp); + tabbedPane.addTab(Inter.getLocText("FR-Designer_Event"), esp); + tabbedPane.addTab(Inter.getLocText("FR-Widget_Mobile_Terminal"), wsp); + } + + + /** + * 选中的组件是否在参数面板里 + * + * @param designer 设计器 + * @return 是则返回true + */ + public boolean hasSelectParaPane(FormDesigner designer) { + XCreator xCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); + if (xCreator == null) { + xCreator = designer.getRootComponent(); + } + XLayoutContainer container = XCreatorUtils.getHotspotContainer(xCreator); + //TODO container可能为空,引发空指针异常 + return xCreator.acceptType(XWParameterLayout.class) || container.acceptType(XWParameterLayout.class); + } + + public void setEditingFormDesigner(BaseFormDesigner editor) { + FormDesigner fd = (FormDesigner) editor; + super.setEditingFormDesigner(fd); + } + + private void clearDockingView() { + propertyTable = null; + eventTable = null; + if (widgetPropertyTables != null) { + widgetPropertyTables.clear(); + } + JScrollPane psp = new JScrollPane(); + psp.setBorder(null); + this.add(psp, BorderLayout.CENTER); + } + + /** + * 属性表监听界面事件(编辑,删除,选中,改变大小) + */ + private class WidgetPropertyDesignerAdapter implements DesignerEditListener { + AbstractPropertyTable propertyTable; + + WidgetPropertyDesignerAdapter(AbstractPropertyTable propertyTable) { + this.propertyTable = propertyTable; + } + + @Override + public void fireCreatorModified(DesignerEvent evt) { + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { + propertyTable.initPropertyGroups(designer); + } else if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED) { + repaint(); + } + } + + @Override + public boolean equals(Object o) { + return o instanceof WidgetPropertyDesignerAdapter && ((WidgetPropertyDesignerAdapter) o).propertyTable == this.propertyTable; + } + } + + /** + * 事件表监听界面事件(编辑,选中) + */ + private class EventPropertyDesignerAdapter implements DesignerEditListener { + EventPropertyTable propertyTable; + + EventPropertyDesignerAdapter(EventPropertyTable eventTable) { + this.propertyTable = eventTable; + } + + @Override + public void fireCreatorModified(DesignerEvent evt) { + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) { + propertyTable.refresh(); + } + } + + @Override + public boolean equals(Object o) { + return o instanceof EventPropertyDesignerAdapter; + } + } + + /** + * 移动端属性表监听界面事件(改变大小,编辑,选中,增加控件) + */ + private class mobileWidgetDesignerAdapter implements DesignerEditListener { + + mobileWidgetDesignerAdapter() { + } + + /** + * 响应界面改变事件 + * + * @param evt 事件 + */ + public void fireCreatorModified(DesignerEvent evt) { + if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED + || evt.getCreatorEventID() == DesignerEvent.CREATOR_ADDED) { + int value = downPanel.getVerticalScrollBar().getValue(); + if (hasSelectParaPane(getEditingFormDesigner())) { + cardLayout.show(centerPane, PARA); + mobileParaWidgetTable.refreshData(); + } else { + cardLayout.show(centerPane, BODY); + mobileWidgetTable.refreshData(); + } + //出现滚动条 + downPanel.doLayout(); + //控件列表选中某组件,触发表单中选中控件,选中事件又触发列表刷新,滚动条回到0 + //此处设置滚动条值为刷新前 + downPanel.getVerticalScrollBar().setValue(value); + } + } + } + + @Override + public Location preferredLocation() { + return Location.WEST_BELOW; + } } \ No newline at end of file