plough 8 years ago
parent
commit
945b6fabf2
  1. 21
      designer_base/build.dev.gradle
  2. 70
      designer_base/build.dev.gradle.bak
  3. 70
      designer_base/src/com/fr/design/actions/edit/CopyAction.java
  4. 1130
      designer_base/src/com/fr/design/beans/location/MoveUtils.java
  5. 7
      designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java
  6. 2
      designer_base/src/com/fr/design/locale/designer.properties
  7. 2
      designer_base/src/com/fr/design/locale/designer_en_US.properties
  8. 2
      designer_base/src/com/fr/design/locale/designer_ja_JP.properties
  9. 2
      designer_base/src/com/fr/design/locale/designer_ko_KR.properties
  10. 2
      designer_base/src/com/fr/design/locale/designer_zh_CN.properties
  11. 2
      designer_base/src/com/fr/design/locale/designer_zh_TW.properties
  12. 67
      designer_base/src/com/fr/design/mainframe/BaseJForm.java
  13. 20
      designer_base/src/com/fr/design/mainframe/toolbar/ToolBarMenuDockPlus.java
  14. 73
      designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java
  15. 303
      designer_base/src/com/fr/design/utils/ComponentUtils.java
  16. 20
      designer_chart/build.dev.gradle
  17. 85
      designer_chart/build.dev.gradle.bak
  18. 2
      designer_chart/src/com/fr/design/chart/fun/IndependentChartUIProvider.java
  19. 19
      designer_form/build.dev.gradle
  20. 4
      designer_form/build.dev.gradle.bak
  21. 177
      designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java
  22. 59
      designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java
  23. 361
      designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java
  24. 701
      designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java
  25. 2385
      designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java
  26. 210
      designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java
  27. 333
      designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java
  28. 744
      designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java
  29. 182
      designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java
  30. 1388
      designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java
  31. 170
      designer_form/src/com/fr/design/mainframe/ConnectorHelper.java
  32. 1239
      designer_form/src/com/fr/design/mainframe/EditingMouseListener.java
  33. 239
      designer_form/src/com/fr/design/mainframe/FormDesigner.java
  34. 572
      designer_form/src/com/fr/design/mainframe/FormSelection.java
  35. 394
      designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java
  36. 1589
      designer_form/src/com/fr/design/mainframe/JForm.java
  37. 692
      designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java
  38. 736
      designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java

21
designer_base/build.dev.gradle

@ -1,8 +1,25 @@
apply plugin: 'java'
tasks.withType(JavaCompile){
options.encoding = 'UTF-8'
}
buildscript {
repositories {
maven {
url "http://www.eveoh.nl/files/maven2"
}
}
dependencies {
classpath "nl.eveoh:gradle-aspectj:1.2"
}
}
ext.aspectjVersion = '1.7.4'
apply plugin: 'aspectj'
repositories {
mavenCentral()
}
//jdk版本
sourceCompatibility=1.7
//jar包版本

70
designer_base/build.dev.gradle.bak

@ -0,0 +1,70 @@
apply plugin: 'java'
tasks.withType(JavaCompile){
options.encoding = 'UTF-8'
}
//jdk版本
sourceCompatibility=1.7
//jar包版本
version='8.0'
//jar包重命名
jar{
baseName='fr-designer-core'
}
def srcDir="."
//
sourceSets{
main{
java{
srcDirs=["${srcDir}/src"]
}
}
}
//
FileTree files =fileTree(dir:'./',include:'build.*.gradle')
def buildDir=files[0].path.substring(0,files[0].path.lastIndexOf ('\\'))
buildDir=buildDir.substring(0,buildDir.lastIndexOf ('\\'))
def branchName=buildDir.substring(buildDir.lastIndexOf ('\\')+1)
//
dependencies{
compile fileTree(dir:"../../../finereport-lib-stable/${branchName}",include:'**/*.jar')
compile fileTree(dir:'../../../',include:"finereport-*-stable/${branchName}/**/build/libs/*.jar")
testCompile 'junit:junit:4.12'
}
//.java文件到classes文件夹下参与打包
task copyFile(type:Copy,dependsOn:compileJava){
copy{
from ("${srcDir}/src"){
exclude '**/.setting/**','.classpath','.project','**/*.java','**/*.db','**/*.g','**/package.html'
}
into 'build/classes/main'
}
}
//js文件
task compressJS{
ant.taskdef(name:'yuicompress',classname:'com.yahoo.platform.yui.compressor.YUICompressTask'){
classpath {
fileset(dir:'../../../finereport-lib4build-stable',includes:'**/*.jar')
}
}
ant.yuicompress(linebreak:"500",warn:"false", munge:"yes",preserveallsemicolons:"false",charset:"utf-8",encoding:"utf-8",outputfolder:'build/classes/main'){
fileset (dir:"${srcDir}/src"){
include (name:'**/*.js')
include (name:'**/*.css')
}
}
}
jar.dependsOn compressJS

70
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;
}
}

1130
designer_base/src/com/fr/design/beans/location/MoveUtils.java

File diff suppressed because it is too large Load Diff

7
designer_base/src/com/fr/design/beans/location/WidgetForbidWindow.java

