/****************************************************************************** * Copyright (C) 2008 Low Heng Sin All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * *****************************************************************************/ package org.adempiere.webui; import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import org.adempiere.webui.component.Label; import org.adempiere.webui.component.Mask; import org.adempiere.webui.component.Tabpanel; import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.session.SessionManager; import org.compiere.util.Util; import org.zkoss.zk.au.out.AuOuter; import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.ui.AbstractComponent; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.HtmlBasedComponent; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.event.OpenEvent; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Cell; import org.zkoss.zul.Div; import org.zkoss.zul.Grid; import org.zkoss.zul.LayoutRegion; import org.zkoss.zul.Popup; import org.zkoss.zul.Row; import org.zkoss.zul.Rows; import org.zkoss.zul.Space; import org.zkoss.zul.Window; import org.zkoss.zul.Window.Mode; /** * Some static UI helper methods * @author Low Heng Sin * */ public final class LayoutUtils { public static final String ON_REDRAW_EVENT = "onRedraw"; /** * @param layout */ @Deprecated(forRemoval = true, since = "11") public static void sendDeferLayoutEvent(org.zkoss.zul.Borderlayout layout, int timeout) { /* this is not required anymore */ // StringBuilder content = new StringBuilder(); // content.append("ad_deferRenderBorderLayout('") // .append(layout.getUuid()) // .append("',").append(timeout).append(");"); // // AuScript as = new AuScript(null, content.toString()); // Clients.response("deferRenderBorderLayout", as); } /** * append cls to target's sclass property * @param cls * @param target */ public static void addSclass(String cls, HtmlBasedComponent target) { final String sclass = target.getSclass(); if (!hasSclass(cls, target)) target.setSclass(sclass == null ? cls : sclass + " " + cls); } /** * * @param cls * @param target * @return true if target's sclass property contain cls */ public static boolean hasSclass(String cls, HtmlBasedComponent target) { String sclass = target.getSclass(); if (sclass == null) sclass = ""; return cls == null || ((" " + sclass + " ").indexOf(" " + cls + " ") > -1); } /** * create right align label (wrapped in div) * @param label * @return right align label (wrapped in div) */ public static Component makeRightAlign(Label label) { Div div = new Div(); div.setStyle("text-align: right"); div.appendChild(label); return div; } /** * open popup window overlapping ref component * @param ref * @param window */ public static void openPopupWindow(Component ref, Window window) { openPopupWindow(ref, window, 0); } /** * open popup window overlapping ref component * @param ref * @param window * @param delayMs */ public static void openPopupWindow(Component ref, Window window, int delayMs) { openPopupWindow(ref, window, "overlap", delayMs); } /** * open popup window relative to ref component * @param ref * @param window * @param position Refer to https://www.zkoss.org/javadoc/latest/jsdoc/_global_/jqzk.html#position-_global_.Dimension-_global_.String-_global_.Map- */ public static void openPopupWindow(Component ref, Window window, String position) { openPopupWindow(ref, window, position, 0); } /** * open popup window relative to ref component * @param ref * @param window * @param position Refer to https://www.zkoss.org/javadoc/latest/jsdoc/_global_/jqzk.html#position-_global_.Dimension-_global_.String-_global_.Map- * @param delayMs */ public static void openPopupWindow(Component ref, Window window, String position, int delayMs) { if (window.getPage() == null) window.setPage(ref.getPage()); StringBuilder script = new StringBuilder(); if (delayMs > 0) { script.append("setTimeout(function() { "); } script.append("idempiere.show_popup_window('#") .append(ref.getUuid()) .append("','#") .append(window.getUuid()) .append("','") .append(position) .append("'); "); script.append("zk.Widget.$('#").append(window.getUuid()).append("').focus(); "); if (delayMs > 0) { script.append(" }, ").append(delayMs).append(");"); } window.doPopup(); Clients.response("_openPopupWindow_", new AuScript(window, script.toString())); window.focus(); } /** * open overlapped window (mode overlapped) relative to ref component * @param ref * @param window * @param position Refer to https://www.zkoss.org/javadoc/latest/jsdoc/_global_/jqzk.html#position-_global_.Dimension-_global_.String-_global_.Map- */ public static void openOverlappedWindow(Component ref, Window window, String position) { if (window.getPage() == null) window.setPage(ref.getPage()); StringBuilder script = new StringBuilder(); script.append("idempiere.show_popup_window('#") .append(ref.getUuid()) .append("','#") .append(window.getUuid()) .append("','") .append(position) .append("');"); window.doOverlapped(); Clients.response("_openPopupWindow_", new AuScript(window, script.toString())); } /** * position opened window relative to ref component * @param ref * @param window * @param position Refer to https://www.zkoss.org/javadoc/latest/jsdoc/_global_/jqzk.html#position-_global_.Dimension-_global_.String-_global_.Map- */ public static void positionWindow(Component ref, Window window, String position) { StringBuilder script = new StringBuilder(); script.append("idempiere.show_popup_window('#") .append(ref.getUuid()) .append("','#") .append(window.getUuid()) .append("','") .append(position) .append("');"); Clients.response("_openPopupWindow_", new AuScript(window, script.toString())); } /** * position component relative to ref component * @param ref * @param component * @param position Refer to https://www.zkoss.org/javadoc/latest/jsdoc/_global_/jqzk.html#position-_global_.Dimension-_global_.String-_global_.Map- */ public static void positionComponent(Component ref, Component component, String position) { StringBuilder script = new StringBuilder(); script.append("(function() {let w = zk('#") .append(component.getUuid()) .append("'); ") .append("let ref=zk.Widget.$('#") .append(ref.getUuid()) .append("'); ") .append("w.position(") .append("ref.$n(),'") .append(position) .append("');})()"); Clients.response("_positionComponent_", new AuScript(component, script.toString())); } /** * open embedded window relative to ref component * @param ref * @param window * @param position Refer to https://www.zkoss.org/javadoc/latest/jsdoc/_global_/jqzk.html#position-_global_.Dimension-_global_.String-_global_.Map- */ public static void openEmbeddedWindow(Component ref, Window window, String position) { StringBuilder script = new StringBuilder(); script.append("idempiere.show_popup_window('#") .append(ref.getUuid()) .append("','#") .append(window.getUuid()) .append("','") .append(position) .append("');"); window.setVisible(true); window.setMode(Mode.EMBEDDED); Clients.response("_openEmbeddedWindow_", new AuScript(window, script.toString())); } /** * open highlighted window relative to ref component * @param ref * @param window * @param position Refer to https://www.zkoss.org/javadoc/latest/jsdoc/_global_/jqzk.html#position-_global_.Dimension-_global_.String-_global_.Map- */ public static void openHighlightedWindow(Component ref, Window window, String position) { StringBuilder script = new StringBuilder(); script.append("idempiere.show_popup_window('#") .append(ref.getUuid()) .append("','#") .append(window.getUuid()) .append("','") .append(position) .append("');"); window.setMode(Mode.HIGHLIGHTED); Clients.response("_openHighlightedWindow_", new AuScript(window, script.toString())); } /** * Force redraw of component * @param component */ public static void redraw(AbstractComponent component) { StringWriter writer = new StringWriter(1024); try { component.redraw(writer); Clients.response(new AuOuter(component, writer.toString())); } catch (IOException e) { e.printStackTrace(); } } /** * @param component * @return true if the component and all its parent are visible */ public static boolean isReallyVisible(Component component) { if (!component.isVisible()) return false; Component parent = component.getParent(); while (parent != null) { if (!parent.isVisible()) return false; parent = parent.getParent(); } return true; } /** * Remove cls from target's sclass property * @param cls * @param target */ public static void removeSclass(String cls, HtmlBasedComponent target) { String sclass = target.getSclass(); if (Util.isEmpty(sclass)) return; sclass = " " + sclass + " "; cls = " " + cls + " "; if (sclass.indexOf(cls) >= 0) { sclass = sclass.replace(cls, " "); sclass = sclass.trim(); target.setSclass(sclass); } } public static final int OVERLAP_TAB_PANEL = 1; public static final int OVERLAP_ALL_PAGE = 2; public static final int OVERLAP_PARENT = 3; public static final int OVERLAP_SELF = 4; /** * show window with a mask below. Depends on ownModel flag, mask is shown over tabPanel, all window or over a component. *
* when ownModel is
* - {@link #OVERLAP_SELF}, mask childOfOwn. if childOfOwn doesn't implement {@link ISupportMask}, make new {@link Mask} object to mask it
* - {@link #OVERLAP_ALL_PAGE}, window show overlap all page
* - {@link #OVERLAP_TAB_PANEL}, window show overlap tabPanel
* - {@link #OVERLAP_PARENT}, search nearest parent of childOfOwn that implement {@link ISupportMask}, if not found use as OVERLAP_ALL_PAGE
*
* @param window
* @param childOfOwn Component below window
* @param ownModel OVERLAP_TAB_PANEL, OVERLAP_ALL_PAGE, OVERLAP_PARENT or OVERLAP_SELF
* @return when show success return ISupportMask object, use {@link ISupportMask#hideMask()} to hide mask.
*/
public static ISupportMask showWindowWithMask(Window window, Component childOfOwn, int ownModel){
ISupportMask ownWindow = null;
// search to top parent, capture parent with interface ISupportMask
if (ownModel == OVERLAP_SELF && ISupportMask.class.isInstance(childOfOwn)){
ownWindow = (ISupportMask) childOfOwn;
}else if (ownModel == OVERLAP_TAB_PANEL){
ownWindow = findMaskParent (childOfOwn, Tabpanel.class);
}else if (ownModel == OVERLAP_PARENT){
ownWindow = findMaskParent (childOfOwn, null);
}else if (ownModel == OVERLAP_ALL_PAGE){
IDesktop desktop = SessionManager.getAppDesktop();
if (desktop != null && ISupportMask.class.isInstance(desktop)){
ownWindow = (ISupportMask)desktop;
}
}
// show window
if (ownWindow != null){
showWindowWithMask (window, ownWindow);
}
return ownWindow;
}
/**
* Show window in center of mask
* @param window
* @param mask
*/
protected static void showWindowWithMask(Window window, ISupportMask mask){
mask.showMask();
mask.getMaskComponent().appendChild(window);
StringBuilder script = new StringBuilder("(function(){let w=zk.Widget.$('#");
script.append(mask.getMaskComponent().getUuid()).append("');");
script.append("let d=zk.Widget.$('#").append(window.getUuid()).append("');w.busy=d;");
script.append("})()");
Clients.response(new AuScript(script.toString()));
LayoutUtils.openOverlappedWindow(mask.getMaskComponent(), window, "middle_center");
}
/**
* Show window over ownWindow with a mask, use when ownWindow doesn't implement {@link ISupportMask}
* @param window
* @param ownWindow
* @param mask if mask = null, make new and return it
* @return {@link Mask} object for hidden mask when close window.
*/
public static Mask showWindowWithMask(Window window, Component ownWindow, Mask mask){
if (mask == null){
mask = new Mask();
}
ownWindow.appendChild(mask);
ownWindow.appendChild(window);
LayoutUtils.openOverlappedWindow(ownWindow, window, "middle_center");
return mask;
}
/**
* find nearest parent of child component that implement {@link ISupportMask}.