diff --git a/designer/designer.iml b/designer/designer.iml
index 796f2413bf..661dcd939d 100644
--- a/designer/designer.iml
+++ b/designer/designer.iml
@@ -7,16 +7,7 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/designer/src/com/fr/design/condition/PresentHighlightPane.java b/designer/src/com/fr/design/condition/PresentHighlightPane.java
index f306ec0f7c..2269ceca19 100644
--- a/designer/src/com/fr/design/condition/PresentHighlightPane.java
+++ b/designer/src/com/fr/design/condition/PresentHighlightPane.java
@@ -97,20 +97,20 @@ public class PresentHighlightPane extends ConditionAttrSingleConditionPane
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/designer_base/src/com/fr/design/beans/location/MoveUtils.java b/designer_base/src/com/fr/design/beans/location/MoveUtils.java
index fe80b463ac..f796768a63 100644
--- a/designer_base/src/com/fr/design/beans/location/MoveUtils.java
+++ b/designer_base/src/com/fr/design/beans/location/MoveUtils.java
@@ -3,8 +3,6 @@
*/
package com.fr.design.beans.location;
-import com.fr.stable.ArrayUtils;
-
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
@@ -98,6 +96,18 @@ public class MoveUtils {
* @param line 吸附线
*/
void setEquidistantLine(Absorptionline line);
+
+ /**
+ * 获取设计器垂直滚动条的值
+ * @return 滚动条的值
+ */
+ int getDesignerScrollVerticalValue();
+
+ /**
+ * 获取设计器水平滚动条的值
+ * @return 滚动条的值
+ */
+ int getDesignerScrollHorizontalValue();
}
public interface RectangleIterator {
@@ -182,6 +192,14 @@ public class MoveUtils {
px.palce = x2 - width;
px.direction = SwingConstants.RIGHT;
}
+ if (Math.abs(bounds.x + bounds.width / 2 - left) <= SORPTION_UNIT) {
+ px.palce = bounds.x + bounds.width / 2;
+ px.direction = SwingConstants.LEFT;
+ }
+ if (Math.abs(bounds.x + bounds.width / 2 - right) <= SORPTION_UNIT) {
+ px.palce = bounds.x + bounds.width / 2 - width;
+ px.direction = SwingConstants.RIGHT;
+ }
}
private static void findY(PlacePointing py, Rectangle bounds, int top, int bottom, int height) {
@@ -211,6 +229,14 @@ public class MoveUtils {
py.palce = y2 - height;
py.direction = SwingConstants.BOTTOM;
}
+ if (Math.abs(bounds.y + bounds.height / 2 - top) <= SORPTION_UNIT) {
+ py.palce = bounds.y + bounds.height / 2;
+ py.direction = SwingConstants.TOP;
+ }
+ if (Math.abs(bounds.y + bounds.height / 2 - bottom) <= SORPTION_UNIT) {
+ py.palce = bounds.y + bounds.height / 2 - height;
+ py.direction = SwingConstants.BOTTOM;
+ }
}
private static void findEquidistantLine(Rectangle bounds, int left, int top, int height, int width) {
@@ -441,7 +467,13 @@ public class MoveUtils {
right = equidistantLines.get(i).getReference();
}
}
- line = Absorptionline.createEquidistantAbsorptionline(operatingRectangle, top, left, bottom, right);
+ operatingRectangle.x -= designer.getDesignerScrollHorizontalValue();
+ operatingRectangle.y -= designer.getDesignerScrollVerticalValue();
+ line = Absorptionline.createEquidistantAbsorptionline(operatingRectangle,
+ top - designer.getDesignerScrollVerticalValue(),
+ left - designer.getDesignerScrollHorizontalValue(),
+ bottom - designer.getDesignerScrollVerticalValue(),
+ right - designer.getDesignerScrollHorizontalValue());
}
designer.setEquidistantLine(line);
}
diff --git a/designer_base/src/com/fr/design/extra/LoginContextListener.java b/designer_base/src/com/fr/design/extra/LoginContextListener.java
new file mode 100644
index 0000000000..ca13544432
--- /dev/null
+++ b/designer_base/src/com/fr/design/extra/LoginContextListener.java
@@ -0,0 +1,8 @@
+package com.fr.design.extra;
+
+/**
+ * Created by lp on 2016/8/16.
+ */
+public interface LoginContextListener {
+ void showLoginContext();
+}
diff --git a/designer_base/src/com/fr/design/extra/LoginPane.java b/designer_base/src/com/fr/design/extra/LoginPane.java
new file mode 100644
index 0000000000..c8c231b24b
--- /dev/null
+++ b/designer_base/src/com/fr/design/extra/LoginPane.java
@@ -0,0 +1,143 @@
+package com.fr.design.extra;
+
+import com.fr.base.FRContext;
+import com.fr.design.DesignerEnvManager;
+import com.fr.design.RestartHelper;
+import com.fr.design.dialog.BasicPane;
+import com.fr.general.ComparatorUtils;
+import com.fr.general.IOUtils;
+import com.fr.general.Inter;
+import com.fr.general.SiteCenter;
+import com.fr.general.http.HttpClient;
+import com.fr.plugin.PluginVerifyException;
+import com.fr.stable.StableUtils;
+
+import javax.swing.*;
+import java.awt.*;
+import java.io.File;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Created by zhaohehe on 16/7/27.
+ */
+public class LoginPane extends BasicPane {
+ private static final String LATEST = "latest";
+
+ public LoginPane() {
+ setLayout(new BorderLayout());
+ if (StableUtils.getMajorJavaVersion() == 8) {
+ String installHome;
+ if (StableUtils.isDebug()) {
+ URL url = ClassLoader.getSystemResource("");
+ installHome = url.getPath();
+ addPane(installHome);
+ } else {
+ installHome = StableUtils.getInstallHome();
+ File file = new File(StableUtils.pathJoin(installHome, "scripts"));
+ if (!file.exists()) {
+ int rv = JOptionPane.showConfirmDialog(
+ this,
+ Inter.getLocText("FR-Designer-Plugin_Shop_Need_Install"),
+ Inter.getLocText("FR-Designer-Plugin_Warning"),
+ JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.INFORMATION_MESSAGE
+ );
+ if (rv == JOptionPane.OK_OPTION) {
+ downloadShopScripts();
+ }
+ } else {
+ addPane(installHome);
+ updateShopScripts();
+ }
+ }
+ } else {
+ }
+ }
+
+ private void addPane(String installHome) {
+ LoginWebPane webPane = new LoginWebPane(new File(installHome).getAbsolutePath(),LoginPane.this);
+ add(webPane, BorderLayout.CENTER);
+ }
+
+ @Override
+ protected String title4PopupWindow() {
+ return Inter.getLocText("FR-Designer-Plugin_Manager");
+ }
+
+ private void downloadShopScripts() {
+ new SwingWorker() {
+ @Override
+ protected Boolean doInBackground() throws Exception {
+ String id = "shop_scripts";
+ String username = DesignerEnvManager.getEnvManager().getBBSName();
+ String password = DesignerEnvManager.getEnvManager().getBBSPassword();
+ try {
+ PluginHelper.downloadPluginFile(id, username, password, new Process() {
+ @Override
+ public void process(Double integer) {
+ }
+ });
+ } catch (PluginVerifyException e) {
+ JOptionPane.showMessageDialog(LoginPane.this, e.getMessage(), Inter.getLocText("FR-Designer-Plugin_Warning"), JOptionPane.ERROR_MESSAGE);
+ return false;
+ } catch (Exception e) {
+ FRContext.getLogger().error(e.getMessage(), e);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected void done() {
+
+ try {
+ if (get()) {
+ IOUtils.unzip(new File(StableUtils.pathJoin(PluginHelper.DOWNLOAD_PATH, PluginHelper.TEMP_FILE)), StableUtils.getInstallHome());
+ int rv = JOptionPane.showOptionDialog(
+ LoginPane.this,
+ Inter.getLocText("FR-Designer-Plugin_Shop_Installed"),
+ Inter.getLocText("FR-Designer-Plugin_Warning"),
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.INFORMATION_MESSAGE,
+ null,
+ new String[]{Inter.getLocText("FR-Designer-Basic_Restart_Designer"), Inter.getLocText("FR-Designer-Basic_Restart_Designer_Later")},
+ null
+ );
+ if (rv == JOptionPane.OK_OPTION) {
+ RestartHelper.restart();
+ }
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ FRContext.getLogger().error(e.getMessage(), e);
+ }
+
+ }
+ }.execute();
+ }
+
+ private void updateShopScripts() {
+ new SwingWorker() {
+ @Override
+ protected Void doInBackground() throws Exception {
+ HttpClient httpClient = new HttpClient(SiteCenter.getInstance().acquireUrlByKind("store.version") + "&version=" + PluginStoreConstants.VERSION);
+ if (httpClient.getResponseCode() == HttpURLConnection.HTTP_OK) {
+ if (!ComparatorUtils.equals(httpClient.getResponseText(), LATEST)) {
+ int rv = JOptionPane.showConfirmDialog(
+ LoginPane.this,
+ Inter.getLocText("FR-Designer-Plugin_Shop_Need_Update"),
+ Inter.getLocText("FR-Designer-Plugin_Warning"),
+ JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.INFORMATION_MESSAGE
+ );
+ if (rv == JOptionPane.OK_OPTION) {
+ downloadShopScripts();
+ }
+ }
+ }
+ return null;
+ }
+ }.execute();
+ }
+}
\ No newline at end of file
diff --git a/designer_base/src/com/fr/design/extra/LoginWebBridge.java b/designer_base/src/com/fr/design/extra/LoginWebBridge.java
new file mode 100644
index 0000000000..5149676937
--- /dev/null
+++ b/designer_base/src/com/fr/design/extra/LoginWebBridge.java
@@ -0,0 +1,188 @@
+package com.fr.design.extra;
+
+import com.fr.base.FRContext;
+import com.fr.design.DesignerEnvManager;
+import com.fr.design.dialog.UIDialog;
+import com.fr.design.gui.ilable.UILabel;
+import com.fr.design.mainframe.DesignerContext;
+import com.fr.general.FRLogger;
+import com.fr.general.SiteCenter;
+import com.fr.general.http.HttpClient;
+import com.fr.stable.EncodeConstants;
+import com.fr.stable.StringUtils;
+import javafx.scene.web.WebEngine;
+
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import javax.swing.*;
+import java.awt.*;
+import java.net.URLEncoder;
+
+/**
+ * Created by zhaohehe on 16/8/1.
+ */
+public class LoginWebBridge {
+
+ private static final String LOGIN_SUCCESS_FLAG = "http://bbs.finereport.com";
+ private static final String LOGININ = "0";
+ private static final String LOGIN_INFO_EMPTY = "-1";
+ private static final String DISCONNECTED = "-2";
+ private static final String UNKNOWN_ERROR = "-3";
+ private static final int TIME_OUT = 10000;
+
+ private static com.fr.design.extra.LoginWebBridge helper;
+ private UIDialog uiDialog;
+ private UILabel uiLabel;
+
+ private boolean testConnection() {
+ HttpClient client = new HttpClient(SiteCenter.getInstance().acquireUrlByKind("bbs.test"));
+ return client.isServerAlive();
+ }
+
+ public static com.fr.design.extra.LoginWebBridge getHelper() {
+ if (helper != null) {
+ return helper;
+ }
+ synchronized (com.fr.design.extra.LoginWebBridge.class) {
+ if (helper == null) {
+ helper = new com.fr.design.extra.LoginWebBridge();
+ }
+ return helper;
+ }
+ }
+
+ public static com.fr.design.extra.LoginWebBridge getHelper(WebEngine webEngine) {
+ getHelper();
+ helper.setEngine(webEngine);
+ return helper;
+ }
+
+ private WebEngine webEngine;
+
+ private LoginWebBridge() {
+ }
+
+ public void setEngine(WebEngine webEngine) {
+ this.webEngine = webEngine;
+ }
+
+ public void setDialogHandle(UIDialog uiDialog) {
+ this.uiDialog = uiDialog;
+ }
+
+ public void setUILabel(UILabel uiLabel) {
+ this.uiLabel = uiLabel;
+ }
+
+ /**
+ * 注册页面
+ */
+ public void registerHref() {
+ try {
+ Desktop.getDesktop().browse(new URI(SiteCenter.getInstance().acquireUrlByKind("bbs.default")));
+ }catch (Exception e) {
+ FRContext.getLogger().info(e.getMessage());
+ }
+ }
+
+ /**
+ * 忘记密码
+ */
+ public void forgetHref() {
+ try {
+ Desktop.getDesktop().browse(new URI(SiteCenter.getInstance().acquireUrlByKind("bbs.default")));
+ }catch (Exception e) {
+ FRContext.getLogger().info(e.getMessage());
+ }
+ }
+
+ /**
+ * 登录操作的回调
+ * @param username
+ * @param password
+ * @return
+ */
+ public String defaultLogin(String username, String password) {
+ if (!StringUtils.isNotBlank(username) && !StringUtils.isNotBlank(password)) {
+ return LOGIN_INFO_EMPTY;
+ }
+ if (!testConnection()) {
+ return DISCONNECTED;
+ }
+ if (login(username, password)) {
+ updateUserInfo(username, password);
+ loginSuccess(username);
+ return LOGININ;
+ }else {
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ /**
+ * 关闭窗口
+ */
+ public void closeWindow() {
+ if (uiDialog != null) {
+ uiDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ uiDialog.setVisible(false);
+ }
+ }
+
+ public void updateUserInfo(String username,String password) {
+ DesignerEnvManager.getEnvManager().setBBSName(username);
+ DesignerEnvManager.getEnvManager().setBBSPassword(password);
+ }
+
+ /**
+ * 关闭窗口并且重新赋值
+ * @param username
+ */
+ public void loginSuccess(String username) {
+ closeWindow();
+ uiLabel.setText(username);
+ }
+
+ /**
+ * 弹出QQ授权页面
+ */
+ public void showQQ() {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ //弹出qq登录的窗口
+ QQLoginPane managerPane = new QQLoginPane();
+ UIDialog qqlog = new QQLoginDialog(DesignerContext.getDesignerFrame(),managerPane);
+ QQLoginWebBridge.getHelper().setDialogHandle(uiDialog);
+ QQLoginWebBridge.getHelper().setQQDialogHandle(qqlog);
+ QQLoginWebBridge.getHelper().setUILabel(uiLabel);
+ qqlog.setVisible(true);
+ }
+ });
+ }
+
+ public boolean login(String username, String password) {
+ if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
+ try {
+ username = URLEncoder.encode(username, EncodeConstants.ENCODING_GBK);
+ password = URLEncoder.encode(password, EncodeConstants.ENCODING_GBK);
+ } catch (UnsupportedEncodingException e) {
+ FRLogger.getLogger().error(e.getMessage());
+ }
+ String url = SiteCenter.getInstance().acquireUrlByKind("bbs.login") + "&username=" + username + "&password=" + password;
+ HttpClient client = new HttpClient(url);
+ client.setTimeout(TIME_OUT);
+ if (client.getResponseCodeNoException() == HttpURLConnection.HTTP_OK) {
+ try {
+ String res = client.getResponseText(EncodeConstants.ENCODING_GBK);
+ if (res.contains(LOGIN_SUCCESS_FLAG)) {
+ return true;
+ }
+ } catch (Exception e) {
+ FRLogger.getLogger().error(e.getMessage());
+ }
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/designer_base/src/com/fr/design/extra/LoginWebPane.java b/designer_base/src/com/fr/design/extra/LoginWebPane.java
new file mode 100644
index 0000000000..f31889c28c
--- /dev/null
+++ b/designer_base/src/com/fr/design/extra/LoginWebPane.java
@@ -0,0 +1,61 @@
+package com.fr.design.extra;
+
+import javafx.application.Platform;
+import javafx.embed.swing.JFXPanel;
+import javafx.event.EventHandler;
+import javafx.scene.Scene;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.web.WebEngine;
+import javafx.scene.web.WebEvent;
+import javafx.scene.web.WebView;
+import netscape.javascript.JSObject;
+
+import javax.swing.*;
+
+/**
+ * Created by zhaohehe on 16/7/26.
+ */
+public class LoginWebPane extends JFXPanel {
+
+ private WebEngine webEngine;
+ private LoginPane loginPane;
+
+ public LoginWebPane(final String installHome,LoginPane loginPane) {
+ this.loginPane = loginPane;
+ Platform.setImplicitExit(false);
+ Platform.runLater(new Runnable() {
+ @Override
+ public void run() {
+ BorderPane root = new BorderPane();
+ Scene scene = new Scene(root);
+ LoginWebPane.this.setScene(scene);
+ WebView webView = new WebView();
+ webEngine = webView.getEngine();
+ webEngine.load("file:///" + installHome + "/scripts/store/web/login.html");
+ webEngine.setOnAlert(new EventHandler>() {
+ @Override
+ public void handle(WebEvent event) {
+ showAlert(event.getData());
+ }
+ });
+ JSObject obj = (JSObject) webEngine.executeScript("window");
+ obj.setMember("LoginHelper", LoginWebBridge.getHelper(webEngine));
+ webView.setContextMenuEnabled(false);//屏蔽右键
+ root.setCenter(webView);
+ }
+ });
+ }
+
+ public void setEngine(WebEngine webEngine) {
+ this.webEngine = webEngine;
+ }
+
+ private void showAlert(final String message) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ JOptionPane.showMessageDialog(LoginWebPane.this, message);
+ }
+ });
+ }
+}
diff --git a/designer_base/src/com/fr/design/extra/PluginManagerPane.java b/designer_base/src/com/fr/design/extra/PluginManagerPane.java
index 64ceea3696..1c9f7aafa4 100644
--- a/designer_base/src/com/fr/design/extra/PluginManagerPane.java
+++ b/designer_base/src/com/fr/design/extra/PluginManagerPane.java
@@ -37,7 +37,7 @@ public class PluginManagerPane extends BasicPane {
public PluginManagerPane() {
setLayout(new BorderLayout());
- if (System.getProperty("java.version").startsWith("1.8")) {
+ if (StableUtils.getMajorJavaVersion() == 8) {
String installHome;
if (StableUtils.isDebug()) {
URL url = ClassLoader.getSystemResource("");
diff --git a/designer_base/src/com/fr/design/extra/PluginWebBridge.java b/designer_base/src/com/fr/design/extra/PluginWebBridge.java
index 144f913da5..82dd4cf356 100644
--- a/designer_base/src/com/fr/design/extra/PluginWebBridge.java
+++ b/designer_base/src/com/fr/design/extra/PluginWebBridge.java
@@ -6,6 +6,7 @@ import com.fr.design.dialog.UIDialog;
import com.fr.design.extra.exe.*;
import com.fr.general.FRLogger;
import com.fr.general.Inter;
+import com.fr.general.SiteCenter;
import com.fr.plugin.Plugin;
import com.fr.plugin.PluginLicense;
import com.fr.plugin.PluginLicenseManager;
@@ -361,6 +362,42 @@ public class PluginWebBridge {
return false;
}
+ /**
+ * 获取系统登录的用户名
+ * @param callback
+ */
+ public void getLoginInfo(final JSObject callback) {
+ Task task = new PluginTask<>(webEngine, callback, new GetLoginInfoExecutor());
+ new Thread(task).start();
+ }
+
+ /**
+ * 打开论坛消息界面
+ */
+ public void getPriviteMessage() {
+ try {
+ Desktop.getDesktop().browse(new URI(SiteCenter.getInstance().acquireUrlByKind("bbs.default")));
+ }catch (Exception exp) {
+ FRContext.getLogger().info(exp.getMessage());
+ }
+ }
+
+ /**
+ * 打开登录页面
+ */
+ public void loginContent() {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ UserLoginContext.fireLoginContextListener();
+ }
+ });
+ }
+
+ public void getUsername() {
+
+ }
+
/**
* 在本地浏览器里打开url
* tips:重载的时候,需要给js调用的方法需要放在前面,否则可能不会被调用(此乃坑)
diff --git a/designer_base/src/com/fr/design/extra/QQLoginDialog.java b/designer_base/src/com/fr/design/extra/QQLoginDialog.java
new file mode 100644
index 0000000000..1a64161741
--- /dev/null
+++ b/designer_base/src/com/fr/design/extra/QQLoginDialog.java
@@ -0,0 +1,34 @@
+package com.fr.design.extra;
+
+import com.fr.design.dialog.BasicPane;
+import com.fr.design.dialog.UIDialog;
+import com.fr.design.utils.gui.GUICoreUtils;
+import com.fr.general.Inter;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * Created by zhaohehe on 16/7/28.
+ */
+public class QQLoginDialog extends UIDialog {
+ private static final Dimension DEFAULT_SHOP = new Dimension(700, 500);
+
+ public QQLoginDialog(Frame frame, BasicPane pane) {
+ super(frame);
+ setUndecorated(true);
+ JPanel panel = (JPanel) getContentPane();
+ panel.setLayout(new BorderLayout());
+ add(pane, BorderLayout.CENTER);
+ setSize(DEFAULT_SHOP);
+ GUICoreUtils.centerWindow(this);
+ setResizable(false);
+ setTitle(Inter.getLocText("FR-Designer-Plugin_Manager"));
+
+ }
+
+ @Override
+ public void checkValid() throws Exception {
+ }
+
+}
\ No newline at end of file
diff --git a/designer_base/src/com/fr/design/extra/QQLoginPane.java b/designer_base/src/com/fr/design/extra/QQLoginPane.java
new file mode 100644
index 0000000000..2bbdd7e539
--- /dev/null
+++ b/designer_base/src/com/fr/design/extra/QQLoginPane.java
@@ -0,0 +1,145 @@
+package com.fr.design.extra;
+
+import com.fr.base.FRContext;
+import com.fr.design.DesignerEnvManager;
+import com.fr.design.RestartHelper;
+import com.fr.design.dialog.BasicPane;
+import com.fr.general.ComparatorUtils;
+import com.fr.general.IOUtils;
+import com.fr.general.Inter;
+import com.fr.general.SiteCenter;
+import com.fr.general.http.HttpClient;
+import com.fr.plugin.PluginVerifyException;
+import com.fr.stable.StableUtils;
+
+import javax.swing.*;
+import java.awt.*;
+import java.io.File;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Created by zhaohehe on 16/7/28.
+ */
+public class QQLoginPane extends BasicPane {
+ private static final String LATEST = "latest";
+
+ public QQLoginPane() {
+ setLayout(new BorderLayout());
+ if (StableUtils.getMajorJavaVersion() == 8) {
+ String installHome;
+ if (StableUtils.isDebug()) {
+ URL url = ClassLoader.getSystemResource("");
+ installHome = url.getPath();
+ addPane(installHome);
+ } else {
+ installHome = StableUtils.getInstallHome();
+ File file = new File(StableUtils.pathJoin(installHome, "scripts"));
+ if (!file.exists()) {
+ int rv = JOptionPane.showConfirmDialog(
+ this,
+ Inter.getLocText("FR-Designer-Plugin_Shop_Need_Install"),
+ Inter.getLocText("FR-Designer-Plugin_Warning"),
+ JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.INFORMATION_MESSAGE
+ );
+ if (rv == JOptionPane.OK_OPTION) {
+ downloadShopScripts();
+ }
+ } else {
+ addPane(installHome);
+ updateShopScripts();
+ }
+ }
+ } else {
+ }
+ }
+
+ private void addPane(String installHome) {
+ QQLoginWebPane webPane = new QQLoginWebPane(new File(installHome).getAbsolutePath());
+ add(webPane, BorderLayout.CENTER);
+ }
+
+
+ @Override
+ protected String title4PopupWindow() {
+ return Inter.getLocText("FR-Designer-Plugin_Manager");
+ }
+
+
+ private void downloadShopScripts() {
+ new SwingWorker() {
+ @Override
+ protected Boolean doInBackground() throws Exception {
+ String id = "shop_scripts";
+ String username = DesignerEnvManager.getEnvManager().getBBSName();
+ String password = DesignerEnvManager.getEnvManager().getBBSPassword();
+ try {
+ PluginHelper.downloadPluginFile(id, username, password, new Process() {
+ @Override
+ public void process(Double integer) {
+ }
+ });
+ } catch (PluginVerifyException e) {
+ JOptionPane.showMessageDialog(QQLoginPane.this, e.getMessage(), Inter.getLocText("FR-Designer-Plugin_Warning"), JOptionPane.ERROR_MESSAGE);
+ return false;
+ } catch (Exception e) {
+ FRContext.getLogger().error(e.getMessage(), e);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected void done() {
+
+ try {
+ if (get()) {
+ IOUtils.unzip(new File(StableUtils.pathJoin(PluginHelper.DOWNLOAD_PATH, PluginHelper.TEMP_FILE)), StableUtils.getInstallHome());
+ int rv = JOptionPane.showOptionDialog(
+ QQLoginPane.this,
+ Inter.getLocText("FR-Designer-Plugin_Shop_Installed"),
+ Inter.getLocText("FR-Designer-Plugin_Warning"),
+ JOptionPane.YES_NO_OPTION,
+ JOptionPane.INFORMATION_MESSAGE,
+ null,
+ new String[]{Inter.getLocText("FR-Designer-Basic_Restart_Designer"), Inter.getLocText("FR-Designer-Basic_Restart_Designer_Later")},
+ null
+ );
+ if (rv == JOptionPane.OK_OPTION) {
+ RestartHelper.restart();
+ }
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ FRContext.getLogger().error(e.getMessage(), e);
+ }
+
+ }
+ }.execute();
+ }
+
+ private void updateShopScripts() {
+ new SwingWorker() {
+ @Override
+ protected Void doInBackground() throws Exception {
+ HttpClient httpClient = new HttpClient(SiteCenter.getInstance().acquireUrlByKind("store.version") + "&version=" + PluginStoreConstants.VERSION);
+ if (httpClient.getResponseCode() == HttpURLConnection.HTTP_OK) {
+ if (!ComparatorUtils.equals(httpClient.getResponseText(), LATEST)) {
+ int rv = JOptionPane.showConfirmDialog(
+ QQLoginPane.this,
+ Inter.getLocText("FR-Designer-Plugin_Shop_Need_Update"),
+ Inter.getLocText("FR-Designer-Plugin_Warning"),
+ JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.INFORMATION_MESSAGE
+ );
+ if (rv == JOptionPane.OK_OPTION) {
+ downloadShopScripts();
+ }
+ }
+ }
+ return null;
+ }
+ }.execute();
+ }
+}
\ No newline at end of file
diff --git a/designer_base/src/com/fr/design/extra/QQLoginWebBridge.java b/designer_base/src/com/fr/design/extra/QQLoginWebBridge.java
new file mode 100644
index 0000000000..a038d56ce0
--- /dev/null
+++ b/designer_base/src/com/fr/design/extra/QQLoginWebBridge.java
@@ -0,0 +1,105 @@
+package com.fr.design.extra;
+
+import com.fr.design.DesignerEnvManager;
+import com.fr.design.dialog.UIDialog;
+import com.fr.design.gui.ilable.UILabel;
+import javafx.scene.web.WebEngine;
+import org.json.JSONObject;
+
+import javax.swing.*;
+
+/**
+ * Created by lp on 2016/8/10.
+ */
+public class QQLoginWebBridge {
+
+ private static com.fr.design.extra.QQLoginWebBridge helper;
+ private WebEngine webEngine;
+ private static String LOGINSUCCESS = "ok";
+ private static String LOGINFAILED = "failed";
+ private UIDialog uiDialog;
+ private UILabel uiLabel;
+ private UIDialog qqDialog;
+ private String username;
+
+
+ private QQLoginWebBridge() {
+ }
+
+ public static com.fr.design.extra.QQLoginWebBridge getHelper() {
+ if (helper != null) {
+ return helper;
+ }
+ synchronized (com.fr.design.extra.QQLoginWebBridge.class) {
+ if (helper == null) {
+ helper = new com.fr.design.extra.QQLoginWebBridge();
+ }
+ return helper;
+ }
+ }
+
+ public void setEngine(WebEngine webEngine) {
+ this.webEngine = webEngine;
+ }
+
+ public void setDialogHandle(UIDialog uiDialog) {
+ this.uiDialog = uiDialog;
+ }
+
+ public void setQQDialogHandle(UIDialog uiDialog) {
+ this.qqDialog = uiDialog;
+ }
+
+ public void setUILabel(UILabel uiLabel) {
+ this.uiLabel = uiLabel;
+ }
+
+ public void setLoginlabel() {
+ username = DesignerEnvManager.getEnvManager().getBBSName();
+ }
+
+ public static com.fr.design.extra.QQLoginWebBridge getHelper(WebEngine webEngine) {
+ getHelper();
+ helper.setEngine(webEngine);
+ return helper;
+ }
+
+ /**
+ * 关闭QQ授权窗口
+ */
+ public void closeQQWindow() {
+ if (qqDialog != null) {
+ qqDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ qqDialog.setVisible(false);
+ }
+ }
+
+ /**
+ * 关闭父窗口
+ */
+ public void closeParentWindow() {
+ if (uiDialog != null) {
+ uiDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ uiDialog.setVisible(false);
+ }
+ }
+
+ /**
+ * 获取用户信息
+ * @param userInfo
+ */
+ public void getLoginInfo(String userInfo) {
+ JSONObject jo = new JSONObject(userInfo);
+ String status = jo.get("status").toString();
+ if (status.equals(LOGINSUCCESS)) {
+ String username = jo.get("username").toString();
+ closeQQWindow();
+ closeParentWindow();
+ uiLabel.setText(username);
+ DesignerEnvManager.getEnvManager().setBBSName(username);
+ }else if (status.equals(LOGINFAILED)){
+ //账号没有QQ授权
+ closeQQWindow();
+ }
+ }
+}
diff --git a/designer_base/src/com/fr/design/extra/QQLoginWebPane.java b/designer_base/src/com/fr/design/extra/QQLoginWebPane.java
new file mode 100644
index 0000000000..9644f06663
--- /dev/null
+++ b/designer_base/src/com/fr/design/extra/QQLoginWebPane.java
@@ -0,0 +1,55 @@
+package com.fr.design.extra;
+
+import javafx.application.Platform;
+import javafx.embed.swing.JFXPanel;
+import javafx.event.EventHandler;
+import javafx.scene.Scene;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.web.WebEngine;
+import javafx.scene.web.WebEvent;
+import javafx.scene.web.WebView;
+import netscape.javascript.JSObject;
+
+import javax.swing.*;
+
+/**
+ * Created by zhaohehe on 16/7/28.
+ */
+public class QQLoginWebPane extends JFXPanel {
+
+ private WebEngine webEngine;
+
+ public QQLoginWebPane(final String installHome) {
+ Platform.setImplicitExit(false);
+ Platform.runLater(new Runnable() {
+ @Override
+ public void run() {
+ BorderPane root = new BorderPane();
+ Scene scene = new Scene(root);
+ QQLoginWebPane.this.setScene(scene);
+ WebView webView = new WebView();
+ webEngine = webView.getEngine();
+ webEngine.load("file:///" + installHome + "/scripts/store/web/qqLogin.html");
+ webEngine.setOnAlert(new EventHandler>() {
+ @Override
+ public void handle(WebEvent event) {
+ showAlert(event.getData());
+ }
+ });
+ JSObject obj = (JSObject) webEngine.executeScript("window");
+ obj.setMember("QQLoginHelper", QQLoginWebBridge.getHelper(webEngine));
+ webView.setContextMenuEnabled(false);//屏蔽右键
+ root.setCenter(webView);
+ }
+ });
+ }
+
+ private void showAlert(final String message) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ JOptionPane.showMessageDialog(QQLoginWebPane.this, message);
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/designer_base/src/com/fr/design/extra/UserLoginContext.java b/designer_base/src/com/fr/design/extra/UserLoginContext.java
new file mode 100644
index 0000000000..a6d68f076a
--- /dev/null
+++ b/designer_base/src/com/fr/design/extra/UserLoginContext.java
@@ -0,0 +1,28 @@
+package com.fr.design.extra;
+
+import java.util.ArrayList;
+
+/**
+ * Created by lp on 2016/8/16.
+ */
+public class UserLoginContext {
+ private static ArrayList fireLoginContextListener = new ArrayList();
+
+ /**
+ * 触发登录框弹出的监听器
+ */
+ public static void fireLoginContextListener() {
+ for (LoginContextListener l : fireLoginContextListener) {
+ l.showLoginContext();
+ }
+ }
+
+ /**
+ * 添加一个弹出登录框的监听事件
+ *
+ * @param l 登录框弹出监听事件
+ */
+ public static void addLoginContextListener(LoginContextListener l) {
+ fireLoginContextListener.add(l);
+ }
+}
diff --git a/designer_base/src/com/fr/design/extra/exe/GetLoginInfoExecutor.java b/designer_base/src/com/fr/design/extra/exe/GetLoginInfoExecutor.java
new file mode 100644
index 0000000000..79fb20dce5
--- /dev/null
+++ b/designer_base/src/com/fr/design/extra/exe/GetLoginInfoExecutor.java
@@ -0,0 +1,37 @@
+package com.fr.design.extra.exe;
+
+import com.fr.design.DesignerEnvManager;
+import com.fr.design.extra.Process;
+
+/**
+ * Created by lp on 2016/8/16.
+ */
+public class GetLoginInfoExecutor implements Executor {
+ private String result = "[]";
+
+ @Override
+ public String getTaskFinishMessage() {
+ return result;
+ }
+
+ @Override
+ public Command[] getCommands() {
+ return new Command[]{
+ new Command() {
+ @Override
+ public String getExecuteMessage() {
+ return null;
+ }
+
+ @Override
+ public void run(Process process) {
+ String username = DesignerEnvManager.getEnvManager().getBBSName();
+ if (username == null) {
+ }else {
+ result = username;
+ }
+ }
+ }
+ };
+ }
+}
diff --git a/designer_base/src/com/fr/design/fun/JavaScriptActionProvider.java b/designer_base/src/com/fr/design/fun/JavaScriptActionProvider.java
index dfb4cdca09..f3e00932a3 100644
--- a/designer_base/src/com/fr/design/fun/JavaScriptActionProvider.java
+++ b/designer_base/src/com/fr/design/fun/JavaScriptActionProvider.java
@@ -1,6 +1,7 @@
package com.fr.design.fun;
import com.fr.design.beans.FurtherBasicBeanPane;
+import com.fr.design.javascript.JavaScriptActionPane;
import com.fr.js.JavaScript;
import com.fr.stable.fun.mark.Mutable;
@@ -13,6 +14,8 @@ public interface JavaScriptActionProvider extends Mutable{
int CURRENT_LEVEL = 1;
-
FurtherBasicBeanPane extends JavaScript> getJavaScriptActionPane();
+
+ FurtherBasicBeanPane extends JavaScript> getJavaScriptActionPane(JavaScriptActionPane pane);
+
}
\ No newline at end of file
diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractJavaScriptActionProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractJavaScriptActionProvider.java
index 504a8b73ef..69e2770320 100644
--- a/designer_base/src/com/fr/design/fun/impl/AbstractJavaScriptActionProvider.java
+++ b/designer_base/src/com/fr/design/fun/impl/AbstractJavaScriptActionProvider.java
@@ -1,6 +1,9 @@
package com.fr.design.fun.impl;
+import com.fr.design.beans.FurtherBasicBeanPane;
import com.fr.design.fun.JavaScriptActionProvider;
+import com.fr.design.javascript.JavaScriptActionPane;
+import com.fr.js.JavaScript;
import com.fr.stable.fun.impl.AbstractProvider;
import com.fr.stable.fun.mark.API;
@@ -18,4 +21,9 @@ public abstract class AbstractJavaScriptActionProvider extends AbstractProvider
public String mark4Provider() {
return getClass().getName();
}
+
+ @Override
+ public FurtherBasicBeanPane extends JavaScript> getJavaScriptActionPane(JavaScriptActionPane pane) {
+ return getJavaScriptActionPane();
+ }
}
\ No newline at end of file
diff --git a/designer_base/src/com/fr/design/javascript/JavaScriptActionPane.java b/designer_base/src/com/fr/design/javascript/JavaScriptActionPane.java
index d293939443..52648e444a 100644
--- a/designer_base/src/com/fr/design/javascript/JavaScriptActionPane.java
+++ b/designer_base/src/com/fr/design/javascript/JavaScriptActionPane.java
@@ -56,7 +56,7 @@ public abstract class JavaScriptActionPane extends UIComboBoxPane {
Set javaScriptActionProviders = ExtraDesignClassManager.getInstance().getArray(JavaScriptActionProvider.XML_TAG);
if (javaScriptActionProviders != null) {
for (JavaScriptActionProvider jsp : javaScriptActionProviders) {
- paneList.add(jsp.getJavaScriptActionPane());
+ paneList.add(jsp.getJavaScriptActionPane(this));
}
}
// 自定义事件
diff --git a/designer_base/src/com/fr/design/style/background/gradient/FixedGradientBar.java b/designer_base/src/com/fr/design/style/background/gradient/FixedGradientBar.java
new file mode 100644
index 0000000000..33df00bc59
--- /dev/null
+++ b/designer_base/src/com/fr/design/style/background/gradient/FixedGradientBar.java
@@ -0,0 +1,19 @@
+package com.fr.design.style.background.gradient;
+
+import com.fr.design.style.background.gradient.GradientBar;
+
+/**
+ * 这个bar不能拖拽滑动
+ */
+public class FixedGradientBar extends GradientBar {
+ private static final long serialVersionUID = 2787525421995954889L;
+
+ public FixedGradientBar(int minvalue, int maxvalue) {
+ super(minvalue, maxvalue);
+ }
+
+ @Override
+ protected void addMouseDragListener() {
+ //不添加拖拽事件
+ }
+}
\ No newline at end of file
diff --git a/designer_base/src/com/fr/design/utils/DesignUtils.java b/designer_base/src/com/fr/design/utils/DesignUtils.java
index 8ed8aa6175..d6a2ab8a58 100644
--- a/designer_base/src/com/fr/design/utils/DesignUtils.java
+++ b/designer_base/src/com/fr/design/utils/DesignUtils.java
@@ -230,12 +230,15 @@ public class DesignUtils {
private static FRFont getCurrentLocaleFont(){
FRFont guiFRFont;
- Locale defaultLocale = Locale.getDefault();
+ Locale defaultLocale = FRContext.getLocale();
if (isDisplaySimSun(defaultLocale)) {
guiFRFont = getNamedFont("SimSun");
} else if(isDisplayDialog(defaultLocale)) {
guiFRFont = getNamedFont("Dialog");
+ } else if(isDisplayJapaneseFont(defaultLocale)){
+ //日文设计器默认用MS Mincho字体渲染
+ guiFRFont = getNamedFont("MS Mincho");
} else {
guiFRFont = getNamedFont("Tahoma");
}
@@ -267,11 +270,14 @@ public class DesignUtils {
private static boolean isDisplaySimSun(Locale defaultLocale){
return ComparatorUtils.equals(defaultLocale, Locale.SIMPLIFIED_CHINESE);
}
+
+ private static boolean isDisplayJapaneseFont(Locale defaultLocale){
+ return ComparatorUtils.equals(defaultLocale, Locale.JAPANESE)
+ || ComparatorUtils.equals(defaultLocale, Locale.JAPAN);
+ }
private static boolean isDisplayDialog(Locale defaultLocale){
- return ComparatorUtils.equals(defaultLocale, Locale.TRADITIONAL_CHINESE)
- || ComparatorUtils.equals(defaultLocale, Locale.JAPANESE)
- || ComparatorUtils.equals(defaultLocale, Locale.JAPAN)
+ return ComparatorUtils.equals(defaultLocale, Locale.TRADITIONAL_CHINESE)
|| ComparatorUtils.equals(defaultLocale, Locale.KOREAN)
|| ComparatorUtils.equals(defaultLocale, Locale.KOREA);
}
diff --git a/designer_chart/designer_chart.iml b/designer_chart/designer_chart.iml
deleted file mode 100644
index cde6262d74..0000000000
--- a/designer_chart/designer_chart.iml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/designer_chart/src/com/fr/design/chart/gui/ChartComponent.java b/designer_chart/src/com/fr/design/chart/gui/ChartComponent.java
index 3700299c0f..a33fdc1663 100644
--- a/designer_chart/src/com/fr/design/chart/gui/ChartComponent.java
+++ b/designer_chart/src/com/fr/design/chart/gui/ChartComponent.java
@@ -319,4 +319,6 @@ public class ChartComponent extends MiddleChartComponent implements MouseListene
g2d.drawImage(chartImage, 0, 0, chartWidth, chartHeight, null);
}
}
+
+
}
\ No newline at end of file
diff --git a/designer_chart/src/com/fr/design/chart/series/SeriesCondition/LabelBorderAttrPane.java b/designer_chart/src/com/fr/design/chart/series/SeriesCondition/LabelBorderAttrPane.java
index 86e9586234..676fef17dc 100644
--- a/designer_chart/src/com/fr/design/chart/series/SeriesCondition/LabelBorderAttrPane.java
+++ b/designer_chart/src/com/fr/design/chart/series/SeriesCondition/LabelBorderAttrPane.java
@@ -24,7 +24,7 @@ public abstract class LabelBorderAttrPane extends ConditionAttrSingleConditionPa
public LabelBorderAttrPane(ConditionAttributesPane conditionAttributesPane, boolean isRemove, String label) {
super(conditionAttributesPane, isRemove);
nameLabel = new UILabel(label);
- linePane = new BorderAttriPane();
+ linePane = initBorderAttrPane();
if (isRemove) {
this.add(nameLabel);
@@ -33,6 +33,10 @@ public abstract class LabelBorderAttrPane extends ConditionAttrSingleConditionPa
this.labelName = label;
}
+ protected BorderAttriPane initBorderAttrPane(){
+ return new BorderAttriPane();
+ }
+
@Override
public String nameForPopupMenuItem() {
return labelName;
diff --git a/designer_chart/src/com/fr/design/chart/series/SeriesCondition/LabelBorderPane.java b/designer_chart/src/com/fr/design/chart/series/SeriesCondition/LabelBorderPane.java
index cc9385d3ab..e4e1b3548a 100644
--- a/designer_chart/src/com/fr/design/chart/series/SeriesCondition/LabelBorderPane.java
+++ b/designer_chart/src/com/fr/design/chart/series/SeriesCondition/LabelBorderPane.java
@@ -12,7 +12,7 @@ import com.fr.general.Inter;
*/
public class LabelBorderPane extends LabelBorderAttrPane {
- private AttrBorder attrBorder = new AttrBorder();
+ protected AttrBorder attrBorder = new AttrBorder();
public LabelBorderPane(ConditionAttributesPane conditionAttributesPane) {
super(conditionAttributesPane, true, Inter.getLocText(new String[]{"Border", "Format"}));
diff --git a/designer_chart/src/com/fr/design/mainframe/chart/ChartEditPane.java b/designer_chart/src/com/fr/design/mainframe/chart/ChartEditPane.java
index c39aca7bd8..c3a2e1d502 100644
--- a/designer_chart/src/com/fr/design/mainframe/chart/ChartEditPane.java
+++ b/designer_chart/src/com/fr/design/mainframe/chart/ChartEditPane.java
@@ -79,6 +79,10 @@ public class ChartEditPane extends BasicPane implements AttributeChange,Prepare4
registerDSChangeListener();
}
+ public static ChartEditPane getSingleton() {
+ return singleton;
+ }
+
//构建主面板
protected void createTabsPane() {
Icon[] iconArray = new Icon[paneList.size()];
diff --git a/designer_chart/src/com/fr/design/mainframe/chart/gui/style/ChartFillStylePane.java b/designer_chart/src/com/fr/design/mainframe/chart/gui/style/ChartFillStylePane.java
index 5de599d9a5..b077db7ef1 100644
--- a/designer_chart/src/com/fr/design/mainframe/chart/gui/style/ChartFillStylePane.java
+++ b/designer_chart/src/com/fr/design/mainframe/chart/gui/style/ChartFillStylePane.java
@@ -12,7 +12,7 @@ import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.layout.TableLayout;
import com.fr.design.layout.TableLayoutHelper;
-import com.fr.design.style.background.gradient.GradientBar;
+import com.fr.design.style.background.gradient.FixedGradientBar;
import com.fr.general.Inter;
import com.fr.stable.StringUtils;
@@ -33,7 +33,7 @@ public class ChartFillStylePane extends BasicBeanPane{
protected UIComboBox styleSelectBox;
protected JPanel customPane;
protected JPanel changeColorSetPane;
- protected GradientBar colorGradient;
+ protected FixedGradientBar colorGradient;
protected CardLayout cardLayout;
@@ -55,7 +55,7 @@ public class ChartFillStylePane extends BasicBeanPane{
customPane.add(buttonPane, BorderLayout.NORTH);
changeColorSetPane = new JPanel(cardLayout = new CardLayout());
- changeColorSetPane.add(colorGradient = new GradientBar(4, 130), "gradient");
+ changeColorSetPane.add(colorGradient = new FixedGradientBar(4, 130), "gradient");
changeColorSetPane.add(colorAcc = new ChartAccColorPane(), "acc");
cardLayout.show(changeColorSetPane, "acc");
customPane.add(changeColorSetPane, BorderLayout.CENTER);
diff --git a/designer_form/designer_form.iml b/designer_form/designer_form.iml
deleted file mode 100644
index 8429811089..0000000000
--- a/designer_form/designer_form.iml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java
index 6b72255edf..3c0f1155c6 100644
--- a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java
@@ -9,18 +9,31 @@ 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.designer.properties.FRFitLayoutPropertiesGroupModel;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.design.utils.ComponentUtils;
import com.fr.design.utils.gui.LayoutUtils;
+import com.fr.general.ComparatorUtils;
+import com.fr.general.FRLogger;
-public class FRAbsoluteLayoutAdapter extends AbstractLayoutAdapter {
+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;
@@ -33,43 +46,215 @@ public class FRAbsoluteLayoutAdapter extends AbstractLayoutAdapter {
* @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.canEnterIntoAbsolutePane()){
+ return false;
+ }
XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer((XCreator)comp).getTopLayout();
- if(topLayout != null && !topLayout.isEditable()){
+ if(topLayout != null){
+ if (topLayout.isEditable()){
+ //判断有没有和当前控件重叠
+ //先计算当前控件的位置
+ 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++) {
+ WAbsoluteLayout.BoundsWidget temp = (WAbsoluteLayout.BoundsWidget) wAbsoluteLayout.getWidget(i);
+ Rectangle rectangle = temp.getBounds();
+ if (curRec.intersects(rectangle)){
+ return false;
+ }
+ }
+ if (creatorX < 0
+ || creatorX + creator.getWidth() > container.getWidth()
+ || creatorY < 0
+ || creatorY + creator.getHeight() > container.getHeight()) {
+ return false;
+ }
+ return x >= 0 && y >= 0 && creator.getHeight() <= container.getHeight()
+ && creator.getWidth() <= container.getWidth();
+ }
+ //绝对布局嵌套,处于内层,不可编辑,不添加,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;
+ }
+
+ /**
+ * 判断是否鼠标在组件的三等分区域,如果组件在布局管理器中间,上下左右都可能会三等分
+ * @param parentComp 鼠标所在区域的组件
+ * @param x 坐标x
+ * @param y 坐标y
+ * @return 是则返回true
+ */
+ public boolean isTrisectionArea(Component parentComp, int x, int y) {
+ XCreator creator = (XCreator)parentComp;
+ trisectAreaDirect = 0;
+ if (container.getComponentCount()<=1) {
+ return false;
+ }
+ int maxWidth = parentComp.getWidth();
+ int maxHeight = parentComp.getHeight();
+ int xL = parentComp.getX();
+ int yL = parentComp.getY();
+ // 组件宽高的十分之一和默认值取大
+ int minRangeWidth = Math.max(maxWidth/BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
+ int minRangeHeight = Math.max(maxHeight/BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
+ if(yyL+maxHeight-minRangeHeight) {
+ // 在组件下侧三等分
+ trisectAreaDirect = COMP_BOTTOM;
+ } else if (xxL+maxWidth-minRangeWidth) {
+ // 在组件右侧三等分
+ trisectAreaDirect = COMP_RIGHT;
+ }
+ // tab布局的边界特殊处理,不进行三等分
+ if(!creator.getTargetChildrenList().isEmpty()){
return false;
}
- boolean isAccept = x >= 0 && y >= 0 && creator.getHeight() <= container.getHeight()
- && creator.getWidth() <= container.getWidth();
- return isAccept;
+
+ return !ComparatorUtils.equals(trisectAreaDirect, 0);
}
- @Override
+ 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 (XCreatorUtils.getParentXLayoutContainer(creator) != null) {
+ if(!isAdd2ParentLayout) {
Rectangle r = ComponentUtils.getRelativeBounds(container);
- 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;
- }
+ x = x - r.x;
+ y = y - r.y;
+ if (XCreatorUtils.getParentXLayoutContainer(creator) != null) {
- fix(creator, x, y);
+ 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.shouldScaleCreator() || creator.hasTitleStyle()) {
- addParentCreator(creator);
- } else {
- container.add(creator, creator.toData().getWidgetName());
+ if (creator.hasTitleStyle()) {
+ addParentCreator(creator);
+ } else {
+ container.add(creator, creator.toData().getWidgetName());
+ }
+ XWAbsoluteLayout layout = (XWAbsoluteLayout) container;
+ layout.updateBoundsWidget(creator);
+ 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 rightComps;
+ protected java.util.List leftComps;
+ protected java.util.List downComps;
+ protected java.util.List upComps;
+ // 三等分时计算对应侧的组件
+ protected boolean isFindRelatedComps = false;
+ // 渲染时只计算对应的bounds而不调整
+ private boolean isCalculateChildPos = false;
+ private int[] childPosition = null; //painter用的位置
+ protected int minWidth = 0; // 最小尺寸,由于屏幕百分比里不同,显示的最小大小也不同
+ protected int minHeight = 0;
+ protected int actualVal = 0; // 存在间隔时,add move drag 判断对齐等都要考虑
+ protected PaddingMargin margin; // 布局容器边距
+ /**
+ * 在添加组件状态时,当鼠标移动到某个容器上方时,如果该容器有布局管理器,则会调用该布局
+ * 管理适配器的accept来决定当前位置是否可以放置,并提供特殊的标识,比如红色区域标识。比
+ * 如在BorderLayout中,如果某个方位已经放置了组件,则此时应该返回false标识该区域不可以
+ * 放置。
+ *
+ * @param creator 组件
+ * @param x 添加的位置x,该位置是相对于container的
+ * @param y 添加的位置y,该位置是相对于container的
+ * @return 是否可以放置
+ */
+ @Override
+ public boolean accept(XCreator creator, int x, int y) {
+ return false;
+ }
+
+ @Override
+ protected void addComp(XCreator creator, int x, int y) {
+
+ }
+
+ public FRBodyLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ }
+
+ /**
+ * 交叉点区域时,能否对应位置放入组件
+ * @param comp 待放置组件
+ * @param x x
+ * @param y y
+ * @return 能否放入
+ */
+ protected boolean canAcceptWhileCrossPoint(Component comp, int x, int y) {
+ int cX = comp.getX(), cY = comp.getY(), cH = comp.getHeight(), cW = comp.getWidth();
+ Component topComp = container.getTopComp(cX, cY);
+ Component bottomComp = container.getBottomComp(cX, cY, cH);
+ Component rightComp = container.getRightComp(cX, cY, cW);
+ Component leftComp = container.getLeftComp(cX, cY);
+ int minLength = 0, min = minHeight * 2;
+ boolean isNotDefaultArea = false;
+ if (ComparatorUtils.equals(crossPointAreaDirect, COMP_LEFT_TOP)) {
+ isNotDefaultArea = (topComp == null) || (topComp.getX() != cX);
+ minLength = isNotDefaultArea ? Math.min(cH, leftComp.getHeight()) : Math.min(cW, topComp.getWidth());
+ min = isNotDefaultArea ? min : minWidth * 2;
+ } else if (ComparatorUtils.equals(crossPointAreaDirect, COMP_RIGHT_BOTTOM)) {
+ bottomComp = container.getRightBottomComp(cX, cY, cH, cW);
+ isNotDefaultArea = (bottomComp == null) || (bottomComp.getX()+bottomComp.getWidth() != cX + cW) ;
+ rightComp = container.getBottomRightComp(cX, cY, cH, cW);
+ minLength = isNotDefaultArea ? Math.min(cH, rightComp.getHeight()) : Math.min(cW, bottomComp.getWidth());
+ min = isNotDefaultArea ? min : minWidth * 2;
+ } else if (ComparatorUtils.equals(crossPointAreaDirect, COMP_LEFT_BOTTOM)) {
+ leftComp = container.getBottomLeftComp(cX, cY, cH);
+ isNotDefaultArea = (leftComp == null) || (leftComp.getY() + leftComp.getHeight() != cY + cH);
+ minLength = isNotDefaultArea ? Math.min(cW, bottomComp.getWidth()) : Math.min(cH, leftComp.getHeight());
+ min = isNotDefaultArea ? minWidth * 2 : min;
+ } else if (ComparatorUtils.equals(crossPointAreaDirect, COMP_RIGHT_TOP)) {
+ isNotDefaultArea = (rightComp == null) || (rightComp.getY() != cY) ;
+ topComp = container.getRightTopComp(cX, cY, cW);
+ minLength = isNotDefaultArea ? Math.min(cW, topComp.getWidth()) : Math.min(cH, rightComp.getWidth());
+ min = isNotDefaultArea ? minWidth * 2 : min ;
+ } else if (ComparatorUtils.equals(crossPointAreaDirect, COMP_TOP)) {
+ minLength= Math.min(rightComp.getHeight(), Math.min(cH, leftComp.getHeight()));
+ } else if (ComparatorUtils.equals(crossPointAreaDirect, COMP_BOTTOM)) {
+ leftComp = container.getBottomLeftComp(cX, cY, cH);
+ rightComp = container.getBottomRightComp(cX, cY, cH, cW);
+ minLength = Math.min(rightComp.getHeight(), Math.min(cH, leftComp.getHeight()));
+ } else {
+ if (ComparatorUtils.equals(crossPointAreaDirect, COMP_RIGHT)) {
+ topComp = container.getRightTopComp(cX, cY, cW);
+ bottomComp = container.getRightBottomComp(cX, cY, cH, cW);
+ }
+ minLength = Math.min(topComp.getWidth(), Math.min(cW, bottomComp.getWidth()));
+ min = minWidth * 2;
+ }
+ // 有间隔的话,要考虑容纳间隔
+ return minLength >= min + actualVal;
+ }
+
+ /**
+ * 三等分区域时,能否对应位置放入组件
+ * @param comp 待放置组件
+ * @param x x
+ * @param y y
+ * @return 能否放入
+ */
+ protected boolean canAcceptWhileTrisection(Component comp, int x, int y) {
+ //符合三等分,实际区域不满足三等分的大小
+ int cX = comp.getX(), cY = comp.getY(), cH = comp.getHeight(), cW = comp.getWidth();
+ int upMinHeight = 0, downMinHeight = 0, leftMinWidth = 0, rightMinWidth = 0;
+ if (ComparatorUtils.equals(trisectAreaDirect, COMP_TOP)) {
+ upMinHeight = getUpMinHeightComp(cY, x);
+ downMinHeight = getDownMinHeightComp(comp, y);
+ return upMinHeight == 0 ? downMinHeight >= minHeight * 2 + actualVal : (upMinHeight + downMinHeight) >= minHeight * 3 + actualVal;
+ } else if(ComparatorUtils.equals(trisectAreaDirect, COMP_BOTTOM)) {
+ upMinHeight = getUpMinHeightComp(cY + cH + actualVal, x);
+ if (cY + cH + DEFAULT_AREA_LENGTH>container.getHeight() - margin.getBottom()){
+ downMinHeight = 0;
+ } else {
+ Component targetComp = container.getBottomComp(x, cY, cH);
+ downMinHeight = getDownMinHeightComp(targetComp, cY + cH + DEFAULT_AREA_LENGTH + actualVal);
+ }
+ return downMinHeight == 0 ? (upMinHeight >= minHeight * 2 + actualVal) : ((upMinHeight+downMinHeight) >= minHeight * 3 + actualVal);
+ } else if(ComparatorUtils.equals(trisectAreaDirect, COMP_LEFT)) {
+ rightMinWidth = getMinRightWidth(cX, 0, y);
+ if(cX - DEFAULT_AREA_LENGTH < margin.getLeft()) {
+ leftMinWidth = 0;
+ } else {
+ Component targetRightComp = container.getLeftComp(cX, y);
+ leftMinWidth = getMinLeftWidth(targetRightComp, cX - DEFAULT_AREA_LENGTH - actualVal);
+ }
+ return leftMinWidth == 0 ? (rightMinWidth >= minWidth * 2 + actualVal) : ((leftMinWidth+rightMinWidth) >= minWidth * 3 + actualVal);
+ } else if(ComparatorUtils.equals(trisectAreaDirect, COMP_RIGHT)) {
+ leftMinWidth = getMinLeftWidth(comp, x);
+ rightMinWidth = getMinRightWidth(cX, cW, y);
+ return rightMinWidth == 0 ? (leftMinWidth >= minWidth * 2 + actualVal) : ((leftMinWidth+rightMinWidth) >= minWidth * 3 + actualVal);
+ }
+ return false;
+ }
+
+ /**
+ * 返回当前组件所在y值上方的所有组件中最小高度,且保证这些控件是相邻不隔断的
+ * 判断对齐时考虑间隔
+ */
+ private int getUpMinHeightComp(int cY, int x) {
+ if (cY == margin.getTop()) {
+ return 0;
+ }
+ int max=container.getWidth() - margin.getRight();
+ int mouseX = x;
+ int minHeight = cY;
+ int bott = 0;
+ if (isFindRelatedComps) {
+ upComps = new ArrayList();
+ }
+ for(; mouseX margin.getLeft()) {
+ Component comp = container.getTopComp(mouseX, cY);
+ bott = comp.getHeight() + comp.getY()+actualVal;
+ if (bott == cY) {
+ if (comp.getHeight() < minHeight) {
+ minHeight = comp.getHeight();
+ }
+ mouseX = comp.getX()-DEFAULT_AREA_LENGTH-actualVal;
+ if (isFindRelatedComps) {
+ upComps.add(comp);
+ }
+ } else{
+ break;
+ }
+ }
+ return minHeight;
+ }
+
+ /**
+ * 返回和当前组件相同y坐标的所有组件中最小高度,且保证这些控件是相邻不隔断的
+ * 判断对齐时考虑间隔
+ */
+ private int getDownMinHeightComp(Component currentcomp, int y) {
+ int cX = currentcomp.getX();
+ int cY = currentcomp.getY();
+ int minHeight = currentcomp.getHeight();
+ int max=container.getWidth() - margin.getRight();
+ if (isFindRelatedComps) {
+ downComps = new ArrayList();
+ }
+ int mouseX = cX + DEFAULT_AREA_LENGTH;
+ while (mouseX < max) {
+ Component comp = container.getComponentAt(mouseX, y);
+ if (comp.getY() == cY) {
+ if (comp.getHeight() < minHeight) {
+ minHeight = comp.getHeight();
+ }
+ mouseX = comp.getX() + comp.getWidth() + DEFAULT_AREA_LENGTH + actualVal;
+ if (isFindRelatedComps) {
+ downComps.add(comp);
+ }
+ }else{
+ break;
+ }
+ }
+ mouseX = cX - DEFAULT_AREA_LENGTH - actualVal;
+ while(mouseX > margin.getLeft()) {
+ Component comp = container.getComponentAt(mouseX, y);
+ if (comp.getY() == cY) {
+ if (comp.getHeight() < minHeight) {
+ minHeight = comp.getHeight();
+ }
+ mouseX = comp.getX() - DEFAULT_AREA_LENGTH - actualVal;
+ if (isFindRelatedComps) {
+ downComps.add(comp);
+ }
+ }else{
+ break;
+ }
+ }
+ return minHeight;
+ }
+
+ /**
+ * 返回当前组件右侧相同x的所有组件中最小宽度,且保证这些控件是相邻不隔断的
+ * 判断对齐时考虑间隔
+ */
+ private int getMinRightWidth(int cX, int cW, int y) {
+ int xL = cX + DEFAULT_AREA_LENGTH ;
+ xL = cW == 0 ? xL : (xL + cW + actualVal);
+ if (xL > container.getWidth() - margin.getRight()){
+ return 0;
+ }
+ // 以当前组件紧挨着右侧的组件为基准,在y轴方向查找符合条件的组件
+ Component targetComp = container.getComponentAt(xL, y);
+ int minWidth = targetComp.getWidth();
+ int max = container.getHeight() - margin.getBottom();
+ if (isFindRelatedComps) {
+ rightComps = new ArrayList();
+ }
+ int mouseY = targetComp.getY() + DEFAULT_AREA_LENGTH;
+ while (mouseY margin.getTop()) {
+ Component comp = container.getComponentAt(xL, mouseY);
+ if (comp.getX() == targetComp.getX()) {
+ if (comp.getWidth() < minWidth) {
+ minWidth = comp.getWidth();
+ }
+ mouseY = comp.getY() - DEFAULT_AREA_LENGTH - actualVal;
+ if (isFindRelatedComps) {
+ rightComps.add(comp);
+ }
+ }else{
+ break;
+ }
+ }
+ return minWidth;
+ }
+
+ /**
+ * 返回当前组件垂直方向同侧的组件(组件右边界相连)中最小宽度
+ * 判断对齐时考虑间隔
+ */
+ private int getMinLeftWidth(Component currentComp, int x) {
+ int minWidth = currentComp.getWidth();
+ int compRightLength = currentComp.getX() + currentComp.getWidth();
+ int max = container.getHeight() - margin.getBottom();
+ if (isFindRelatedComps) {
+ leftComps = new ArrayList();
+ }
+ int rightx = 0;
+ int mouseY = currentComp.getY() + DEFAULT_AREA_LENGTH;
+ while(mouseYmargin.getTop()) {
+ Component comp = container.getComponentAt(x, mouseY);
+ rightx = comp.getX()+comp.getWidth();
+ if (rightx == compRightLength) {
+ if (comp.getWidth() < minWidth) {
+ minWidth = comp.getWidth();
+ }
+ mouseY = comp.getY() - DEFAULT_AREA_LENGTH - actualVal;
+ if (isFindRelatedComps) {
+ leftComps.add(comp);
+ }
+ }else{
+ break;
+ }
+ }
+ return minWidth;
+ }
+
+ /**
+ * 判断是否鼠标在组件的三等分区域,如果组件在布局管理器中间,上下左右都可能会三等分
+ * @param parentComp 鼠标所在区域的组件
+ * @param x 坐标x
+ * @param y 坐标y
+ * @return 是则返回true
+ */
+ public boolean isTrisectionArea(Component parentComp, int x, int y) {
+ XCreator creator = (XCreator)parentComp;
+ 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);
+ }
+
+ /**
+ * 是否为组件交叉点区域 或者是相邻三组建中间点
+ * @param currentComp 当前组件
+ * @param x 坐标x
+ * @param y 坐标y
+ * @return 是则返回true
+ */
+ public boolean isCrossPointArea(Component currentComp, int x, int y) {
+ // 3个及以上都会出现交叉点区域(包括边界处的)
+ if(currentComp == null || container.getComponentCount() <= 2){
+ return false;
+ }
+ int cX = currentComp.getX();
+ int cY = currentComp.getY();
+ int cW = currentComp.getWidth();
+ int cH = currentComp.getHeight();
+ int areaWidth = Math.max(cW / BORDER_PROPORTION ,DEFAULT_AREA_LENGTH);
+ int areaHeight = Math.max(cH / BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
+ int rx = cX + cW;
+ int by = cY + cH;
+ int objX = cX + areaWidth;
+ int objY = cY + areaHeight;
+ int containerW = container.getWidth() - margin.getRight();
+ int containerH = container.getHeight() - margin.getBottom();
+ if (x < objX && y < objY) {
+ //左上角区域
+ crossPointAreaDirect = cY > margin.getTop() || cX > margin.getLeft() ? COMP_LEFT_TOP : 0;
+ } else if (y < objY && x > rx - areaWidth){
+ //右上角
+ crossPointAreaDirect = cY > margin.getTop() || rx < containerW ? COMP_RIGHT_TOP : 0;
+ } else if (x < objX && y > by - areaHeight) {
+ //左下角
+ crossPointAreaDirect = cX > margin.getLeft() || by < containerH ? COMP_LEFT_BOTTOM : 0;
+ } else if (x > rx-areaWidth && y > by - areaHeight) {
+ //右下角
+ crossPointAreaDirect = by < containerH || rx < containerW ? COMP_RIGHT_BOTTOM : 0;
+ } else {
+ isMiddlePosition(currentComp, x, y, areaWidth, areaHeight);
+ }
+ // tab布局的边界特殊处理
+ XCreator creator = (XCreator)currentComp;
+ if(!creator.getTargetChildrenList().isEmpty()){
+ return false;
+ }
+ return crossPointAreaDirect != 0;
+ }
+
+ private void isMiddlePosition(Component comp, int x, int y, int areaWidth , int areaHeight) {
+ int cX = comp.getX();
+ int cY = comp.getY();
+ int cW = comp.getWidth();
+ int cH = comp.getHeight();
+ boolean isCrosspoint = false;
+ if (x > (cX + cW / 2 - areaWidth) && x < (cX + cW / 2 + areaWidth)) {
+ // 上下边框线中间位置
+ Component leftComp = container.getLeftComp(cX, cY);
+ Component rightComp = container.getRightComp(cX, cY, cW);
+ if (y < cY + areaHeight) {
+ isCrosspoint = leftComp != null && rightComp != null && leftComp.getY() == cY && rightComp.getY() == cY;
+ crossPointAreaDirect = isCrosspoint ? COMP_TOP : 0;
+ } else if (y > cY + cH - areaHeight) {
+ leftComp = container.getBottomLeftComp(cX, cY, cH);
+ rightComp = container.getBottomRightComp(cX, cY, cH, cW);
+ if (leftComp != null && rightComp != null) {
+ isCrosspoint = leftComp.getY() + leftComp.getHeight() == cY + cH && rightComp.getY() + rightComp.getHeight() == cY + cH;
+ }
+ crossPointAreaDirect = isCrosspoint ? COMP_BOTTOM : 0;
+ }
+ } else if (y > (cY + cH / 2 - areaHeight) && y < (cY + cH / 2 + areaHeight)) {
+ // 左右边框线中间位置
+ Component topComp = container.getTopComp(cX, cY);
+ Component bottomComp = container.getBottomComp(cX, cY, cH);
+ if (x < (cX + areaWidth)) {
+ isCrosspoint = topComp != null && bottomComp != null && topComp.getX() == cX && bottomComp.getX() == cX;
+ crossPointAreaDirect = isCrosspoint ? COMP_LEFT : 0;
+ } else if (x > (cX + cW - areaWidth)) {
+ topComp = container.getRightTopComp(cX, cY, cW);
+ bottomComp = container.getRightBottomComp(cX, cY, cH, cW);
+ if (topComp != null && bottomComp != null) {
+ isCrosspoint = topComp.getX() + topComp.getWidth() == cX + cW && bottomComp.getX() + bottomComp.getWidth() == cX+cW;
+ }
+ crossPointAreaDirect = isCrosspoint ? COMP_RIGHT : 0;
+ }
+ }
+ }
+
+ /**
+ * 初始化周边组件列表
+ */
+ protected void initCompsList() {
+ rightComps = new ArrayList();
+ leftComps = new ArrayList();
+ upComps = new ArrayList();
+ downComps = new ArrayList();
+ }
+
+ /**
+ * 清除周边组件列表
+ */
+ protected void clearCompsList() {
+ rightComps = null;
+ leftComps = null;
+ upComps = null;
+ downComps = null;
+ }
+
+ /**
+ * 平分,正常情况拖入组件时,按照上1/4区域、下1/4区域为上下平分,中左侧1/2区域、中右侧1/2区域为左右平分
+ * @param currentComp 当前位置组件
+ * @param child 待放置组件
+ * @param x x
+ * @param y y
+ */
+ protected void fixHalve(Component currentComp, XCreator child, int x, int y) {
+ XCreator creator = (XCreator)currentComp;
+ if(!creator.getTargetChildrenList().isEmpty()){
+ fixHalveOfTab(creator,child,x,y);
+ return;
+ }
+ int maxWidth = currentComp.getWidth();
+ int maxHeight = currentComp.getHeight();
+ int xL = currentComp.getX();
+ int yL = currentComp.getY();
+ Dimension dim = new Dimension();
+ boolean isDividUp = y - yL <= maxHeight * TOP_HALF;
+ boolean isDividDown = y - yL >= maxHeight * BOTTOM_HALF;
+ boolean isDividLeft = x - xL < maxWidth / 2;
+ int finalX = xL;
+ int finalY = yL;
+ int finalW = maxWidth;
+ int finalH = maxHeight;
+ if (isDividUp){
+ dim.width = maxWidth;
+ dim.height = maxHeight / 2 - actualVal / 2;
+ finalY = yL + dim.height + actualVal;
+ finalH = maxHeight - dim.height - actualVal;
+ } else if(isDividDown){
+ // 若当前区域高度非偶数,那么和isDividUp时计算一致,否则永远都是上半部分小1px
+ dim.height = maxHeight / 2 - actualVal / 2;
+ dim.width = maxWidth;
+ finalH = maxHeight - dim.height - actualVal;
+ yL = yL + finalH + actualVal;
+ } else if(isDividLeft){
+ dim.width = maxWidth / 2 - actualVal / 2;
+ dim.height = maxHeight;
+ finalX = xL + dim.width + actualVal;
+ finalW = maxWidth - dim.width - actualVal;
+ } else {
+ finalW = maxWidth / 2 - actualVal / 2;
+ xL = xL + finalW + actualVal;
+ dim.width = maxWidth - finalW - actualVal;
+ dim.height = maxHeight;
+ }
+ if (isCalculateChildPos) {
+ childPosition = new int[]{xL, yL, dim.width, dim.height};
+ } else {
+ currentComp.setLocation(finalX, finalY);
+ currentComp.setSize(finalW, finalH);
+ child.setLocation(xL, yL);
+ child.setSize(dim);
+ }
+ }
+
+ // 边界判断抄得原来的逻辑
+ // tab布局的边界拖入新组件,和当前tab布局平分,这时候的actualVal组建间隔是tab里面的组建间隔
+ // 不应该在外层自适应布局添加
+ private void fixHalveOfTab(XCreator currentCreator, XCreator child, int x, int y){
+ int maxWidth = currentCreator.getWidth();
+ int maxHeight = currentCreator.getHeight();
+ int xL = currentCreator.getX();
+ int yL = currentCreator.getY();
+ Dimension dim = new Dimension();
+ int position = getPositionOfFix(currentCreator, x, y);
+ int finalX = xL;
+ int finalY = yL;
+ int finalW = maxWidth;
+ int finalH = maxHeight;
+ switch(position){
+ case COMP_TOP:
+ dim.width = maxWidth;
+ dim.height = maxHeight / 2;
+ finalY = yL + dim.height;
+ finalH = maxHeight - dim.height;
+ break;
+ case COMP_BOTTOM:
+ dim.height = maxHeight / 2;
+ dim.width = maxWidth;
+ finalH = maxHeight-dim.height;
+ yL = yL + finalH;
+ break;
+ case COMP_LEFT:
+ dim.width = maxWidth / 2;
+ dim.height = maxHeight;
+ finalX = xL + dim.width;
+ finalW = maxWidth - dim.width;
+ break;
+ default:
+ finalW = maxWidth / 2;
+ xL = xL + finalW;
+ dim.width = maxWidth - finalW;
+ dim.height = maxHeight;
+ }
+ if (isCalculateChildPos) {
+ childPosition = new int[]{xL, yL, dim.width, dim.height};
+ } else {
+ currentCreator.setLocation(finalX, finalY);
+ currentCreator.setSize(finalW, finalH);
+ currentCreator.recalculateChildWidth(finalW);
+ currentCreator.recalculateChildHeight(finalH);
+ child.setLocation(xL, yL);
+ child.setSize(dim);
+ }
+ }
+
+ private int getPositionOfFix(XCreator currentCreator,int x,int y){
+ int position = 0;
+ XLayoutContainer cardLayout = ((XWCardMainBorderLayout) currentCreator).getCardPart();
+ XLayoutContainer container = (XLayoutContainer) cardLayout.getComponent(0);
+ Rectangle rect = ComponentUtils.getRelativeBounds(container);
+ int tempX = x - rect.x;
+ int tempY = y - rect.y + WCardMainBorderLayout.TAB_HEIGHT;
+ int containerX = container.getX();
+ int containerY = container.getY();
+ int containerWidth = container.getWidth();
+ int containerHeight = container.getHeight();
+ // 当前坐标点
+ Rectangle currentXY = new Rectangle(tempX, tempY, 1, 1);
+ // 上边缘
+ Rectangle upEdge = new Rectangle(containerX, containerY, containerWidth, BORDER_PROPORTION);
+ if(upEdge.intersects(currentXY)){
+ position = COMP_TOP;
+ }
+ int bottomY = containerY + containerHeight - BORDER_PROPORTION;
+ // 下边缘
+ Rectangle bottomEdge = new Rectangle(containerX, bottomY, containerWidth, BORDER_PROPORTION);
+ if(bottomEdge.intersects(currentXY)){
+ position = COMP_BOTTOM;
+ }
+ //左右边缘的高度 -10*2 是为了不和上下边缘重合
+ int verticalHeight = containerHeight - BORDER_PROPORTION * 2;
+ int leftY = containerY + BORDER_PROPORTION;
+ // 左边缘
+ Rectangle leftEdge = new Rectangle(containerX, leftY, BORDER_PROPORTION, verticalHeight);
+ if(leftEdge.intersects(currentXY)){
+ position = COMP_LEFT;
+ }
+ return position;
+ }
+
+ /**
+ * 组件交叉区域进行插入时,调整受到变动的其他组件,之前是交叉区域插入也按照三等分逻辑,后面测试中发现有bug,改为和bi一样的鼠标所在侧平分
+ * 默认左上角、右下角区域是垂直方向插入组件
+ * 右上角和左下角是水平方向插入组件,这样避免田字块时重复
+ * @param currentComp 当前位置组件
+ * @param child 待放置组件
+ * @param x x
+ * @param y y
+ */
+ protected void fixCrossPointArea(Component currentComp, XCreator child, int x, int y) {
+ //计算前先全部初始化待调整控件所在的list
+ initCompsList();
+ switch(crossPointAreaDirect) {
+ case COMP_LEFT_TOP :
+ dealCrossPointAtLeftTop(currentComp, child);
+ break;
+ case COMP_RIGHT_BOTTOM :
+ dealCrossPointAtRightBottom(currentComp, child);
+ break;
+ case COMP_LEFT_BOTTOM :
+ dealCrossPointAtLeftBottom(currentComp, child);
+ break;
+ case COMP_RIGHT_TOP :
+ dealCrossPointAtRightTop(currentComp, child);
+ break;
+ case COMP_TOP :
+ dealCrossPointAtTop(currentComp, child);
+ break;
+ case COMP_BOTTOM :
+ dealCrossPointAtBottom(currentComp, child);
+ break;
+ case COMP_LEFT :
+ dealCrossPointAtLeft(currentComp, child);
+ break;
+ case COMP_RIGHT :
+ dealCrossPointAtRight(currentComp, child);
+ break;
+ }
+ crossPointAreaDirect = 0;
+ clearCompsList();
+ }
+
+ /**
+ * 左上交叉区域插入组件,默认垂直方向插入
+ */
+ private void dealCrossPointAtLeftTop(Component currentComp, XCreator child) {
+ int minDH = 0, minRW = 0, childw = 0, childh = 0;
+ int cX = currentComp.getX();
+ int cY = currentComp.getY();
+ int cH = currentComp.getHeight();
+ int cW = currentComp.getWidth();
+ Component topComp = container.getTopComp(cX, cY);
+ Component leftComp = container.getLeftComp(cX, cY);
+ //上方没有组件或者有一个x坐标不相同的组件
+ if (topComp==null || topComp.getX()!=cX) {
+ minDH = cH < leftComp.getHeight() ? cH : leftComp.getHeight();
+ downComps.add(leftComp);
+ downComps.add(currentComp);
+ int dLength = minDH / 2;
+ childw = leftComp.getWidth()+cW+actualVal;
+ childh = dLength-actualVal / 2;
+ if (isCalculateChildPos) {
+ childPosition = new int[]{leftComp.getX(), leftComp.getY(), childw, childh};
+ } else{
+ //先设置child位置,不然leftComp坐标调整后就不对了
+ child.setLocation(leftComp.getX(), leftComp.getY());
+ child.setSize(childw, childh);
+ calculateBottomComps(dLength);
+ }
+ } else {
+ rightComps.add(currentComp);
+ rightComps.add(topComp);
+ minRW = cW margin.getLeft()) {
+ Component targetRightComp = container.getLeftComp(cX, y);
+ minLeftW = getMinLeftWidth(targetRightComp, cX-DEFAULT_AREA_LENGTH);
+ }
+ dealTrisectAtRight(child, minLeftW, minRightW);
+ }
+ crossPointAreaDirect = 0;
+ clearCompsList();
+ }
+
+ /**
+ * 当前组件上边界区域三等分
+ */
+ private void dealTrisectAtTop(XCreator child, int minUH, int minDH) {
+ // 三等分有间隔时,实际是两侧都要减去半个间隔大小
+ int averageH = (minUH+minDH - actualVal) / 3;
+ int dLength = 0;
+ int uLength = 0;
+ if (minDH==0) {
+ dLength = 0;
+ uLength = minUH / 2;
+ calculateTopComps(uLength, child, uLength);
+ return;
+ } else if(minUH == 0){
+ dLength = minDH / 2;
+ int witdh = container.getWidth() - margin.getLeft() - margin.getRight();
+ if (!isCalculateChildPos) {
+ calculateBottomComps(dLength);
+ child.setLocation(margin.getLeft(), margin.getRight());
+ child.setSize(witdh, dLength - actualVal / 2);
+ } else {
+ childPosition = new int[] {margin.getLeft(), margin.getRight(), witdh, dLength - actualVal / 2};
+ }
+ return;
+ } else if (minUH >= minDH) {
+ minDH -= actualVal / 2;
+ if ((minDH * 2 / 3) < minHeight) {
+ dLength = minDH - minHeight;
+ }else {
+ dLength = minDH / 3;
+ }
+ uLength = averageH - dLength;
+ } else{
+ minUH -= actualVal / 2;
+ if ((minUH * 2 / 3) < minHeight) {
+ uLength = minUH - minHeight;
+ }else {
+ uLength = minUH / 3;
+ }
+ dLength = averageH - uLength;
+ }
+ if (!isCalculateChildPos) {
+ calculateBottomComps(dLength);
+ }
+ // 计算两侧时,都额外去掉半个间隔,3等分和平分交叉点不同,只能特殊处理下
+ averageH += actualVal / 2;
+ calculateTopComps(uLength, child, averageH);
+ }
+
+ /**
+ * 当前组件右边界区域三等分
+ */
+ private void dealTrisectAtRight(XCreator child, int minLW, int minRW) {
+ int averageW = (minLW + minRW - actualVal) / 3;
+ int leftLength = 0;
+ int rightLength = 0;
+ if (minLW == 0) {
+ rightLength = minRW / 2;
+ int height = container.getHeight() - margin.getBottom() - margin.getTop();
+ if (!isCalculateChildPos) {
+ calculateRightComps(rightLength);
+ child.setLocation(margin.getLeft(), margin.getRight());
+ child.setSize(rightLength - actualVal / 2, height);
+ } else {
+ childPosition = new int[] {margin.getLeft(), margin.getRight(), rightLength - actualVal / 2, height};
+ }
+ return;
+ } else if(minRW == 0){
+ leftLength = minLW / 2;
+ calculateLeftComps(leftLength, child, leftLength);
+ return;
+ } else if (minRW >= minLW) {
+ minLW -= actualVal / 2;
+ if(minLW * 2 / 3 < minWidth) {
+ leftLength = minLW - minWidth;
+ } else {
+ leftLength = minLW / 3;
+ }
+ rightLength = averageW - leftLength;
+ } else {
+ minRW -= actualVal / 2;
+ if(minRW * 2 / 3 < minWidth) {
+ rightLength = minRW - minWidth;
+ } else {
+ rightLength = minRW / 3;
+ }
+ leftLength = averageW - rightLength;
+ }
+ if (!isCalculateChildPos) {
+ calculateRightComps(rightLength);
+ }
+ // averageW 是已经去除间隔后的大小,所以再加上半个间隔,否则处理时会变小
+ averageW += actualVal / 2;
+ calculateLeftComps(leftLength, child, averageW);
+ }
+
+ private void calculateBottomComps(int length) {
+ length += actualVal / 2;
+ for (int i = 0,num = downComps.size(); i < num; i++){
+ Component comp = downComps.get(i);
+ comp.setLocation(comp.getX(), comp.getY() + length);
+ int offset = comp.getHeight() - length;
+ comp.setSize(comp.getWidth(), offset);
+ XCreator creator = (XCreator)comp;
+ creator.recalculateChildHeight(offset);
+ }
+ }
+
+ private void calculateTopComps(int length, XCreator child, int averageH) {
+ length += actualVal / 2;
+ int childWidth = (upComps.size() - 1) * actualVal;
+ int childX = container.getWidth() - margin.getLeft() - margin.getRight();
+ int childY = 0;
+ if(upComps.size() > INDEX_ZERO){
+ childY = upComps.get(INDEX_ZERO).getY() + upComps.get(INDEX_ZERO).getHeight() - length;
+ }
+ for (int i = 0,num = upComps.size(); i < num; i++){
+ Component comp = upComps.get(i);
+ childWidth += comp.getWidth();
+ if (comp.getX() < childX){
+ childX = comp.getX();
+ }
+ if (!isCalculateChildPos) {
+ int offset = comp.getHeight() - length;
+ comp.setSize(comp.getWidth(), offset);
+ XCreator creator = (XCreator)comp;
+ creator.recalculateChildHeight(offset);
+ }
+ }
+ childY += actualVal;
+ averageH -= actualVal/2;
+ if (isCalculateChildPos) {
+ childPosition = new int[]{childX, childY, childWidth, averageH};
+ } else {
+ child.setLocation(childX, childY);
+ child.setSize(childWidth, averageH);
+ }
+ }
+
+ private void calculateLeftComps(int length, XCreator child, int averageW) {
+ length += actualVal / 2;
+ if (leftComps.isEmpty()) {
+ return;
+ }
+ int childH = (leftComps.size() - 1) * actualVal;
+ int childX = 0;
+ if(leftComps.size() > INDEX_ZERO){
+ childX = leftComps.get(INDEX_ZERO).getX() + leftComps.get(INDEX_ZERO).getWidth() - length;
+ }
+ int childY = container.getHeight() - margin.getBottom();
+ for (int i = 0,num = leftComps.size(); i < num; i++){
+ Component comp = leftComps.get(i);
+ childH += comp.getHeight();
+ if (comp.getY() < childY){
+ childY = comp.getY();
+ }
+ if (!isCalculateChildPos) {
+ int offset = comp.getWidth() - length;
+ comp.setSize(offset, comp.getHeight());
+ XCreator creator = (XCreator)comp;
+ creator.recalculateChildWidth(offset);
+ }
+ }
+ childX += actualVal;
+ averageW -= actualVal/2;
+ if (isCalculateChildPos) {
+ childPosition = new int[]{childX, childY, averageW, childH};
+ } else {
+ child.setLocation(childX, childY);
+ child.setSize(averageW, childH);
+ }
+ }
+
+ private void calculateRightComps(int length) {
+ length += actualVal / 2;
+ for (int i=0,num=rightComps.size(); i rightComps;
- private List leftComps;
- private List downComps;
- private List upComps;
- // 三等分时计算对应侧的组件
- private boolean isFindRelatedComps = false;
- // 渲染时只计算对应的bounds而不调整
- private boolean isCalculateChildPos = false;
- private int[] childPosition = null; //painter用的位置
private HoverPainter painter;
- private int minWidth = 0; // 最小尺寸,由于屏幕百分比里不同,显示的最小大小也不同
- private int minHeight = 0;
- private int actualVal = 0; // 存在间隔时,add move drag 判断对齐等都要考虑
- private PaddingMargin margin; // 布局容器边距
/**
* 构造函数
@@ -129,7 +95,7 @@ public class FRFitLayoutAdapter extends AbstractLayoutAdapter {
updateCreatorBackBound();
}
- private void updateCreatorBackBound() {
+ public void updateCreatorBackBound() {
for (int i=0,size=container.getComponentCount(); i= min+actualVal;
- }
-
- private boolean canAcceptWhileTrisection(Component comp, int x, int y) {
- //符合三等分,实际区域不满足三等分的大小
- int cX = comp.getX(), cY = comp.getY(), cH = comp.getHeight(), cW = comp.getWidth();
- int upMinHeight = 0, downMinHeight = 0, leftMinWidth = 0, rightMinWidth = 0;
- if (ComparatorUtils.equals(trisectAreaDirect, COMP_TOP)) {
- upMinHeight = getUpMinHeightComp(cY, x);
- downMinHeight = getDownMinHeightComp(comp, y);
- return upMinHeight==0 ? downMinHeight>= minHeight*2+actualVal : (upMinHeight+downMinHeight)>= minHeight*3+actualVal;
- } else if(ComparatorUtils.equals(trisectAreaDirect, COMP_BOTTOM)) {
- upMinHeight = getUpMinHeightComp(cY+cH+actualVal, x);
- if (cY+cH+DEFAULT_AREA_LENGTH>container.getHeight() - margin.getBottom()){
- downMinHeight = 0;
- } else {
- Component targetComp = container.getBottomComp(x, cY, cH);
- downMinHeight = getDownMinHeightComp(targetComp, cY+cH+DEFAULT_AREA_LENGTH+actualVal);
- }
- return downMinHeight == 0 ? upMinHeight>= minHeight*2+actualVal : (upMinHeight+downMinHeight)>= minHeight*3+actualVal;
- } else if(ComparatorUtils.equals(trisectAreaDirect, COMP_LEFT)) {
- rightMinWidth = getMinRightWidth(cX, 0, y);
- if(cX-DEFAULT_AREA_LENGTH < margin.getLeft()) {
- leftMinWidth = 0;
- } else {
- Component targetRightComp = container.getLeftComp(cX, y);
- leftMinWidth = getMinLeftWidth(targetRightComp, cX-DEFAULT_AREA_LENGTH - actualVal);
- }
- return leftMinWidth==0 ? rightMinWidth>=minWidth*2+actualVal : (leftMinWidth+rightMinWidth)>= minWidth*3+actualVal;
- } else if(ComparatorUtils.equals(trisectAreaDirect, COMP_RIGHT)) {
- leftMinWidth = getMinLeftWidth(comp, x);
- rightMinWidth = getMinRightWidth(cX, cW, y);
- return rightMinWidth==0 ? leftMinWidth>=minWidth*2+actualVal : (leftMinWidth+rightMinWidth)>= minWidth*3+actualVal;
- }
- return false;
- }
-
- /**
- * 返回当前组件所在y值上方的所有组件中最小高度,且保证这些控件是相邻不隔断的
- * 判断对齐时考虑间隔
- */
- private int getUpMinHeightComp(int cY, int x) {
- if (cY == margin.getTop()) {
- return 0;
- }
- int max=container.getWidth() - margin.getRight();
- int mouseX = x;
- int minHeight = cY;
- int bott = 0;
- if (isFindRelatedComps) {
- upComps = new ArrayList();
- }
- for(; mouseX margin.getLeft()) {
- Component comp = container.getTopComp(mouseX, cY);
- bott = comp.getHeight()+comp.getY()+actualVal;
- if (bott == cY) {
- if (comp.getHeight() < minHeight) {
- minHeight = comp.getHeight();
- }
- mouseX = comp.getX()-DEFAULT_AREA_LENGTH-actualVal;
- if (isFindRelatedComps) {
- upComps.add(comp);
- }
- } else{
- break;
- }
- }
- return minHeight;
- }
-
- /**
- * 返回和当前组件相同y坐标的所有组件中最小高度,且保证这些控件是相邻不隔断的
- * 判断对齐时考虑间隔
- */
- private int getDownMinHeightComp(Component currentcomp, int y) {
- int cX = currentcomp.getX();
- int cY = currentcomp.getY();
- int minHeight = currentcomp.getHeight();
- int max=container.getWidth() - margin.getRight();
- if (isFindRelatedComps) {
- downComps = new ArrayList();
- }
- int mouseX = cX + DEFAULT_AREA_LENGTH;
- while (mouseX < max) {
- Component comp = container.getComponentAt(mouseX, y);
- if (comp.getY()==cY) {
- if (comp.getHeight() < minHeight) {
- minHeight = comp.getHeight();
- }
- mouseX = comp.getX()+comp.getWidth()+DEFAULT_AREA_LENGTH + actualVal;
- if (isFindRelatedComps) {
- downComps.add(comp);
- }
- }else{
- break;
- }
- }
- mouseX = cX - DEFAULT_AREA_LENGTH-actualVal;
- while(mouseX > margin.getLeft()) {
- Component comp = container.getComponentAt(mouseX, y);
- if (comp.getY()==cY) {
- if (comp.getHeight() < minHeight) {
- minHeight = comp.getHeight();
- }
- mouseX = comp.getX() - DEFAULT_AREA_LENGTH - actualVal;
- if (isFindRelatedComps) {
- downComps.add(comp);
- }
- }else{
- break;
- }
- }
- return minHeight;
+ protected boolean canAcceptWhileCrossPoint(Component comp, int x, int y) {
+ return super.canAcceptWhileCrossPoint(comp, x, y);
}
-
- /**
- * 返回当前组件右侧相同x的所有组件中最小宽度,且保证这些控件是相邻不隔断的
- * 判断对齐时考虑间隔
- */
- private int getMinRightWidth(int cX, int cW, int y) {
- int xL = cX+DEFAULT_AREA_LENGTH ;
- xL = cW==0 ? xL : xL+cW+actualVal;
- if (xL>container.getWidth() - margin.getRight()){
- return 0;
- }
- // 以当前组件紧挨着右侧的组件为基准,在y轴方向查找符合条件的组件
- Component targetComp = container.getComponentAt(xL, y);
- int minWidth = targetComp.getWidth();
- int max=container.getHeight() - margin.getBottom();
- if (isFindRelatedComps) {
- rightComps = new ArrayList();
- }
- int mouseY = targetComp.getY() + DEFAULT_AREA_LENGTH;
- while (mouseYmargin.getTop()) {
- Component comp = container.getComponentAt(xL, mouseY);
- if (comp.getX()==targetComp.getX()) {
- if (comp.getWidth() < minWidth) {
- minWidth = comp.getWidth();
- }
- mouseY = comp.getY() - DEFAULT_AREA_LENGTH - actualVal;
- if (isFindRelatedComps) {
- rightComps.add(comp);
- }
- }else{
- break;
- }
- }
- return minWidth;
- }
-
- /**
- * 返回当前组件垂直方向同侧的组件(组件右边界相连)中最小宽度
- * 判断对齐时考虑间隔
- */
- private int getMinLeftWidth(Component currentComp, int x) {
- int minWidth = currentComp.getWidth();
- int compRightLength = currentComp.getX()+currentComp.getWidth();
- int max=container.getHeight() - margin.getBottom();
- if (isFindRelatedComps) {
- leftComps = new ArrayList();
- }
- int rightx = 0;
- int mouseY = currentComp.getY()+DEFAULT_AREA_LENGTH;
- while(mouseYmargin.getTop()) {
- Component comp = container.getComponentAt(x, mouseY);
- rightx = comp.getX()+comp.getWidth();
- if (rightx == compRightLength) {
- if (comp.getWidth() < minWidth) {
- minWidth = comp.getWidth();
- }
- mouseY = comp.getY() - DEFAULT_AREA_LENGTH - actualVal;
- if (isFindRelatedComps) {
- leftComps.add(comp);
- }
- }else{
- break;
- }
- }
- return minWidth;
+
+ protected boolean canAcceptWhileTrisection(Component comp, int x, int y) {
+ return super.canAcceptWhileTrisection(comp, x, y);
}
/**
@@ -543,36 +240,7 @@ public class FRFitLayoutAdapter extends AbstractLayoutAdapter {
* @return 是则返回true
*/
public boolean isTrisectionArea(Component parentComp, int x, int y) {
- XCreator creator = (XCreator)parentComp;
- if (container.getComponentCount()<=1) {
- return false;
- }
- int maxWidth = parentComp.getWidth();
- int maxHeight = parentComp.getHeight();
- int xL = parentComp.getX();
- int yL = parentComp.getY();
- // 组件宽高的十分之一和默认值取大
- int minRangeWidth = Math.max(maxWidth/BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
- int minRangeHeight = Math.max(maxHeight/BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
- if(yyL+maxHeight-minRangeHeight) {
- // 在组件下侧三等分
- trisectAreaDirect = COMP_BOTTOM;
- } else if (xxL+maxWidth-minRangeWidth) {
- // 在组件右侧三等分
- trisectAreaDirect = COMP_RIGHT;
- }
- // tab布局的边界特殊处理,不进行三等分
- if(!creator.getTargetChildrenList().isEmpty()){
- return false;
- }
-
- return !ComparatorUtils.equals(trisectAreaDirect, 0);
+ return super.isTrisectionArea(parentComp, x, y);
}
/**
@@ -583,96 +251,15 @@ public class FRFitLayoutAdapter extends AbstractLayoutAdapter {
* @return 是则返回true
*/
public boolean isCrossPointArea(Component currentComp, int x, int y) {
- // 3个及以上都会出现交叉点区域(包括边界处的)
- if(currentComp == null || container.getComponentCount() <= 2){
- return false;
- }
- int cX = currentComp.getX();
- int cY = currentComp.getY();
- int cW = currentComp.getWidth();
- int cH = currentComp.getHeight();
- int areaWidth = Math.max(cW/BORDER_PROPORTION ,DEFAULT_AREA_LENGTH);
- int areaHeight = Math.max(cH/BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
- int rx = cX + cW;
- int by = cY + cH;
- int objX = cX + areaWidth;
- int objY = cY + areaHeight;
- int containerW = container.getWidth() - margin.getRight();
- int containerH = container.getHeight() - margin.getBottom();
- if (x margin.getTop() || cX > margin.getLeft() ? COMP_LEFT_TOP : 0;
- } else if (yrx-areaWidth){
- //右上角
- crossPointAreaDirect = cY>margin.getTop() || rx < containerW ? COMP_RIGHT_TOP : 0;
- } else if (xby-areaHeight) {
- //左下角
- crossPointAreaDirect = cX>margin.getLeft() || byrx-areaWidth && y>by-areaHeight) {
- //右下角
- crossPointAreaDirect = bycX+cW/2-areaWidth && x cY + cH - areaHeight) {
- leftComp = container.getBottomLeftComp(cX, cY, cH);
- rightComp = container.getBottomRightComp(cX, cY, cH, cW);
- if (leftComp!=null && rightComp!=null) {
- isCrosspoint = leftComp.getY()+leftComp.getHeight() == cY + cH && rightComp.getY()+rightComp.getHeight()== cY + cH;
- }
- crossPointAreaDirect = isCrosspoint ? COMP_BOTTOM : 0;
- }
- } else if (y>cY+cH/2-areaHeight && y cX+cW-areaWidth) {
- topComp = container.getRightTopComp(cX, cY, cW);
- bottomComp = container.getRightBottomComp(cX, cY, cH, cW);
- if (topComp!=null && bottomComp!=null) {
- isCrosspoint = topComp.getX()+topComp.getWidth()==cX+cW && bottomComp.getX()+bottomComp.getWidth()== cX+cW;
- }
- crossPointAreaDirect = isCrosspoint ? COMP_RIGHT : 0;
- }
- }
- }
-
- private void initCompsList() {
- rightComps = new ArrayList();
- leftComps = new ArrayList();
- upComps = new ArrayList();
- downComps = new ArrayList();
+
+ protected void initCompsList() {
+ super.initCompsList();
}
-
- private void clearCompsList() {
- rightComps = null;
- leftComps = null;
- upComps = null;
- downComps = null;
+
+ protected void clearCompsList() {
+ super.clearCompsList();
}
private Rectangle adjustBackupBound(Rectangle backupBound,XWCardMainBorderLayout mainLayout){
// 参数界面高度对纵坐标产生的影响
@@ -1057,604 +644,28 @@ public class FRFitLayoutAdapter extends AbstractLayoutAdapter {
/**
* 平分,正常情况拖入组件时,按照上1/4区域、下1/4区域为上下平分,中左侧1/2区域、中右侧1/2区域为左右平分
*/
- private void fixHalve(Component currentComp, XCreator child, int x, int y) {
- XCreator creator = (XCreator)currentComp;
- if(!creator.getTargetChildrenList().isEmpty()){
- fixHalveOfTab(creator,child,x,y);
- return;
- }
- int maxWidth = currentComp.getWidth();
- int maxHeight = currentComp.getHeight();
- int xL = currentComp.getX();
- int yL = currentComp.getY();
- Dimension dim = new Dimension();
- boolean isDividUp = y - yL<=maxHeight*TOP_HALF;
- boolean isDividDown = y - yL>=maxHeight*BOTTOM_HALF;
- boolean isDividLeft = x -xL margin.getLeft()) {
- Component targetRightComp = container.getLeftComp(cX, y);
- minLeftW = getMinLeftWidth(targetRightComp, cX-DEFAULT_AREA_LENGTH);
- }
- dealTrisectAtRight(child, minLeftW, minRightW);
- }
- crossPointAreaDirect = 0;
- clearCompsList();
+ protected void fixTrisect(Component currentComp, XCreator child, int x, int y) {
+ super.fixTrisect(currentComp, child, x, y);
}
-
- /**
- * 当前组件上边界区域三等分
- */
- private void dealTrisectAtTop(XCreator child, int minUH, int minDH) {
- // 三等分有间隔时,实际是两侧都要减去半个间隔大小
- int averageH = (minUH+minDH - actualVal)/3;
- int dLength = 0;
- int uLength = 0;
- if (minDH==0) {
- dLength = 0;
- uLength = minUH/2;
- calculateTopComps(uLength, child, uLength);
- return;
- } else if(minUH==0){
- dLength = minDH/2;
- int witdh = container.getWidth() - margin.getLeft() - margin.getRight();
- if (!isCalculateChildPos) {
- calculateBottomComps(dLength);
- child.setLocation(margin.getLeft(), margin.getRight());
- child.setSize(witdh, dLength - actualVal/2);
- } else {
- childPosition = new int[] {margin.getLeft(), margin.getRight(), witdh, dLength - actualVal/2};
- }
- return;
- } else if (minUH >= minDH) {
- minDH -= actualVal/2;
- if ((minDH*2/3)=minLW) {
- minLW -= actualVal/2;
- if(minLW*2/3 INDEX_ZERO){
- childY = upComps.get(INDEX_ZERO).getY()+upComps.get(INDEX_ZERO).getHeight()-length;
- }
- for (int i=0,num=upComps.size(); i INDEX_ZERO){
- childX = leftComps.get(INDEX_ZERO).getX()+leftComps.get(INDEX_ZERO).getWidth()-length;
- }
- int childY = container.getHeight() - margin.getBottom();
- for (int i=0,num=leftComps.size(); i designer.getRootComponent().getHeight() && designer.getSelectionModel().hasSelectionComponent()
+ } else if (y > designer.getRootComponent().getHeight() + designer.getParaHeight() && designer.getSelectionModel().hasSelectionComponent()
&& !designer.getSelectionModel().getSelection().getSelectedCreator().acceptType(XWParameterLayout.class)) {
- y = designer.getRootComponent().getHeight();
+ y = designer.getRootComponent().getHeight() + designer.getParaHeight();
}
return new Point(x, y);
}
@@ -111,6 +114,7 @@ public abstract class AccessDirection implements Direction {
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){
diff --git a/designer_form/src/com/fr/design/designer/beans/location/Inner.java b/designer_form/src/com/fr/design/designer/beans/location/Inner.java
index 9e17b4ac30..c54796a0ab 100644
--- a/designer_form/src/com/fr/design/designer/beans/location/Inner.java
+++ b/designer_form/src/com/fr/design/designer/beans/location/Inner.java
@@ -40,9 +40,9 @@ public class Inner extends AccessDirection {
}
if (y < 0) {
y = 0;
- } else if (y + current_bounds.getHeight() > designer.getRootComponent().getHeight()
+ } else if (y + current_bounds.getHeight() > (designer.getRootComponent().getHeight() + designer.getParaHeight())
&& designer.getSelectionModel().hasSelectionComponent()) {
- y = designer.getRootComponent().getHeight() - current_bounds.height;
+ y = designer.getRootComponent().getHeight() + designer.getParaHeight() - current_bounds.height;
}
return new Point(x, y);
}
@@ -119,6 +119,16 @@ public class Inner extends AccessDirection {
public void setEquidistantLine(Absorptionline line) {
designer.getStateModel().setEquidistantLine(line);
}
+
+ @Override
+ public int getDesignerScrollHorizontalValue() {
+ return designer.getArea().getHorizontalValue();
+ }
+
+ @Override
+ public int getDesignerScrollVerticalValue() {
+ return designer.getArea().getVerticalValue();
+ }
};
//判断当前操作的是不是参数面板,要特殊处理
boolean isParameterLayout = ((XCreator)(designer.getSelectionModel().getSelection().getSelectedCreator().getParent())).acceptType(XWParameterLayout.class);
diff --git a/designer_form/src/com/fr/design/designer/beans/models/AddingModel.java b/designer_form/src/com/fr/design/designer/beans/models/AddingModel.java
index 21c68f605d..ee02afa655 100644
--- a/designer_form/src/com/fr/design/designer/beans/models/AddingModel.java
+++ b/designer_form/src/com/fr/design/designer/beans/models/AddingModel.java
@@ -2,6 +2,7 @@ package com.fr.design.designer.beans.models;
import java.awt.Rectangle;
+import com.fr.design.designer.creator.XWAbsoluteLayout;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.designer.beans.AdapterBus;
import com.fr.design.designer.beans.ComponentAdapter;
@@ -115,6 +116,12 @@ public class AddingModel {
* @return 成功返回true
*/
public boolean add2Container(FormDesigner designer, XLayoutContainer container, int x, int y) {
+ //考虑不同布局嵌套的情况,获取顶层容器
+ XLayoutContainer xLayoutContainer = container.getTopLayout();
+ if(xLayoutContainer != null && xLayoutContainer.acceptType(XWAbsoluteLayout.class)){
+ container = xLayoutContainer;
+ }
+
Rectangle rect = ComponentUtils.getRelativeBounds(container);
if(!ComparatorUtils.equals(container.getOuterLayout(), container.getBackupParent())){
return added = container.getLayoutAdapter().addBean(creator,x,y);
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/FRAbsoluteLayoutPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/FRAbsoluteLayoutPainter.java
index 04e6018fc2..61e9260e37 100644
--- a/designer_form/src/com/fr/design/designer/beans/painters/FRAbsoluteLayoutPainter.java
+++ b/designer_form/src/com/fr/design/designer/beans/painters/FRAbsoluteLayoutPainter.java
@@ -1,6 +1,13 @@
package com.fr.design.designer.beans.painters;
+import com.fr.design.designer.beans.adapters.layout.FRAbsoluteLayoutAdapter;
+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.form.util.XCreatorConstants;
+import com.fr.design.mainframe.DesignerFrame;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.general.FRLogger;
import java.awt.*;
@@ -8,19 +15,189 @@ import java.awt.*;
* Created by zhouping on 2016/7/11.
*/
public class FRAbsoluteLayoutPainter extends AbstractPainter {
+
+ private static final int BORDER_PROPORTION = 10;
+ private static final int X = 0;
+ private static final int Y = 1;
+ private static final int WIDTH = 2;
+ private static final int HEIGHT = 3;
+
+ private static final Color DEPEND_LINE_COLOR = new Color(200, 200, 200);
+ private static final int DEPEND_LINE_SCOPE = 3;
+
+ /**
+ * 构造函数
+ * @param container
+ */
public FRAbsoluteLayoutPainter(XLayoutContainer container) {
super(container);
}
/**
* 组件渲染
- *
- * @param g 画图类
+ * @param g 画图类
* @param startX 开始位置x
* @param startY 开始位置y
*/
@Override
public void paint(Graphics g, int startX, int startY) {
+ if(hotspot_bounds == null && creator != null && container != null){
+ drawDependingLine(g);
+ return;
+ }
super.paint(g, startX, startY);
+
+ int x = hotspot.x - hotspot_bounds.x;
+ int y = hotspot.y - hotspot_bounds.y;
+ FRAbsoluteLayoutAdapter adapter = (FRAbsoluteLayoutAdapter) container.getLayoutAdapter();
+
+ int[] hot_rec;
+
+ boolean accept = adapter.accept(creator, x, y);
+ //如果absolute不可编辑那么就将之当普通控件处理,在周围添加控件,
+ //否则,只往内部添加,不需要出现蓝色悬浮提示框
+ if(container.isEditable() && accept){
+ return;
+ }
+ Component currentComp = container.getComponentAt(x, y);
+ //不可编辑的时候要获取顶层的绝对布局容器
+ if (XCreatorUtils.getHotspotContainer((XCreator) currentComp) != null) {
+ currentComp = XCreatorUtils.getHotspotContainer((XCreator) currentComp).getTopLayout();
+ if (currentComp == null) {
+ FRLogger.getLogger().info("FRAbsoluteLayoutPainter get currentComp null!");
+ return;
+ }
+ }
+ else{
+ FRLogger.getLogger().info("FRAbsoluteLayoutPainter getHotspotContainer currentComp null!");
+ return;
+ }
+ Color bColor = XCreatorConstants.FIT_LAYOUT_HOTSPOT_COLOR;
+ if (accept) {
+ y = (y == container.getHeight()) ? y - 1 : y;
+ x = (x == container.getWidth()) ? x - 1 : x;
+ hot_rec = adapter.getChildPosition(currentComp, creator, x + hotspot_bounds.x, y + hotspot_bounds.y);
+ } else {
+ bColor = XCreatorConstants.LAYOUT_FORBIDDEN_COLOR;
+ Rectangle rec = currentComp.getBounds();
+ hot_rec = currentComp == container ? new int[]{x, y, 0, 0} : new int[]{rec.x, rec.y, rec.width, rec.height};
+ }
+ drawRegionBackground(g, hot_rec[X], hot_rec[Y] + startY, hot_rec[WIDTH], hot_rec[HEIGHT], bColor, accept);
+ if (accept) {
+ //画交叉区域和中间点区域
+ //拖入的区域也改为整个渲染,点区域的后画下,不然被遮住了
+ paintCrossPoint(currentComp, g, x, y);
+ }
+ }
+
+ private void paintCrossPoint(Component currentComp, Graphics g, int x, int y) {
+ if (currentComp == container) {
+ return;
+ }
+ Color bColor = XCreatorConstants.FIT_LAYOUT_POINT_COLOR;
+ int cX = currentComp.getX(), cY = currentComp.getY(), cH = currentComp.getHeight(), cW = currentComp.getWidth();
+ int defaultWidth = cW / BORDER_PROPORTION, defaultHeight = cH / BORDER_PROPORTION;
+ // 交叉点提示区域最大值为10px
+ int defaultLength = Math.min(BORDER_PROPORTION, Math.min(defaultWidth, defaultHeight));
+ Component topComp = container.getTopComp(cX, cY);
+ Component bottomComp = container.getBottomComp(cX, cY, cH);
+ Component rightComp = container.getRightComp(cX, cY, cW); //组件的左右组件要区分上侧和下侧
+ Component leftComp = container.getLeftComp(cX, cY);
+ boolean top = topComp != null && topComp != container, left = leftComp != null && leftComp != container,
+ bottom = bottomComp != null && bottomComp != container, right = rightComp != null && rightComp != container;
+ if (top || left) {
+ drawRegionBackground(g, cX + hotspot_bounds.x, cY + hotspot_bounds.y, defaultLength, defaultLength, bColor, true);
+ }
+ if (bottom || left) {
+ drawRegionBackground(g, cX + hotspot_bounds.x, cY + cH - defaultLength + hotspot_bounds.y, defaultLength, defaultLength, bColor,true);
+ }
+ if (top || right) {
+ drawRegionBackground(g, cX + cW - defaultLength + hotspot_bounds.x, cY + hotspot_bounds.y, defaultLength, defaultLength, bColor,true);
+ }
+ if (bottom || right) {
+ drawRegionBackground(g, cX + cW - defaultLength + hotspot_bounds.x, cY + cH - defaultLength + hotspot_bounds.y, defaultLength, defaultLength, bColor,true);
+ }
+ if (left && right) {
+ if (leftComp.getY() == cY && rightComp.getY() == cY) {
+ drawRegionBackground(g, cX + cW / 2 - defaultWidth + hotspot_bounds.x, cY + hotspot_bounds.y, defaultWidth * 2, defaultLength, bColor,true);
+ }
+ //底边线位置,左右组件都不为null且低端对齐,取左、右靠下侧组件判断
+ leftComp = container.getBottomLeftComp(cX, cY, cH);
+ rightComp = container.getBottomRightComp(cX, cY, cH, cW);
+ if ((leftComp.getY() + leftComp.getHeight() == cY + cH) && (rightComp.getY() + rightComp.getHeight()== cY + cH)) {
+ drawRegionBackground(g, cX + cW / 2 - defaultWidth + hotspot_bounds.x, cY + cH - defaultLength + hotspot_bounds.y, defaultWidth * 2, defaultLength, bColor,true);
+ }
+ }
+ if (top && bottom) {
+ if (topComp.getX() == cX && bottomComp.getX() == cX) {
+ drawRegionBackground(g, cX + hotspot_bounds.x, cY + cH / 2 - defaultHeight + hotspot_bounds.y, defaultLength, defaultHeight * 2, bColor,true);
+ }
+ // 右边线位置,上下组件不为null且右端对齐,取上、下靠右侧组件判断
+ topComp = container.getRightTopComp(cX, cY, cW);
+ bottomComp = container.getRightBottomComp(cX, cY, cH, cW);
+ if ((topComp.getX() + topComp.getWidth() == cX + cW) && (bottomComp.getX() + bottomComp.getWidth() == cX + cW)) {
+ drawRegionBackground(g, cX + cW - defaultLength + hotspot_bounds.x, cY + cH / 2 - defaultHeight + hotspot_bounds.y, defaultLength, defaultHeight * 2, bColor,true);
+ }
+ }
+ }
+
+ // 画依附线
+ private void drawDependingLine(Graphics g){
+ Graphics2D g2d = (Graphics2D) g;
+ Stroke backup = g2d.getStroke();
+
+ // 当前拖拽组件的坐标
+ int oriX = creator.getX();
+ int oriY = creator.getY();
+
+ // 拖拽位置的即时坐标
+ double x = hotspot.getX();
+ double y = hotspot.getY();
+
+ // 容器所有的内部组件的横纵坐标值
+ int[] posXs = container.getHors();
+ int[] posYs = container.getVeris();
+
+ // 依附线的坐标
+ int lineX = 0;
+ int lineY = 0;
+
+ // 根据拖拽位置调整依附线的坐标
+ lineX = getDependLinePos(lineX, posXs, oriX, x);
+ lineY = getDependLinePos(lineY, posYs, oriY, y);
+
+
+ g2d.setStroke(backup);
+ g2d.setColor(DEPEND_LINE_COLOR);
+ if(lineX != 0){
+ g2d.drawRect(lineX, 0, 0, container.getHeight());
+ }
+ if(lineY != 0){
+ g2d.drawRect(0, lineY, container.getWidth(), 0);
+ }
+
+ }
+
+ /**
+ * 根据容器内部组件的横纵坐标值画依附线
+ *
+ * @param lineCoordinate 依附线坐标值
+ * @param referCoordinates 容器内部所有组件坐标值
+ * @param oriCoordinate 当前拖拽组件坐标
+ * @param currentCoordinate 拖拽位置的即时坐标
+ * @return 依附线的坐标
+ *
+ */
+ private int getDependLinePos(int lineCoordinate,int referCoordinates[],int oriCoordinate,double currentCoordinate){
+ for(int i = 0; i < referCoordinates.length; i++){
+ if(referCoordinates[i] == oriCoordinate){
+ continue;
+ }
+ if(currentCoordinate > referCoordinates[i] - DEPEND_LINE_SCOPE && currentCoordinate < referCoordinates[i] + DEPEND_LINE_SCOPE){
+ lineCoordinate = referCoordinates[i];
+ break;
+ }
+ }
+ return lineCoordinate;
}
}
diff --git a/designer_form/src/com/fr/design/designer/creator/XCreator.java b/designer_form/src/com/fr/design/designer/creator/XCreator.java
index c9b05f9b60..62cfe0b256 100644
--- a/designer_form/src/com/fr/design/designer/creator/XCreator.java
+++ b/designer_form/src/com/fr/design/designer/creator/XCreator.java
@@ -316,6 +316,14 @@ public abstract class XCreator extends JPanel implements XComponent, XCreatorToo
return true;
}
+ /**
+ * 该组件是否可以拖入绝对布局
+ * @return 是则返回true
+ */
+ public boolean canEnterIntoAbsolutePane() {
+ return true;
+ }
+
/**
* 该组件是否可以拖拽(表单中参数面板和自适应布局不可以拖拽)
* @return 是则返回true
diff --git a/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java b/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java
index 3a110e3217..a1fc32c402 100644
--- a/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java
+++ b/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java
@@ -21,10 +21,9 @@ import com.fr.design.designer.beans.models.SelectionModel;
import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
import com.fr.design.form.layout.FRAbsoluteLayout;
import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.icon.IconPathConstants;
-import com.fr.design.mainframe.EditingMouseListener;
-import com.fr.design.mainframe.FormArea;
-import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.*;
import com.fr.design.mainframe.widget.editors.PaddingMarginEditor;
import com.fr.design.mainframe.widget.editors.WLayoutBorderStyleEditor;
import com.fr.design.mainframe.widget.renderer.LayoutBorderStyleRenderer;
@@ -34,10 +33,14 @@ import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
import com.fr.form.ui.container.WFitLayout;
+import com.fr.form.ui.container.WLayout;
import com.fr.general.FRScreen;
import com.fr.general.IOUtils;
import com.fr.general.Inter;
import com.fr.stable.core.PropertyChangeAdapter;
+import org.eclipse.swt.internal.gdip.Rect;
+
+import javax.swing.*;
/**
* @author richer
@@ -47,6 +50,8 @@ public class XWAbsoluteLayout extends XLayoutContainer {
private static final int EDIT_BTN_WIDTH = 60;
private static final int EDIT_BTN_HEIGHT = 24;
+ private int minWidth = WLayout.MIN_WIDTH;
+ private int minHeight = WLayout.MIN_HEIGHT;
//由于屏幕分辨率不同,界面上的容器大小可能不是默认的100%,此时拖入组件时,保存的大小按照100%时的计算
protected double containerPercent = 1.0;
@@ -73,6 +78,16 @@ public class XWAbsoluteLayout extends XLayoutContainer {
initPercent();
}
+ /**
+ * 初始化时默认的组件大小
+ *
+ * @return 默认Dimension
+ */
+ @Override
+ public Dimension initEditorSize() {
+ return new Dimension(500, 300);
+ }
+
//根据屏幕大小来确定显示的百分比, 1440*900默认100%, 1366*768缩放90%
private void initPercent(){
Toolkit toolkit = Toolkit.getDefaultToolkit();
@@ -97,6 +112,35 @@ public class XWAbsoluteLayout extends XLayoutContainer {
*/
public void setContainerPercent(double containerPercent) {
this.containerPercent = containerPercent;
+ minWidth = (int) (XWAbsoluteLayout.MIN_WIDTH*containerPercent);
+ minHeight = (int) (XWAbsoluteLayout.MIN_HEIGHT*containerPercent);
+ }
+
+ /**
+ * 返回界面处根据百分比调整后的最小宽度
+ * @return 最小宽度
+ */
+ public int getActualMinWidth() {
+ return this.minWidth;
+ }
+
+ /**
+ * 返回界面处根据百分比调整后的最小高度
+ * @return 最小高度
+ */
+ public int getActualMinHeight() {
+ return this.minHeight;
+ }
+
+ /**
+ * 返回界面处根据百分比调整后的间隔大小(且为偶数)
+ * @return 间隔
+ */
+ public int getAcualInterval() {
+ // adapter那边交叉三等分、删除都要判断是否对齐,所以间隔转为偶数
+ int interval = (int) (toData().getCompInterval()*containerPercent);
+ int val = interval/2;
+ return val*2;
}
/**
@@ -114,16 +158,54 @@ public class XWAbsoluteLayout extends XLayoutContainer {
}
/**
- * 新增删除拉伸后更新每个组件的BoundsWidget
+ * 新增删除拉伸后单个组件的BoundsWidget
*/
public void updateBoundsWidget(XCreator xCreator) {
WAbsoluteLayout layout = this.toData();
- if (xCreator.shouldScaleCreator() || xCreator.hasTitleStyle()) {
+ if (xCreator.hasTitleStyle()) {
xCreator = (XLayoutContainer)xCreator.getParent();
}
+ if (xCreator.acceptType(XWAbsoluteLayout.class)){
+ ((XWAbsoluteLayout) xCreator).updateBoundsWidget();
+ }
BoundsWidget boundsWidget = layout.getBoundsWidget(xCreator.toData());
Rectangle rectangle = dealWidgetBound(xCreator.getBounds());
- boundsWidget.setCalculatedBounds(rectangle);
+ }
+
+ private Rectangle calculateBound(Rectangle rec, double pw, double ph){
+ Rectangle calRec = new Rectangle(0,0,0,0);
+ calRec.x = (int)(rec.x / pw);
+ calRec.y = (int)(rec.y / ph);
+ calRec.width = (int)(rec.width / pw);
+ calRec.height = (int)(rec.height / ph);
+ return calRec;
+ }
+
+ /**
+ * 新增删除拉伸后每个组件的BoundsWidget
+ */
+ public void updateBoundsWidget() {
+ WAbsoluteLayout layout = this.toData();
+ Rectangle backupBound = this.getBackupBound();
+ Rectangle currentBound = this.getBounds();
+ if (backupBound != null && layout.getCompState() == WAbsoluteLayout.STATE_FIT) {
+ double percentW = ((double) backupBound.width / (double) currentBound.width);
+ double percentH = ((double) backupBound.height / (double) currentBound.height);
+ for (int index = 0, n = this.getComponentCount(); index < n; index++){
+ XCreator creator = (XCreator) this.getComponent(index);
+ BoundsWidget wgt = layout.getBoundsWidget(creator.toData());
+ // 用当前的显示大小计算后调正具体位置
+ Rectangle wgtBound = creator.getBounds();
+ Rectangle rec = calculateBound(wgtBound, percentW, percentH);
+ wgt.setBounds(rec);
+ creator.setBounds(rec);
+ //绝对布局嵌套,要更新内部的绝对布局
+ if (creator.acceptType(XWAbsoluteLayout.class)){
+ creator.setBackupBound(wgtBound);
+ ((XWAbsoluteLayout) creator).updateBoundsWidget();
+ }
+ }
+ }
}
/**
@@ -159,7 +241,7 @@ public class XWAbsoluteLayout extends XLayoutContainer {
@Override
protected String getIconName() {
- return "layout_absolute.png";
+ return "layout_absolute_new.png";
}
/**
diff --git a/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java b/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java
index a67e7c878c..8f4df6e749 100644
--- a/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java
+++ b/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java
@@ -744,6 +744,10 @@ public class XWFitLayout extends XLayoutContainer {
tabLayout.updateBoundsWidget();
}
}
+ //如果子组件是绝对布局,则内部的widget也要更新
+ if (creator.acceptType(XWAbsoluteLayout.class)){
+ ((XWAbsoluteLayout) creator).updateBoundsWidget();
+ }
}
layout.setContainerHeight(containerHeight);
layout.setContainerWidth(containerWidth);
@@ -801,6 +805,7 @@ public class XWFitLayout extends XLayoutContainer {
BoundsWidget bw = wlayout.getBoundsWidget(wgt);
wlayout.removeWidget(bw);
updateBoundsWidget();
+ ((FRFitLayoutAdapter)getLayoutAdapter()).updateCreatorBackBound();
}
/**
diff --git a/designer_form/src/com/fr/design/form/parameter/XFormSubmit.java b/designer_form/src/com/fr/design/form/parameter/XFormSubmit.java
index 094fdeb7a4..3d8f3d9146 100644
--- a/designer_form/src/com/fr/design/form/parameter/XFormSubmit.java
+++ b/designer_form/src/com/fr/design/form/parameter/XFormSubmit.java
@@ -1 +1 @@
-package com.fr.design.form.parameter;
import com.fr.design.designer.creator.XButton;
import com.fr.design.designer.creator.XCreator;
import com.fr.form.parameter.FormSubmitButton;
import java.awt.*;
/**
* 提交按钮
* @editor zhou
* @since 2012-3-23下午3:36:00
*/
public class XFormSubmit extends XButton {
public XFormSubmit(FormSubmitButton widget, Dimension initSize) {
super(widget, initSize);
}
/**
* 是否有查询按钮
* @param xCreator 控件或容器
* @return 有无查询按钮
*/
public boolean SearchQueryCreators(XCreator xCreator) {
return true;
}
/**
* 该组件是否可以拖入表单主体
* @return 是则返回true
*/
public boolean canEnterIntoAdaptPane(){
return false;
}
@Override
protected String getIconName() {
return "preview_16.png";
}
}
\ No newline at end of file
+package com.fr.design.form.parameter;
import com.fr.design.designer.creator.XButton;
import com.fr.design.designer.creator.XCreator;
import com.fr.form.parameter.FormSubmitButton;
import java.awt.*;
/**
* 提交按钮
* @editor zhou
* @since 2012-3-23下午3:36:00
*/
public class XFormSubmit extends XButton {
public XFormSubmit(FormSubmitButton widget, Dimension initSize) {
super(widget, initSize);
}
/**
* 是否有查询按钮
* @param xCreator 控件或容器
* @return 有无查询按钮
*/
public boolean SearchQueryCreators(XCreator xCreator) {
return true;
}
/**
* 该组件是否可以拖入表单主体
* @return 是则返回true
*/
public boolean canEnterIntoAdaptPane(){
return false;
}
/**
* 该组件是否可以拖入绝对布局
*
* @return 是则返回true
*/
@Override
public boolean canEnterIntoAbsolutePane() {
return false;
}
@Override
protected String getIconName() {
return "preview_16.png";
}
}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java b/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java
index e99888c726..fef70c588d 100644
--- a/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java
+++ b/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java
@@ -1 +1 @@
-package com.fr.design.gui.core;
import javax.swing.Icon;
import com.fr.base.BaseUtils;
import com.fr.form.ui.ElementCaseEditor;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.WCardLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.form.ui.container.WHorizontalBoxLayout;
import com.fr.form.ui.container.WParameterLayout;
import com.fr.form.ui.container.WVerticalBoxLayout;
import com.fr.general.Inter;
/**
* Author : Shockway
* Date: 13-6-17
* Time: 上午10:40
*/
public class FormWidgetOption extends WidgetOption {
/**
* 返回名字
* @return 名字
*/
@Override
public String optionName() {
return null;
}
/**
* 返回图标
* @return 图标
*/
@Override
public Icon optionIcon() {
return null;
}
/**
* 组件类
* @return 类
*/
@Override
public Class extends Widget> widgetClass() {
return null;
}
/**
* 返回组件
* @return 控件
*/
@Override
public Widget createWidget() {
return null;
}
/*
* 表单容器
*/
public static WidgetOption[] getFormContainerInstance() {
return new WidgetOption[] { ABSOLUTELAYOUTCONTAINER, BORDERLAYOUTCONTAINER, HORIZONTALBOXLAYOUTCONTAINER, VERTICALBOXLAYOUTCONTAINER,
CARDLAYOUTCONTAINER, FITLAYOUTCONTAINER };
}
/**
* 表单工具栏上的布局
* @return 控件
*/
public static WidgetOption[] getFormLayoutInstance() {
return new WidgetOption[] {CARDLAYOUTCONTAINER/*, ABSOLUTELAYOUTCONTAINER*/};
}
public static final WidgetOption ABSOLUTELAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_AbsoluteLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_absolute.png"),
WAbsoluteLayout.class);
public static final WidgetOption BORDERLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_BorderLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_border.png"),
WBorderLayout.class);
public static final WidgetOption CARDLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_CardLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/card_layout_16.png"),
WCardLayout.class);
public static final WidgetOption HORIZONTALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_Layout-HBox"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_h_16.png"),
WHorizontalBoxLayout.class);
public static final WidgetOption VERTICALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_VerticalBoxLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"),
WVerticalBoxLayout.class);
public static final WidgetOption FITLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter.getLocText("FR-Designer-Layout_Adaptive_Layout"),
BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"),
WFitLayout.class);
public static final WidgetOption PARAMETERCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_Para-Body"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_parameter.png"),
WParameterLayout.class);
public static final WidgetOption ELEMENTCASE = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_Form-Report"), BaseUtils.readIcon("/com/fr/web/images/form/resources/report_16.png"),
ElementCaseEditor.class);
}
\ No newline at end of file
+package com.fr.design.gui.core;
import javax.swing.Icon;
import com.fr.base.BaseUtils;
import com.fr.form.ui.ElementCaseEditor;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.WCardLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.form.ui.container.WHorizontalBoxLayout;
import com.fr.form.ui.container.WParameterLayout;
import com.fr.form.ui.container.WVerticalBoxLayout;
import com.fr.general.Inter;
/**
* Author : Shockway
* Date: 13-6-17
* Time: 上午10:40
*/
public class FormWidgetOption extends WidgetOption {
/**
* 返回名字
* @return 名字
*/
@Override
public String optionName() {
return null;
}
/**
* 返回图标
* @return 图标
*/
@Override
public Icon optionIcon() {
return null;
}
/**
* 组件类
* @return 类
*/
@Override
public Class extends Widget> widgetClass() {
return null;
}
/**
* 返回组件
* @return 控件
*/
@Override
public Widget createWidget() {
return null;
}
/*
* 表单容器
*/
public static WidgetOption[] getFormContainerInstance() {
return new WidgetOption[] { ABSOLUTELAYOUTCONTAINER, BORDERLAYOUTCONTAINER, HORIZONTALBOXLAYOUTCONTAINER, VERTICALBOXLAYOUTCONTAINER,
CARDLAYOUTCONTAINER, FITLAYOUTCONTAINER };
}
/**
* 表单工具栏上的布局
* @return 控件
*/
public static WidgetOption[] getFormLayoutInstance() {
return new WidgetOption[] {CARDLAYOUTCONTAINER/*, ABSOLUTELAYOUTCONTAINER*/};
}
public static final WidgetOption ABSOLUTELAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_AbsoluteLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_absolute_new.png"),
WAbsoluteLayout.class);
public static final WidgetOption BORDERLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_BorderLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_border.png"),
WBorderLayout.class);
public static final WidgetOption CARDLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_CardLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/card_layout_16.png"),
WCardLayout.class);
public static final WidgetOption HORIZONTALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_Layout-HBox"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_h_16.png"),
WHorizontalBoxLayout.class);
public static final WidgetOption VERTICALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_VerticalBoxLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"),
WVerticalBoxLayout.class);
public static final WidgetOption FITLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter.getLocText("FR-Designer-Layout_Adaptive_Layout"),
BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"),
WFitLayout.class);
public static final WidgetOption PARAMETERCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_Para-Body"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_parameter.png"),
WParameterLayout.class);
public static final WidgetOption ELEMENTCASE = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_Form-Report"), BaseUtils.readIcon("/com/fr/web/images/form/resources/report_16.png"),
ElementCaseEditor.class);
}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/mainframe/FormCreatorDropTarget.java b/designer_form/src/com/fr/design/mainframe/FormCreatorDropTarget.java
index ed4cf4190a..1172a4b645 100644
--- a/designer_form/src/com/fr/design/mainframe/FormCreatorDropTarget.java
+++ b/designer_form/src/com/fr/design/mainframe/FormCreatorDropTarget.java
@@ -20,11 +20,7 @@ import com.fr.design.designer.beans.HoverPainter;
import com.fr.design.designer.beans.Painter;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.beans.models.AddingModel;
-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.designer.creator.*;
import com.fr.design.form.util.XCreatorConstants;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.icon.IconPathConstants;
@@ -135,8 +131,16 @@ public class FormCreatorDropTarget extends DropTarget {
// 取消前一个焦点容器的提示渲染器
designer.setPainter(null);
}
-
- painter = AdapterBus.getContainerPainter(designer, container);
+ //获取painter的时候要考虑布局之间嵌套的问题
+ XLayoutContainer xLayoutContainer = container.getTopLayout();
+ if (xLayoutContainer != null && xLayoutContainer.getParent() != null
+ && ((XLayoutContainer)xLayoutContainer.getParent()).acceptType(XWAbsoluteLayout.class)){
+ if(!xLayoutContainer.isEditable()){
+ xLayoutContainer = (XLayoutContainer)xLayoutContainer.getParent();
+ }
+ }
+ painter = AdapterBus.getContainerPainter(designer,
+ xLayoutContainer != null && xLayoutContainer.acceptType(XWAbsoluteLayout.class) ? xLayoutContainer : container);
// 为界面设计器设置提示渲染提示器
designer.setPainter(painter);
diff --git a/designer_form/src/com/fr/design/mainframe/FormDesigner.java b/designer_form/src/com/fr/design/mainframe/FormDesigner.java
index 40add69153..544d89ec7d 100644
--- a/designer_form/src/com/fr/design/mainframe/FormDesigner.java
+++ b/designer_form/src/com/fr/design/mainframe/FormDesigner.java
@@ -46,7 +46,6 @@ import com.fr.general.Inter;
import com.fr.plugin.ExtraClassManager;
import com.fr.stable.ArrayUtils;
import com.fr.stable.bridge.StableFactory;
-import edu.emory.mathcs.backport.java.util.Arrays;
import javax.swing.*;
import javax.swing.border.Border;
@@ -60,6 +59,7 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
diff --git a/designer_form/src/com/fr/design/mainframe/FormDesignerUI.java b/designer_form/src/com/fr/design/mainframe/FormDesignerUI.java
index 9fc5cb1bfb..259e1b65ef 100644
--- a/designer_form/src/com/fr/design/mainframe/FormDesignerUI.java
+++ b/designer_form/src/com/fr/design/mainframe/FormDesignerUI.java
@@ -95,9 +95,9 @@ public class FormDesignerUI extends ComponentUI {
if (designer.getPainter() != null) {
// ComponentAdapter和LayoutAdapter提供的额外的Painter,该Painter一般用于提示作用,
- // 相当于一个浮动层
+ // 相当于一个浮动层, 要考虑参数面板的高度
designer.getPainter().paint(g, designer.getArea().getHorizontalValue(),
- designer.getArea().getVerticalValue());
+ designer.getArea().getVerticalValue() + designer.getParaHeight());
}
AddingModel addingModel = designer.getAddingModel();