@ -22,7 +22,6 @@ public class WidgetForbidWindow extends JWindow {
*/
public WidgetForbidWindow() {
this.add(promptButton);
this.setSize(WIDTH, HEIGHT);
}
@ -31,18 +30,16 @@ public class WidgetForbidWindow extends JWindow {
*
* @param x x坐标
* @param y y坐标
*
*/
public void showWindow(int x, int y){
public void showWindow(int x, int y) {
this.setLocation(x - WIDTH / 2, y - HEIGHT / 2);
this.setVisible(true);
}
/**
* 隐藏当前窗口
*
*/
public void hideWindow(){
public void hideWindow() {
this.setVisible(false);
}
}

2
designer_base/src/com/fr/design/locale/designer.properties

@ -543,7 +543,7 @@ FR-Designer_Left_Display=Left
FR-Designer_About_Version=Version
FR-Designer_About_CopyRight=Copy Right
FR-Designer_Service_Phone=Service Phone
FR-Designer_Allow_Blank=Allow Blank
FR-Designer_Allow_Null=Allow Null
FR-Designer_PageSetup_Page=Page
FR-Designer_Custom_Job_Description=Description
FR-Designer_Property=Property

2
designer_base/src/com/fr/design/locale/designer_en_US.properties

@ -544,7 +544,7 @@ FR-Designer_Left_Display=Left
FR-Designer_About_Version=Version
FR-Designer_About_CopyRight=Copy Right
FR-Designer_Service_Phone=Service Phone
FR-Designer_Allow_Blank=Allow Null
FR-Designer_Allow_Null=Allow Null
FR-Designer_PageSetup_Page=Page
FR-Designer_Custom_Job_Description=Description
FR-Designer_Property=Property

2
designer_base/src/com/fr/design/locale/designer_ja_JP.properties

@ -518,7 +518,7 @@ FR-Designer_Left_Display=\u5DE6\u8868\u793A
FR-Designer_About_Version=\u30D0\u30FC\u30B8\u30E7\u30F3
FR-Designer_About_CopyRight=\u8457\u4F5C\u6A29\u6240\u6709
FR-Designer_Service_Phone=\u30B5\u30FC\u30D3\u30B9\u96FB\u8A71\uFF1A
FR-Designer_Allow_Blank=\u7A7A\u6B04\u3042\u308A
FR-Designer_Allow_Null=\u7A7A\u6B04\u3042\u308A
FR-Designer_PageSetup_Page=\u30DA\u30FC\u30B8
FR-Designer_Custom_Job_Description=\u8A18\u8FF0
FR-Designer_Property=\u5C5E\u6027

2
designer_base/src/com/fr/design/locale/designer_ko_KR.properties

@ -514,7 +514,7 @@ FR-Designer_Left_Display=\uC67C\uCABD\uBCF4\uC774\uAE30
FR-Designer_About_Version=\uBC84\uC804
FR-Designer_About_CopyRight=\uD310\uAD8C\uC18C\uC720
FR-Designer_Service_Phone=\uC11C\uBE44\uC2A4\uC804\uD654\uFF1A
FR-Designer_Allow_Blank=\uBE48\uCE78\uD5C8\uC6A9
FR-Designer_Allow_Null=\uBE48\uCE78\uD5C8\uC6A9
FR-Designer_PageSetup_Page=\uC6F9\uD398\uC774\uC9C0
FR-Designer_Custom_Job_Description=\uC124\uBA85
FR-Designer_Property=\uC18D\uC131

2
designer_base/src/com/fr/design/locale/designer_zh_CN.properties

@ -548,7 +548,7 @@ FR-Designer_Left_Display=\u5DE6\u5C55\u793A
FR-Designer_About_Version=\u7248\u672C
FR-Designer_About_CopyRight=\u7248\u6743\u6240\u6709
FR-Designer_Service_Phone=\u670D\u52A1\u7535\u8BDD\uFF1A
FR-Designer_Allow_Blank=\u5141\u8BB8\u4E3A\u7A7A
FR-Designer_Allow_Null=\u5141\u8BB8\u4E3A\u7A7A
FR-Designer_PageSetup_Page=\u9875\u9762
FR-Designer_Custom_Job_Description=\u63CF\u8FF0
FR-Designer_Property=\u5C5E\u6027

2
designer_base/src/com/fr/design/locale/designer_zh_TW.properties

@ -536,7 +536,7 @@ FR-Designer_Left_Display=\u5DE6\u986F\u793A
FR-Designer_About_Version=\u7248\u672C
FR-Designer_About_CopyRight=\u7248\u6B0A\u6240\u6709
FR-Designer_Service_Phone=\u670D\u52D9\u96FB\u8A71\uFF1A
FR-Designer_Allow_Blank=\u5141\u8A31\u70BA\u7A7A\u767D
FR-Designer_Allow_Null=\u5141\u8A31\u70BA\u7A7A\u767D
FR-Designer_PageSetup_Page=\u9801\u9762
FR-Designer_Custom_Job_Description=\u63CF\u8FF0
FR-Designer_Property=\u5C6C\u6027

67
designer_base/src/com/fr/design/mainframe/BaseJForm.java

@ -1 +1,66 @@
package com.fr.design.mainframe; import javax.swing.JComponent; import com.fr.form.FormElementCaseContainerProvider; /** * Author : Shockway * Date: 13-7-15 * Time: 上午10:28 */ public interface BaseJForm extends JTemplateProvider{ public static final String XML_TAG = "JForm"; public static final int FORM_TAB = 0; public static final int ELEMENTCASE_TAB = 1; public static final int ELEMENTCASE_CHANGE_TAB = 2; /** * 刷新所有控件 */ public void refreshAllNameWidgets(); /** * 刷新参数 */ public void populateParameter(); /** * 刷新选中的控件 */ public void refreshSelectedWidget(); /** * 获取当前的Target */ public Object getTarget(); /** * 执行撤销 * * @param o 之前保存的状态 */ public void applyUndoState4Form(BaseUndoState o); /** * 获取当前编辑的组件 */ public JComponent getEditingPane(); /** * 只在Form和ElementCase之间切换 * @param index 切换位置 */ public void tabChanged(int index); /** * 在Form和ElementCase, 以及ElementCase和ElementCase之间切换 * @param index 切换位置 * @param ecContainer ElementCase所在container */ public void tabChanged(int index, FormElementCaseContainerProvider ecContainer); }
package com.fr.design.mainframe;
import javax.swing.JComponent;
import com.fr.form.FormElementCaseContainerProvider;
/**
* Author : Shockway
* Date: 13-7-15
* Time: 上午10:28
*/
public interface BaseJForm extends JTemplateProvider {
String XML_TAG = "JForm";
int FORM_TAB = 0;
int ELEMENTCASE_TAB = 1;
int ELEMENTCASE_CHANGE_TAB = 2;
/**
* 刷新所有控件
*/
void refreshAllNameWidgets();
/**
* 刷新参数
*/
void populateParameter();
/**
* 刷新选中的控件
*/
void refreshSelectedWidget();
/**
* 获取当前的Target
*/
Object getTarget();
/**
* 执行撤销
*
* @param o 之前保存的状态
*/
void applyUndoState4Form(BaseUndoState o);
/**
* 获取当前编辑的组件
*/
JComponent getEditingPane();
/**
* 只在Form和ElementCase之间切换
*
* @param index 切换位置
*/
void tabChanged(int index);
/**
* 在Form和ElementCase, 以及ElementCase和ElementCase之间切换
*
* @param index 切换位置
* @param ecContainer ElementCase所在container
*/
void tabChanged(int index, FormElementCaseContainerProvider ecContainer);
}

20
designer_base/src/com/fr/design/mainframe/toolbar/ToolBarMenuDockPlus.java

@ -12,52 +12,52 @@ public interface ToolBarMenuDockPlus {
*
* @return 工具
*/
public ToolBarDef[] toolbars4Target();
ToolBarDef[] toolbars4Target();
/**
* 文件菜单的子菜单
*
* @return 子菜单
*/
public ShortCut[] shortcut4FileMenu();
ShortCut[] shortcut4FileMenu();
/**
* 目标的菜单
*
* @return 菜单
*/
public MenuDef[] menus4Target();
MenuDef[] menus4Target();
/**
* 表单的工具栏
*
* @return 表单工具栏
*/
public JPanel[] toolbarPanes4Form();
JPanel[] toolbarPanes4Form();
/**
* 表单的工具按钮
*
* @return 工具按钮
*/
public JComponent[] toolBarButton4Form();
JComponent[] toolBarButton4Form();
/**
* 权限细粒度状态下的工具面板
*
* @return 工具面板
*/
public JComponent toolBar4Authority();
JComponent toolBar4Authority();
public int getMenuState();
int getMenuState();
public int getToolBarHeight();
int getToolBarHeight();
/**
* 导出菜单的子菜单 目前用于图表设计器
*
* @return 子菜单
*/
public ShortCut[] shortcut4ExportMenu();
ShortCut[] shortcut4ExportMenu();
}

73
designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java

@ -1 +1,72 @@
package com.fr.design.parameter; import com.fr.base.Parameter; import com.fr.base.parameter.ParameterUI; import com.fr.design.mainframe.AuthorityEditPane; import javax.swing.*; import java.awt.*; /** * 参数设计界面接口 */ public interface ParameterDesignerProvider { public void addListener(ParaDefinitePane paraDefinitePane); public Component createWrapper(); public void setDesignHeight(int height); public Dimension getDesignSize(); public Dimension getPreferredSize(); public void populate(ParameterUI p); public void refreshAllNameWidgets(); public void refresh4TableData(String oldName, String newName); public void refreshParameter(ParaDefinitePane paraDefinitePane); public boolean isWithQueryButton(); public java.util.List<String> getAllXCreatorNameList(); public boolean isWithoutParaXCreator(Parameter[] ps); public boolean isBlank(); public ParameterUI getParaTarget(); public boolean addingParameter2Editor(Parameter parameter, int index); public boolean addingParameter2EditorWithQueryButton(Parameter parameter, int index); public void addingAllParameter2Editor(Parameter[] parameterArray, int currentIndex); public JPanel[] toolbarPanes4Form(); public JComponent[] toolBarButton4Form(); public void initBeforeUpEdit(); public void populateParameterPropertyPane(ParaDefinitePane p); public void initWidgetToolbarPane(); public AuthorityEditPane getAuthorityEditPane(); public JPanel getEastUpPane(); public JPanel getEastDownPane(); public boolean isSupportAuthority(); public void removeSelection(); public ParameterBridge getParaComponent(); }
package com.fr.design.parameter;
import com.fr.base.Parameter;
import com.fr.base.parameter.ParameterUI;
import com.fr.design.mainframe.AuthorityEditPane;
import javax.swing.*;
import java.awt.*;
/**
* 参数设计界面接口
*/
public interface ParameterDesignerProvider {
void addListener(ParaDefinitePane paraDefinitePane);
Component createWrapper();
void setDesignHeight(int height);
Dimension getDesignSize();
Dimension getPreferredSize();
void populate(ParameterUI p);
void refreshAllNameWidgets();
void refresh4TableData(String oldName, String newName);
void refreshParameter(ParaDefinitePane paraDefinitePane);
boolean isWithQueryButton();
java.util.List<String> getAllXCreatorNameList();
boolean isWithoutParaXCreator(Parameter[] ps);
boolean isBlank();
ParameterUI getParaTarget();
boolean addingParameter2Editor(Parameter parameter, int index);
boolean addingParameter2EditorWithQueryButton(Parameter parameter, int index);
void addingAllParameter2Editor(Parameter[] parameterArray, int currentIndex);
JPanel[] toolbarPanes4Form();
JComponent[] toolBarButton4Form();
void initBeforeUpEdit();
void populateParameterPropertyPane(ParaDefinitePane p);
void initWidgetToolbarPane();
AuthorityEditPane getAuthorityEditPane();
JPanel getEastUpPane();
JPanel getEastDownPane();
boolean isSupportAuthority();
void removeSelection();
ParameterBridge getParaComponent();
}

303
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<JComponent> dbcomponents) {
for (JComponent jcomponent : dbcomponents) {
jcomponent.setDoubleBuffered(true);
}
}
/**
* 禁止双缓冲状态并将初始状态为启动双缓冲的组件保存到dbcomponents中
*/
public static void disableBuffer(Component comp, ArrayList<JComponent> dbcomponents) {
if ((comp instanceof JComponent) && comp.isDoubleBuffered()) {
JComponent jcomponent = (JComponent) comp;
dbcomponents.add(jcomponent);
jcomponent.setDoubleBuffered(false);
}
if (comp instanceof Container) {
Container container = (Container) comp;
int count = container.getComponentCount();
if (count > 0) {
for (int i = 0; i < count; i++) {
Component component = container.getComponent(i);
disableBuffer(component, dbcomponents);
}
}
}
}
public static int indexOfComponent(Container container, Component target) {
int count = container.getComponentCount();
for (int i = 0; i < count; i++) {
Component child = container.getComponent(i);
if (child == target) {
return i;
}
}
return -1;
}
/**
* 计算组件root相对于其顶层容器的可见区域
*/
public static Rectangle computeVisibleRectRel2Root(Component root) {
Container container = findAncestorScrollPane(root);
if (container == null) {
return getRelativeBounds(root);
} else {
// 如果是JScrollPane的子组件,需要计算其viewport与改组件的交叉的可见区域
return getBoundsRel2Parent(root, container);
}
}
/**
* 计算组件root相对于其顶层容器的可见区域
*/
public static Rectangle computeVisibleRect(JComponent root) {
Rectangle root_bounds = ComponentUtils.getRelativeBounds(root);
Rectangle rect = computeVisibleRectRel2Root(root);
rect.x -= root_bounds.x;
rect.y -= root_bounds.y;
return rect;
}
private static Rectangle getBoundsRel2Parent(Component child, Container parent) {
Rectangle cRect = getRelativeBounds(child);
Rectangle pRect = getRelativeBounds(parent);
Rectangle bounds = new Rectangle();
Rectangle2D.intersect(cRect, pRect, bounds);
return bounds;
}
public static Container findAncestorScrollPane(Component p) {
if ((p == null) || !(p instanceof Container)) {
return null;
}
Container c = p.getParent();
return findAncestorScrollPane(c);
}
public static boolean isRootComponent(Component root) {
Container parent = root.getParent();
return parent == null;
}
public static boolean isChildOf(Component component, Class parent) {
Container container = component.getParent();
if (container != null) {
if (ComparatorUtils.equals(container.getClass(), parent)) {
return true;
} else {
return isChildOf(container, parent);
}
}
return false;
}
package com.fr.design.utils;
import com.fr.general.ComparatorUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
/**
* 工具类提供常用的工具方法
*/
public class ComponentUtils {
private ComponentUtils() {
}
public static boolean isComponentVisible(Component comp) {
if (!comp.isVisible() && !isRootComponent(comp)) {
return false;
}
Component parent = comp.getParent();
return parent == null || isComponentVisible(parent);
}
/**
* 获取component所在的容器的绝对位置
*/
public static Rectangle getRelativeBounds(Component component) {
Rectangle bounds = new Rectangle(0, 0, component.getWidth(), component.getHeight());
Container parent = component.getParent();
while (parent != null) {
bounds.x += component.getX();
bounds.y += component.getY();
component = parent;
parent = component.getParent();
}
return bounds;
}
/**
* 恢复双缓冲状态dbcomponents保存着初始状态为启动双缓冲的组件
*/
public static void resetBuffer(ArrayList<JComponent> dbcomponents) {
for (JComponent jcomponent : dbcomponents) {
jcomponent.setDoubleBuffered(true);
}
}
/**
* 禁止双缓冲状态并将初始状态为启动双缓冲的组件保存到dbcomponents中
*/
public static void disableBuffer(Component comp, ArrayList<JComponent> dbcomponents) {
if ((comp instanceof JComponent) && comp.isDoubleBuffered()) {
JComponent jcomponent = (JComponent) comp;
dbcomponents.add(jcomponent);
jcomponent.setDoubleBuffered(false);
}
if (comp instanceof Container) {
Container container = (Container) comp;
int count = container.getComponentCount();
if (count > 0) {
for (int i = 0; i < count; i++) {
Component component = container.getComponent(i);
disableBuffer(component, dbcomponents);
}
}
}
}
public static int indexOfComponent(Container container, Component target) {
int count = container.getComponentCount();
for (int i = 0; i < count; i++) {
Component child = container.getComponent(i);
if (child.equals(target)) {
return i;
}
}
return -1;
}
/**
* 计算组件root相对于其顶层容器的可见区域
*/
public static Rectangle computeVisibleRectRel2Root(Component root) {
Container container = findAncestorScrollPane(root);
if (container == null) {
return getRelativeBounds(root);
} else {
// 如果是JScrollPane的子组件,需要计算其viewport与改组件的交叉的可见区域
return getBoundsRel2Parent(root, container);
}
}
/**
* 计算组件root相对于其顶层容器的可见区域
*/
public static Rectangle computeVisibleRect(JComponent root) {
Rectangle rootBounds = ComponentUtils.getRelativeBounds(root);
Rectangle rect = computeVisibleRectRel2Root(root);
rect.x -= rootBounds.x;
rect.y -= rootBounds.y;
return rect;
}
private static Rectangle getBoundsRel2Parent(Component child, Container parent) {
Rectangle cRect = getRelativeBounds(child);
Rectangle pRect = getRelativeBounds(parent);
Rectangle bounds = new Rectangle();
Rectangle2D.intersect(cRect, pRect, bounds);
return bounds;
}
public static Container findAncestorScrollPane(Component p) {
if ((p == null) || !(p instanceof Container)) {
return null;
}
Container c = p.getParent();
return findAncestorScrollPane(c);
}
public static boolean isRootComponent(Component root) {
Container parent = root.getParent();
return parent == null;
}
public static boolean isChildOf(Component component, Class parent) {
Container container = component.getParent();
if (container != null) {
if (ComparatorUtils.equals(container.getClass(), parent)) {
return true;
} else {
return isChildOf(container, parent);
}
}
return false;
}
}

20
designer_chart/build.dev.gradle

@ -1,8 +1,26 @@
apply plugin: 'java'
tasks.withType(JavaCompile){
options.encoding = 'UTF-8'
}
buildscript {
repositories {
maven {
url "http://www.eveoh.nl/files/maven2"
}
}
dependencies {
classpath "nl.eveoh:gradle-aspectj:1.2"
}
}
ext.aspectjVersion = '1.7.4'
apply plugin: 'aspectj'
repositories {
mavenCentral()
}
//jdk版本
sourceCompatibility=1.7
//jar包的版本

85
designer_chart/build.dev.gradle.bak

@ -0,0 +1,85 @@
apply plugin: 'java'
tasks.withType(JavaCompile){
options.encoding = 'UTF-8'
}
buildscript {
repositories {
maven {
url "http://www.eveoh.nl/files/maven2"
}
}
dependencies {
classpath "nl.eveoh:gradle-aspectj:1.2"
}
}
ext.aspectjVersion = '1.7.4'
apply plugin: 'aspectj'
repositories {
mavenCentral()
}
//jdk版本
sourceCompatibility=1.7
//jar包的版本
version='8.0'
def srcDir="."
//jar包进行重命名
jar{
baseName='fr-designer-chart'
}
sourceSets{
main{
java{
srcDirs=["${srcDir}/src"]
}
}
}
FileTree files =fileTree(dir:'./',include:'build.*.gradle')
def buildDir=files[0].path.substring(0,files[0].path.lastIndexOf ('\\'))
buildDir=buildDir.substring(0,buildDir.lastIndexOf ('\\'))
def branchName=buildDir.substring(buildDir.lastIndexOf ('\\')+1)
//
dependencies{
compile fileTree(dir:"../../../finereport-lib-stable/${branchName}",include:'**/*.jar')
compile fileTree(dir:'../../../',include:"finereport-*-stable/${branchName}/**/build/libs/*.jar")
testCompile 'junit:junit:4.12'
}
//.java classes文件夹下参与打包
task copyFile(type:Copy,dependsOn:compileJava){
copy{
from ("${srcDir}/src"){
exclude '**/.setting/**','.classpath','.project','**/*.java','**/*.db','**/*.g','**/package.html'
}
into 'build/classes/main'
}
}
//js文件
task compressJS{
ant.taskdef(name:'yuicompress',classname:'com.yahoo.platform.yui.compressor.YUICompressTask'){
classpath {
fileset(dir:'../../../finereport-lib4build-stable',includes:'**/*.jar')
}
}
ant.yuicompress(linebreak:"500",warn:"false", munge:"yes",preserveallsemicolons:"false",charset:"utf-8",encoding:"utf-8",outputfolder:'build/classes/main'){
fileset (dir:"${srcDir}/src"){
include (name:'**/*.js')
include (name:'**/*.css')
}
}
}
jar.dependsOn compressJS

2
designer_chart/src/com/fr/design/chart/fun/IndependentChartUIProvider.java

@ -22,7 +22,7 @@ public interface IndependentChartUIProvider extends Level {
String XML_TAG = "IndependentChartUIProvider";
int CURRENT_API_LEVEL = 4;
int CURRENT_API_LEVEL = 3;
/**
* 图表的类型定义界面类型就是属性表的第一个界面

19
designer_form/build.dev.gradle

@ -1,8 +1,25 @@
apply plugin: 'java'
tasks.withType(JavaCompile){
options.encoding = 'UTF-8'
}
buildscript {
repositories {
maven {
url "http://www.eveoh.nl/files/maven2"
}
}
dependencies {
classpath "nl.eveoh:gradle-aspectj:1.2"
}
}
ext.aspectjVersion = '1.7.4'
apply plugin: 'aspectj'
repositories {
mavenCentral()
}
//jdk版本
sourceCompatibility=1.7
//jar包版本

4
designer_form/build.dev.gradle.bak

@ -4,7 +4,7 @@ tasks.withType(JavaCompile){
options.encoding = 'UTF-8'
}
//jdk版本
sourceCompatibility=1.8
sourceCompatibility=1.7
//jar包版本
version='8.0'
@ -20,7 +20,7 @@ sourceSets{
main{
java{
srcDirs=["${srcDir}/src",
"${srcDir}/../designer/src"]
"${srcDir}/../designer/src"]
}
}
}

177
designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java

@ -1,85 +1,94 @@
package com.fr.design.designer.beans;
import com.fr.design.beans.GroupModel;
import com.fr.design.designer.creator.XCreator;
/**
* 该接口是LayoutManager的BeanInfo类标准Java平台没有提供布局管理器的BeanInfo类
* 对于界面设计工具来说还需一些特殊的行为
* @since 6.5.3
*/
public interface LayoutAdapter {
/**
* 在添加组件状态时当鼠标移动到某个容器上方时如果该容器有布局管理器则会调用该布局
* 管理适配器的accept来决定当前位置是否可以放置并提供特殊的标识比如红色区域标识
* 如在BorderLayout中如果某个方位已经放置了组件则此时应该返回false标识该区域不可以
* 放置
*@param creator 组件
*@param x 添加的位置x该位置是相对于container的
*@param y 添加的位置y该位置是相对于container的
*@return 是否可以放置
*/
boolean accept(XCreator creator, int x, int y);
/**
* 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适如果不合适就需要重新fix一下
* @param creator 组件
*/
void fix(XCreator creator);
/**
* 组件的ComponentAdapter在添加组件时如果发现布局管理器不为空会继而调用该布局管理器的
* addComp方法来完成组件的具体添加在该方法内布局管理器可以提供额外的功能
* @param creator 被添加的新组件
* @param x 添加的位置x该位置是相对于container的
* @param y 添加的位置y该位置是相对于container的
* @return 是否添加成功成功返回true否则false
*/
boolean addBean(XCreator creator, int x, int y);
/**
* 返回该布局管理适配器的Painter为容器提供放置位置的标识
*/
HoverPainter getPainter();
/**
* 显示parent的字组件child解决CardLayout中显示某个非显示组件的特殊情况
* @param child 组件
*/
void showComponent(XCreator child);
void addNextComponent(XCreator dragged);
/**
* 组件叠放顺序前插入
* @param target 目标组件
* @param added 插入组件
*/
void addBefore(XCreator target, XCreator added);
/**
* 组件叠放顺序后插入
* @param target 目标组件
* @param added 放置组件
*/
void addAfter(XCreator target, XCreator added);
/**
* 能否放置更多组件
* @return 能则返回true
*/
boolean canAcceptMoreComponent();
ConstraintsGroupModel getLayoutConstraints(XCreator creator);
GroupModel getLayoutProperties();
/**
* 删除组件
* @param creator 组件
* @param initWidth 组件之前宽度
* @param initHeight 组件之前高度
*/
void removeBean(XCreator creator, int initWidth, int initHeight);
package com.fr.design.designer.beans;
import com.fr.design.beans.GroupModel;
import com.fr.design.designer.creator.XCreator;
/**
* 该接口是LayoutManager的BeanInfo类标准Java平台没有提供布局管理器的BeanInfo类
* 对于界面设计工具来说还需一些特殊的行为
*
* @since 6.5.3
*/
public interface LayoutAdapter {
/**
* 在添加组件状态时当鼠标移动到某个容器上方时如果该容器有布局管理器则会调用该布局
* 管理适配器的accept来决定当前位置是否可以放置并提供特殊的标识比如红色区域标识
* 如在BorderLayout中如果某个方位已经放置了组件则此时应该返回false标识该区域不可以
* 放置
*
* @param creator 组件
* @param x 添加的位置x该位置是相对于container的
* @param y 添加的位置y该位置是相对于container的
* @return 是否可以放置
*/
boolean accept(XCreator creator, int x, int y);
/**
* 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适如果不合适就需要重新fix一下
*
* @param creator 组件
*/
void fix(XCreator creator);
/**
* 组件的ComponentAdapter在添加组件时如果发现布局管理器不为空会继而调用该布局管理器的
* addComp方法来完成组件的具体添加在该方法内布局管理器可以提供额外的功能
*
* @param creator 被添加的新组件
* @param x 添加的位置x该位置是相对于container的
* @param y 添加的位置y该位置是相对于container的
* @return 是否添加成功成功返回true否则false
*/
boolean addBean(XCreator creator, int x, int y);
/**
* 返回该布局管理适配器的Painter为容器提供放置位置的标识
*/
HoverPainter getPainter();
/**
* 显示parent的字组件child解决CardLayout中显示某个非显示组件的特殊情况
*
* @param child 组件
*/
void showComponent(XCreator child);
void addNextComponent(XCreator dragged);
/**
* 组件叠放顺序前插入
*
* @param target 目标组件
* @param added 插入组件
*/
void addBefore(XCreator target, XCreator added);
/**
* 组件叠放顺序后插入
*
* @param target 目标组件
* @param added 放置组件
*/
void addAfter(XCreator target, XCreator added);
/**
* 能否放置更多组件
*
* @return 能则返回true
*/
boolean canAcceptMoreComponent();
ConstraintsGroupModel getLayoutConstraints(XCreator creator);
GroupModel getLayoutProperties();
/**
* 删除组件
*
* @param creator 组件
* @param initWidth 组件之前宽度
* @param initHeight 组件之前高度
*/
void removeBean(XCreator creator, int initWidth, int initHeight);
}

59
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;
}
}

361
designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java

@ -1,174 +1,189 @@
package com.fr.design.designer.beans.adapters.layout;
import java.awt.LayoutManager;
import com.fr.general.ComparatorUtils;
import com.fr.design.beans.GroupModel;
import com.fr.design.designer.beans.ConstraintsGroupModel;
import com.fr.design.designer.beans.HoverPainter;
import com.fr.design.designer.beans.LayoutAdapter;
import com.fr.design.designer.beans.painters.NullPainter;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWidgetCreator;
import com.fr.design.utils.ComponentUtils;
import com.fr.design.utils.gui.LayoutUtils;
public abstract class AbstractLayoutAdapter implements LayoutAdapter {
protected XLayoutContainer container;
protected LayoutManager layout;
public AbstractLayoutAdapter(XLayoutContainer container) {
this.container = container;
this.layout = container.getLayout();
}
/**
* 是否使用控件备份大小
* @param xCreator 控件
* @return 所在容器相同且支持备份的话返回true
*/
public boolean whetherUseBackupSize(XCreator xCreator) {
Class clazz = container.getClass();
Class bkClazz = null;
if(xCreator.getBackupParent() != null) {
bkClazz = xCreator.getBackupParent().getClass();
}
return ComparatorUtils.equals(bkClazz, clazz)
&& supportBackupSize();
}
/**
* 是否支持用备份大小
* @return
*/
public boolean supportBackupSize() {
return false;
}
/**
* 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适如果不合适就需要重新fix一下
* @param creator 组件
*/
public void fix(XCreator creator) {
}
/**
* 显示parent的字组件child解决CardLayout中显示某个非显示组件的特殊情况
* @param child 组件
*/
@Override
public void showComponent(XCreator child) {
child.setVisible(true);
}
/**
* 组件的ComponentAdapter在添加组件时如果发现布局管理器不为空会继而调用该布局管理器的
* addComp方法来完成组件的具体添加在该方法内布局管理器可以提供额外的功能
* @param creator 被添加的新组件
* @param x 添加的位置x该位置是相对于container的
* @param y 添加的位置y该位置是相对于container的
* @return 是否添加成功成功返回true否则false
*/
@Override
public boolean addBean(XCreator creator, int x, int y) {
if (!accept(creator, x, y)) {
return false;
}
addComp(creator, x, y);
((XWidgetCreator) creator).recalculateChildrenSize();
return true;
}
/**
* 删除组件
* @param creator 组件
* @param initWidth 组件之前宽度
* @param initHeight 组件之前高度
*/
public void removeBean(XCreator creator, int creatorWidth, int creatorHeight) {
delete(creator, creatorWidth, creatorHeight);
}
protected void delete(XCreator creator, int creatorWidth, int creatorHeight) {
}
protected abstract void addComp(XCreator creator, int x, int y);
/**
* 增加下一个组件
* @param dragged 组件
*/
@Override
public void addNextComponent(XCreator dragged) {
container.add(dragged);
LayoutUtils.layoutRootContainer(container);
}
/**
* 目标控件位置插入组件
* @param target 目标
* @param added 增加组件
*/
@Override
public void addBefore(XCreator target, XCreator added) {
int index = ComponentUtils.indexOfComponent(container, target);
if (index == -1) {
container.add(added, 0);
} else {
container.add(added, index);
}
LayoutUtils.layoutRootContainer(container);
}
/**
* 插在目标组件后面
* @param target 目标
* @param added 增加组件
*/
@Override
public void addAfter(XCreator target, XCreator added) {
int index = ComponentUtils.indexOfComponent(container, target);
if (index == -1) {
container.add(added);
} else {
index++;
if (index >= container.getComponentCount()) {
container.add(added);
} else {
container.add(added, index);
}
}
LayoutUtils.layoutRootContainer(container);
}
@Override
public HoverPainter getPainter() {
return new NullPainter(container);
}
/**
* 是否能接收更多的组件
* @return 能则返回true
*/
@Override
public boolean canAcceptMoreComponent() {
return true;
}
@Override
public ConstraintsGroupModel getLayoutConstraints(XCreator creator) {
return null;
}
@Override
public GroupModel getLayoutProperties() {
return null;
}
package com.fr.design.designer.beans.adapters.layout;
import com.fr.design.beans.GroupModel;
import com.fr.design.designer.beans.ConstraintsGroupModel;
import com.fr.design.designer.beans.HoverPainter;
import com.fr.design.designer.beans.LayoutAdapter;
import com.fr.design.designer.beans.painters.NullPainter;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWidgetCreator;
import com.fr.design.utils.ComponentUtils;
import com.fr.design.utils.gui.LayoutUtils;
import com.fr.general.ComparatorUtils;
import java.awt.*;
public abstract class AbstractLayoutAdapter implements LayoutAdapter {
protected XLayoutContainer container;
protected LayoutManager layout;
public AbstractLayoutAdapter(XLayoutContainer container) {
this.container = container;
this.layout = container.getLayout();
}
/**
* 是否使用控件备份大小
*
* @param xCreator 控件
* @return 所在容器相同且支持备份的话返回true
*/
public boolean whetherUseBackupSize(XCreator xCreator) {
Class clazz = container.getClass();
Class bkClazz = null;
if (xCreator.getBackupParent() != null) {
bkClazz = xCreator.getBackupParent().getClass();
}
return ComparatorUtils.equals(bkClazz, clazz)
&& supportBackupSize();
}
/**
* 是否支持用备份大小
*
* @return
*/
public boolean supportBackupSize() {
return false;
}
/**
* 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适如果不合适就需要重新fix一下
*
* @param creator 组件
*/
public void fix(XCreator creator) {
}
/**
* 显示parent的字组件child解决CardLayout中显示某个非显示组件的特殊情况
*
* @param child 组件
*/
@Override
public void showComponent(XCreator child) {
child.setVisible(true);
}
/**
* 组件的ComponentAdapter在添加组件时如果发现布局管理器不为空会继而调用该布局管理器的
* addComp方法来完成组件的具体添加在该方法内布局管理器可以提供额外的功能
*
* @param creator 被添加的新组件
* @param x 添加的位置x该位置是相对于container的
* @param y 添加的位置y该位置是相对于container的
* @return 是否添加成功成功返回true否则false
*/
@Override
public boolean addBean(XCreator creator, int x, int y) {
if (!accept(creator, x, y)) {
return false;
}
addComp(creator, x, y);
((XWidgetCreator) creator).recalculateChildrenSize();
return true;
}
/**
* 删除组件
*
* @param creator 组件
* @param creatorWidth
* @param creatorHeight
*/
public void removeBean(XCreator creator, int creatorWidth, int creatorHeight) {
delete(creator, creatorWidth, creatorHeight);
}
protected void delete(XCreator creator, int creatorWidth, int creatorHeight) {
}
protected abstract void addComp(XCreator creator, int x, int y);
/**
* 增加下一个组件
*
* @param dragged 组件
*/
@Override
public void addNextComponent(XCreator dragged) {
container.add(dragged);
LayoutUtils.layoutRootContainer(container);
}
/**
* 目标控件位置插入组件
*
* @param target 目标
* @param added 增加组件
*/
@Override
public void addBefore(XCreator target, XCreator added) {
int index = ComponentUtils.indexOfComponent(container, target);
if (index == -1) {
container.add(added, 0);
} else {
container.add(added, index);
}
LayoutUtils.layoutRootContainer(container);
}
/**
* 插在目标组件后面
*
* @param target 目标
* @param added 增加组件
*/
@Override
public void addAfter(XCreator target, XCreator added) {
int index = ComponentUtils.indexOfComponent(container, target);
if (index == -1) {
container.add(added);
} else {
index++;
if (index >= container.getComponentCount()) {
container.add(added);
} else {
container.add(added, index);
}
}
LayoutUtils.layoutRootContainer(container);
}
@Override
public HoverPainter getPainter() {
return new NullPainter(container);
}
/**
* 是否能接收更多的组件
*
* @return 能则返回true
*/
@Override
public boolean canAcceptMoreComponent() {
return true;
}
@Override
public ConstraintsGroupModel getLayoutConstraints(XCreator creator) {
return null;
}
@Override
public GroupModel getLayoutProperties() {
return null;
}
public XLayoutContainer getContainer() {
return this.container;
}
}

701
designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java

@ -1,354 +1,349 @@
package com.fr.design.designer.beans.adapters.layout;
import java.awt.*;
import com.fr.design.beans.GroupModel;
import com.fr.design.designer.beans.ConstraintsGroupModel;
import com.fr.design.designer.beans.HoverPainter;
import com.fr.design.designer.beans.painters.FRAbsoluteLayoutPainter;
import com.fr.design.designer.creator.*;
import com.fr.design.designer.properties.BoundsGroupModel;
import com.fr.design.designer.properties.FRAbsoluteLayoutPropertiesGroupModel;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.design.utils.ComponentUtils;
import com.fr.design.utils.gui.LayoutUtils;
import com.fr.form.ui.widget.BoundsWidget;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRLogger;
public class FRAbsoluteLayoutAdapter extends FRBodyLayoutAdapter {
//是不是添加到父容器上
private boolean isAdd2ParentLayout = false;
private HoverPainter painter;
public FRAbsoluteLayoutAdapter(XLayoutContainer container) {
super(container);
painter = new FRAbsoluteLayoutPainter(container);
initMinSize();
}
private void initMinSize() {
XWAbsoluteLayout layout = (XWAbsoluteLayout) container;
minWidth = layout.getActualMinWidth();
minHeight = layout.getActualMinHeight();
actualVal = layout.getAcualInterval();
margin = layout.toData().getMargin();
}
@Override
public HoverPainter getPainter() {
return painter;
}
/**
* 是否能在指定位置添加组件
* @param creator 组件
* @param x 坐标x
* @param y 坐标y
* @return 能则返回true
*/
//这个地方的逻辑非常复杂,
// 1.当前绝对布局是不可编辑且是最外层,那么其他控件添加在它周围,
// 2.当前绝对布局是不可编辑且不是最外层,那么控件不可添加,(嵌套)
// 3.当前绝对布局可编辑,那么控件添加
@Override
public boolean accept(XCreator creator, int x, int y) {
Component comp = container.getComponentAt(x, y);
//布局控件要先判断是不是可编辑
//可以编辑,按原有逻辑判断
//不可编辑,当成一整个控件处理
if (comp == null){
return false;
}
//参数面板内的组件不允许拖往绝对布局中
if (creator.getParent() != null && ((XCreator)creator.getParent()).acceptType(XWParameterLayout.class)){
Rectangle rec = creator.getBounds();
rec.y = creator.getParent().getHeight() - rec.height;
creator.setBounds(rec);
return false;
}
//判断下组件能不能拖入绝对布局
if (!creator.canEnterIntoAbsolutePane()){
return false;
}
XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator)comp).getTopLayout();
if(topLayout != null){
if (topLayout.isEditable()){
return topLayoutAccept(creator, x, y, topLayout);
}
//绝对布局嵌套,处于内层,不可编辑,不添加,topLayout只能获取到最外层可编辑的布局
else if (((XLayoutContainer)topLayout.getParent()).acceptType(XWAbsoluteLayout.class)) {
return false;
}
else {
return acceptWidget(creator, x, y);
}
}
else{
FRLogger.getLogger().error("top layout is null!");
}
return false;
}
//toplayout假如可以编辑的话就往里面添加组件
private boolean topLayoutAccept(XCreator creator, int x, int y, XLayoutContainer topLayout) {
//判断有没有和当前控件重叠
//先计算当前控件的位置
int creatorX, creatorY;
if (XCreatorUtils.getParentXLayoutContainer(creator) != null) {
Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator);
creatorX = creatorRectangle.x;
creatorY = creatorRectangle.y;
} else {
int w = creator.getWidth() / 2;
int h = creator.getHeight() / 2;
creatorX = x - w;
creatorY = y - h;
}
//再判断和布局中其他控件重叠
Rectangle curRec = new Rectangle(creatorX, creatorY, creator.getWidth(), creator.getHeight());
WAbsoluteLayout wAbsoluteLayout = (WAbsoluteLayout)topLayout.toData();
for (int i = 0, count = wAbsoluteLayout.getWidgetCount(); i < count; i++) {
BoundsWidget temp = (BoundsWidget) wAbsoluteLayout.getWidget(i);
Rectangle rectangle = temp.getBounds();
if (curRec.intersects(rectangle)){
return false;
}
}
if (creatorX < 0 || creatorX + creator.getWidth() > container.getWidth()) {
return false;
}
if (creatorY < 0 || creatorY + creator.getHeight() > container.getHeight()){
return false;
}
return x >= 0 && y >= 0 && creator.getHeight() <= container.getHeight()
&& creator.getWidth() <= container.getWidth();
}
/**
* 判断是否鼠标在组件的三等分区域如果组件在布局管理器中间上下左右都可能会三等分
* @param parentComp 鼠标所在区域的组件
* @param x 坐标x
* @param y 坐标y
* @return 是则返回true
*/
public boolean isTrisectionArea(Component parentComp, int x, int y) {
XCreator creator = (XCreator)parentComp;
trisectAreaDirect = 0;
if (container.getComponentCount()<=1) {
return false;
}
int maxWidth = parentComp.getWidth();
int maxHeight = parentComp.getHeight();
int xL = parentComp.getX();
int yL = parentComp.getY();
// 组件宽高的十分之一和默认值取大
int minRangeWidth = Math.max(maxWidth/BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
int minRangeHeight = Math.max(maxHeight/BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
if(y<yL+minRangeHeight ) {
// 在组件上侧三等分
trisectAreaDirect = COMP_TOP;
} else if(y>yL+maxHeight-minRangeHeight) {
// 在组件下侧三等分
trisectAreaDirect = COMP_BOTTOM;
} else if (x<xL+minRangeWidth) {
// 在组件左侧三等分
trisectAreaDirect = COMP_LEFT;
} else if(x>xL+maxWidth-minRangeWidth) {
// 在组件右侧三等分
trisectAreaDirect = COMP_RIGHT;
}
// tab布局的边界特殊处理,不进行三等分
if(!creator.getTargetChildrenList().isEmpty()){
return false;
}
return !ComparatorUtils.equals(trisectAreaDirect, 0);
}
//当前绝对布局不可编辑,就当成一个控件,组件添加在周围
private boolean acceptWidget(XCreator creator, int x, int y){
isFindRelatedComps = false;
//拖入组件判断时,先判断是否为交叉点区域,其次三等分区域,再次平分区域
Component comp = container.getComponentAt(x, y);
boolean isMatchEdge = false;
//如果当前处于边缘地带, 那么就把他贴到父容器上
XLayoutContainer parent = container.findNearestFit();
container = parent != null ? parent : container;
isAdd2ParentLayout = true;
int componentHeight = comp.getHeight();
int componentWidth = comp.getWidth();
//上半部分高度
int upHeight = (int) (componentHeight * TOP_HALF) + comp.getY();
//下半部分高度
int downHeight = (int) (componentHeight * BOTTOM_HALF) + comp.getY();
if (isCrossPointArea(comp, x, y)) {
return canAcceptWhileCrossPoint(comp, x, y);
}
if (isTrisectionArea(comp, x, y)) {
return canAcceptWhileTrisection(comp, x, y);
}
boolean horizonValid = componentWidth >= minWidth * 2 + actualVal;
boolean verticalValid = componentHeight >= minHeight * 2 + actualVal;
return y > upHeight && y < downHeight ? horizonValid : verticalValid;
}
/**
* 组件的ComponentAdapter在添加组件时如果发现布局管理器不为空会继而调用该布局管理器的
* addComp方法来完成组件的具体添加在该方法内布局管理器可以提供额外的功能
*
* @param creator 被添加的新组件
* @param x 添加的位置x该位置是相对于container的
* @param y 添加的位置y该位置是相对于container的
* @return 是否添加成功成功返回true否则false
*/
@Override
public boolean addBean(XCreator creator, int x, int y) {
Rectangle rect = ComponentUtils.getRelativeBounds(container);
int posX = x + rect.x;
int posY = y + rect.y;
if (!accept(creator, x, y)) {
return false;
}
addComp(creator, posX, posY);
((XWidgetCreator) creator).recalculateChildrenSize();
return true;
}
@Override
protected void addComp(XCreator creator, int x, int y) {
if(!isAdd2ParentLayout) {
Rectangle r = ComponentUtils.getRelativeBounds(container);
x = x - r.x;
y = y - r.y;
if (XCreatorUtils.getParentXLayoutContainer(creator) != null) {
Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator);
x = creatorRectangle.x - r.x;
y = creatorRectangle.y - r.y;
} else {
int w = creator.getWidth() / 2;
int h = creator.getHeight() / 2;
x = x - w;
y = y - h;
}
fix(creator, x, y);
if (creator.hasTitleStyle()) {
addParentCreator(creator);
} else {
container.add(creator, creator.toData().getWidgetName());
}
XWAbsoluteLayout layout = (XWAbsoluteLayout) container;
layout.updateBoundsWidget(creator);
updateCreatorBackBound();
LayoutUtils.layoutRootContainer(container);
}else{
fixAbsolute(creator, x, y);
if (creator.shouldScaleCreator() || creator.hasTitleStyle()) {
addParentCreator(creator);
} else {
container.add(creator, creator.toData().getWidgetName());
}
XWFitLayout layout = (XWFitLayout) container;
// 更新对应的BoundsWidget
layout.updateBoundsWidget();
updateCreatorBackBound();
}
}
private void updateCreatorBackBound() {
for (int i=0,size=container.getComponentCount(); i<size; i++) {
XCreator creator = (XCreator) container.getComponent(i);
creator.updateChildBound(minHeight);
creator.setBackupBound(creator.getBounds());
}
}
private void addParentCreator(XCreator child) {
XLayoutContainer parentPanel = child.initCreatorWrapper(child.getHeight());
container.add(parentPanel, child.toData().getWidgetName());
}
/**
* 新拖入组件时计算调整其他关联组件位置大小
* @param child 新拖入的组件
* @param x 鼠标所在x坐标
* @param y 鼠标所在y坐标
*/
private void fixAbsolute(XCreator child, int x, int y) {
Component parentComp = container.getComponentAt(x, y);
if (container.getComponentCount()==0){
child.setLocation(0, 0);
child.setSize(parentComp.getWidth(), parentComp.getHeight());
} else if(isCrossPointArea(parentComp, x, y)){
//交叉区域插入组件时,根据具体位置进行上下或者左右或者相邻三个组件的位置大小插入
fixCrossPointArea(parentComp, child, x, y);
return;
} else if (isTrisectionArea(parentComp, x, y)) {
// 在边界三等分区域,就不再和组件二等分了
fixTrisect(parentComp, child, x, y);
return;
} else{
fixHalve(parentComp, child, x, y);
}
}
/**
* 组件拖拽后调整大小
* @param creator 组件
*/
@Override
public void fix(XCreator creator) {
WAbsoluteLayout wabs = (WAbsoluteLayout)container.toData();
fix(creator,creator.getX(),creator.getY());
wabs.setBounds(creator.toData(),creator.getBounds());
XWAbsoluteLayout layout = (XWAbsoluteLayout) container;
layout.updateBoundsWidget(creator);
}
/**
* 调整组件大小到合适尺寸位置
* @param creator 组件
* @param x 坐标x
* @param y 坐标y
*/
public void fix(XCreator creator ,int x, int y) {
int height = creator.getHeight();
int width = creator.getWidth();
if (x < 0) {
width += x;
x = 0;
} else if (x + creator.getWidth() > container.getWidth()) {
width = container.getWidth() - x;
}
if (y < 0) {
height += y;
y = 0;
} else if (y + creator.getHeight() > container.getHeight()) {
height = container.getHeight() - y;
}
creator.setBounds(x, y, width, height);
}
@Override
public ConstraintsGroupModel getLayoutConstraints(XCreator creator) {
return new BoundsGroupModel((XWAbsoluteLayout)container, creator);
}
@Override
public GroupModel getLayoutProperties() {
XWAbsoluteLayout xwAbsoluteLayout = (XWAbsoluteLayout) container;
return new FRAbsoluteLayoutPropertiesGroupModel(xwAbsoluteLayout);
}
package com.fr.design.designer.beans.adapters.layout;
import com.fr.design.beans.GroupModel;
import com.fr.design.designer.beans.ConstraintsGroupModel;
import com.fr.design.designer.beans.HoverPainter;
import com.fr.design.designer.beans.painters.FRAbsoluteLayoutPainter;
import com.fr.design.designer.creator.*;
import com.fr.design.designer.properties.BoundsGroupModel;
import com.fr.design.designer.properties.FRAbsoluteLayoutPropertiesGroupModel;
import com.fr.design.utils.ComponentUtils;
import com.fr.design.utils.gui.LayoutUtils;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRLogger;
import java.awt.*;
public class FRAbsoluteLayoutAdapter extends FRBodyLayoutAdapter {
//是不是添加到父容器上
private boolean isAdd2ParentLayout = false;
private HoverPainter painter;
public FRAbsoluteLayoutAdapter(XLayoutContainer container) {
super(container);
painter = new FRAbsoluteLayoutPainter(container);
initMinSize();
}
private void initMinSize() {
XWAbsoluteLayout layout = (XWAbsoluteLayout) container;
minWidth = layout.getActualMinWidth();
minHeight = layout.getActualMinHeight();
actualVal = layout.getAcualInterval();
margin = layout.toData().getMargin();
}
@Override
public HoverPainter getPainter() {
return painter;
}
/**
* 是否能在指定位置添加组件
*
* @param creator 组件
* @param x 坐标x
* @param y 坐标y
* @return 能则返回true
*/
//这个地方的逻辑非常复杂,
// 1.当前绝对布局是不可编辑且是最外层,那么其他控件添加在它周围,
// 2.当前绝对布局是不可编辑且不是最外层,那么控件不可添加,(嵌套)
// 3.当前绝对布局可编辑,那么控件添加
@Override
public boolean accept(XCreator creator, int x, int y) {
Component comp = container.getComponentAt(x, y);
//布局控件要先判断是不是可编辑
//可以编辑,按原有逻辑判断
//不可编辑,当成一整个控件处理
if (comp == null) {
return false;
}
//参数面板内的组件不允许拖往绝对布局中
if (creator.getParent() != null && ((XCreator) creator.getParent()).acceptType(XWParameterLayout.class)) {
Rectangle rec = creator.getBounds();
rec.y = creator.getParent().getHeight() - rec.height;
creator.setBounds(rec);
return false;
}
//判断组件能不能拖入绝对布局
if (!creator.canEnterIntoAbsolutePane()) {
return false;
}
XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator) comp).getTopLayout();
if (topLayout != null) {
if (topLayout.isEditable()) {
return topLayoutAccept(creator, x, y);
}
//绝对布局嵌套,处于内层,不可编辑,不添加,topLayout只能获取到最外层可编辑的布局
else if (((XLayoutContainer) topLayout.getParent()).acceptType(XWAbsoluteLayout.class)) {
return false;
} else {
return acceptWidget(x, y);
}
} else {
FRLogger.getLogger().error("top layout is null!");
}
return false;
}
//topLayout假如可以编辑的话就往里面添加组件
private boolean topLayoutAccept(XCreator creator, int x, int y) {
//允许组件重叠,可以不判断有没有和当前控件重叠
//先计算当前控件的位置
int creatorX, creatorY;
if (XCreatorUtils.getParentXLayoutContainer(creator) != null) {
Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator);
creatorX = creatorRectangle.x;
creatorY = creatorRectangle.y;
} else {
//这边计算得到的组件其实位置是正确的,
//因为传入的x和y已经加上了宽度或者高度的一半,再减去相同的宽度和高度的一半是没区别的,
// 例如高度为21,那么就是+10-10;
// 高度为20,那么就是+10-10; 没区别
int w = creator.getWidth() / 2;
int h = creator.getHeight() / 2;
creatorX = x - w;
creatorY = y - h;
}
if (creatorX < 0 || creatorX + creator.getWidth() > container.getWidth()) {
return false;
}
if (creatorY < 0 || creatorY + creator.getHeight() > container.getHeight()) {
return false;
}
return x >= 0 && y >= 0 && creator.getHeight() <= container.getHeight()
&& creator.getWidth() <= container.getWidth();
}
/**
* 判断是否鼠标在组件的三等分区域如果组件在布局管理器中间上下左右都可能会三等分
*
* @param parentComp 鼠标所在区域的组件
* @param x 坐标x
* @param y 坐标y
* @return 是则返回true
*/
public boolean isTrisectionArea(Component parentComp, int x, int y) {
XCreator creator = (XCreator) parentComp;
trisectAreaDirect = 0;
if (container.getComponentCount() <= 1) {
return false;
}
int maxWidth = parentComp.getWidth();
int maxHeight = parentComp.getHeight();
int xL = parentComp.getX();
int yL = parentComp.getY();
// 组件宽高的十分之一和默认值取大
int minRangeWidth = Math.max(maxWidth / BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
int minRangeHeight = Math.max(maxHeight / BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
if (y < yL + minRangeHeight) {
// 在组件上侧三等分
trisectAreaDirect = COMP_TOP;
} else if (y > yL + maxHeight - minRangeHeight) {
// 在组件下侧三等分
trisectAreaDirect = COMP_BOTTOM;
} else if (x < xL + minRangeWidth) {
// 在组件左侧三等分
trisectAreaDirect = COMP_LEFT;
} else if (x > xL + maxWidth - minRangeWidth) {
// 在组件右侧三等分
trisectAreaDirect = COMP_RIGHT;
}
// tab布局的边界特殊处理,不进行三等分
if (!creator.getTargetChildrenList().isEmpty()) {
return false;
}
return !ComparatorUtils.equals(trisectAreaDirect, 0);
}
//当前绝对布局不可编辑,就当成一个控件,组件添加在周围
private boolean acceptWidget(int x, int y) {
isFindRelatedComps = false;
//拖入组件判断时,先判断是否为交叉点区域,其次三等分区域,再次平分区域
Component comp = container.getComponentAt(x, y);
//如果当前处于边缘地带, 那么就把他贴到父容器上
XLayoutContainer parent = container.findNearestFit();
container = parent != null ? parent : container;
isAdd2ParentLayout = true;
int componentHeight = comp.getHeight();
int componentWidth = comp.getWidth();
//上半部分高度
int upHeight = (int) (componentHeight * TOP_HALF) + comp.getY();
//下半部分高度
int downHeight = (int) (componentHeight * BOTTOM_HALF) + comp.getY();
if (isCrossPointArea(comp, x, y)) {
return canAcceptWhileCrossPoint(comp, x, y);
}
if (isTrisectionArea(comp, x, y)) {
return canAcceptWhileTrisection(comp, x, y);
}
boolean horizonValid = componentWidth >= minWidth * 2 + actualVal;
boolean verticalValid = componentHeight >= minHeight * 2 + actualVal;
return y > upHeight && y < downHeight ? horizonValid : verticalValid;
}
/**
* 组件的ComponentAdapter在添加组件时如果发现布局管理器不为空会继而调用该布局管理器的
* addComp方法来完成组件的具体添加在该方法内布局管理器可以提供额外的功能
*
* @param creator 被添加的新组件
* @param x 添加的位置x该位置是相对于container的
* @param y 添加的位置y该位置是相对于container的
* @return 是否添加成功成功返回true否则false
*/
@Override
public boolean addBean(XCreator creator, int x, int y) {
Rectangle rect = ComponentUtils.getRelativeBounds(container);
int posX = x + rect.x;
int posY = y + rect.y;
if (!accept(creator, x, y)) {
return false;
}
addComp(creator, posX, posY);
((XWidgetCreator) creator).recalculateChildrenSize();
return true;
}
@Override
protected void addComp(XCreator creator, int x, int y) {
if (!isAdd2ParentLayout) {
Rectangle r = ComponentUtils.getRelativeBounds(container);
x = x - r.x;
y = y - r.y;
if (XCreatorUtils.getParentXLayoutContainer(creator) != null) {
Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator);
x = creatorRectangle.x - r.x;
y = creatorRectangle.y - r.y;
} else {
int w = creator.getWidth() / 2;
int h = creator.getHeight() / 2;
x = x - w;
y = y - h;
}
fix(creator, x, y);
if (creator.hasTitleStyle()) {
addParentCreator(creator);
} else {
container.add(creator, creator.toData().getWidgetName());
}
XWAbsoluteLayout layout = (XWAbsoluteLayout) container;
layout.updateBoundsWidget(creator);
updateCreatorBackBound();
LayoutUtils.layoutRootContainer(container);
} else {
fixAbsolute(creator, x, y);
if (creator.shouldScaleCreator() || creator.hasTitleStyle()) {
addParentCreator(creator);
} else {
container.add(creator, creator.toData().getWidgetName());
}
XWFitLayout layout = (XWFitLayout) container;
// 更新对应的BoundsWidget
layout.updateBoundsWidget();
updateCreatorBackBound();
}
}
private void updateCreatorBackBound() {
for (int i = 0, size = container.getComponentCount(); i < size; i++) {
XCreator creator = (XCreator) container.getComponent(i);
creator.updateChildBound(minHeight);
creator.setBackupBound(creator.getBounds());
}
}
private void addParentCreator(XCreator child) {
XLayoutContainer parentPanel = child.initCreatorWrapper(child.getHeight());
container.add(parentPanel, child.toData().getWidgetName());
}
/**
* 新拖入组件时计算调整其他关联组件位置大小
*
* @param child 新拖入的组件
* @param x 鼠标所在x坐标
* @param y 鼠标所在y坐标
*/
private void fixAbsolute(XCreator child, int x, int y) {
Component parentComp = container.getComponentAt(x, y);
if (container.getComponentCount() == 0) {
child.setLocation(0, 0);
child.setSize(parentComp.getWidth(), parentComp.getHeight());
} else if (isCrossPointArea(parentComp, x, y)) {
//交叉区域插入组件时,根据具体位置进行上下或者左右或者相邻三个组件的位置大小插入
fixCrossPointArea(parentComp, child, x, y);
//TODO 尽量不要出现这种写法吧?if else条件要么互斥,要么多个if判断return,不要在一条if else语句里面return吧?
return;
} else if (isTrisectionArea(parentComp, x, y)) {
// 在边界三等分区域,就不再和组件二等分了
fixTrisect(parentComp, child, x, y);
return;
} else {
fixHalve(parentComp, child, x, y);
}
}
/**
* 组件拖拽后调整大小
*
* @param creator 组件
*/
@Override
public void fix(XCreator creator) {
WAbsoluteLayout wabs = (WAbsoluteLayout) container.toData();
fix(creator, creator.getX(), creator.getY());
wabs.setBounds(creator.toData(), creator.getBounds());
XWAbsoluteLayout layout = (XWAbsoluteLayout) container;
layout.updateBoundsWidget(creator);
}
/**
* 调整组件大小到合适尺寸位置
*
* @param creator 组件
* @param x 坐标x
* @param y 坐标y
*/
public void fix(XCreator creator, int x, int y) {
int height = creator.getHeight();
int width = creator.getWidth();
if (x < 0) {
width += x;
x = 0;
} else if (x + creator.getWidth() > container.getWidth()) {
width = container.getWidth() - x;
}
if (y < 0) {
height += y;
y = 0;
} else if (y + creator.getHeight() > container.getHeight()) {
height = container.getHeight() - y;
}
creator.setBounds(x, y, width, height);
}
@Override
public ConstraintsGroupModel getLayoutConstraints(XCreator creator) {
return new BoundsGroupModel((XWAbsoluteLayout) container, creator);
}
@Override
public GroupModel getLayoutProperties() {
XWAbsoluteLayout xwAbsoluteLayout = (XWAbsoluteLayout) container;
return new FRAbsoluteLayoutPropertiesGroupModel(xwAbsoluteLayout);
}
}

