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 getJavaScriptActionPane(); + + FurtherBasicBeanPane 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 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 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 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();