2385
designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java

File diff suppressed because it is too large Load Diff

210
designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java

@ -1,108 +1,104 @@
/**
*
*/
package com.fr.design.designer.beans.adapters.layout;
import com.fr.design.beans.GroupModel;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.designer.creator.XWidgetCreator;
import com.fr.design.designer.creator.cardlayout.XWCardLayout;
import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout;
import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
import com.fr.design.designer.properties.FRTabFitLayoutPropertiesGroupModel;
import com.fr.design.utils.ComponentUtils;
import com.fr.form.ui.LayoutBorderStyle;
import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout;
import com.fr.general.ComparatorUtils;
import java.awt.*;
/**
* tab布局tabFit适配器
*
* @author focus
* @date 2014-6-24
*/
public class FRTabFitLayoutAdapter extends FRFitLayoutAdapter {
//标题栏高度对tab布局内部组件的y坐标造成了偏移
private static int TAB_HEIGHT = 40;
/**
* 构造函数
*
* @param container XWTabFitLayout容器
*/
public FRTabFitLayoutAdapter(XLayoutContainer container) {
super(container);
}
/**
* 返回布局自身属性方便一些特有设置在layout刷新时处理
*/
@Override
public GroupModel getLayoutProperties() {
XWTabFitLayout xfl = (XWTabFitLayout) container;
return new FRTabFitLayoutPropertiesGroupModel(xfl);
}
/**
* 组件的ComponentAdapter在添加组件时如果发现布局管理器不为空会继而调用该布局管理器的
* addComp方法来完成组件的具体添加在该方法内布局管理器可以提供额外的功能
*
* @param creator 被添加的新组件
* @param x 添加的位置x该位置是相对于container的
* @param y 添加的位置y该位置是相对于container的
* @return 是否添加成功成功返回true否则false
*/
@Override
public boolean addBean(XCreator creator, int x, int y) {
// 经过accept判断后,container会被改变,先备份
XLayoutContainer backUpContainer = container;
Rectangle rect = ComponentUtils.getRelativeBounds(container);
int posX = x - rect.x;
int posY = y - rect.y;
if (!accept(creator, posX, posY)) {
return false;
}
// posX,posY是新拖入组件相对于容器的位置,若在tab布局的边缘,则需要把新组件添加到
// 父层自适应布局中,这时候的添加位置就是tab布局所在的位置
if (this.intersectsEdge(posX, posY, backUpContainer)) {
if (!ComparatorUtils.equals(backUpContainer.getOuterLayout(), backUpContainer.getBackupParent())) {
XWTabFitLayout tabLayout = (XWTabFitLayout) backUpContainer;
y = adjustY(y, tabLayout);
}
addComp(creator, x, y);
((XWidgetCreator) creator).recalculateChildrenSize();
return true;
}
// 如果不在边缘,容器为本自适应布局,增加组件的位置就是相对于容器的位置
addComp(creator, posX, posY);
((XWidgetCreator) creator).recalculateChildrenSize();
return true;
}
// tab布局的纵坐标受到tab高度的影响,判断的上边界取得是里面XWTabFitLayout的上边界,
// 实际计算的时候的纵坐标用了外层的CardMainBorerLayout,需要将tab高度减掉
//将y值变为相对坐标以实现获取到鼠标drop位置的控件
//TODO 可以直接在这边将x,y都变成相对坐标,这样在后面判断拖进来的新控件放置方式的时候就不用再判断了
private int adjustY(int y, XWTabFitLayout tabLayout) {
XWCardLayout cardLayout = (XWCardLayout) tabLayout.getBackupParent();
LayoutBorderStyle style = cardLayout.toData().getBorderStyle();
if (container.getLocation().y == WBorderLayout.DEFAULT_SIZE) {
y = y - WBorderLayout.DEFAULT_SIZE;
}
if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) {
y = y - WCardMainBorderLayout.TAB_HEIGHT;
}
return y;
}
protected Rectangle getLayoutBound(XWCardMainBorderLayout mainLayout) {
return ComponentUtils.getRelativeBounds(mainLayout);
}
/**
*
*/
package com.fr.design.designer.beans.adapters.layout;
import com.fr.design.beans.GroupModel;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWidgetCreator;
import com.fr.design.designer.creator.cardlayout.XWCardLayout;
import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout;
import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
import com.fr.design.designer.properties.FRTabFitLayoutPropertiesGroupModel;
import com.fr.design.utils.ComponentUtils;
import com.fr.form.ui.LayoutBorderStyle;
import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout;
import com.fr.general.ComparatorUtils;
import java.awt.*;
/**
* tab布局tabFit适配器
*
* @author focus
* @date 2014-6-24
*/
public class FRTabFitLayoutAdapter extends FRFitLayoutAdapter {
/**
* 构造函数
*
* @param container XWTabFitLayout容器
*/
public FRTabFitLayoutAdapter(XLayoutContainer container) {
super(container);
}
/**
* 返回布局自身属性方便一些特有设置在layout刷新时处理
*/
@Override
public GroupModel getLayoutProperties() {
XWTabFitLayout xfl = (XWTabFitLayout) container;
return new FRTabFitLayoutPropertiesGroupModel(xfl);
}
/**
* 组件的ComponentAdapter在添加组件时如果发现布局管理器不为空会继而调用该布局管理器的
* addComp方法来完成组件的具体添加在该方法内布局管理器可以提供额外的功能
*
* @param creator 被添加的新组件
* @param x 添加的位置x该位置是相对于container的
* @param y 添加的位置y该位置是相对于container的
* @return 是否添加成功成功返回true否则false
*/
@Override
public boolean addBean(XCreator creator, int x, int y) {
// 经过accept判断后,container会被改变,先备份
XLayoutContainer backUpContainer = container;
Rectangle rect = ComponentUtils.getRelativeBounds(container);
int posX = x - rect.x;
int posY = y - rect.y;
if (!accept(creator, posX, posY)) {
return false;
}
// posX,posY是新拖入组件相对于容器的位置,若在tab布局的边缘,则需要把新组件添加到l
// 父层自适应布局中,这时候的添加位置就是tab布局所在的位置
if (this.intersectsEdge(posX, posY, backUpContainer)) {
if (!ComparatorUtils.equals(backUpContainer.getOuterLayout(), backUpContainer.getBackupParent())) {
XWTabFitLayout tabLayout = (XWTabFitLayout) backUpContainer;
y = adjustY(y, tabLayout);
}
addComp(creator, x, y);
((XWidgetCreator) creator).recalculateChildrenSize();
return true;
}
// 如果不在边缘,容器为本自适应布局,增加组件的位置就是相对于容器的位置
addComp(creator, posX, posY);
((XWidgetCreator) creator).recalculateChildrenSize();
return true;
}
// tab布局的纵坐标受到tab高度的影响,判断的上边界取得是里面XWTabFitLayout的上边界,
// 实际计算的时候的纵坐标用了外层的CardMainBorerLayout,需要将tab高度减掉
//将y值变为相对坐标以实现获取到鼠标drop位置的控件
//TODO 可以直接在这边将x,y都变成相对坐标,这样在后面判断拖进来的新控件放置方式的时候就不用再判断了
private int adjustY(int y, XWTabFitLayout tabLayout) {
XWCardLayout cardLayout = (XWCardLayout) tabLayout.getBackupParent();
LayoutBorderStyle style = cardLayout.toData().getBorderStyle();
if (container.getLocation().y == WBorderLayout.DEFAULT_SIZE) {
y = y - WBorderLayout.DEFAULT_SIZE;
}
if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) {
y = y - WCardMainBorderLayout.TAB_HEIGHT;
}
return y;
}
protected Rectangle getLayoutBound(XWCardMainBorderLayout mainLayout) {
return ComponentUtils.getRelativeBounds(mainLayout);
}
}

333
designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java

@ -3,19 +3,17 @@
*/
package com.fr.design.designer.beans.location;
import java.awt.*;
import com.fr.design.beans.location.Absorptionline;
import com.fr.design.beans.location.MoveUtils;
import com.fr.design.designer.creator.*;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.FormSelection;
import com.fr.design.utils.ComponentUtils;
import com.fr.form.main.Form;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.form.ui.container.WParameterLayout;
import com.fr.form.ui.widget.BoundsWidget;
import java.awt.*;
/**
* @author richer
* @since 6.5.3
@ -26,197 +24,184 @@ public abstract class AccessDirection implements Direction {
private int ymin;
private int xmin;
abstract int getCursor();
protected abstract Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
Rectangle oldbounds);
protected int[] sorption(int x, int y,Rectangle current_bounds, FormDesigner designer) {
// 自适应布局不需要吸附线,但需要对齐线,对齐线后面处理
if (!designer.hasWAbsoluteLayout()) {
designer.getStateModel().setEquidistantLine(null);
designer.getStateModel().setXAbsorptionline(null);
designer.getStateModel().setYAbsorptionline(null);
return new int[] { x, y };
} else {
int posy = current_bounds.y;
Point relativePoint = getRelativePoint(x, y, current_bounds,designer);
sorptionPoint(relativePoint,current_bounds, designer);
return new int[] { relativePoint.x, relativePoint.y };
}
}
protected Point getRelativePoint(int x, int y, Rectangle current_bounds,FormDesigner designer) {
if (x < 0) {
x = 0;
} else if (x > designer.getRootComponent().getWidth() && designer.getSelectionModel().hasSelectionComponent()) {
x = designer.getRootComponent().getWidth();
}
abstract int getCursor();
protected abstract Rectangle getDraggedBounds(int dx, int dy, Rectangle currentBounds, FormDesigner designer,
Rectangle oldBounds);
protected int[] sorption(int x, int y, Rectangle currentBounds, FormDesigner designer) {
// 自适应布局不需要吸附线,但需要对齐线,对齐线后面处理
if (!designer.hasWAbsoluteLayout()) {
designer.getStateModel().setEquidistantLine(null);
designer.getStateModel().setXAbsorptionline(null);
designer.getStateModel().setYAbsorptionline(null);
return new int[]{x, y};
} else {
Point relativePoint = getRelativePoint(x, y, currentBounds, designer);
sorptionPoint(relativePoint, currentBounds, designer);
return new int[]{relativePoint.x, relativePoint.y};
}
}
protected Point getRelativePoint(int x, int y, Rectangle currentBounds, FormDesigner designer) {
if (x < 0) {
x = 0;
} else if (x > designer.getRootComponent().getWidth() && designer.getSelectionModel().hasSelectionComponent()) {
x = designer.getRootComponent().getWidth();
}
//参数面板可以无下限拉长
if (y < 0) {
y = 0;
} else if (y > designer.getRootComponent().getHeight() + designer.getParaHeight() && designer.getSelectionModel().hasSelectionComponent()
if (y < 0) {
y = 0;
} else if (y > designer.getRootComponent().getHeight() + designer.getParaHeight() && designer.getSelectionModel().hasSelectionComponent()
&& !designer.getSelectionModel().getSelection().getSelectedCreator().acceptType(XWParameterLayout.class)) {
y = designer.getRootComponent().getHeight() + designer.getParaHeight();
}
return new Point(x, y);
}
protected void sorptionPoint(Point point, Rectangle current_bounds,FormDesigner designer) {
boolean findInX = current_bounds.getWidth() <= MoveUtils.SORPTION_UNIT ? true : false;
boolean findInY = current_bounds.getHeight() <= MoveUtils.SORPTION_UNIT ? true : false;
WAbsoluteLayout layout =getLayout(designer);
FormSelection selection = designer.getSelectionModel().getSelection();
boolean isWidgetsIntersect = false;
for (int i = 0, count = layout.getWidgetCount(); i < count; i++) {
BoundsWidget temp = (BoundsWidget) layout.getWidget(i);
if (!temp.isVisible() || selection.contains(temp.getWidget())) {
continue;
}
Rectangle bounds = getWidgetRelativeBounds(temp.getBounds(), selection);
if (!findInX) {
int x1 = bounds.x;
if (Math.abs(x1 - point.x) <= MoveUtils.SORPTION_UNIT) {
point.x = x1;
findInX = true;
}
int x2 = bounds.x + bounds.width;
if (Math.abs(x2 - point.x) <= MoveUtils.SORPTION_UNIT) {
point.x = x2;
findInX = true;
}
}
if (!findInY) {
int y1 = bounds.y;
if (Math.abs(y1 - point.y) <= MoveUtils.SORPTION_UNIT) {
point.y = y1;
findInY = true;
}
int y2 = bounds.y + bounds.height;
if (Math.abs(y2 - point.y) <= MoveUtils.SORPTION_UNIT) {
point.y = y2;
findInY = true;
}
}
if (findInX && findInY) {
break;
}
if (current_bounds.intersects(bounds) && !(layout instanceof WParameterLayout)){
isWidgetsIntersect = true;
}
}
processRectangleIntersects(designer, point.x, point.y, isWidgetsIntersect);
setDesignerStateModelProperties(designer, findInX, findInY, current_bounds, point);
}
private void setDesignerStateModelProperties (FormDesigner designer, boolean findInX, boolean findInY, Rectangle current_bounds, Point point) {
designer.getStateModel().setXAbsorptionline(findInX && current_bounds.getWidth() > MoveUtils.SORPTION_UNIT ? Absorptionline.createXAbsorptionline(point.x) : null);
designer.getStateModel().setYAbsorptionline(findInY && current_bounds.getHeight() > MoveUtils.SORPTION_UNIT ? Absorptionline.createYAbsorptionline(point.y) : null);
designer.getStateModel().setEquidistantLine(null);
}
private Rectangle getWidgetRelativeBounds(Rectangle bounds, FormSelection selection){
Rectangle relativeRec = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator());
if (parent == null) {
return relativeRec;
}
Rectangle rec = ComponentUtils.getRelativeBounds(parent);
relativeRec.x += rec.x;
relativeRec.y += rec.y;
return relativeRec;
}
private void processRectangleIntersects(FormDesigner designer, int x, int y, boolean isIntersects){
if(isIntersects){
if(designer.getLocationOnScreen() != null) {
MoveUtils.displayForbidWindow(x + designer.getLocationOnScreen().x, y + designer.getLocationOnScreen().y);
}
designer.setWidgetsIntersect(true);
}
else{
MoveUtils.hideForbidWindow();
designer.setWidgetsIntersect(false);
}
}
private WAbsoluteLayout getLayout(final FormDesigner designer){
y = designer.getRootComponent().getHeight() + designer.getParaHeight();
}
return new Point(x, y);
}
protected void sorptionPoint(Point point, Rectangle currentBounds, FormDesigner designer) {
boolean findInX = currentBounds.getWidth() <= MoveUtils.SORPTION_UNIT;
boolean findInY = currentBounds.getHeight() <= MoveUtils.SORPTION_UNIT;
WAbsoluteLayout layout = getLayout(designer);
FormSelection selection = designer.getSelectionModel().getSelection();
for (int i = 0, count = layout.getWidgetCount(); i < count; i++) {
BoundsWidget temp = (BoundsWidget) layout.getWidget(i);
if (!temp.isVisible() || selection.contains(temp.getWidget())) {
continue;
}
Rectangle bounds = getWidgetRelativeBounds(temp.getBounds(), selection);
if (!findInX) {
int x1 = bounds.x;
if (Math.abs(x1 - point.x) <= MoveUtils.SORPTION_UNIT) {
point.x = x1;
findInX = true;
}
int x2 = bounds.x + bounds.width;
if (Math.abs(x2 - point.x) <= MoveUtils.SORPTION_UNIT) {
point.x = x2;
findInX = true;
}
}
if (!findInY) {
int y1 = bounds.y;
if (Math.abs(y1 - point.y) <= MoveUtils.SORPTION_UNIT) {
point.y = y1;
findInY = true;
}
int y2 = bounds.y + bounds.height;
if (Math.abs(y2 - point.y) <= MoveUtils.SORPTION_UNIT) {
point.y = y2;
findInY = true;
}
}
if (findInX && findInY) {
break;
}
}
setDesignerStateModelProperties(designer, findInX, findInY, currentBounds, point);
}
private void setDesignerStateModelProperties(FormDesigner designer, boolean findInX, boolean findInY, Rectangle
currentBounds, Point point) {
designer.getStateModel().setXAbsorptionline(findInX && currentBounds.getWidth() > MoveUtils.SORPTION_UNIT ? Absorptionline.createXAbsorptionline(point.x) : null);
designer.getStateModel().setYAbsorptionline(findInY && currentBounds.getHeight() > MoveUtils.SORPTION_UNIT ? Absorptionline.createYAbsorptionline(point.y) : null);
designer.getStateModel().setEquidistantLine(null);
}
private Rectangle getWidgetRelativeBounds(Rectangle bounds, FormSelection selection) {
Rectangle relativeRec = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator());
if (parent == null) {
return relativeRec;
}
Rectangle rec = ComponentUtils.getRelativeBounds(parent);
relativeRec.x += rec.x;
relativeRec.y += rec.y;
return relativeRec;
}
private WAbsoluteLayout getLayout(final FormDesigner designer) {
XLayoutContainer formLayoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator(
designer.getTarget().getContainer());
WAbsoluteLayout layout;
if (formLayoutContainer.acceptType(XWBorderLayout.class)){//看起来这边的作用应该是为了区别cpt(得到XWParameterLayout)还是frm(得到XWBorderLayout)的参数界面
Container container = designer.getSelectionModel().getSelection().getSelectedCreator().getParent();
if(container instanceof XWAbsoluteLayout){
layout = ((XWAbsoluteLayout)container).toData();
}
else {
layout = (WAbsoluteLayout) designer.getParaComponent().toData();
}
} else{
if (formLayoutContainer.acceptType(XWBorderLayout.class)) {//看起来这边的作用应该是为了区别cpt(得到XWParameterLayout)还是frm(得到XWBorderLayout)的参数界面
Container container = designer.getSelectionModel().getSelection().getSelectedCreator().getParent();
if (container instanceof XWAbsoluteLayout) {
layout = ((XWAbsoluteLayout) container).toData();
} else {
layout = (WAbsoluteLayout) designer.getParaComponent().toData();
}
} else {
layout = (WAbsoluteLayout) designer.getTarget().getContainer();
}
return layout;
return layout;
}
/**
* 拖拽
* @param dx 坐标x
* @param dy 坐标y
* @param designer 设计界面
*/
public void drag(int dx, int dy, FormDesigner designer) {
Rectangle rec = getDraggedBounds(dx, dy, designer.getSelectionModel().getSelection().getRelativeBounds(), designer, designer.getSelectionModel().getSelection().getBackupBounds());
/**
* 拖拽
*
* @param dx 坐标x
* @param dy 坐标y
* @param designer 设计界面
*/
public void drag(int dx, int dy, FormDesigner designer) {
Rectangle rec = getDraggedBounds(dx, dy, designer.getSelectionModel().getSelection().getRelativeBounds(), designer, designer.getSelectionModel().getSelection().getBackupBounds());
if (rec != null) {
designer.getSelectionModel().getSelection().setSelectionBounds(rec, designer);
} else {
return;
}
//设定控件最小高度21,因每次拖曳至少移动1,防止控件高度等于21时,拖曳导致rec.y的变化使得控件不停的向上或向下移动。
if(rec.height == MINHEIGHT){
if (rec.height == MINHEIGHT) {
ymin = rec.y;
}
if(rec.height == MINHEIGHT - 1){
if (rec.height == MINHEIGHT - 1) {
ymin = ymin == rec.y ? rec.y : rec.y - 1;
}
if(rec.height < MINHEIGHT){
if (rec.height < MINHEIGHT) {
rec.height = MINHEIGHT;
rec.y = ymin;
}
// 增加下宽度也设最小为21
if (rec.width == MINWIDTH) {
xmin = rec.x;
xmin = rec.x;
}
if(rec.width == MINWIDTH - 1){
xmin = xmin == rec.x ? rec.x : rec.x - 1;
if (rec.width == MINWIDTH - 1) {
xmin = xmin == rec.x ? rec.x : rec.x - 1;
}
if (rec.width < MINWIDTH) {
rec.width = MINWIDTH;
rec.x = xmin;
rec.width = MINWIDTH;
rec.x = xmin;
}
}
/**
* 更新鼠标指针形状
*
* @param formEditor 设计界面组件
*/
public void updateCursor(FormDesigner formEditor) {
// 调用位置枚举的多态方法getCursor获取鼠标形状
int type = getCursor();
if (type != formEditor.getCursor().getType()) {
// 设置当前形状
formEditor.setCursor(Cursor.getPredefinedCursor(type));
}
if(rec != null) {
designer.getSelectionModel().getSelection().setSelectionBounds(rec, designer);
}
}
/**
* 更新鼠标指针形状
* @param formEditor 设计界面组件
*/
public void updateCursor(FormDesigner formEditor) {
// 调用位置枚举的多态方法getCursor获取鼠标形状
int type = getCursor();
if (type != formEditor.getCursor().getType()) {
// 设置当前形状
formEditor.setCursor(Cursor.getPredefinedCursor(type));
}
}
/**
* 生成组件备用的bound
* @param formEditor 设计界面组件
*/
public void backupBounds(FormDesigner formEditor) {
formEditor.getSelectionModel().getSelection().backupBounds();
}
}
/**
* 生成组件备用的bound
*
* @param formEditor 设计界面组件
*/
public void backupBounds(FormDesigner formEditor) {
formEditor.getSelectionModel().getSelection().backupBounds();
}
}

744
designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java

@ -1,328 +1,418 @@
package com.fr.design.designer.beans.models;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import com.fr.design.designer.beans.AdapterBus;
import com.fr.design.designer.beans.LayoutAdapter;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.beans.location.Direction;
import com.fr.design.designer.beans.location.Location;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.form.util.XCreatorConstants;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.FormSelection;
import com.fr.design.mainframe.FormSelectionUtils;
import com.fr.design.utils.gui.LayoutUtils;
import com.fr.stable.ArrayUtils;
/**
* 该model保存当前选择的组件和剪切版信息
*/
public class SelectionModel {
private static final int DELTA_X_Y = 20; //粘贴时候的偏移距离
private static FormSelection CLIP_BOARD = new FormSelection();
private FormDesigner designer;
private FormSelection selection;
private Rectangle hotspot_bounds;
public SelectionModel(FormDesigner designer) {
this.designer = designer;
selection = new FormSelection();
}
/**
* 重置清空formSelction以及选择区域
*/
public void reset() {
selection.reset();
hotspot_bounds = null;
}
/**
* formSelction是否为空
* @return 是否为空
*/
public static boolean isEmpty(){
return CLIP_BOARD.isEmpty();
}
/**
* 鼠标点击一下所选中的单个组件按下Ctrl或者shift键时鼠标可以进行多选
* @param e 鼠标事件
*/
public void selectACreatorAtMouseEvent(MouseEvent e) {
if (!e.isControlDown() && !e.isShiftDown()) {
// 如果Ctrl或者Shift键盘没有按下,则清除已经选择的组件
selection.reset();
}
// 获取e所在的组件
XCreator comp = designer.getComponentAt(e);
//布局组件的顶层布局如不可编辑,要获取其顶层布局
XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(comp).getTopLayout();
if(topLayout != null && !topLayout.isEditable()){
comp = topLayout;
}
// 如果父层是scale和title两个专属容器,返回其父层,组件本身是不让被选中的
if (comp != designer.getRootComponent() && comp != designer.getParaComponent()) {
XCreator parentContainer = (XCreator) comp.getParent();
comp = parentContainer.isDedicateContainer() ? parentContainer : comp;
}
if (selection.removeSelectedCreator(comp) || selection.addSelectedCreator(comp)) {
designer.getEditListenerTable().fireCreatorModified(comp, DesignerEvent.CREATOR_SELECTED);
designer.repaint();
}
}
/**
* 将所选组件剪切到剪切板上
*/
public void cutSelectedCreator2ClipBoard() {
if (hasSelectionComponent()) {
selection.cut2ClipBoard(CLIP_BOARD);
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED);
designer.repaint();
}
}
/**
* 复制当前选中的组件到剪切板
*/
public void copySelectedCreator2ClipBoard() {
if (!selection.isEmpty()) {
selection.copy2ClipBoard(CLIP_BOARD);
}
}
/**
* 从剪切板粘帖组件
* @return
*/
public boolean pasteFromClipBoard() {
if (!CLIP_BOARD.isEmpty()) {
XLayoutContainer parent = null;
if (!hasSelectionComponent()) {
FormSelectionUtils.paste2Container(designer, designer.getRootComponent(),CLIP_BOARD, DELTA_X_Y, DELTA_X_Y);
} else {
parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator());
if (parent != null) {
Rectangle rec = selection.getSelctionBounds();
FormSelectionUtils.paste2Container(designer, parent,CLIP_BOARD, rec.x + DELTA_X_Y, rec.y + DELTA_X_Y);
}
}
} else {
Toolkit.getDefaultToolkit().beep();
}
return false;
}
public FormSelection getSelection() {
return selection;
}
/**
* 删除当前所有选择的组件
*/
public void deleteSelection() {
XCreator[] roots = selection.getSelectedCreators();
if (roots.length > 0) {
for (XCreator creator : roots) {
if(creator.acceptType(XWParameterLayout.class)){
designer.removeParaComponent();
}
removeCreatorFromContainer(creator, creator.getWidth(), creator.getHeight());
creator.removeAll();
// 清除被选中的组件
selection.reset();
}
setSelectedCreator(designer.getRootComponent());
// 触发事件
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_DELETED);
designer.repaint();
}
}
/**
* 从选择组件中删除某组件
*
* @param creator 组件
* @param creatorWidth 组件之前宽度
* @param creatorHeight 组件之前高度
*/
public void removeCreator(XCreator creator, int creatorWidth, int creatorHeight) {
selection.removeCreator(creator);
removeCreatorFromContainer(creator, creatorWidth, creatorHeight);
designer.repaint();
}
/**
* 设置选择区域
*/
public void setHotspotBounds(Rectangle rect) {
hotspot_bounds = rect;
}
/**
* 获得当前选择区域
*/
public Rectangle getHotspotBounds() {
return hotspot_bounds;
}
private void removeCreatorFromContainer(XCreator creator, int creatorWidth, int creatorHeight) {
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator);
if (parent == null) {
return;
}
boolean changeCreator = creator.shouldScaleCreator() || creator.hasTitleStyle();
if (parent.acceptType(XWFitLayout.class) && changeCreator) {
creator = (XCreator) creator.getParent();
}
parent.getLayoutAdapter().removeBean(creator, creatorWidth, creatorHeight);
// 删除其根组件,同时就删除了同时被选择的叶子组件
parent.remove(creator);
LayoutManager layout = parent.getLayout();
if (layout != null) {
// 刷新组件容器的布局
LayoutUtils.layoutContainer(parent);
}
}
/**
* 是否有组件被选择如果所选组件是最底层容器也视为无选择
* @return 是则返回true
*/
public boolean hasSelectionComponent() {
return !selection.isEmpty() && selection.getSelectedCreator().getParent() != null;
}
/**
* 移动组件至指定位置
* @param x 坐标x
* @param y 坐标y
*/
public void move(int x, int y) {
for (XCreator creator : selection.getSelectedCreators()) {
creator.setLocation(creator.getX() + x, creator.getY() + y);
LayoutAdapter layoutAdapter = AdapterBus.searchLayoutAdapter(designer, creator);
if (layoutAdapter != null) {
layoutAdapter.fix(creator);
}
}
designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(),
DesignerEvent.CREATOR_SELECTED);
}
/**
* 释放捕获
*/
public void releaseDragging() {
designer.setPainter(null);
selection.fixCreator(designer);
designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(),
DesignerEvent.CREATOR_RESIZED);
}
public Direction getDirectionAt(MouseEvent e) {
Direction dir;
if (e.isControlDown() || e.isShiftDown()) {
XCreator creator = designer.getComponentAt(e.getX(), e.getY(), selection.getSelectedCreators());
if (creator != designer.getRootComponent() && selection.addedable(creator)) {
return Location.add;
}
}
if (hasSelectionComponent()) {
int x = e.getX() + designer.getArea().getHorizontalValue();
int y = e.getY() + designer.getArea().getVerticalValue();
dir = getDirection(selection.getRelativeBounds(), x, y);
if (selection.size() == 1) {
if (!ArrayUtils.contains(selection.getSelectedCreator().getDirections(), dir.getActual())) {
dir = Location.outer;
}
}
} else {
dir = Location.outer;
}
if (designer.getDesignerMode().isFormParameterEditor() && dir == Location.outer) {
dir = designer.getLoc2Root(e);
}
return dir;
}
private Direction getDirection(Rectangle bounds, int x, int y) {
if (x < (bounds.x - XCreatorConstants.RESIZE_BOX_SIZ)) {
return Location.outer;
} else if ((x >= (bounds.x - XCreatorConstants.RESIZE_BOX_SIZ)) && (x <= bounds.x)) {
if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) {
return Location.outer;
} else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) {
return Location.left_top;
} else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) {
return Location.left;
} else if ((y >= (bounds.y + bounds.height))
&& (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) {
return Location.left_bottom;
} else {
return Location.outer;
}
} else if ((x > bounds.x) && (x < (bounds.x + bounds.width))) {
if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) {
return Location.outer;
} else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) {
return Location.top;
} else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) {
return Location.inner;
} else if ((y >= (bounds.y + bounds.height))
&& (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) {
return Location.bottom;
} else {
return Location.outer;
}
} else if ((x >= (bounds.x + bounds.width))
&& (x <= (bounds.x + bounds.width + XCreatorConstants.RESIZE_BOX_SIZ))) {
if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) {
return Location.outer;
} else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) {
return Location.right_top;
} else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) {
return Location.right;
} else if ((y >= (bounds.y + bounds.height))
&& (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) {
return Location.right_bottom;
} else {
return Location.outer;
}
} else {
return Location.outer;
}
}
private void fireCreatorSelected() {
designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(),
DesignerEvent.CREATOR_SELECTED);
}
public void setSelectedCreator(XCreator rootComponent) {
selection.setSelectedCreator(rootComponent);
fireCreatorSelected();
}
public void setSelectedCreators(ArrayList<XCreator> rebuildSelection) {
selection.setSelectedCreators(rebuildSelection);
fireCreatorSelected();
}
package com.fr.design.designer.beans.models;
import com.fr.design.designer.beans.AdapterBus;
import com.fr.design.designer.beans.LayoutAdapter;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.beans.location.Direction;
import com.fr.design.designer.beans.location.Location;
import com.fr.design.designer.creator.*;
import com.fr.design.designer.creator.cardlayout.XWCardLayout;
import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout;
import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
import com.fr.design.form.util.XCreatorConstants;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.FormSelection;
import com.fr.design.mainframe.FormSelectionUtils;
import com.fr.design.utils.gui.LayoutUtils;
import com.fr.stable.ArrayUtils;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
/**
* 该model保存当前选择的组件和剪切版信息
*/
public class SelectionModel {
//被粘贴组件在所选组件位置处往下、往右各错开20像素。执行多次粘贴时,在上一次粘贴的位置处错开20像素。
private static final int DELTA_X_Y = 20; //粘贴时候的偏移距离
private static final int BORDER_PROPORTION = 20;
private static FormSelection clipboard = new FormSelection();
private FormDesigner designer;
private FormSelection selection;
private Rectangle hotspotBounds;
public SelectionModel(FormDesigner designer) {
this.designer = designer;
selection = new FormSelection();
}
/**
* 重置清空formSelction以及选择区域
*/
public void reset() {
selection.reset();
hotspotBounds = null;
}
/**
* formSelction是否为空
*
* @return 是否为空
*/
public static boolean isEmpty() {
return clipboard.isEmpty();
}
/**
* 鼠标点击一下所选中的单个组件按下Ctrl或者shift键时鼠标可以进行多选
*
* @param e 鼠标事件
*/
public void selectACreatorAtMouseEvent(MouseEvent e) {
if (!e.isControlDown() && !e.isShiftDown()) {
// 如果Ctrl或者Shift键盘没有按下,则清除已经选择的组件
selection.reset();
}
// 获取e所在的组件
XCreator comp = designer.getComponentAt(e);
//布局组件的顶层布局如不可编辑,要获取其顶层布局
XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(comp).getTopLayout();
if (topLayout != null && !topLayout.isEditable()) {
comp = topLayout;
}
// 如果父层是scale和title两个专属容器,返回其父层,组件本身是不让被选中的
if (comp != designer.getRootComponent() && comp != designer.getParaComponent()) {
XCreator parentContainer = (XCreator) comp.getParent();
comp = parentContainer.isDedicateContainer() ? parentContainer : comp;
}
if (selection.removeSelectedCreator(comp) || selection.addSelectedCreator(comp)) {
designer.getEditListenerTable().fireCreatorModified(comp, DesignerEvent.CREATOR_SELECTED);
designer.repaint();
}
}
/**
* 将所选组件剪切到剪切板上
*/
public void cutSelectedCreator2ClipBoard() {
if (hasSelectionComponent()) {
selection.cut2ClipBoard(clipboard);
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED);
designer.repaint();
}
}
/**
* 复制当前选中的组件到剪切板
*/
public void copySelectedCreator2ClipBoard() {
if (!selection.isEmpty()) {
selection.copy2ClipBoard(clipboard);
}
}
/**
* 从剪切板粘帖组件
*
* @return
*/
public boolean pasteFromClipBoard() {
if (!clipboard.isEmpty()) {
if (!hasSelectionComponent()) {
//未选
unselectedPaste();
} else {
//已选
selectedPaste();
}
} else {
Toolkit.getDefaultToolkit().beep();
}
return false;
}
public FormSelection getSelection() {
return selection;
}
/**
* 粘贴时未选择组件
*/
private void unselectedPaste() {
if (designer.getClass().equals(FormDesigner.class)) {
if (selection.getSelectedCreator() instanceof XWFitLayout) {
if (selection.getSelectedCreator().getClass().equals(XWTabFitLayout.class)) {
Rectangle rec = selection.getRelativeBounds();
//Tab布局
FormSelectionUtils.paste2Container(designer, (XLayoutContainer) selection.getSelectedCreator(),
clipboard,
rec.x + rec.width / 2,
rec.y + BORDER_PROPORTION);
} else {
Rectangle rec = selection.getRelativeBounds();
//自适应布局
FormSelectionUtils.paste2Container(designer, designer.getRootComponent(),
clipboard,
rec.x + rec.width / 2,
rec.y + BORDER_PROPORTION);
}
} else {
//绝对布局
//编辑器外面还有两层容器,使用designer.getRootComponent()获取到的是编辑器中层的容器,不是编辑器表层
//当前选择的就是编辑器表层
FormSelectionUtils.paste2Container(designer, (XLayoutContainer) selection.getSelectedCreator(),
clipboard,
DELTA_X_Y,
DELTA_X_Y);
}
} else {
//cpt本地组件复用,编辑器就一层,是最底层,使用designer.getRootComponent()就可以获取到
//使用selection.getSelectedCreator()也应该是可以获取到的。
FormSelectionUtils.paste2Container(designer, designer.getRootComponent(),
clipboard,
DELTA_X_Y,
DELTA_X_Y);
}
}
/**
* 粘贴时选择组件
*/
private void selectedPaste() {
XLayoutContainer parent = null;
//获取到编辑器的表层容器(已选的组件的父容器就是表层容器)
parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator());
if (parent != null && selection.getSelectedCreator().getParent() instanceof XWFitLayout) {
//自适应布局
Rectangle rec = selection.getRelativeBounds();
FormSelectionUtils.paste2Container(designer, parent, clipboard, rec.x + rec.width / 2, rec.y +
rec.height - BORDER_PROPORTION);
} else if (parent != null && selection.getSelectedCreator().getParent() instanceof XWAbsoluteLayout) {
//绝对布局
Rectangle rec = selection.getSelctionBounds();
FormSelectionUtils.paste2Container(designer, parent, clipboard, rec.x + DELTA_X_Y, rec.y + DELTA_X_Y);
}
}
/**
* 删除当前所有选择的组件
*/
public void deleteSelection() {
XCreator[] roots = selection.getSelectedCreators();
if (roots.length > 0) {
for (XCreator creator : roots) {
if (creator.acceptType(XWParameterLayout.class)) {
designer.removeParaComponent();
}
removeCreatorFromContainer(creator, creator.getWidth(), creator.getHeight());
creator.removeAll();
// 清除被选中的组件
selection.reset();
}
setSelectedCreator(designer.getRootComponent());
// 触发事件
designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_DELETED);
designer.repaint();
}
}
/**
* 从选择组件中删除某组件
*
* @param creator 组件
* @param creatorWidth 组件之前宽度
* @param creatorHeight 组件之前高度
*/
public void removeCreator(XCreator creator, int creatorWidth, int creatorHeight) {
selection.removeCreator(creator);
removeCreatorFromContainer(creator, creatorWidth, creatorHeight);
designer.repaint();
}
/**
* 设置选择区域
*/
public void setHotspotBounds(Rectangle rect) {
hotspotBounds = rect;
}
/**
* 获得当前选择区域
*/
public Rectangle getHotspotBounds() {
return hotspotBounds;
}
private void removeCreatorFromContainer(XCreator creator, int creatorWidth, int creatorHeight) {
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator);
if (parent == null) {
return;
}
boolean changeCreator = creator.shouldScaleCreator() || creator.hasTitleStyle();
if (parent.acceptType(XWFitLayout.class) && changeCreator) {
creator = (XCreator) creator.getParent();
}
parent.getLayoutAdapter().removeBean(creator, creatorWidth, creatorHeight);
// 删除其根组件,同时就删除了同时被选择的叶子组件
parent.remove(creator);
LayoutManager layout = parent.getLayout();
if (layout != null) {
// 刷新组件容器的布局
LayoutUtils.layoutContainer(parent);
}
}
/**
* 是否有组件被选择如果所选组件是最底层容器也视为无选择
*
* @return 是则返回true
* yaoh.wu 不应该通过判断是否是最底层容器来判断是否选择了组件
* 而是应该判断选择的容器是否是编辑器的最表层容器,也就是点击空白地方选择的容器
* 但是直接判断选择的容器是否是编辑器最表层类型又会引发拖动时选不上的情况
* 因此通过判断父容器来实现
* <p>
* 举例frm组件复用 绝对布局情况下不选择时有三层容器
* 底层@see {@link com.fr.design.designer.creator.XWBorderLayout}
* 中层@see {@link XWFitLayout}
* 表层@see {@link com.fr.design.designer.creator.XWAbsoluteBodyLayout}
* <p>
* 但是编辑窗口的最外层其实是表层@see {@link com.fr.design.designer.creator.XWAbsoluteBodyLayout},
* 其他两层不是靠添加组件就可以编辑的
*/
public boolean hasSelectionComponent() {
XCreator selectionXCreator = selection.getSelectedCreator();
if (designer.getClass().equals(FormDesigner.class)) {
//frm本地组件复用
if (selectionXCreator != null) {
//选中的是否是tab布局编辑器本身
boolean tabEditor = selectionXCreator.getClass().equals(XWCardMainBorderLayout.class)
|| selectionXCreator.getClass().equals(XWCardLayout.class)
|| selectionXCreator.getClass().equals(XWTabFitLayout.class);
//选中的是否是frm绝对布局编辑器本身
boolean absoluteEditor = selectionXCreator.getClass().equals(XWAbsoluteBodyLayout.class);
//选中的是否是相对布局编辑器本身
boolean relativeEditor = selectionXCreator.getClass().equals(XWFitLayout.class);
return !(tabEditor || absoluteEditor || relativeEditor);
} else {
return false;
}
} else {
//cpt本地组件复用,selection.getSelectedCreator().getParent()=@XWParameterLayout instanceof @XWAbsoluteLayout
return selectionXCreator != null && selectionXCreator.getParent() != null;
}
}
/**
* 移动组件至指定位置
*
* @param x 坐标x
* @param y 坐标y
*/
public void move(int x, int y) {
for (XCreator creator : selection.getSelectedCreators()) {
creator.setLocation(creator.getX() + x, creator.getY() + y);
LayoutAdapter layoutAdapter = AdapterBus.searchLayoutAdapter(designer, creator);
if (layoutAdapter != null) {
layoutAdapter.fix(creator);
}
}
designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(),
DesignerEvent.CREATOR_SELECTED);
}
/**
* 释放捕获
*/
public void releaseDragging() {
designer.setPainter(null);
selection.fixCreator(designer);
designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(),
DesignerEvent.CREATOR_RESIZED);
}
public Direction getDirectionAt(MouseEvent e) {
Direction dir;
if (e.isControlDown() || e.isShiftDown()) {
XCreator creator = designer.getComponentAt(e.getX(), e.getY(), selection.getSelectedCreators());
if (creator != designer.getRootComponent() && selection.addedable(creator)) {
return Location.add;
}
}
if (hasSelectionComponent()) {
int x = e.getX() + designer.getArea().getHorizontalValue();
int y = e.getY() + designer.getArea().getVerticalValue();
dir = getDirection(selection.getRelativeBounds(), x, y);
if (selection.size() == 1 && !ArrayUtils.contains(selection.getSelectedCreator().getDirections(), dir
.getActual())) {
dir = Location.outer;
}
} else {
dir = Location.outer;
}
if (designer.getDesignerMode().isFormParameterEditor() && dir == Location.outer) {
dir = designer.getLoc2Root(e);
}
return dir;
}
private Direction getDirection(Rectangle bounds, int x, int y) {
if (x < (bounds.x - XCreatorConstants.RESIZE_BOX_SIZ)) {
return Location.outer;
} else if ((x >= (bounds.x - XCreatorConstants.RESIZE_BOX_SIZ)) && (x <= bounds.x)) {
if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) {
return Location.outer;
} else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) {
return Location.left_top;
} else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) {
return Location.left;
} else if ((y >= (bounds.y + bounds.height))
&& (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) {
return Location.left_bottom;
} else {
return Location.outer;
}
} else if ((x > bounds.x) && (x < (bounds.x + bounds.width))) {
if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) {
return Location.outer;
} else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) {
return Location.top;
} else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) {
return Location.inner;
} else if ((y >= (bounds.y + bounds.height))
&& (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) {
return Location.bottom;
} else {
return Location.outer;
}
} else if ((x >= (bounds.x + bounds.width))
&& (x <= (bounds.x + bounds.width + XCreatorConstants.RESIZE_BOX_SIZ))) {
if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) {
return Location.outer;
} else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) {
return Location.right_top;
} else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) {
return Location.right;
} else if ((y >= (bounds.y + bounds.height))
&& (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) {
return Location.right_bottom;
} else {
return Location.outer;
}
} else {
return Location.outer;
}
}
private void fireCreatorSelected() {
designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(),
DesignerEvent.CREATOR_SELECTED);
}
public void setSelectedCreator(XCreator rootComponent) {
selection.setSelectedCreator(rootComponent);
fireCreatorSelected();
}
public void setSelectedCreators(ArrayList<XCreator> rebuildSelection) {
selection.setSelectedCreators(rebuildSelection);
fireCreatorSelected();
}
}

182
designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java

@ -1,88 +1,96 @@
/**
*
*/
package com.fr.design.designer.creator;
import com.fr.form.ui.container.WLayout;
import java.awt.*;
import java.beans.IntrospectionException;
import java.util.ArrayList;
/**
* 一些控件专属的容器如标题容器sclae容器
* @author jim
* @date 2014-11-7
*/
public abstract class DedicateLayoutContainer extends XLayoutContainer {
public DedicateLayoutContainer(WLayout widget, Dimension initSize) {
super(widget, initSize);
}
/**
* 得到属性名
* @return 属性名
* @throws IntrospectionException
*/
public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
return new CRPropertyDescriptor[0];
}
/**
* 返回容器图标
*
* @return
*/
@Override
public String getIconPath() {
if(this.getXCreator(XWScaleLayout.INDEX) != null){
return this.getXCreator(XWScaleLayout.INDEX).getIconPath();
}
return "/com/fr/web/images/form/resources/text_field_16.png";
}
/**
* 控件树不显示此组件
* @param path 控件树list
*/
public void notShowInComponentTree(ArrayList<Component> path) {
path.remove(path.size()-1);
}
/**
* 重置组件的名称
* @param name 名称
*/
public void resetCreatorName(String name) {
super.resetCreatorName(name);
XCreator child = getXCreator(XWScaleLayout.INDEX);
child.toData().setWidgetName(name);
}
/**
* 返回对应属性表的组件scale和title返回其子组件
* @return 组件
*/
public XCreator getPropertyDescriptorCreator() {
return getXCreator(XWScaleLayout.INDEX);
}
/**
* 是否作为控件树的叶子节点
* @return 是则返回true
*/
public boolean isComponentTreeLeaf() {
return true;
}
/**
* 是否为sclae和title专属容器
* @return 是则返回true
*/
public boolean isDedicateContainer() {
return true;
}
/**
*
*/
package com.fr.design.designer.creator;
import com.fr.form.ui.container.WLayout;
import java.awt.*;
import java.beans.IntrospectionException;
import java.util.ArrayList;
/**
* 一些控件专属的容器如标题容器sclae容器
*
* @author jim
* @date 2014-11-7
*/
public abstract class DedicateLayoutContainer extends XLayoutContainer {
public DedicateLayoutContainer(WLayout widget, Dimension initSize) {
super(widget, initSize);
}
/**
* 得到属性名
*
* @return 属性名
* @throws IntrospectionException
*/
public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
return new CRPropertyDescriptor[0];
}
/**
* 返回容器图标
*
* @return
*/
@Override
public String getIconPath() {
if (this.getXCreator(XWScaleLayout.INDEX) != null) {
return this.getXCreator(XWScaleLayout.INDEX).getIconPath();
}
return "/com/fr/web/images/form/resources/text_field_16.png";
}
/**
* 控件树不显示此组件
*
* @param path 控件树list
*/
public void notShowInComponentTree(ArrayList<Component> path) {
path.remove(path.size() - 1);
}
/**
* 重置组件的名称
*
* @param name 名称
*/
public void resetCreatorName(String name) {
super.resetCreatorName(name);
XCreator child = getXCreator(XWScaleLayout.INDEX);
//实现WTitleLayout的SetWidgetName
child.toData().setWidgetName(name);
}
/**
* 返回对应属性表的组件scale和title返回其子组件
*
* @return 组件
*/
public XCreator getPropertyDescriptorCreator() {
return getXCreator(XWScaleLayout.INDEX);
}
/**
* 是否作为控件树的叶子节点
*
* @return 是则返回true
*/
public boolean isComponentTreeLeaf() {
return true;
}
/**
* 是否为sclae和title专属容器
*
* @return 是则返回true
*/
public boolean isDedicateContainer() {
return true;
}
}

1388
designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java

File diff suppressed because it is too large Load Diff

170
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<Point> 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<Point> 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<Point> createDefalutNode(Point startPoint, Point endPoint) {
long s = System.currentTimeMillis();
ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(), new Point(startPoint), new Point(endPoint));
ArrayList<Point> 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<Point> createDefalutNode(Point startPoint, Point endPoint) {
long s = System.currentTimeMillis();
ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(), new Point(startPoint), new Point(endPoint));
ArrayList<Point> 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;
}
}

1239
designer_form/src/com/fr/design/mainframe/EditingMouseListener.java

File diff suppressed because it is too large Load Diff

239
designer_form/src/com/fr/design/mainframe/FormDesigner.java

@ -6,7 +6,10 @@ import com.fr.design.DesignState;
import com.fr.design.designer.TargetComponent;
import com.fr.design.designer.beans.AdapterBus;
import com.fr.design.designer.beans.Painter;
import com.fr.design.designer.beans.actions.CopyAction;
import com.fr.design.designer.beans.actions.CutAction;
import com.fr.design.designer.beans.actions.FormDeleteAction;
import com.fr.design.designer.beans.actions.PasteAction;
import com.fr.design.designer.beans.adapters.layout.FRParameterLayoutAdapter;
import com.fr.design.designer.beans.events.CreatorEventListenerTable;
import com.fr.design.designer.beans.events.DesignerEditListener;
@ -43,7 +46,6 @@ import com.fr.form.ui.container.WFitLayout;
import com.fr.general.ComparatorUtils;
import com.fr.general.FRLogger;
import com.fr.general.Inter;
import com.fr.plugin.ExtraClassManager;
import com.fr.stable.ArrayUtils;
import com.fr.stable.bridge.StableFactory;
@ -65,11 +67,10 @@ import java.util.List;
/**
* 设计界面组件该组件是界面设计工具的核心主要负责的是被设计界面的显示界面设计操作状态的 显示编辑状态的显示等等
*/
public class FormDesigner extends TargetComponent<Form> implements TreeSelectionListener, InvocationHandler, BaseFormDesigner ,ParaDefinitePane{
public class FormDesigner extends TargetComponent<Form> implements TreeSelectionListener, InvocationHandler, BaseFormDesigner, ParaDefinitePane {
protected static final ArrayList<String> NAME_ARRAY_LIST = new ArrayList<String>(
Arrays.asList(new String[]{Inter.getLocText("M_Edit-Cut"), Inter.getLocText("M_Edit-Copy"), Inter.getLocText("M_Edit-Delete")})
);
private static final int BORDER_WIDTH = 6;
//底层容器的默认大小
protected static final Dimension LARGE_PREFERRED_SIZE = new Dimension(WBorderLayout.DEFAULT_WIDTH, WBorderLayout.DEFAULT_HEIGHT);
private int paraHeight = 0;
@ -81,7 +82,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
private XLayoutContainer paraComponent;
private boolean drawLineMode;
private FormArea formArea;
private ConnectorHelper ConnectorHelper;
private ConnectorHelper connectorHelper;
private boolean isReportBlockEditing = false;
//组件重叠
@ -104,7 +105,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
// 编辑状态的事件表
private CreatorEventListenerTable edit;
protected Action[] designer_actions;
protected Action[] designerActions;
private FormDesignerModeForSpecial<?> desigerMode;
private Action switchAction;
private FormElementCaseContainerProvider elementCaseContainer;
@ -159,7 +160,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
ParameterPropertyPane.getInstance().populateBean(this);
}
public Parameter[] getNoRepeatParas(Parameter[] paras){
public Parameter[] getNoRepeatParas(Parameter[] paras) {
List<Parameter> paraList = new ArrayList<Parameter>();
java.util.Set set = new java.util.HashSet();
for (Parameter p : paras) {
@ -171,23 +172,23 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
return paraList.toArray(new Parameter[paraList.size()]);
}
public void setParameterArray(Parameter[] ps){
public void setParameterArray(Parameter[] ps) {
parameterArray = ps;
}
public Parameter[] getParameterArray(){
public Parameter[] getParameterArray() {
return parameterArray;
}
/**
* 刷新参数
*/
public void refreshParameter(){
public void refreshParameter() {
XLayoutContainer rootContainer = this.getParaComponent();
if (rootContainer != null){
if (rootContainer != null) {
java.util.List<String> namelist = new ArrayList<String>();
rootContainer.getAllXCreatorNameList(rootContainer,namelist);
rootContainer.getAllXCreatorNameList(rootContainer, namelist);
// parameterArray是报表的所有参数, nameList是已经在参数面板添加过控件的参数名
// 与已有的参数列表比较 如果已经存在 就除去
Parameter[] ps = getParameterArray();
@ -201,7 +202,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
EastRegionContainerPane.getInstance().setParameterHeight(ParameterPropertyPane.getInstance(this).getPreferredSize().height);
}
private void removeSame(Parameter[] parameters, List<String> namelist){
private void removeSame(Parameter[] parameters, List<String> namelist) {
for (Parameter parameter : parameters) {
for (String name : namelist) {
if (name.equalsIgnoreCase(parameter.getName())) {
@ -214,20 +215,22 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 是否有查询按钮
* @return 有无查询按钮
*
* @return 有无查询按钮
*/
public boolean isWithQueryButton(){
public boolean isWithQueryButton() {
XLayoutContainer rootContainer = this.getParaComponent();
return rootContainer != null && rootContainer.SearchQueryCreators(rootContainer);
}
/**
* 加入参数到参数面板
*
* @param parameter 参数
* @return 是否加入
*/
public void addingParameter2Editor(Parameter parameter){
if(getParaComponent() == null){
public void addingParameter2Editor(Parameter parameter) {
if (getParaComponent() == null) {
addParaPaneTooltips();
return;
}
@ -242,11 +245,11 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
if (!(this.autoAddComponent(xLabel, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE)
+ FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) {
return ;
return;
}
if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE)
+ SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) {
return ;
return;
}
currentIndex++;
parameterArray = (Parameter[]) ArrayUtils.removeElement(parameterArray, parameter);
@ -256,11 +259,12 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 加入参数到参数面板有查询按钮
*
* @param parameter 参数
* @return 是否加入
*/
public void addingParameter2EditorWithQueryButton(Parameter parameter){
if(getParaComponent() == null){
public void addingParameter2EditorWithQueryButton(Parameter parameter) {
if (getParaComponent() == null) {
addParaPaneTooltips();
return;
}
@ -276,12 +280,12 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
if (!(this.autoAddComponent(xLabel, FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP
* (currentIndex / NUM_IN_A_LINE)))) {
return ;
return;
}
if (!(this.autoAddComponent(xCreator, SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP
* (currentIndex / NUM_IN_A_LINE)))) {
return ;
return;
}
FormSubmitButton formSubmitButton = new FormSubmitButton();
formSubmitButton.setWidgetName("Search");
@ -289,7 +293,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
xCreator = XCreatorUtils.createXCreator(formSubmitButton);
if (!(this.autoAddComponent(xCreator, 270, FIRST_V_LOCATION + V_COMPONENT_GAP
* (currentIndex / NUM_IN_A_LINE)))) {
return ;
return;
}
currentIndex = currentIndex + NUM_IN_A_LINE - currentIndex % NUM_IN_A_LINE;
parameterArray = (Parameter[]) ArrayUtils.removeElement(parameterArray, parameter);
@ -300,8 +304,8 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 一键添加所有参数
*/
public void addingAllParameter2Editor(){
if(getParaComponent() == null){
public void addingAllParameter2Editor() {
if (getParaComponent() == null) {
addParaPaneTooltips();
return;
}
@ -350,16 +354,17 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
EastRegionContainerPane.getInstance().refreshDownPane();
}
private void addParaPaneTooltips(){
JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(),Inter.getLocText("FR-Designer-Form-Please_Drag_ParaPane"),
private void addParaPaneTooltips() {
JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("FR-Designer-Form-Please_Drag_ParaPane"),
Inter.getLocText("FR-Designer_Tooltips"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
}
/**
* 自动添加组件
* @param xCreator 组件
* @param x 横坐标
* @param y 纵坐标
*
* @param xCreator 组件
* @param x 横坐标
* @param y 纵坐标
* @return 是否添加成功
*/
public boolean autoAddComponent(XCreator xCreator, int x, int y) {
@ -375,10 +380,11 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 在参数很多时全部添加的时候可以向下一次排版若去掉就会在参数面板堆到一起
*
* @param creator 组件
* @param x 长度
* @param y 长度
* @param layout 布局
* @param x 长度
* @param y 长度
* @param layout 布局
* @return 是否扩展
*/
public boolean prepareForAdd(XCreator creator, int x, int y, XWParameterLayout layout) {
@ -404,9 +410,9 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 加入参数面板
*/
public void addParaComponent(){
public void addParaComponent() {
if (paraComponent != null) {
return ;
return;
}
paraHeight = WBorderLayout.DEFAULT_SIZE;
paraComponent = new XWParameterLayout();
@ -414,7 +420,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
paraComponent.setSize(paraComponent.initEditorSize());
XWBorderLayout formLayoutContainer = (XWBorderLayout) rootComponent.getParent();
formLayoutContainer.toData().setNorthSize(paraHeight);
formLayoutContainer.add(paraComponent,WBorderLayout.NORTH);
formLayoutContainer.add(paraComponent, WBorderLayout.NORTH);
//设下northSize,增加para后,重置border大小,这时候para和root的大小会自适应调整
formLayoutContainer.setSize(formLayoutContainer.getWidth(), formLayoutContainer.getHeight() + paraHeight);
selectionModel.reset();
@ -424,30 +430,33 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
}
/**
* 返回根节点父容器
* @return 父容器
* 返回根节点父容器
*
* @return 父容器
*/
public Component getTopContainer(){
if(rootComponent != null){
public Component getTopContainer() {
if (rootComponent != null) {
// 返回root所在的父容器,非designer
return LayoutUtils.getTopContainer(rootComponent);
}
return XCreatorUtils.createXCreator(this.getTarget().getContainer());
return XCreatorUtils.createXCreator(this.getTarget().getContainer());
}
/**
* 返回参数界面高度
* @return para高度
*
* @return para高度
*/
public int getParaHeight(){
public int getParaHeight() {
return paraHeight;
}
/**
* 重置para的高度
* @param height 高度
*
* @param height 高度
*/
public void setParaHeight(int height){
public void setParaHeight(int height) {
XWBorderLayout container = (XWBorderLayout) getTopContainer();
container.toData().setNorthSize(height);
container.setSize(container.getWidth(), container.getHeight() + height - getParaHeight());
@ -457,7 +466,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 删除参数界面
*/
public void removeParaComponent(){
public void removeParaComponent() {
XWBorderLayout formLayoutContainer = (XWBorderLayout) getTopContainer();
formLayoutContainer.toData().removeWidget(paraComponent.toData());
paraHeight = 0;
@ -472,41 +481,42 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 切换
* @param elementCaseContainer 容器
*
* @param elementCaseContainer 容器
*/
public void switchTab(FormElementCaseContainerProvider elementCaseContainer){
if(this.switchAction == null){
public void switchTab(FormElementCaseContainerProvider elementCaseContainer) {
if (this.switchAction == null) {
return;
}
this.elementCaseContainer = elementCaseContainer;
this.switchAction.actionPerformed(null);
}
public void setElementCaseContainer(FormElementCaseContainerProvider elementCaseContainer){
public void setElementCaseContainer(FormElementCaseContainerProvider elementCaseContainer) {
this.elementCaseContainer = elementCaseContainer;
}
public FormElementCaseProvider getElementCase(){
public FormElementCaseProvider getElementCase() {
return this.elementCaseContainer.getElementCase();
}
public String getElementCaseContainerName(){
public String getElementCaseContainerName() {
return this.elementCaseContainer.getElementCaseContainerName();
}
public void setElementCase(FormElementCaseProvider elementCase){
public void setElementCase(FormElementCaseProvider elementCase) {
this.elementCaseContainer.setElementCase(elementCase);
}
public void setElementCaseBackground(BufferedImage image){
public void setElementCaseBackground(BufferedImage image) {
this.elementCaseContainer.setBackground(image);
}
public Dimension getElementCaseContainerSize(){
public Dimension getElementCaseContainerSize() {
return this.elementCaseContainer.getSize();
}
public FormElementCaseContainerProvider getElementCaseContainer(){
public FormElementCaseContainerProvider getElementCaseContainer() {
return this.elementCaseContainer;
}
@ -524,6 +534,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 增加监听事件
*
* @param listener 界面组件编辑事件
*/
public void addDesignerEditListener(DesignerEditListener listener) {
@ -539,15 +550,15 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 表单则判断参数面板是否为绝对布局
*
* @return 是则返回true
*/
public boolean hasWAbsoluteLayout() {
if (paraComponent != null && paraComponent.acceptType(XWParameterLayout.class)){
if (paraComponent != null && paraComponent.acceptType(XWParameterLayout.class)) {
return true;
}
else{
} else {
if (this.getSelectionModel().getSelection().getSelectedCreator().getParent() != null
&& ((XLayoutContainer)this.getSelectionModel().getSelection().getSelectedCreator().getParent()).acceptType(XWAbsoluteLayout.class)){
&& ((XLayoutContainer) this.getSelectionModel().getSelection().getSelectedCreator().getParent()).acceptType(XWAbsoluteLayout.class)) {
return true;
}
}
@ -555,7 +566,8 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
}
/**
* 设置是否为报表块编辑
* 设置是否为报表块编辑
*
* @param isEditing 是否为报表块编辑
*/
public void setReportBlockEditing(boolean isEditing) {
@ -564,25 +576,27 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 是否为报表块编辑
*
* @return 是否为报表块编辑
*/
public boolean isReportBlockEditing() {
return this.isReportBlockEditing;
}
public void setWidgetsIntersect(boolean isWidgetsIntersect){
public void setWidgetsIntersect(boolean isWidgetsIntersect) {
this.isWidgetsIntersect = isWidgetsIntersect;
}
public boolean isWidgetsIntersect(){
public boolean isWidgetsIntersect() {
return this.isWidgetsIntersect;
}
/**
* 是否重命名控件
*
* @param creator 组件
* @param newName 新的组件名
* @return 组件名有变化且不和其他一样返回true
* @return 组件名有变化且不和其他一样返回true
*/
public boolean renameCreator(XCreator creator, String newName) {
if (ComparatorUtils.equals(creator.toData().getWidgetName(), newName)) {
@ -609,16 +623,17 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 更新界面布局重绘
* @param proxy 动态代理类
*
* @param proxy 动态代理类
* @param method 接口方法
* @param args 参数
* @param args 参数
* @return 不返回任何对象
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(rootComponent != null){
if (rootComponent != null) {
LayoutUtils.layoutRootContainer(rootComponent);
}
if(paraComponent != null){
if (paraComponent != null) {
LayoutUtils.layoutRootContainer(paraComponent);
}
repaint();
@ -654,6 +669,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 增加组件事件
*
* @param h 动态代理
*/
public void addInvocationHandler(InvocationHandler h) {
@ -678,7 +694,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
}
/**
* 设置其UI类为DesignerUI负责渲染
* 设置其UI类为DesignerUI负责渲染
*/
@Override
public void updateUI() {
@ -741,15 +757,13 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 更新边框线状态
*
* @param e 鼠标事件
*/
public void updateDrawLineMode(MouseEvent e) {
Point p = ConnectorHelper.getNearWidgetPoint(e);
if (p == null) {
XComponent comp = getComponentAt(e);
if (comp == rootComponent) {
p = new Point(e.getX() + formArea.getHorizontalValue(), e.getY() + formArea.getVerticalValue());
}
Point p = connectorHelper.getNearWidgetPoint(e);
if (p == null && getComponentAt(e) == rootComponent) {
p = new Point(e.getX() + formArea.getHorizontalValue(), e.getY() + formArea.getVerticalValue());
}
stateModel.startDrawLine(p);
}
@ -761,7 +775,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
// 撤销恢复操作都会refreshRoot,这时候的target.getContainer里的widget会和之前不一样,所以不用root判断来取
XLayoutContainer formLayoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator(this.getTarget().getContainer());
// 布局默认都是1,底层的border改为0,不然没意义
this.getTarget().getContainer().setMargin(new PaddingMargin(0,0,0,0));
this.getTarget().getContainer().setMargin(new PaddingMargin(0, 0, 0, 0));
formLayoutContainer.setBorder(null);
if (formLayoutContainer.acceptType(XWBorderLayout.class)) {
WBorderLayout borderLayout = (WBorderLayout) formLayoutContainer.toData();
@ -774,7 +788,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
refreshNorth(northWidget, formLayoutContainer);
refreshCenter(centerWidget, formLayoutContainer);
} else {
} else {
formLayoutContainer.setSize(LARGE_PREFERRED_SIZE);
setRootComponent(formLayoutContainer);
}
@ -790,9 +804,9 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
}
XLayoutContainer northContainer = (XLayoutContainer) XCreatorUtils.createXCreator(northWidget);
paraHeight = ((XWBorderLayout)formLayoutContainer).toData().getNorthSize();
paraHeight = ((XWBorderLayout) formLayoutContainer).toData().getNorthSize();
paraComponent = northContainer;
northContainer.setSize(0,paraHeight);
northContainer.setSize(0, paraHeight);
formLayoutContainer.add(northContainer, WBorderLayout.NORTH);
}
@ -841,14 +855,16 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 是否是报表的参数面板
* @return (表单的)
*
* @return (表单的)
*/
public boolean isFormParaDesigner(){
public boolean isFormParaDesigner() {
return false;
}
/**
* 是否为底层容器
* 是否为底层容器
*
* @param comp 组件
* @return 是则返回true
*/
@ -923,10 +939,10 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
}
public SelectionModel getSelectionModel() {
if (paraComponent!=null){
paraComponent.setSize(paraComponent.getWidth(),getParaHeight());
if (paraComponent != null) {
paraComponent.setSize(paraComponent.getWidth(), getParaHeight());
Rectangle rec = rootComponent.getBounds();
rootComponent.setBounds(rec.x,getParaHeight(),rec.width,rec.height);
rootComponent.setBounds(rec.x, getParaHeight(), rec.width, rec.height);
}
return selectionModel;
}
@ -941,6 +957,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 拖拽准备
*
* @param xCreator 组件
*/
public void startDraggingBean(XCreator xCreator) {
@ -953,11 +970,12 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
}
/**
* 拖拽时相关处理
* @param xCreator 组件
* 拖拽时相关处理
*
* @param xCreator 组件
* @param lastPressEvent 鼠标事件
* @param x 坐标x
* @param y 坐标y
* @param x 坐标x
* @param y 坐标y
*/
public void startDraggingComponent(XCreator xCreator, MouseEvent lastPressEvent, int x, int y) {
// 根据所选择的组件的BeanInfo生成相应的AddingModel
@ -978,6 +996,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 改变组件值
*
* @param e 组件选择事件
*/
@Override
@ -1024,6 +1043,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 是否支持权限编辑
*
* @return 是则返回true
*/
public boolean isSupportAuthority() {
@ -1048,7 +1068,8 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
}
/**
* 是否含有action名
* 是否含有action名
*
* @param name action名
* @return 有则返回true
*/
@ -1058,6 +1079,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 显示组件
*
* @param comp 组件
*/
public void makeVisible(XCreator comp) {
@ -1088,16 +1110,16 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 返回复制粘贴删除等动作
* 鼠标右键菜单
*
* @return 同上
*/
public Action[] getActions() {
if (designer_actions == null) {
//先把复制粘贴按钮去掉,只留下删除
// designer_actions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this),
// new FormDeleteAction(this)};
designer_actions = new Action[]{new FormDeleteAction(this)};
if (designerActions == null) {
designerActions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this),
new FormDeleteAction(this)};
}
return designer_actions;
return designerActions;
}
protected Border getOuterBorder() {
@ -1120,6 +1142,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 返回表单区域
*
* @return 表单区域
*/
public FormArea getArea() {
@ -1128,6 +1151,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 设置上层区域
*
* @param formArea 表单区域
*/
public void setParent(FormArea formArea) {
@ -1136,14 +1160,15 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 绘制组件根节点
*
* @param clipg 图形
*/
public void paintContent(Graphics clipg) {
rootComponent.paint(clipg);
}
public void paintPara(Graphics clipg){
if(paraComponent != null){
public void paintPara(Graphics clipg) {
if (paraComponent != null) {
paraComponent.paint(clipg);
}
}
@ -1157,14 +1182,16 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 返回连线类
*
* @return ConnectorHelper类
*/
public ConnectorHelper getDrawLineHelper() {
return ConnectorHelper;
return connectorHelper;
}
/**
* 是否画线模式
* 是否画线模式
*
* @return 是则返回true
*/
public boolean isDrawLineMode() {
@ -1173,6 +1200,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 设置DrawLineMode
*
* @param mode 是or或
*/
public void setDrawLineMode(boolean mode) {
@ -1199,6 +1227,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 返回表单控件权限编辑pane
*
* @return 同上
*/
public AuthorityEditPane createAuthorityEditPane() {
@ -1249,6 +1278,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 粘贴
*
* @return
*/
@Override
@ -1259,6 +1289,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 剪切
*
* @return
*/
@Override
@ -1273,6 +1304,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 工具栏菜单
*
* @return 同上
*/
@Override
@ -1286,6 +1318,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 模版菜单
*
* @return 同上
*/
@Override
@ -1295,6 +1328,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 权限菜单
*
* @return 同上
*/
public ShortCut[] shortCuts4Authority() {
@ -1304,6 +1338,7 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 返回ToolBarDef
*
* @return 同上
*/
@Override
@ -1313,10 +1348,12 @@ public class FormDesigner extends TargetComponent<Form> implements TreeSelection
/**
* 返回工具栏按钮组件
*
* @return 同上
*/
public JComponent[] toolBarButton4Form() {
return new JComponent[0];
return new JComponent[]{new CutAction(this).createToolBarComponent(), new CopyAction(this).createToolBarComponent(), new PasteAction(this).createToolBarComponent(),
new FormDeleteAction(this).createToolBarComponent()};
}

572
designer_form/src/com/fr/design/mainframe/FormSelection.java

@ -20,288 +20,300 @@ import com.fr.design.utils.gui.LayoutUtils;
public class FormSelection {
private ArrayList<XCreator> selection;
private Rectangle backupBounds;
private ArrayList<Rectangle> recs = new ArrayList<Rectangle>();
public FormSelection() {
selection = new ArrayList<XCreator>();
}
/**
* 重置选中的组件
*/
public void reset() {
selection.clear();
}
/**
* 是否没有选中的组件
* @return 为空返回true
*/
public boolean isEmpty() {
return selection.isEmpty();
}
/**
* 选中的组件数量
* @return 选中的组件数量
*/
public int size() {
return selection.size();
}
/**
* 去除选中的组件中指定组件
* @param creator 待去除组件
*/
public void removeCreator(XCreator creator) {
selection.remove(creator);
}
/**
* 是否成功删除选择的组件
* @param comp 组件
* @return 是则返回true
*/
public boolean removeSelectedCreator(XCreator comp) {
if (selection.size() > 1 && selection.contains(comp)) {
removeCreator(comp);
return true;
}
return false;
}
/**
* 成功增加选中的组件
* @param creator 组件
* @return 成功增加返回true
*/
public boolean addSelectedCreator(XCreator creator) {
if (addedable(creator)) {
selection.add(creator);
return true;
}
return false;
}
/**
* 是否是可以增加的
* @param creator 组件
* @return 是则返回true
*/
public boolean addedable(XCreator creator) {
if (selection.isEmpty()) {
return true;
}
XLayoutContainer container = XCreatorUtils.getParentXLayoutContainer(creator);
if (!(container instanceof XWAbsoluteLayout)) {
return false;
}
for (XCreator selected : selection) {
if (selected == creator || XCreatorUtils.getParentXLayoutContainer(selected) != container) {
return false;
}
}
return true;
}
/**
* 返回选中的第一个组件为空返回null
* @return 返回选中组件
*/
public XCreator getSelectedCreator() {
return !selection.isEmpty() ? selection.get(0) : null;
}
/**
* 返回选中的所有组件
* @return 所有组件s
*/
public XCreator[] getSelectedCreators() {
return selection.toArray(new XCreator[selection.size()]);
}
public Widget[] getSelectedWidgets() {
Widget[] selectWidget = new Widget[selection.size()];
for (int i = 0; i < selection.size(); i++) {
selectWidget[i] = selection.get(i).toData();
}
return selectWidget;
}
public void setSelectedCreator(XCreator creator) {
reset();
selection.add(creator);
}
public void setSelectedCreators(ArrayList<XCreator> selections) {
reset();
for (XCreator creator : selections) {
if (addedable(creator)) {
selection.add(creator);
}
}
}
/**
* 是否包含当前控件
* @param widget 控件
* @return 是则返回true
*/
public boolean contains(Widget widget) {
for (XCreator creator : selection) {
if (creator.toData() == widget) {
return true;
}
}
return false;
}
public int[] getDirections() {
if (this.selection.size() > 1) {
return Direction.ALL;
} else if (this.selection.size() == 1) {
return this.selection.get(0).getDirections();
} else {
return new int[0];
}
}
/**
* 备份组件的bound
*/
public void backupBounds() {
backupBounds = getRelativeBounds();
recs.clear();
for (XComponent comp : selection) {
recs.add(comp.getBounds());
}
}
public Rectangle getBackupBounds() {
return backupBounds;
}
public Rectangle getRelativeBounds() {
Rectangle bounds = getSelctionBounds();
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.get(0));
if (parent == null) {
return bounds;
}
Rectangle rec = ComponentUtils.getRelativeBounds(parent);
bounds.x += rec.x;
bounds.y += rec.y;
return bounds;
}
public Rectangle getSelctionBounds() {
if(selection.isEmpty()) {
return new Rectangle();
}
Rectangle bounds = selection.get(0).getBounds();
for (int i = 1, len = selection.size(); i < len; i++) {
bounds = bounds.union(selection.get(i).getBounds());
}
return bounds;
}
public void setSelectionBounds(Rectangle rec, FormDesigner designer) {
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.get(0));
Rectangle backupBounds = new Rectangle(this.backupBounds);
if (parent != null) {
Rectangle r = ComponentUtils.getRelativeBounds(parent);
rec.x -= r.x;
rec.y -= r.y;
backupBounds.x -= r.x;
backupBounds.y -= r.y;
}
int size = selection.size();
if (size == 1) {
XCreator creator = selection.get(0);
creator.setBounds(rec);
if(creator.acceptType(XWParameterLayout.class)){
designer.setParaHeight((int)rec.getHeight());
private ArrayList<XCreator> selection;
private Rectangle backupBounds;
private ArrayList<Rectangle> recs = new ArrayList<Rectangle>();
public FormSelection() {
selection = new ArrayList<XCreator>();
}
/**
* 重置选中的组件
*/
public void reset() {
selection.clear();
}
/**
* 是否没有选中的组件
*
* @return 为空返回true
*/
public boolean isEmpty() {
return selection.isEmpty();
}
/**
* 选中的组件数量
*
* @return 选中的组件数量
*/
public int size() {
return selection.size();
}
/**
* 去除选中的组件中指定组件
*
* @param creator 待去除组件
*/
public void removeCreator(XCreator creator) {
selection.remove(creator);
}
/**
* 是否成功删除选择的组件
*
* @param comp 组件
* @return 是则返回true
*/
public boolean removeSelectedCreator(XCreator comp) {
if (selection.size() > 1 && selection.contains(comp)) {
removeCreator(comp);
return true;
}
return false;
}
/**
* 成功增加选中的组件
*
* @param creator 组件
* @return 成功增加返回true
*/
public boolean addSelectedCreator(XCreator creator) {
if (addedable(creator)) {
selection.add(creator);
return true;
}
return false;
}
/**
* 是否是可以增加的
*
* @param creator 组件
* @return 是则返回true
*/
public boolean addedable(XCreator creator) {
if (selection.isEmpty()) {
return true;
}
XLayoutContainer container = XCreatorUtils.getParentXLayoutContainer(creator);
if (!(container instanceof XWAbsoluteLayout)) {
return false;
}
for (XCreator selected : selection) {
if (selected == creator || XCreatorUtils.getParentXLayoutContainer(selected) != container) {
return false;
}
}
return true;
}
/**
* 返回选中的第一个组件为空返回null
*
* @return 返回选中组件
*/
public XCreator getSelectedCreator() {
return !selection.isEmpty() ? selection.get(0) : null;
}
/**
* 返回选中的所有组件
*
* @return 所有组件s
*/
public XCreator[] getSelectedCreators() {
return selection.toArray(new XCreator[selection.size()]);
}
public Widget[] getSelectedWidgets() {
Widget[] selectWidget = new Widget[selection.size()];
for (int i = 0; i < selection.size(); i++) {
selectWidget[i] = selection.get(i).toData();
}
return selectWidget;
}
public void setSelectedCreator(XCreator creator) {
reset();
selection.add(creator);
}
public void setSelectedCreators(ArrayList<XCreator> selections) {
reset();
for (XCreator creator : selections) {
if (addedable(creator)) {
selection.add(creator);
}
}
}
/**
* 是否包含当前控件
*
* @param widget 控件
* @return 是则返回true
*/
public boolean contains(Widget widget) {
for (XCreator creator : selection) {
if (creator.toData() == widget) {
return true;
}
}
return false;
}
public int[] getDirections() {
if (this.selection.size() > 1) {
return Direction.ALL;
} else if (this.selection.size() == 1) {
return this.selection.get(0).getDirections();
} else {
return new int[0];
}
}
/**
* 备份组件的bound
*/
public void backupBounds() {
backupBounds = getRelativeBounds();
recs.clear();
for (XComponent comp : selection) {
recs.add(comp.getBounds());
}
}
public Rectangle getBackupBounds() {
return backupBounds;
}
public Rectangle getRelativeBounds() {
Rectangle bounds = getSelctionBounds();
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.get(0));
if (parent == null) {
return bounds;
}
Rectangle rec = ComponentUtils.getRelativeBounds(parent);
bounds.x += rec.x;
bounds.y += rec.y;
return bounds;
}
public Rectangle getSelctionBounds() {
if (selection.isEmpty()) {
return new Rectangle();
}
Rectangle bounds = selection.get(0).getBounds();
for (int i = 1, len = selection.size(); i < len; i++) {
bounds = bounds.union(selection.get(i).getBounds());
}
return bounds;
}
public void setSelectionBounds(Rectangle rec, FormDesigner designer) {
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(selection.get(0));
Rectangle backupBounds = new Rectangle(this.backupBounds);
if (parent != null) {
Rectangle r = ComponentUtils.getRelativeBounds(parent);
rec.x -= r.x;
rec.y -= r.y;
backupBounds.x -= r.x;
backupBounds.y -= r.y;
}
int size = selection.size();
if (size == 1) {
XCreator creator = selection.get(0);
creator.setBounds(rec);
if (creator.acceptType(XWParameterLayout.class)) {
designer.setParaHeight((int) rec.getHeight());
designer.getArea().doLayout();
}
LayoutUtils.layoutContainer(creator);
} else if (size > 1) {
for (int i = 0; i < selection.size(); i++) {
Rectangle newBounds = new Rectangle(recs.get(i));
newBounds.x = rec.x + (newBounds.x - backupBounds.x) * rec.width / backupBounds.width;
newBounds.y = rec.y + (newBounds.y - backupBounds.y) * rec.height / backupBounds.height;
newBounds.width = rec.width * newBounds.width / backupBounds.width;
newBounds.height = rec.height * newBounds.height / backupBounds.height;
XCreator creator = selection.get(i);
creator.setBounds(newBounds);
if(creator.acceptType(XWParameterLayout.class)){
designer.setParaHeight((int)rec.getHeight());
LayoutUtils.layoutContainer(creator);
} else if (size > 1) {
for (int i = 0; i < selection.size(); i++) {
Rectangle newBounds = new Rectangle(recs.get(i));
newBounds.x = rec.x + (newBounds.x - backupBounds.x) * rec.width / backupBounds.width;
newBounds.y = rec.y + (newBounds.y - backupBounds.y) * rec.height / backupBounds.height;
newBounds.width = rec.width * newBounds.width / backupBounds.width;
newBounds.height = rec.height * newBounds.height / backupBounds.height;
XCreator creator = selection.get(i);
creator.setBounds(newBounds);
if (creator.acceptType(XWParameterLayout.class)) {
designer.setParaHeight((int) rec.getHeight());
designer.getArea().doLayout();
}
}
LayoutUtils.layoutRootContainer(designer.getRootComponent());
}
}
/**
* 调整组件大小
* @param designer 设计界面组件
*/
public void fixCreator(FormDesigner designer) {
for (XCreator creator : selection) {
LayoutAdapter layoutAdapter = AdapterBus.searchLayoutAdapter(designer, creator);
if (layoutAdapter != null) {
creator.setBackupBound(backupBounds);
layoutAdapter.fix(creator);
}
}
}
private void removeCreatorFromContainer(XCreator creator) {
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator);
if (parent == null) {
return;
}
// 删除其根组件,同时就删除了同时被选择的叶子组件
parent.remove(creator);
LayoutManager layout = parent.getLayout();
if (layout != null) {
// 刷新组件容器的布局
LayoutUtils.layoutContainer(parent);
}
}
/**
* 剪切选中的所有组件
* @param clipBoard 剪切板
*/
public void cut2ClipBoard(FormSelection clipBoard) {
clipBoard.reset();
clipBoard.selection.addAll(selection);
for (XCreator creator : selection) {
removeCreatorFromContainer(creator);
}
reset();
}
/**
* 复制选中的所有组件
* @param clipBoard 复制板
*/
public void copy2ClipBoard(FormSelection clipBoard) {
clipBoard.reset();
for (XCreator root : selection) {
try {
XCreator creator = XCreatorUtils.createXCreator((Widget) root.toData().clone());
creator.setBounds(root.getBounds());
clipBoard.selection.add(creator);
} catch (CloneNotSupportedException e) {
FRContext.getLogger().error(e.getMessage(), e);
}
}
}
}
LayoutUtils.layoutRootContainer(designer.getRootComponent());
}
}
/**
* 调整组件大小
*
* @param designer 设计界面组件
*/
public void fixCreator(FormDesigner designer) {
for (XCreator creator : selection) {
LayoutAdapter layoutAdapter = AdapterBus.searchLayoutAdapter(designer, creator);
if (layoutAdapter != null) {
creator.setBackupBound(backupBounds);
layoutAdapter.fix(creator);
}
}
}
private void removeCreatorFromContainer(XCreator creator) {
XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator);
if (parent == null) {
return;
}
// 删除其根组件,同时就删除了同时被选择的叶子组件
parent.remove(creator);
LayoutManager layout = parent.getLayout();
if (layout != null) {
// 刷新组件容器的布局
LayoutUtils.layoutContainer(parent);
}
}
/**
* 剪切选中的所有组件
*
* @param clipBoard 剪切板
*/
public void cut2ClipBoard(FormSelection clipBoard) {
clipBoard.reset();
clipBoard.selection.addAll(selection);
for (XCreator creator : selection) {
removeCreatorFromContainer(creator);
}
reset();
}
/**
* 复制选中的所有组件
*
* @param clipBoard 复制板
*/
public void copy2ClipBoard(FormSelection clipBoard) {
clipBoard.reset();
for (XCreator root : selection) {
try {
XCreator creator = XCreatorUtils.createXCreator((Widget) root.toData().clone());
creator.setBounds(root.getBounds());
clipBoard.selection.add(creator);
} catch (CloneNotSupportedException e) {
FRContext.getLogger().error(e.getMessage(), e);
}
}
}
}

394
designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java

@ -1,126 +1,270 @@
package com.fr.design.mainframe;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.fr.base.FRContext;
import com.fr.general.ComparatorUtils;
import com.fr.design.designer.beans.LayoutAdapter;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWAbsoluteLayout;
import com.fr.form.main.ClonedWidgetCreator;
import com.fr.form.ui.Widget;
public class FormSelectionUtils {
public static void paste2Container(FormDesigner designer, XLayoutContainer parent, FormSelection selection, int x,
int y) {
LayoutAdapter adapter = parent.getLayoutAdapter();
if (selection.size() == 1) {
try {
XCreator creator = selection.getSelectedCreator();
Widget cloned = new ClonedWidgetCreator(designer.getTarget()).clonedWidgetWithNoRepeatName(creator
.toData());
XCreator clondCreator = XCreatorUtils.createXCreator(cloned, creator.getSize());
if (adapter.addBean(clondCreator, x + clondCreator.getWidth() / 2, y + clondCreator.getHeight() / 2)) {
designer.getSelectionModel().getSelection().setSelectedCreator(clondCreator);
designer.getEditListenerTable().fireCreatorModified(clondCreator, DesignerEvent.CREATOR_PASTED);
return;
}
} catch (CloneNotSupportedException e) {
FRContext.getLogger().error(e.getMessage(), e);
}
} else if (selection.size() > 1) {
if (parent instanceof XWAbsoluteLayout) {
designer.getSelectionModel().getSelection().reset();
Rectangle rec = selection.getSelctionBounds();
for (XCreator creator : selection.getSelectedCreators()) {
try {
Widget cloned = new ClonedWidgetCreator(designer.getTarget())
.clonedWidgetWithNoRepeatName(creator.toData());
XCreator clondCreator = XCreatorUtils.createXCreator(cloned, creator.getSize());
// 设置位置,移动20x20,防止被粘帖的组件重叠,照顾表单布局情况下
adapter.addBean(clondCreator, x + creator.getX() - rec.x + clondCreator.getWidth() / 2, y
+ creator.getY() - rec.y + clondCreator.getHeight() / 2);
designer.getSelectionModel().getSelection().addSelectedCreator(clondCreator);
} catch (CloneNotSupportedException e) {
FRContext.getLogger().error(e.getMessage(), e);
}
}
designer.getEditListenerTable().fireCreatorModified(
designer.getSelectionModel().getSelection().getSelectedCreator(), DesignerEvent.CREATOR_PASTED);
return;
}
}
Toolkit.getDefaultToolkit().beep();
}
public static void rebuildSelection(FormDesigner designer) {
ArrayList<XCreator> newSelection = new ArrayList<XCreator>();
List<Widget> widgetList = new ArrayList<Widget>();
for (XCreator comp : designer.getSelectionModel().getSelection().getSelectedCreators()) {
widgetList.add(comp.toData());
}
designer.getSelectionModel().setSelectedCreators(
rebuildSelection(designer.getRootComponent(), widgetList, newSelection));
}
public static ArrayList<XCreator> rebuildSelection(XCreator rootComponent, Widget[] selectWidgets) {
List<Widget> selectionWidget = new ArrayList<Widget>();
if(selectWidgets != null){
selectionWidget.addAll(Arrays.asList(selectWidgets));
}
return FormSelectionUtils.rebuildSelection(rootComponent, selectionWidget, new ArrayList<XCreator>());
}
private static ArrayList<XCreator> rebuildSelection(XCreator rootComponent, List<Widget> selectionWidget,
ArrayList<XCreator> newSelection) {
FormSelectionUtils._rebuild(rootComponent, selectionWidget, newSelection);
if (newSelection.isEmpty()) {
newSelection.add(rootComponent);
}
return newSelection;
}
private static void _rebuild(XCreator root, List<Widget> selectionWidget, List<XCreator> newSelection) {
if (selectionWidget.isEmpty()) {
return;
}
for (Widget x : selectionWidget) {
if (ComparatorUtils.equals(x, root.toData())) {
if (!newSelection.contains(root)) {
newSelection.add(root);
selectionWidget.remove(x);
}
break;
}
}
int count = root.getComponentCount();
for (int i = 0; i < count && !selectionWidget.isEmpty(); i++) {
Component c = root.getComponent(i);
if (c instanceof XCreator) {
XCreator creator = (XCreator) c;
for (Widget x : selectionWidget) {
if (ComparatorUtils.equals(x, creator.toData())) {
newSelection.add(creator);
selectionWidget.remove(x);
break;
}
}
if (c instanceof XLayoutContainer) {
_rebuild((XLayoutContainer) c, selectionWidget, newSelection);
} else {
continue;
}
}
}
}
package com.fr.design.mainframe;
import com.fr.base.FRContext;
import com.fr.design.designer.beans.LayoutAdapter;
import com.fr.design.designer.beans.adapters.layout.AbstractLayoutAdapter;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.creator.*;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WTitleLayout;
import com.fr.general.ComparatorUtils;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FormSelectionUtils {
//组件复制时坐标偏移
private static final int DELAY_X = 20;
private static final int DELAY_Y = 20;
//组件复制时是否已经向左上偏移
private static boolean backoffset = false;
//组件重命名后缀
private static final String POSTFIX = "_c";
private FormSelectionUtils() {
}
/**
* @param designer 编辑器
* @param parent 粘贴依据的组件
* @param clipboard 剪贴板内容
* @param x x
* @param y y
*/
public static void paste2Container(FormDesigner designer, XLayoutContainer parent,
FormSelection clipboard, int x, int y) {
LayoutAdapter adapter = parent.getLayoutAdapter();
if (parent instanceof XWAbsoluteLayout) {
//绝对布局
absolutePaste(designer, clipboard, adapter, x, y);
return;
} else if (parent instanceof XWFitLayout) {
//相对布局
relativePaste(designer, clipboard, adapter, x, y);
return;
}
Toolkit.getDefaultToolkit().beep();
}
/**
* 绝对布局粘贴
*
* @param designer
* @param clipboard
* @param adapter
* @param x
* @param y
*/
private static void absolutePaste(FormDesigner designer, FormSelection clipboard, LayoutAdapter adapter, int x, int y) {
designer.getSelectionModel().getSelection().reset();
Rectangle rec = clipboard.getSelctionBounds();
for (XCreator creator : clipboard.getSelectedCreators()) {
try {
Widget copied = copyWidget(designer, creator);
XCreator copiedCreator = XCreatorUtils.createXCreator(copied, creator.getSize());
// 获取位置
Point point = getPasteLocation((AbstractLayoutAdapter) adapter,
copiedCreator,
x + creator.getX() - rec.x + copiedCreator.getWidth() / 2,
y + creator.getY() - rec.y + copiedCreator.getHeight() / 2);
boolean addSuccess = adapter.addBean(copiedCreator, point.x, point.y);
if (addSuccess) {
designer.getSelectionModel().getSelection().addSelectedCreator(copiedCreator);
}
} catch (CloneNotSupportedException e) {
FRContext.getLogger().error(e.getMessage(), e);
}
}
rebuildSelection(designer);
designer.getEditListenerTable().fireCreatorModified(
designer.getSelectionModel().getSelection().getSelectedCreator(), DesignerEvent.CREATOR_PASTED);
}
/**
* 相对布局粘贴
*
* @param designer
* @param clipboard
* @param adapter
* @param x
* @param y
*/
private static void relativePaste(FormDesigner designer, FormSelection clipboard, LayoutAdapter adapter, int x, int y) {
designer.getSelectionModel().getSelection().reset();
for (XCreator creator : clipboard.getSelectedCreators()) {
try {
Widget copied = copyWidget(designer, creator);
XCreator copiedCreator = XCreatorUtils.createXCreator(copied, creator.getSize());
boolean addSuccess = adapter.addBean(copiedCreator, x, y);
if (addSuccess) {
designer.getSelectionModel().getSelection().addSelectedCreator(copiedCreator);
}
} catch (CloneNotSupportedException e) {
FRContext.getLogger().error(e.getMessage(), e);
}
}
rebuildSelection(designer);
designer.getEditListenerTable().fireCreatorModified(
designer.getSelectionModel().getSelection().getSelectedCreator(), DesignerEvent.CREATOR_PASTED);
}
/**
* 组件复用绝对布局获取粘贴组件位置
*
* @param layoutAdapter 绝对布局容器AbstractLayoutAdapter
* @param copiedCreator 复制的组件
* @param x x=组件x + clonedCreator.getWidth() / 2
* @param y y=组件y + clonedCreator.getHeight() / 2
* 除2的步骤会导致当宽度或者高度为奇数是中心点向左上各偏移一个像素
* 由于中心点向左上各偏移一个像素依赖中心点计算的右下点就会相应的想做上偏移一个像素导致结果不准确
* @return 新位置坐标
*/
private static Point getPasteLocation(AbstractLayoutAdapter layoutAdapter, XCreator copiedCreator, int x, int y) {
//当宽度为奇数时 设置偏移
int xoffset = (copiedCreator.getWidth() & 1) == 1 ? 1 : 0;
//当高度为奇数时 设置偏移
int yoffset = (copiedCreator.getHeight() & 1) == 1 ? 1 : 0;
if (!layoutAdapter.accept(copiedCreator, x, y)) {
XLayoutContainer container = layoutAdapter.getContainer();
boolean xOut = x < 0 || x + copiedCreator.getWidth() / 2 + xoffset > container.getWidth();
boolean yOut = y < 0 || y + copiedCreator.getHeight() / 2 + yoffset > container.getHeight();
/*
* 组件原始位置位于布局的右下角
* 和布局右下边界线紧挨
* 粘贴时组件在原始位置向左错开20像素
* x,y同时越界
*/
if (xOut && yOut) {
x = backoffset ? container.getWidth() - copiedCreator.getWidth() / 2 - xoffset
: container.getWidth() - copiedCreator.getWidth() / 2 - DELAY_X - xoffset;
y = backoffset ?
container.getHeight() - copiedCreator.getHeight() / 2 - yoffset
: container.getHeight() - copiedCreator.getHeight() / 2 - DELAY_Y - yoffset;
backoffset = !backoffset;
return new Point(x, y);
}
/*
* 组件原始位置与布局边界距离小于20像素下边界&右边界同时小于或者任意一个边界小于
* 则粘贴时距离小于20像素一侧直接贴近布局边界
* 距离大于20像素的一侧正常错开
* x,y中只有一个越界
*/
else if ((xOut || yOut)) {
x = xOut ? container.getWidth() - copiedCreator.getWidth() / 2 - xoffset : x;
y = yOut ? container.getHeight() - copiedCreator.getHeight() / 2 - yoffset : y;
return new Point(x, y);
}
}
return new Point(x, y);
}
/**
* 拷贝组件
*
* @param formDesigner
* @param xCreator
* @return
* @throws CloneNotSupportedException
*/
private static Widget copyWidget(FormDesigner formDesigner, XCreator xCreator) throws
CloneNotSupportedException {
ArrayList<String> nameSpace = new ArrayList<String>();
Widget copied = (Widget) xCreator.toData().clone();
//重命名拷贝的组件
String name = getCopiedName(formDesigner, copied, nameSpace);
if (copied instanceof WTitleLayout) {
XWTitleLayout xwTitleLayout = new XWTitleLayout((WTitleLayout) copied, xCreator.getSize());
xwTitleLayout.resetCreatorName(name);
} else {
copied.setWidgetName(name);
}
return copied;
}
/**
* 组件拷贝命名规则
*
* @param formDesigner
* @param copied
* @param nameSpace
* @return name
*/
private static String getCopiedName(FormDesigner formDesigner, Widget copied, ArrayList<String> nameSpace) {
StringBuffer name = new StringBuffer(copied.getWidgetName());
do {
name.append(POSTFIX);
} while (formDesigner.getTarget().isNameExist(name.toString()) || nameSpace.contains(name.toString()));
nameSpace.add(name.toString());
return name.toString();
}
public static void rebuildSelection(FormDesigner designer) {
ArrayList<XCreator> newSelection = new ArrayList<XCreator>();
List<Widget> widgetList = new ArrayList<Widget>();
for (XCreator comp : designer.getSelectionModel().getSelection().getSelectedCreators()) {
widgetList.add(comp.toData());
}
designer.getSelectionModel().setSelectedCreators(
rebuildSelection(designer.getRootComponent(), widgetList, newSelection));
}
public static ArrayList<XCreator> rebuildSelection(XCreator rootComponent, Widget[] selectWidgets) {
List<Widget> selectionWidget = new ArrayList<Widget>();
if (selectWidgets != null) {
selectionWidget.addAll(Arrays.asList(selectWidgets));
}
return FormSelectionUtils.rebuildSelection(rootComponent, selectionWidget, new ArrayList<XCreator>());
}
private static ArrayList<XCreator> rebuildSelection(XCreator rootComponent, List<Widget> selectionWidget,
ArrayList<XCreator> newSelection) {
FormSelectionUtils.rebuild(rootComponent, selectionWidget, newSelection);
if (newSelection.isEmpty()) {
newSelection.add(rootComponent);
}
return newSelection;
}
private static void rebuild(XCreator root, List<Widget> selectionWidget, List<XCreator> newSelection) {
if (selectionWidget.isEmpty()) {
return;
}
for (Widget x : selectionWidget) {
if (ComparatorUtils.equals(x, root.toData())) {
if (!newSelection.contains(root)) {
newSelection.add(root);
selectionWidget.remove(x);
}
break;
}
}
int count = root.getComponentCount();
for (int i = 0; i < count && !selectionWidget.isEmpty(); i++) {
Component c = root.getComponent(i);
if (c instanceof XCreator) {
XCreator creator = (XCreator) c;
for (Widget x : selectionWidget) {
if (ComparatorUtils.equals(x, creator.toData())) {
newSelection.add(creator);
selectionWidget.remove(x);
break;
}
}
if (c instanceof XLayoutContainer) {
rebuild((XLayoutContainer) c, selectionWidget, newSelection);
}
}
}
}
}

1589
designer_form/src/com/fr/design/mainframe/JForm.java

File diff suppressed because it is too large Load Diff

692
designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java

@ -1,346 +1,348 @@
package com.fr.design.mainframe;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.*;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itable.GroupRenderer;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.*;
import com.fr.general.ComparatorUtils;
import com.fr.general.Inter;
import com.fr.stable.StringUtils;
/**
* MobileWidgetTable类主要显示各种容器的控件列表bodytab绝对布局快不包括参数面板
* Created with IntelliJ IDEA.
* User: zx
* Date: 14-9-15
* Time: 下午4:52
* Modified by fanglei at 2017/01/23
*/
public class MobileWidgetTable extends JTable {
private FormDesigner designer;
private String[][] cellData;
private String[] headers = {Inter.getLocText("Form-Widget_Name")};
private static final int WIDGET_TABLE_ROW_HEIGHT = 22;
private UILabel moveComponent = new UILabel(); // 作为拖动时候随鼠标移动的那个半透明控件
private int selectedRow = -1;
private int GAP = 11;
private boolean draging = false;
private boolean collapsed = false; // 控件列表是否折叠
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
//第一行渲染成为标题的样子
if (row == 0) {
return new GroupRenderer();
}
return super.getCellRenderer(row, column);
}
public MobileWidgetTable(FormDesigner designer) {
this.designer = designer;
cellData = getData();
this.setTableProperties();
TableModel defaultModel = new BeanTableModel();
this.setModel(defaultModel);
this.repaint();
this.setDefaultRenderer(Object.class,new DefaultTableCellRenderer());
refreshData();
this.addMouseListener(mouseAdapter);
this.addMouseMotionListener(mouseAdapter);
add(moveComponent);
}
private void setTableProperties() {
JTableHeader header = getTableHeader();
header.setReorderingAllowed(false);
header.setPreferredSize(new Dimension(0, 0)); // 隐藏表头
GroupRenderer headerRenderer = new GroupRenderer();
headerRenderer.setPreferredSize(new Dimension(0, 0)); //这行代码隐藏表头。因为要实现折叠效果,表头不好监听事件
headerRenderer.setHorizontalAlignment(JLabel.LEFT);
header.setDefaultRenderer(headerRenderer);
this.setRowHeight(WIDGET_TABLE_ROW_HEIGHT);
this.setGridColor(new Color(212, 208, 200));
this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
this.setColumnSelectionAllowed(false);
this.setRowSelectionAllowed(false);
this.setFillsViewportHeight(false);
this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
}
private MouseAdapter mouseAdapter = new MouseAdapter() {
/**
* 鼠标按下时处理的事件设置当前选中的行列
* @param e
*/
@Override
public void mousePressed(MouseEvent e) {
getInstance().setCellSelected();
if (selectedRow == 0 && !e.isPopupTrigger() && e.getClickCount() == 1 && e.getX() < WIDGET_TABLE_ROW_HEIGHT / 2){ // 如果是点击在第一行
toggleCollapse();
}
}
/**
* 鼠标放开时处理的事件如果是正在拖动则执行换位操作重新绘制属性表如果不是则什么也不做
* 所谓的换行就是简单的重新拿到一次表格数据然后重新绘制表格
* @param e
*/
@Override
public void mouseReleased(MouseEvent e) {
if(!draging){
return;
}
draging = false;
moveComponent.setVisible(false);
int toIndex = e.getY() < GAP ? 0 : (int)Math.rint((e.getY() - GAP)/WIDGET_TABLE_ROW_HEIGHT) + 1;
//当鼠标放开时,将选中的容器调整至新的顺序
((WSortLayout)designer.getSelectionModel().getSelection().getSelectedCreator().toData()).adjustOrder(selectedRow - 1, toIndex - 1);
//拿取排序后表格数据,然后重绘表格
getInstance().refreshData();
getInstance().repaint();
designer.fireTargetModified();
getInstance().setCellSelected();
}
/**
* 设置鼠标在属性表区域移动时候的事件
* @param e
*/
@Override
public void mouseMoved(MouseEvent e) {
int overRow = 0;
for (int i = 0;i < getRowCount();i++) {
if (e.getY() > i * WIDGET_TABLE_ROW_HEIGHT && e.getY() <= (i + 1) * WIDGET_TABLE_ROW_HEIGHT){
overRow = i; //判断鼠标在哪一行
}
}
//如果鼠标移动到当前选中的行上面的时候
if (overRow == selectedRow && selectedRow > 0) {
//把当前选中的那一行的光标改成(除了第一列)移动样式MOVE_CURSOR
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
} else {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
/**
* 鼠标拖动事件如果鼠标当前是<code>MOVE_CURSOR</code>状态则执行开始拖动的代码
* 绘制一个<code>moveComponent</code>来跟随鼠标移动
* @param e
*/
@Override
public void mouseDragged(MouseEvent e) {
int width = getColumnModel().getColumn(0).getWidth();
//如果当前选中的行的范围是合理的话,就可以拖动
if (selectedRow < getRowCount() && selectedRow > 0){
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
draging = true;
moveComponent.setText(getValueAt(selectedRow,0).toString());
moveComponent.setLocation(0, e.getY() - GAP);
moveComponent.setSize(new Dimension(width, WIDGET_TABLE_ROW_HEIGHT));
moveComponent.setVisible(true);
moveComponent.setForeground(Color.lightGray);
moveComponent.setBorder(BorderFactory.createLineBorder(Color.lightGray));
}
}
/**
* 设置鼠标单击时处理的事件单击控件列表进入控件属性表
* @param e
*/
@Override
public void mouseClicked(MouseEvent e) {
if(selectedRow > 0){
//当前点击的控件的名字
String widgetName = cellData[selectedRow][0];
if (StringUtils.isNotEmpty(widgetName)){
//当前选择的容器
XCreator selectedContainer = designer.getSelectionModel().getSelection().getSelectedCreator();
WLayout selectedWidget = (WLayout)selectedContainer.toData();
//当前选择的容器中的控件数量
int count = selectedWidget.getWidgetCount();
for (int i = 0;i < count ;i++){
XCreator xCreator = (XCreator) selectedContainer.getComponent(i);
Widget widget = xCreator.toData();
if (ComparatorUtils.equals(widgetName, widget.getWidgetName())) {
getEditingDesigner().getSelectionModel().setSelectedCreator(xCreator);
}
}
}
} else if (selectedRow == 0){ // 如果是点击在第一行
if (!e.isPopupTrigger() && e.getClickCount() > 1) {
toggleCollapse();
}
}
}
/**
* 鼠标离开属性表区域事件
* @param e
*/
public void mouseExited(MouseEvent e) {
draging = false;
moveComponent.setVisible(false);
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
};
public MobileWidgetTable getInstance(){
return this;
}
public FormDesigner getEditingDesigner(){
return designer;
}
/**
* 设置当前get到的行列的单元格为选中状态
*/
private void setCellSelected() {
selectedRow = getSelectedRow();
if (selectedRow != -1) {
this.setRowSelectionInterval(selectedRow, selectedRow);
this.setColumnSelectionInterval(0, 0);
}
}
/**
* 切换属性组折叠属性true/false
*/
private void toggleCollapse() {
this.setCollapsed(!this.isCollapsed());
//这里获取表格的父控件是为了当表格被折叠了后,装表格的父控件也要相应的重新布局一下
//比如折叠之后表格行数应该比原来的少,占用父容器空间应该小点,不重新布局父容器,表格大小不会改变
Container parent = MobileWidgetTable.this.getParent();
if (parent != null) {
parent.revalidate();
}
repaint();
}
/**
* 重新get排序后的数据
*/
public void refreshData(){
cellData = getData();
}
/**
* 获取选中控件的控件列表
*
* @return String[][] 二维数组[0][0]widgetName
*/
private String[][] getData(){
if(designer.isFormParaDesigner()){
return new String[0][0];
}
//选择的控件
Widget selectedModel = designer.getSelectionModel().getSelection().getSelectedCreator().toData();
if(selectedModel == null){
return new String[0][0];
}
// 选择的控件有两种类型,一种是WLayout,代表容器,一种是Widget,代表控件
if (selectedModel.acceptType(WSortLayout.class)) {
List<String> mobileWidgetList = ((WSortLayout)selectedModel).getOrderedMobileWidgetList();
String[][] widgetName = new String[mobileWidgetList.size() + 1][1];
widgetName[0][0] = Inter.getLocText("FR-Designer_WidgetOrder");
for (int i = 0; i < mobileWidgetList.size(); i++) {
widgetName[i + 1][0] = mobileWidgetList.get(i);
}
return widgetName;
} else {
return new String[0][0];
}
}
public boolean isCollapsed() {
return collapsed;
}
public void setCollapsed(boolean collapsed) {
this.collapsed = collapsed;
}
/**
* 自定义的tableEditor类
*/
public class BeanTableModel extends DefaultTableModel {
public BeanTableModel() {
super(cellData,headers);
}
@Override
public int getRowCount() {
if (isCollapsed()) {
return 1;
}
return cellData.length;
}
@Override
public int getColumnCount() {
return 1;
}
@Override
public Object getValueAt(int row, int column) {
if (row >= getRowCount() || column >= getColumnCount()) {
return null;
}
if (row == 0) {
return (isCollapsed()? "+" : "-") + cellData[row][0];
}
return cellData[row][0];
}
@Override
public String getColumnName(int column) {
return headers[0];
}
@Override
public void setValueAt(Object aValue, int row, int column) {
if (row >= getRowCount() || column >= getColumnCount()) {
return;
}
if (aValue == null) {
cellData[row] = null;
return;
}
cellData[row][0] = aValue.toString();
}
/**
* 是否可编辑
* @param row 行号
* @param column 列号
* @return 是否可编辑
*/
public boolean isCellEditable(int row, int column) {
return false;
}
}
package com.fr.design.mainframe;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.*;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itable.GroupRenderer;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.*;
import com.fr.general.ComparatorUtils;
import com.fr.general.Inter;
import com.fr.stable.StringUtils;
/**
* MobileWidgetTable类主要显示各种容器的控件列表bodytab绝对布局快不包括参数面板
* Created with IntelliJ IDEA.
* User: zx
* Date: 14-9-15
* Time: 下午4:52
* Modified by fanglei at 2017/01/23
*/
public class MobileWidgetTable extends JTable {
private FormDesigner designer;
private String[][] cellData;
private String[] headers = {Inter.getLocText("Form-Widget_Name")};
private static final int WIDGET_TABLE_ROW_HEIGHT = 22;
private UILabel moveComponent = new UILabel(); // 作为拖动时候随鼠标移动的那个半透明控件
private int selectedRow = -1;
private static final int GAP = 11;
private boolean draging = false;
private boolean collapsed = false; // 控件列表是否折叠
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
//第一行渲染成为标题的样子
if (row == 0) {
return new GroupRenderer();
}
return super.getCellRenderer(row, column);
}
public MobileWidgetTable(FormDesigner designer) {
this.designer = designer;
cellData = getData();
this.setTableProperties();
TableModel defaultModel = new BeanTableModel();
this.setModel(defaultModel);
this.repaint();
this.setDefaultRenderer(Object.class, new DefaultTableCellRenderer());
refreshData();
this.addMouseListener(mouseAdapter);
this.addMouseMotionListener(mouseAdapter);
add(moveComponent);
}
private void setTableProperties() {
JTableHeader header = getTableHeader();
header.setReorderingAllowed(false);
header.setPreferredSize(new Dimension(0, 0)); // 隐藏表头
GroupRenderer headerRenderer = new GroupRenderer();
headerRenderer.setPreferredSize(new Dimension(0, 0)); //这行代码隐藏表头。因为要实现折叠效果,表头不好监听事件
headerRenderer.setHorizontalAlignment(JLabel.LEFT);
header.setDefaultRenderer(headerRenderer);
this.setRowHeight(WIDGET_TABLE_ROW_HEIGHT);
this.setGridColor(new Color(212, 208, 200));
this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
this.setColumnSelectionAllowed(false);
this.setRowSelectionAllowed(false);
this.setFillsViewportHeight(false);
this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
}
private MouseAdapter mouseAdapter = new MouseAdapter() {
/**
* 鼠标按下时处理的事件设置当前选中的行列
* @param e
*/
@Override
public void mousePressed(MouseEvent e) {
getInstance().setCellSelected();
if (selectedRow == 0 && !e.isPopupTrigger() && e.getClickCount() == 1 && e.getX() < WIDGET_TABLE_ROW_HEIGHT / 2) { // 如果是点击在第一行
toggleCollapse();
}
}
/**
* 鼠标放开时处理的事件如果是正在拖动则执行换位操作重新绘制属性表如果不是则什么也不做
* 所谓的换行就是简单的重新拿到一次表格数据然后重新绘制表格
* @param e
*/
@Override
public void mouseReleased(MouseEvent e) {
if (!draging) {
return;
}
draging = false;
moveComponent.setVisible(false);
int toIndex = e.getY() < GAP ? 0 : (int) Math.rint((e.getY() - GAP) / WIDGET_TABLE_ROW_HEIGHT) + 1;
//当鼠标放开时,将选中的容器调整至新的顺序
((WSortLayout) designer.getSelectionModel().getSelection().getSelectedCreator().toData()).adjustOrder(selectedRow - 1, toIndex - 1);
//拿取排序后表格数据,然后重绘表格
getInstance().refreshData();
getInstance().repaint();
designer.fireTargetModified();
getInstance().setCellSelected();
}
/**
* 设置鼠标在属性表区域移动时候的事件
* @param e
*/
@Override
public void mouseMoved(MouseEvent e) {
int overRow = 0;
for (int i = 0; i < getRowCount(); i++) {
if (e.getY() > i * WIDGET_TABLE_ROW_HEIGHT && e.getY() <= (i + 1) * WIDGET_TABLE_ROW_HEIGHT) {
overRow = i; //判断鼠标在哪一行
}
}
//如果鼠标移动到当前选中的行上面的时候
if (overRow == selectedRow && selectedRow > 0) {
//把当前选中的那一行的光标改成(除了第一列)移动样式MOVE_CURSOR
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
} else {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
/**
* 鼠标拖动事件如果鼠标当前是<code>MOVE_CURSOR</code>状态则执行开始拖动的代码
* 绘制一个<code>moveComponent</code>来跟随鼠标移动
* @param e
*/
@Override
public void mouseDragged(MouseEvent e) {
int width = getColumnModel().getColumn(0).getWidth();
//如果当前选中的行的范围是合理的话,就可以拖动
if (selectedRow < getRowCount() && selectedRow > 0) {
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
draging = true;
moveComponent.setText(getValueAt(selectedRow, 0).toString());
moveComponent.setLocation(0, e.getY() - GAP);
moveComponent.setSize(new Dimension(width, WIDGET_TABLE_ROW_HEIGHT));
moveComponent.setVisible(true);
moveComponent.setForeground(Color.lightGray);
moveComponent.setBorder(BorderFactory.createLineBorder(Color.lightGray));
}
}
/**
* 设置鼠标单击时处理的事件单击控件列表进入控件属性表
* @param e
*/
@Override
public void mouseClicked(MouseEvent e) {
if (selectedRow > 0) {
//当前点击的控件的名字
String widgetName = cellData[selectedRow][0];
if (StringUtils.isNotEmpty(widgetName)) {
//当前选择的容器
XCreator selectedContainer = designer.getSelectionModel().getSelection().getSelectedCreator();
WLayout selectedWidget = (WLayout) selectedContainer.toData();
//当前选择的容器中的控件数量
int count = selectedWidget.getWidgetCount();
for (int i = 0; i < count; i++) {
XCreator xCreator = (XCreator) selectedContainer.getComponent(i);
Widget widget = xCreator.toData();
if (ComparatorUtils.equals(widgetName, widget.getWidgetName())) {
getEditingDesigner().getSelectionModel().setSelectedCreator(xCreator);
}
}
}
} else if (selectedRow == 0) { // 如果是点击在第一行
if (!e.isPopupTrigger() && e.getClickCount() > 1) {
toggleCollapse();
}
}
}
/**
* 鼠标离开属性表区域事件
* @param e
*/
public void mouseExited(MouseEvent e) {
draging = false;
moveComponent.setVisible(false);
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
};
public MobileWidgetTable getInstance() {
return this;
}
public FormDesigner getEditingDesigner() {
return designer;
}
/**
* 设置当前get到的行列的单元格为选中状态
*/
private void setCellSelected() {
selectedRow = getSelectedRow();
if (selectedRow != -1) {
this.setRowSelectionInterval(selectedRow, selectedRow);
this.setColumnSelectionInterval(0, 0);
}
}
/**
* 切换属性组折叠属性true/false
*/
private void toggleCollapse() {
this.setCollapsed(!this.isCollapsed());
//这里获取表格的父控件是为了当表格被折叠了后,装表格的父控件也要相应的重新布局一下
//比如折叠之后表格行数应该比原来的少,占用父容器空间应该小点,不重新布局父容器,表格大小不会改变
Container parent = MobileWidgetTable.this.getParent();
if (parent != null) {
parent.revalidate();
}
repaint();
}
/**
* 重新get排序后的数据
*/
public void refreshData() {
cellData = getData();
}
/**
* 获取选中控件的控件列表
*
* @return String[][] 二维数组[0][0]widgetName
*/
private String[][] getData() {
if (designer.isFormParaDesigner()) {
return new String[0][0];
}
//选择的控件
XCreator selectedCreator = designer.getSelectionModel().getSelection().getSelectedCreator();
Widget selectedModel = selectedCreator != null ? selectedCreator.toData() : null;
if (selectedModel == null) {
return new String[0][0];
}
// 选择的控件有两种类型,一种是WLayout,代表容器,一种是Widget,代表控件
if (selectedModel.acceptType(WSortLayout.class)) {
List<String> mobileWidgetList = ((WSortLayout) selectedModel).getOrderedMobileWidgetList();
String[][] widgetName = new String[mobileWidgetList.size() + 1][1];
widgetName[0][0] = Inter.getLocText("FR-Designer_WidgetOrder");
for (int i = 0; i < mobileWidgetList.size(); i++) {
widgetName[i + 1][0] = mobileWidgetList.get(i);
}
return widgetName;
} else {
return new String[0][0];
}
}
public boolean isCollapsed() {
return collapsed;
}
public void setCollapsed(boolean collapsed) {
this.collapsed = collapsed;
}
/**
* 自定义的tableEditor类
*/
public class BeanTableModel extends DefaultTableModel {
public BeanTableModel() {
super(cellData, headers);
}
@Override
public int getRowCount() {
if (isCollapsed()) {
return 1;
}
return cellData.length;
}
@Override
public int getColumnCount() {
return 1;
}
@Override
public Object getValueAt(int row, int column) {
if (row >= getRowCount() || column >= getColumnCount()) {
return null;
}
if (row == 0) {
return (isCollapsed() ? "+" : "-") + cellData[row][0];
}
return cellData[row][0];
}
@Override
public String getColumnName(int column) {
return headers[0];
}
@Override
public void setValueAt(Object aValue, int row, int column) {
if (row >= getRowCount() || column >= getColumnCount()) {
return;
}
if (aValue == null) {
cellData[row] = null;
return;
}
cellData[row][0] = aValue.toString();
}
/**
* 是否可编辑
*
* @param row 行号
* @param column 列号
* @return 是否可编辑
*/
public boolean isCellEditable(int row, int column) {
return false;
}
}
}

736
designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java

@ -1,366 +1,372 @@
package com.fr.design.mainframe;
import com.fr.base.BaseUtils;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.designer.beans.events.DesignerEditListener;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.designer.properties.EventPropertyTable;
import com.fr.design.designer.properties.WidgetPropertyTable;
import com.fr.design.fun.WidgetPropertyUIProvider;
import com.fr.design.gui.frpane.UITabbedPane;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.itable.AbstractPropertyTable;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.form.ui.Widget;
import com.fr.general.Inter;
import com.fr.stable.ArrayUtils;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 控件属性表绘制
* Modified by fanglei
*/
public class WidgetPropertyPane extends FormDockView implements BaseWidgetPropertyPane {
private static final String PARA = "para";
private static final String BODY = "body";
private WidgetPropertyTable propertyTable; // 控件的属性表
private EventPropertyTable eventTable; // 控件的事件表
private List<AbstractPropertyTable> widgetPropertyTables; // 这个变量应该是保存控件拓展的属性tab
private FormDesigner designer; // 当前designer
private UIScrollPane psp; // 用来装载属性表table的容器
private UIScrollPane esp; //用来装载事件table的容器
private JPanel wsp; // 装载移动端tab的容器,包括移动端属性表和控件拓展的移动端属性表
private MobileParaWidgetTable mobileParaWidgetTable; // 参数面板的移动端属性tab(和body的移动端属性tab区别是没有标签名column)
private MobileWidgetTable mobileWidgetTable; // body的移动端属性tab
private UIScrollPane downPanel; // 这个滚动容器是用于装载centerPane的
private JPanel centerPane; // 此centerPane采用的是cardLayout布局,装载着mobileWidgetTable和mobileBodyWidgetTable
private CardLayout cardLayout; // 卡片布局,选中参数面板时显示mobileWidgetTable,选中body时显示mobileBodyWidgetTable
private JTableHeader header;//把表头单独get出来作为一个组件
public static WidgetPropertyPane getInstance() {
if (HOLDER.singleton == null) {
HOLDER.singleton = new WidgetPropertyPane();
}
return HOLDER.singleton;
}
public static WidgetPropertyPane getInstance(FormDesigner formEditor) {
HOLDER.singleton.setEditingFormDesigner(formEditor);
HOLDER.singleton.refreshDockingView();
return HOLDER.singleton;
}
private static class HOLDER {
private static WidgetPropertyPane singleton = new WidgetPropertyPane();
}
private WidgetPropertyPane() {
setLayout(FRGUIPaneFactory.createBorderLayout());
}
@Override
public String getViewTitle() {
return Inter.getLocText("Form-Widget_Property_Table");
}
@Override
public Icon getViewIcon() {
return BaseUtils.readIcon("/com/fr/design/images/m_report/attributes.png");
}
@Override
/**
* 绘制属性表tab
*/
public void refreshDockingView() {
designer = this.getEditingFormDesigner();
removeAll();
if (designer == null) {
clearDockingView();
return;
}
widgetPropertyTables = new ArrayList<AbstractPropertyTable>();
//依次创建属性表、事件表、移动端表,再将它们整合到TabPane中去
this.createPropertyTable();
this.createEventTable();
this.createMobileWidgetTable();
this.createTabPane();
this.initTables();
}
/**
* 初始化属性表事件表移动端拓展的属性表
*/
private void initTables() {
propertyTable.initPropertyGroups(null);
eventTable.refresh();
for (AbstractPropertyTable propertyTable : widgetPropertyTables) {
propertyTable.initPropertyGroups(designer);
}
}
/**
* 创建属性表table
*/
private void createPropertyTable() {
propertyTable = new WidgetPropertyTable(designer);
designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable));
propertyTable.setBorder(null);
psp = new UIScrollPane(propertyTable); // 用来装载属性表table
psp.setBorder(null);
}
/**
* 创建事件表事件选项卡不是JTable
*/
private void createEventTable() {
eventTable = new EventPropertyTable(designer);
designer.addDesignerEditListener(new EventPropertyDesignerAdapter(eventTable));
eventTable.setBorder(null);
esp = new UIScrollPane(eventTable); //用来装载事件table
esp.setBorder(null);
}
/**
* 创建移动端控件列表
*/
private void createMobileWidgetTable() {
//加上表头后,这里不再使用borderLayout布局,而采用BoxLayout布局
wsp = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane();
wsp.setBorder(null);
mobileParaWidgetTable = new MobileParaWidgetTable(designer);
mobileWidgetTable = new MobileWidgetTable(designer);
designer.addDesignerEditListener(new mobileWidgetDesignerAdapter());
centerPane = FRGUIPaneFactory.createCardLayout_S_Pane();
cardLayout = (CardLayout) centerPane.getLayout();
centerPane.add(mobileParaWidgetTable, PARA);// 采用卡片布局的容器必须指定卡片名字,如果没有卡片名字
// 就会出现:Exception in thread "main" java.lang.IllegalArgumentException:
// cannot add to layout: constraint must be a string
// 第二个参数代表卡片的名字。后来show方法调用时通过名字找到要显示的卡片
centerPane.add(mobileWidgetTable, BODY); //这两句代码,是把JTable放到一个JPanel中去了,表头不会显示,
//只有放到JScrollPanel中去表头才能正常显示,这就是MobileWidgetTable中定义了表头却没有显示的原因!
//解决方案:MobileWidgetTable实在无法直接放到JScrollPanel中去的时候,应该把表头get出来单独作为一个组件显示
if(hasSelectParaPane(designer)){
cardLayout.show(centerPane,PARA);
header = mobileParaWidgetTable.getTableHeader();
} else {
cardLayout.show(centerPane,BODY);
header = mobileWidgetTable.getTableHeader();
}
downPanel = new UIScrollPane(centerPane);
downPanel.setBorder(new LineBorder(Color.GRAY));
//获取拓展移动端属性tab
WidgetPropertyUIProvider[] widgetAttrProviders = getExtraPropertyUIProviders();
addWidgetAttr(widgetAttrProviders);
}
/**
* 将属性表事件表移动端控件列表整合到TabPane里面去
*/
private void createTabPane() {
UITabbedPane tabbedPane = new UITabbedPane(); // tab选项卡容器
initTabPane(tabbedPane);
add(tabbedPane, BorderLayout.CENTER);
}
/**
* 获取当前控件扩展的属性tab
* 来源有两个:
* 1, 各个控件从各自的Xcreator里扩展例如手机重布局的tab就是从Xcreator中扩展的;
* 2, 所有的控件从插件里扩展.
*
* @return 扩展的tab
*/
private WidgetPropertyUIProvider[] getExtraPropertyUIProviders() {
FormSelection selection = designer.getSelectionModel().getSelection();
WidgetPropertyUIProvider[] embeddedPropertyUIProviders = null;
if (selection != null && selection.getSelectedCreator() != null) {
embeddedPropertyUIProviders = selection.getSelectedCreator().getWidgetPropertyUIProviders();
}
Set<WidgetPropertyUIProvider> set = ExtraDesignClassManager.getInstance().getArray(WidgetPropertyUIProvider.XML_TAG);
return ArrayUtils.addAll(embeddedPropertyUIProviders, set.toArray(new WidgetPropertyUIProvider[set.size()]));
}
/**
* 判断是将拓展的tab放入属性表还是将原来的tab放入属性表
* @param widgetAttrProviders 拓展的tab
*/
private void addWidgetAttr(WidgetPropertyUIProvider[] widgetAttrProviders) {
if (widgetAttrProviders.length == 0) { // 判断有没有拓展的tab,没有就使用原来的
wsp.add(header);
wsp.add(downPanel);
} else {
for (WidgetPropertyUIProvider widgetAttrProvider : widgetAttrProviders) {
AbstractPropertyTable propertyTable = widgetAttrProvider.createWidgetAttrTable();
widgetPropertyTables.add(propertyTable);
designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable));
UIScrollPane uiScrollPane = new UIScrollPane(getExtraBodyTable(propertyTable));
wsp.add(uiScrollPane);
}
}
}
/**
* 如果是body的拓展属性表那么要额外加上一张控件顺序表
* @return
*/
private Component getExtraBodyTable(AbstractPropertyTable abstractPropertyTable) {
Widget selection = designer.getSelectionModel().getSelection().getSelectedCreator().toData();
if (selection.getWidgetName().equals("body")) {
JPanel jPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane();
jPanel.add(abstractPropertyTable);
MobileWidgetTable mobileWidgetTable = new MobileWidgetTable(designer);
jPanel.add(mobileWidgetTable.getTableHeader());
jPanel.add(mobileWidgetTable);
return jPanel;
}
return abstractPropertyTable;
}
private void initTabPane(UITabbedPane tabbedPane) {
tabbedPane.setOpaque(true);
tabbedPane.setBorder(null);
tabbedPane.setTabPlacement(SwingConstants.BOTTOM);
tabbedPane.addTab(Inter.getLocText("FR-Designer_Properties"), psp);
tabbedPane.addTab(Inter.getLocText("FR-Designer_Event"), esp);
tabbedPane.addTab(Inter.getLocText("FR-Widget_Mobile_Terminal"), wsp);
}
//
/**
* 选中的组件是否在参数面板里
* @param designer 设计器
* @return 是则返回true
*/
public boolean hasSelectParaPane(FormDesigner designer){
XCreator xCreator = designer.getSelectionModel().getSelection().getSelectedCreator();
if(xCreator == null){
xCreator = designer.getRootComponent();
}
XLayoutContainer container = XCreatorUtils.getHotspotContainer(xCreator);
return xCreator.acceptType(XWParameterLayout.class) || container.acceptType(XWParameterLayout.class);
}
public void setEditingFormDesigner(BaseFormDesigner editor) {
FormDesigner fd = (FormDesigner) editor;
super.setEditingFormDesigner(fd);
}
private void clearDockingView() {
propertyTable = null;
eventTable = null;
if (widgetPropertyTables != null) {
widgetPropertyTables.clear();
}
JScrollPane psp = new JScrollPane();
psp.setBorder(null);
this.add(psp, BorderLayout.CENTER);
}
/**
* 属性表监听界面事件(编辑删除选中改变大小)
*/
private class WidgetPropertyDesignerAdapter implements DesignerEditListener {
AbstractPropertyTable propertyTable;
WidgetPropertyDesignerAdapter(AbstractPropertyTable propertyTable) {
this.propertyTable = propertyTable;
}
@Override
public void fireCreatorModified(DesignerEvent evt) {
if (evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) {
propertyTable.initPropertyGroups(designer);
} else if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED) {
repaint();
}
}
@Override
public boolean equals(Object o) {
return o instanceof WidgetPropertyDesignerAdapter && ((WidgetPropertyDesignerAdapter) o).propertyTable == this.propertyTable;
}
}
/**
* 事件表监听界面事件编辑选中
*/
private class EventPropertyDesignerAdapter implements DesignerEditListener {
EventPropertyTable propertyTable;
EventPropertyDesignerAdapter(EventPropertyTable eventTable) {
this.propertyTable = eventTable;
}
@Override
public void fireCreatorModified(DesignerEvent evt) {
if (evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) {
propertyTable.refresh();
}
}
@Override
public boolean equals(Object o) {
return o instanceof EventPropertyDesignerAdapter;
}
}
/**
* 移动端属性表监听界面事件改变大小编辑选中增加控件
*/
private class mobileWidgetDesignerAdapter implements DesignerEditListener {
mobileWidgetDesignerAdapter() {
}
/**
* 响应界面改变事件
* @param evt 事件
*/
public void fireCreatorModified(DesignerEvent evt) {
if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_ADDED) {
int value = downPanel.getVerticalScrollBar().getValue();
if(hasSelectParaPane(getEditingFormDesigner())){
cardLayout.show(centerPane,PARA);
mobileParaWidgetTable.refreshData();
} else {
cardLayout.show(centerPane,BODY);
mobileWidgetTable.refreshData();
}
//出现滚动条
downPanel.doLayout();
//控件列表选中某组件,触发表单中选中控件,选中事件又触发列表刷新,滚动条回到0
//此处设置滚动条值为刷新前
downPanel.getVerticalScrollBar().setValue(value);
}
}
}
@Override
public Location preferredLocation() {
return Location.WEST_BELOW;
}
package com.fr.design.mainframe;
import com.fr.base.BaseUtils;
import com.fr.design.ExtraDesignClassManager;
import com.fr.design.designer.beans.events.DesignerEditListener;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.designer.properties.EventPropertyTable;
import com.fr.design.designer.properties.WidgetPropertyTable;
import com.fr.design.fun.WidgetPropertyUIProvider;
import com.fr.design.gui.frpane.UITabbedPane;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.itable.AbstractPropertyTable;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.form.ui.Widget;
import com.fr.general.Inter;
import com.fr.stable.ArrayUtils;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 控件属性表绘制
* Modified by fanglei
*/
public class WidgetPropertyPane extends FormDockView implements BaseWidgetPropertyPane {
private static final String PARA = "para";
private static final String BODY = "body";
private WidgetPropertyTable propertyTable; // 控件的属性表
private EventPropertyTable eventTable; // 控件的事件表
private List<AbstractPropertyTable> widgetPropertyTables; // 这个变量应该是保存控件拓展的属性tab
private FormDesigner designer; // 当前designer
private UIScrollPane psp; // 用来装载属性表table的容器
private UIScrollPane esp; //用来装载事件table的容器
private JPanel wsp; // 装载移动端tab的容器,包括移动端属性表和控件拓展的移动端属性表
private MobileParaWidgetTable mobileParaWidgetTable; // 参数面板的移动端属性tab(和body的移动端属性tab区别是没有标签名column)
private MobileWidgetTable mobileWidgetTable; // body的移动端属性tab
private UIScrollPane downPanel; // 这个滚动容器是用于装载centerPane的
private JPanel centerPane; // 此centerPane采用的是cardLayout布局,装载着mobileWidgetTable和mobileBodyWidgetTable
private CardLayout cardLayout; // 卡片布局,选中参数面板时显示mobileWidgetTable,选中body时显示mobileBodyWidgetTable
private JTableHeader header;//把表头单独get出来作为一个组件
public static WidgetPropertyPane getInstance() {
if (HOLDER.singleton == null) {
HOLDER.singleton = new WidgetPropertyPane();
}
return HOLDER.singleton;
}
public static WidgetPropertyPane getInstance(FormDesigner formEditor) {
HOLDER.singleton.setEditingFormDesigner(formEditor);
HOLDER.singleton.refreshDockingView();
return HOLDER.singleton;
}
private static class HOLDER {
private static WidgetPropertyPane singleton = new WidgetPropertyPane();
}
private WidgetPropertyPane() {
setLayout(FRGUIPaneFactory.createBorderLayout());
}
@Override
public String getViewTitle() {
return Inter.getLocText("Form-Widget_Property_Table");
}
@Override
public Icon getViewIcon() {
return BaseUtils.readIcon("/com/fr/design/images/m_report/attributes.png");
}
@Override
/**
* 绘制属性表tab
*/
public void refreshDockingView() {
designer = this.getEditingFormDesigner();
removeAll();
if (designer == null) {
clearDockingView();
return;
}
widgetPropertyTables = new ArrayList<AbstractPropertyTable>();
//依次创建属性表、事件表、移动端表,再将它们整合到TabPane中去
this.createPropertyTable();
this.createEventTable();
this.createMobileWidgetTable();
this.createTabPane();
this.initTables();
}
/**
* 初始化属性表事件表移动端拓展的属性表
*/
private void initTables() {
propertyTable.initPropertyGroups(null);
eventTable.refresh();
for (AbstractPropertyTable propertyTable : widgetPropertyTables) {
propertyTable.initPropertyGroups(designer);
}
}
/**
* 创建属性表table
*/
private void createPropertyTable() {
propertyTable = new WidgetPropertyTable(designer);
designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable));
propertyTable.setBorder(null);
psp = new UIScrollPane(propertyTable); // 用来装载属性表table
psp.setBorder(null);
}
/**
* 创建事件表事件选项卡不是JTable
*/
private void createEventTable() {
eventTable = new EventPropertyTable(designer);
designer.addDesignerEditListener(new EventPropertyDesignerAdapter(eventTable));
eventTable.setBorder(null);
esp = new UIScrollPane(eventTable); //用来装载事件table
esp.setBorder(null);
}
/**
* 创建移动端控件列表
*/
private void createMobileWidgetTable() {
//加上表头后,这里不再使用borderLayout布局,而采用BoxLayout布局
wsp = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane();
wsp.setBorder(null);
mobileParaWidgetTable = new MobileParaWidgetTable(designer);
mobileWidgetTable = new MobileWidgetTable(designer);
designer.addDesignerEditListener(new mobileWidgetDesignerAdapter());
centerPane = FRGUIPaneFactory.createCardLayout_S_Pane();
cardLayout = (CardLayout) centerPane.getLayout();
centerPane.add(mobileParaWidgetTable, PARA);
// 采用卡片布局的容器必须指定卡片名字,如果没有卡片名字
// 就会出现:Exception in thread "main" java.lang.IllegalArgumentException:
// cannot add to layout: constraint must be a string
// 第二个参数代表卡片的名字。后来show方法调用时通过名字找到要显示的卡片
centerPane.add(mobileWidgetTable, BODY); //这两句代码,是把JTable放到一个JPanel中去了,表头不会显示,
//只有放到JScrollPanel中去表头才能正常显示,这就是MobileWidgetTable中定义了表头却没有显示的原因!
//解决方案:MobileWidgetTable实在无法直接放到JScrollPanel中去的时候,应该把表头get出来单独作为一个组件显示
if (hasSelectParaPane(designer)) {
cardLayout.show(centerPane, PARA);
header = mobileParaWidgetTable.getTableHeader();
} else {
cardLayout.show(centerPane, BODY);
header = mobileWidgetTable.getTableHeader();
}
downPanel = new UIScrollPane(centerPane);
downPanel.setBorder(new LineBorder(Color.GRAY));
//获取拓展移动端属性tab
WidgetPropertyUIProvider[] widgetAttrProviders = getExtraPropertyUIProviders();
addWidgetAttr(widgetAttrProviders);
}
/**
* 将属性表事件表移动端控件列表整合到TabPane里面去
*/
private void createTabPane() {
UITabbedPane tabbedPane = new UITabbedPane(); // tab选项卡容器
initTabPane(tabbedPane);
add(tabbedPane, BorderLayout.CENTER);
}
/**
* 获取当前控件扩展的属性tab
* 来源有两个:
* 1, 各个控件从各自的Xcreator里扩展例如手机重布局的tab就是从Xcreator中扩展的;
* 2, 所有的控件从插件里扩展.
*
* @return 扩展的tab
*/
private WidgetPropertyUIProvider[] getExtraPropertyUIProviders() {
FormSelection selection = designer.getSelectionModel().getSelection();
WidgetPropertyUIProvider[] embeddedPropertyUIProviders = null;
if (selection != null && selection.getSelectedCreator() != null) {
embeddedPropertyUIProviders = selection.getSelectedCreator().getWidgetPropertyUIProviders();
}
Set<WidgetPropertyUIProvider> set = ExtraDesignClassManager.getInstance().getArray(WidgetPropertyUIProvider.XML_TAG);
return ArrayUtils.addAll(embeddedPropertyUIProviders, set.toArray(new WidgetPropertyUIProvider[set.size()]));
}
/**
* 判断是将拓展的tab放入属性表还是将原来的tab放入属性表
*
* @param widgetAttrProviders 拓展的tab
*/
private void addWidgetAttr(WidgetPropertyUIProvider[] widgetAttrProviders) {
if (widgetAttrProviders.length == 0) { // 判断有没有拓展的tab,没有就使用原来的
wsp.add(header);
wsp.add(downPanel);
} else {
for (WidgetPropertyUIProvider widgetAttrProvider : widgetAttrProviders) {
AbstractPropertyTable propertyTable = widgetAttrProvider.createWidgetAttrTable();
widgetPropertyTables.add(propertyTable);
designer.addDesignerEditListener(new WidgetPropertyDesignerAdapter(propertyTable));
UIScrollPane uiScrollPane = new UIScrollPane(getExtraBodyTable(propertyTable));
wsp.add(uiScrollPane);
}
}
}
/**
* 如果是body的拓展属性表那么要额外加上一张控件顺序表
*
* @return
*/
private Component getExtraBodyTable(AbstractPropertyTable abstractPropertyTable) {
Widget selection = designer.getSelectionModel().getSelection().getSelectedCreator().toData();
if (selection.getWidgetName().equals("body")) {
JPanel jPanel = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane();
jPanel.add(abstractPropertyTable);
MobileWidgetTable mobileWidgetTable = new MobileWidgetTable(designer);
jPanel.add(mobileWidgetTable.getTableHeader());
jPanel.add(mobileWidgetTable);
return jPanel;
}
return abstractPropertyTable;
}
private void initTabPane(UITabbedPane tabbedPane) {
tabbedPane.setOpaque(true);
tabbedPane.setBorder(null);
tabbedPane.setTabPlacement(SwingConstants.BOTTOM);
tabbedPane.addTab(Inter.getLocText("FR-Designer_Properties"), psp);
tabbedPane.addTab(Inter.getLocText("FR-Designer_Event"), esp);
tabbedPane.addTab(Inter.getLocText("FR-Widget_Mobile_Terminal"), wsp);
}
/**
* 选中的组件是否在参数面板里
*
* @param designer 设计器
* @return 是则返回true
*/
public boolean hasSelectParaPane(FormDesigner designer) {
XCreator xCreator = designer.getSelectionModel().getSelection().getSelectedCreator();
if (xCreator == null) {
xCreator = designer.getRootComponent();
}
XLayoutContainer container = XCreatorUtils.getHotspotContainer(xCreator);
//TODO container可能为空,引发空指针异常
return xCreator.acceptType(XWParameterLayout.class) || container.acceptType(XWParameterLayout.class);
}
public void setEditingFormDesigner(BaseFormDesigner editor) {
FormDesigner fd = (FormDesigner) editor;
super.setEditingFormDesigner(fd);
}
private void clearDockingView() {
propertyTable = null;
eventTable = null;
if (widgetPropertyTables != null) {
widgetPropertyTables.clear();
}
JScrollPane psp = new JScrollPane();
psp.setBorder(null);
this.add(psp, BorderLayout.CENTER);
}
/**
* 属性表监听界面事件(编辑删除选中改变大小)
*/
private class WidgetPropertyDesignerAdapter implements DesignerEditListener {
AbstractPropertyTable propertyTable;
WidgetPropertyDesignerAdapter(AbstractPropertyTable propertyTable) {
this.propertyTable = propertyTable;
}
@Override
public void fireCreatorModified(DesignerEvent evt) {
if (evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) {
propertyTable.initPropertyGroups(designer);
} else if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED) {
repaint();
}
}
@Override
public boolean equals(Object o) {
return o instanceof WidgetPropertyDesignerAdapter && ((WidgetPropertyDesignerAdapter) o).propertyTable == this.propertyTable;
}
}
/**
* 事件表监听界面事件编辑选中
*/
private class EventPropertyDesignerAdapter implements DesignerEditListener {
EventPropertyTable propertyTable;
EventPropertyDesignerAdapter(EventPropertyTable eventTable) {
this.propertyTable = eventTable;
}
@Override
public void fireCreatorModified(DesignerEvent evt) {
if (evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) {
propertyTable.refresh();
}
}
@Override
public boolean equals(Object o) {
return o instanceof EventPropertyDesignerAdapter;
}
}
/**
* 移动端属性表监听界面事件改变大小编辑选中增加控件
*/
private class mobileWidgetDesignerAdapter implements DesignerEditListener {
mobileWidgetDesignerAdapter() {
}
/**
* 响应界面改变事件
*
* @param evt 事件
*/
public void fireCreatorModified(DesignerEvent evt) {
if (evt.getCreatorEventID() == DesignerEvent.CREATOR_RESIZED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED
|| evt.getCreatorEventID() == DesignerEvent.CREATOR_ADDED) {
int value = downPanel.getVerticalScrollBar().getValue();
if (hasSelectParaPane(getEditingFormDesigner())) {
cardLayout.show(centerPane, PARA);
mobileParaWidgetTable.refreshData();
} else {
cardLayout.show(centerPane, BODY);
mobileWidgetTable.refreshData();
}
//出现滚动条
downPanel.doLayout();
//控件列表选中某组件,触发表单中选中控件,选中事件又触发列表刷新,滚动条回到0
//此处设置滚动条值为刷新前
downPanel.getVerticalScrollBar().setValue(value);
}
}
}
@Override
public Location preferredLocation() {
return Location.WEST_BELOW;
}
}
Loading…
Cancel
Save