From 1a095d2d0e953441865f84d5d9378aa597df3f8b Mon Sep 17 00:00:00 2001 From: hengsin Date: Fri, 20 Jan 2023 21:46:00 +0800 Subject: [PATCH] IDEMPIERE-5520 Navigation between Tabs leave Detached DOM objects (Leak) (#1637) - Partial fix plus workaround - Minor clean up and Javadoc fix - Create dynamic style for Detail Tabs only once --- .../org/adempiere/webui/AdempiereWebUI.java | 12 ++ .../adempiere/webui/adwindow/ADTabpanel.java | 65 ++++--- .../webui/adwindow/AbstractADTabbox.java | 46 ++++- .../adwindow/AbstractADWindowContent.java | 155 ++++++++++----- .../webui/adwindow/CompositeADTabbox.java | 25 ++- .../webui/adwindow/GridTabRowRenderer.java | 37 +++- .../src/org/adempiere/webui/apps/AEnv.java | 17 ++ .../adempiere/webui/component/Combobox.java | 16 +- .../org/adempiere/webui/component/Tab.java | 16 +- .../adempiere/webui/editor/WSearchEditor.java | 6 + .../adempiere/webui/editor/WStringEditor.java | 4 + .../webui/info/InfoProductWindow.java | 52 ++++- .../org/adempiere/webui/info/InfoWindow.java | 184 ++++++++++++++++-- .../org/adempiere/webui/panel/InfoPanel.java | 161 ++++++++++++++- .../org/adempiere/webui/panel/LoginPanel.java | 3 + .../org/adempiere/webui/panel/RolePanel.java | 3 + .../adempiere/webui/window/FindWindow.java | 14 +- .../adempiere/webui/window/LoginWindow.java | 7 + 18 files changed, 688 insertions(+), 135 deletions(-) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java index e5c4feaa81..c332cb836d 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java @@ -77,6 +77,7 @@ import org.zkoss.zk.ui.sys.DesktopCache; import org.zkoss.zk.ui.sys.SessionCtrl; import org.zkoss.zk.ui.sys.WebAppCtrl; import org.zkoss.zk.ui.util.Clients; +import org.zkoss.zul.Style; import org.zkoss.zul.Window; /** @@ -329,6 +330,17 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb Env.setContext(ctx, Env.IS_CAN_APPROVE_OWN_DOC, MRole.getDefault().isCanApproveOwnDoc()); Clients.response(new AuScript("zAu.cmd0.clearBusy()")); + //add dynamic style + StringBuilder cssContent = new StringBuilder(); + cssContent.append(".adtab-form-borderlayout .z-south-collapsed:before { "); + cssContent.append("content: \""); + cssContent.append(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Detail"))); + cssContent.append("\"; "); + cssContent.append("} "); + Style style = new Style(); + style.setContent(cssContent.toString()); + appendChild(style); + //init favorite FavouriteController.getInstance(currSess); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java index bea9d494a6..baa207ec3b 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTabpanel.java @@ -117,7 +117,6 @@ import org.zkoss.zul.RowRenderer; import org.zkoss.zul.Separator; import org.zkoss.zul.South; import org.zkoss.zul.Space; -import org.zkoss.zul.Style; import org.zkoss.zul.Tabpanels; import org.zkoss.zul.Tabs; import org.zkoss.zul.Toolbar; @@ -204,7 +203,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer private ArrayList rowList; - List allCollapsibleGroups; + protected List allCollapsibleGroups; private Borderlayout formContainer = null; @@ -411,16 +410,6 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer AD_Tree_ID = MTree.getDefaultAD_Tree_ID ( Env.getAD_Client_ID(Env.getCtx()), gridTab.getKeyColumnName()); - StringBuilder cssContent = new StringBuilder(); - cssContent.append(".adtab-form-borderlayout .z-south-collapsed:before { "); - cssContent.append("content: \""); - cssContent.append(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Detail"))); - cssContent.append("\"; "); - cssContent.append("} "); - Style style = new Style(); - style.setContent(cssContent.toString()); - appendChild(style); - if (gridTab.isTreeTab() && AD_Tree_ID != 0) { Borderlayout layout = new Borderlayout(); @@ -506,6 +495,10 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer createUI(false); } + /** + * + * @param update true if it is update instead of create new + */ protected void createUI(boolean update) { if (update) @@ -711,7 +704,6 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer Cell cell = (Cell) rowg.getFirstChild(); cell.setSclass("z-group-inner"); cell.setColspan(numCols+1); -// rowg.appendChild(cell); allCollapsibleGroups.add(rowg); if (X_AD_FieldGroup.FIELDGROUPTYPE_Tab.equals(field.getFieldGroupType()) || field.getIsCollapsedByDefault()) @@ -1390,6 +1382,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer /** * Refresh current row */ + @Override public void refresh() { gridTab.dataRefresh(); @@ -1399,6 +1392,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer * Activate/deactivate panel * @param activate */ + @Override public void activate(boolean activate) { if (activate) { @@ -1471,6 +1465,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer * @see EventListener#onEvent(Event) */ @SuppressWarnings("unchecked") + @Override public void onEvent(Event event) { if (event.getTarget() == listPanel.getListbox()) @@ -1606,9 +1601,6 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer MTreeNode treeNode = value.getData(); // We Have a TreeNode int nodeID = treeNode.getNode_ID(); - // root of tree selected - ignore - //if (nodeID == 0) - //return; // Search all rows for mode id int size = gridTab.getRowCount(); @@ -1639,6 +1631,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer * @param e * @see DataStatusListener#dataStatusChanged(DataStatusEvent) */ + @Override public void dataStatusChanged(DataStatusEvent e) { //ignore background event @@ -1946,6 +1939,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer /** * @see IADTabpanel#afterSave(boolean) */ + @Override public void afterSave(boolean onSaveEvent) { } @@ -1977,6 +1971,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer /** * @see IADTabpanel#onEnterKey() */ + @Override public boolean onEnterKey() { if (listPanel.isVisible()) { return listPanel.onEnterKey(); @@ -1987,6 +1982,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer /** * @return boolean */ + @Override public boolean isGridView() { return listPanel.isVisible(); } @@ -2022,8 +2018,13 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer private void attachDetailPane() { if (formContainer.getSouth() != null) { formContainer.getSouth().setVisible(true); - if (formContainer.getSouth().isOpen() && detailPane != null && detailPane.getParent() == null) { - formContainer.appendSouth(detailPane); + if (formContainer.getSouth().isOpen()) { + if (detailPane != null) { + if (detailPane.getParent() != formContainer.getSouth()) + formContainer.appendSouth(detailPane); + else + detailPane.setVisible(true); + } } } } @@ -2032,7 +2033,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer if (formContainer.getSouth() != null) { formContainer.getSouth().setVisible(false); if (detailPane != null && detailPane.getParent() != null) { - detailPane.detach(); + detailPane.setVisible(false); } } } @@ -2158,6 +2159,11 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer } } + /** + * + * @param toFocus + * @param checkCurrent true to check if form currently has focus (using zk.currentFocus) + */ protected void focusToEditor(WEditor toFocus, boolean checkCurrent) { Component c = toFocus.getComponent(); if (c instanceof EditorBox) { @@ -2220,10 +2226,18 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer savePreference("TreePanel.Width", width); } } + for(WEditor editor : editors) { + editor.getComponent().setWidgetListener("onFocus", null); + } super.onPageDetached(page); } - void savePreference(String attribute, String value) + /** + * + * @param attribute + * @param value + */ + protected void savePreference(String attribute, String value) { int windowId = getGridTab().getAD_Window_ID(); int adTabId = getGridTab().getAD_Tab_ID(); @@ -2248,6 +2262,9 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer } } + /** + * handle client info event + */ protected void onClientInfo() { if (!uiCreated || gridTab == null) return; int numCols=gridTab.getNumColumns(); @@ -2273,10 +2290,10 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer protected boolean isMobile() { return ClientInfo.isMobile(); } + @Override public void editorTraverse(Callback editorTaverseCallback) { - editorTraverse(editorTaverseCallback, editors); - + editorTraverse(editorTaverseCallback, editors); } @Override @@ -2334,6 +2351,10 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer } + /** + * + * @return {@link AbstractADWindowContenta} + */ public AbstractADWindowContent getADWindowContent() { return windowPanel; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADTabbox.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADTabbox.java index 64db9ecb88..6e78da3b63 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADTabbox.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADTabbox.java @@ -75,11 +75,16 @@ public abstract class AbstractADTabbox extends AbstractUIPart implements IADTabb doAddTab(gTab, tabPanel); }// addTab + /** + * handle add tab to tabbox + * @param tab + * @param tabPanel + */ protected abstract void doAddTab(GridTab tab, IADTabpanel tabPanel); /** * @param index of tab panel - * @return + * @return true if enable */ public boolean isEnabledAt(int index) { @@ -102,10 +107,10 @@ public abstract class AbstractADTabbox extends AbstractUIPart implements IADTabb } /** - * + * Updated selected tab index * @param oldIndex * @param newIndex - * @return + * @return true if successfully switch to newIndex */ public boolean updateSelectedIndex(int oldIndex, int newIndex) { @@ -186,8 +191,17 @@ public abstract class AbstractADTabbox extends AbstractUIPart implements IADTabb } } + /** + * handle tab selection changed event + * @param oldIndex + * @param newIndex + */ protected abstract void doTabSelectionChanged(int oldIndex, int newIndex); + /** + * @param index tab index + * @return true if tab is visible + */ public boolean isDisplay(int index) { if (index >= tabPanelList.size()) return false; @@ -203,10 +217,22 @@ public abstract class AbstractADTabbox extends AbstractUIPart implements IADTabb return true; } + /** + * @param fromIndex + * @param toIndex + * @return true if can navigate to toIndex + */ public boolean canNavigateTo(int fromIndex, int toIndex) { return canNavigateTo(fromIndex, toIndex, false); } + /** + * + * @param fromIndex + * @param toIndex + * @param checkRecordID true to validate record id of fromIndex tab + * @return true if can navigate to toIndex tab + */ public boolean canNavigateTo(int fromIndex, int toIndex, boolean checkRecordID) { IADTabpanel newTab = tabPanelList.get(toIndex); if (newTab instanceof ADTabpanel) @@ -308,6 +334,9 @@ public abstract class AbstractADTabbox extends AbstractUIPart implements IADTabb } // evaluate + /** + * Update display state of tab (visibility, activation and if need invalidate) + */ protected abstract void updateTabState(); /** @@ -318,6 +347,10 @@ public abstract class AbstractADTabbox extends AbstractUIPart implements IADTabb return tabPanelList.size(); } + /** + * @param index + * @return {@link IADTabpanel} + */ public IADTabpanel getADTabpanel(int index) { try @@ -331,11 +364,18 @@ public abstract class AbstractADTabbox extends AbstractUIPart implements IADTabb } } + /** + * Set newIndex as selected tab + * @param newIndex + */ public void setSelectedIndex(int newIndex) { int oldIndex = getSelectedIndex(); updateSelectedIndex(oldIndex, newIndex); } + /** + * @param abstractADWindowPanel + */ public void setADWindowPanel(AbstractADWindowContent abstractADWindowPanel) { this.adWindowPanel = abstractADWindowPanel; } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java index ed69703843..812afc4794 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java @@ -254,6 +254,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements return comp; } + /** + * + * @return {@link BreadCrumb} + */ public BreadCrumb getBreadCrumb() { return breadCrumb; @@ -293,6 +297,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements */ protected abstract IADTabbox createADTab(); + /** + * handle switching of editing status + * @param editStatus true if editing (dirty) + */ protected abstract void switchEditStatus(boolean editStatus); /** @@ -793,7 +801,8 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements getComponent().addEventListener("onInitialQuery", new EventListener() { @Override public void onEvent(Event event) throws Exception { - getComponent().getParent().appendChild(findWindow); + if (findWindow.getParent() != getComponent().getParent()) + getComponent().getParent().appendChild(findWindow); LayoutUtils.openEmbeddedWindow(getComponent().getParent(), findWindow, "overlap"); } }); @@ -824,11 +833,19 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements findWindow.setContentStyle("background-color: #fff; width: 99%; margin: auto;"); } + /** + * + * @return title of window + */ public String getTitle() { return title; } + /** + * + * @return {@link MImage} + */ public MImage getImage() { return image; @@ -837,6 +854,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onDetailRecord() */ + @Override public void onDetailRecord() { adTabbox.onDetailRecord(); @@ -845,6 +863,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onParentRecord() */ + @Override public void onParentRecord() { List parents = breadCrumb.getParentLinks(); @@ -856,6 +875,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onFirst() */ + @Override public void onFirst() { Callback callback = new Callback() { @@ -873,6 +893,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onLast() */ + @Override public void onLast() { Callback callback = new Callback() { @@ -890,6 +911,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onNext() */ + @Override public void onNext() { Callback callback = new Callback() { @@ -907,6 +929,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onPrevious() */ + @Override public void onPrevious() { Callback callback = new Callback() { @@ -922,7 +945,9 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements } /** - * @see ToolbarListener#onPrevious() + * handle tree navigation + * @param gt + * @param rowIndex */ public void onTreeNavigate(final GridTab gt, final int rowIndex) { @@ -931,7 +956,6 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements public void onCallback(Boolean result) { if (result) { gt.navigate(rowIndex); - //focusToActivePanel(); } } }; @@ -955,6 +979,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onLock() */ + @Override public void onLock() { if (!toolbar.isPersonalLock) @@ -1017,6 +1042,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onAttachment() */ + @Override public void onAttachment() { int record_ID = adTabbox.getSelectedGridTab().getRecord_ID(); @@ -1049,6 +1075,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements win.focus(); } + @Override public void onChat() { int recordId = adTabbox.getSelectedGridTab().getRecord_ID(); @@ -1093,6 +1120,9 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements chat.showWindow(); } + /** + * handle post it event + */ public void onPostIt() { int recordId = adTabbox.getSelectedGridTab().getRecord_ID(); @@ -1146,6 +1176,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onToggle() */ + @Override public void onToggle() { adTabbox.getSelectedTabpanel().switchRowPresentation(); @@ -1257,6 +1288,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements * @param event * @see EventListener#onEvent(Event) */ + @Override public void onEvent(Event event) { if (CompositeADTabbox.ON_SELECTION_CHANGED_EVENT.equals(event.getName())) @@ -1407,6 +1439,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements } + /** + * save (if needed) and execute callback + * @param callback + */ public void saveAndNavigate(final Callback callback) { if (adTabbox != null) { @@ -1566,6 +1602,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements * @param e * @see DataStatusListener#dataStatusChanged(DataStatusEvent) */ + @Override public void dataStatusChanged(DataStatusEvent e) { //ignore non-ui thread event. @@ -1955,9 +1992,6 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements toolbar.enableRequests(!isNewRow); toolbar.setPressed("Find", adTabbox.getSelectedGridTab().isQueryActive() || (!isNewRow && (m_onlyCurrentRows || m_onlyCurrentDays > 0))); - /*if (adTabbox.getSelectedGridTab().isQueryActive() && - tabFindWindowHashMap.get(adTabbox.getSelectedGridTab()) != null) - findWindow = tabFindWindowHashMap.get(adTabbox.getSelectedGridTab());*/ toolbar.refreshUserQuery(adTabbox.getSelectedGridTab().getAD_Tab_ID(), getCurrentFindWindow() != null ? getCurrentFindWindow().getAD_UserQuery_ID() : 0); toolbar.enablePrint(adTabbox.getSelectedGridTab().isPrinted() && !isNewRow); @@ -2091,51 +2125,21 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onRefresh() */ + @Override public void onRefresh() { GridTab gridTab = adTabbox.getSelectedGridTab(); - /*if (gridTab != null && gridTab.getTableModel() != null) - { - gridTab.getTableModel().resetCacheSortState(); - } - Column sortColumn = findCurrentSortColumn();*/ onRefresh(true, false); - /*if (sortColumn != null) - { - sortColumn.setSortDirection("natural"); - }*/ if (gridTab.isSortTab()) { // refresh is not refreshing sort tabs IADTabpanel tabPanel = adTabbox.getSelectedTabpanel(); tabPanel.query(false, 0, 0); } } -/* - private Column findCurrentSortColumn() { - IADTabpanel iadtabpanel = getADTab().getSelectedTabpanel(); - if (iadtabpanel instanceof ADTabpanel) { - ADTabpanel adtabpanel = (ADTabpanel) iadtabpanel; - Grid grid = adtabpanel.getGridView().getListbox(); - Columns columns = grid.getColumns(); - if (columns != null) { - List list = columns.getChildren(); - for(int i = 0; i < list.size(); i++) - { - Component c = (Component) list.get(i); - if (c instanceof Column) { - Column column = (Column) c; - if (!"natural".equals(column.getSortDirection())) { - return column; - } - } - } - } - } - return null; - } -*/ + /** * @see ToolbarListener#onHelp() */ + @Override public void onHelp() { closeToolbarPopup("Help"); @@ -2289,6 +2293,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onFind() */ + @Override public void onFind() { if (adTabbox.getSelectedGridTab() == null) @@ -2373,7 +2378,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements }); } - getComponent().getParent().appendChild(getCurrentFindWindow()); + if (getCurrentFindWindow().getParent() != getComponent().getParent()) + getComponent().getParent().appendChild(getCurrentFindWindow()); + else + getCurrentFindWindow().setVisible(true); showBusyMask(getCurrentFindWindow()); LayoutUtils.openEmbeddedWindow(toolbar, getCurrentFindWindow(), "after_start"); } @@ -2515,6 +2523,12 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements }); } + /** + * + * @param onSaveEvent + * @param onNavigationEvent + * @param callback + */ public void onSave(final boolean onSaveEvent, final boolean onNavigationEvent, final Callback callback) { final Callback postCallback = new Callback() { @Override @@ -2543,6 +2557,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements WindowValidatorManager.getInstance().fireWindowValidatorEvent(event, preCallback); } + /** + * handle WPaymentEditor.ON_SAVE_PAYMENT event. + * Do not call this directly + */ public void onSavePayment() { onSave(false, false, new Callback() { @@ -2555,9 +2573,6 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements }); } - /** - * @param onSaveEvent - */ private void onSaveCallback(final boolean onSaveEvent, final boolean onNavigationEvent, final Callback callback) { final boolean wasChanged = toolbar.isSaveEnable(); @@ -2720,6 +2735,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onSaveCreate() */ + @Override public void onSaveCreate() { onSave(true, true, new Callback() { @@ -3037,6 +3053,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onReport() */ + @Override public void onReport() { if (!MRole.getDefault().isCanReport(adTabbox.getSelectedGridTab().getAD_Table_ID())) { @@ -3066,6 +3083,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onZoomAcross() */ + @Override public void onZoomAcross() { if (toolbar.getEvent() != null) { @@ -3098,6 +3116,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onActiveWorkflows() */ + @Override public void onActiveWorkflows() { if (toolbar.getEvent() != null) { @@ -3128,6 +3147,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onRequests() */ + @Override public void onRequests() { if (toolbar.getEvent() != null) @@ -3149,6 +3169,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onProductInfo() */ + @Override public void onProductInfo() { closeToolbarPopup("ProductInfo"); @@ -3161,6 +3182,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * @see ToolbarListener#onArchive() */ + @Override public void onArchive() { if (toolbar.getEvent() != null) @@ -3528,6 +3550,9 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements return mask; } + /** + * hide busy mask + */ public void hideBusyMask() { if (mask != null && mask.getParent() != null) { mask.detach(); @@ -3538,6 +3563,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements } } + /** + * show busy mask over window + * @param window + */ public void showBusyMask(Window window) { getComponent().getParent().appendChild(getMask()); StringBuilder script = new StringBuilder("(function(){let w=zk.Widget.$('#"); @@ -3595,6 +3624,14 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements return false; } + /** + * + * @param wButton + * @param startWOasking + * @param table_ID + * @param record_ID + * @param isProcessMandatory + */ public void executeButtonProcess(final IProcessButton wButton, final boolean startWOasking, final int table_ID, final int record_ID, boolean isProcessMandatory) { @@ -3797,6 +3834,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements * @param event * @see ActionListener#actionPerformed(ActionEvent) */ + @Override public void actionPerformed(final ActionEvent event) { Runnable runnable = new Runnable() { @@ -3857,6 +3895,11 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements } } // processButtonCallout + /** + * + * @param button + * @return {@link IADTabpanel} + */ public IADTabpanel findADTabpanel(IProcessButton button) { IADTabpanel adtab = null; if (button.getADTabpanel() != null) @@ -3982,6 +4025,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements * @see CustomizeGridViewDialog * @see ToolbarListener#onCustomize() */ + @Override public void onCustomize() { ADTabpanel tabPanel = (ADTabpanel) getADTab().getSelectedTabpanel(); CustomizeGridViewDialog.onCustomize(tabPanel, b -> { @@ -4013,18 +4057,35 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements } } + /** + * + * @return true if dirty + */ public boolean isPendingChanges() { return adTabbox.getDirtyADTabpanel() != null; } + /** + * + * @param adwindow + */ public void setADWindow(ADWindow adwindow) { this.adwindow = adwindow; } + /** + * + * @return {@link ADWindow} + */ public ADWindow getADWindow() { return adwindow; } + /** + * + * @param findFields + * @return true if find window found and init ok + */ public boolean getFindWindow(GridField[] findFields) { FindWindow findWindow = getCurrentFindWindow(); if (findWindow != null && isCurrentFindWindowValid()) { @@ -4046,6 +4107,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements return true; } + /** + * + * @return {@link FindWindow} + */ public FindWindow getCurrentFindWindow() { return tabFindWindowHashMap.get(adTabbox.getSelectedGridTab()); } @@ -4114,10 +4179,10 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements /** * Implementation to work key listener for the current open Quick Form. */ - QuickGridView currQGV = null; + protected QuickGridView currQGV = null; /** - * @return + * @return {@link QuickGridView} */ public QuickGridView getCurrQGV() { diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/CompositeADTabbox.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/CompositeADTabbox.java index 5733b59306..cd639b7b24 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/CompositeADTabbox.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/CompositeADTabbox.java @@ -86,6 +86,10 @@ public class CompositeADTabbox extends AbstractADTabbox public CompositeADTabbox(){ } + /** + * Create detail panel at bottom + * @return {@link DetailPane} + */ protected DetailPane createDetailPane() { DetailPane detailPane = new DetailPane(); detailPane.setEventListener(new EventListener() { @@ -285,6 +289,11 @@ public class CompositeADTabbox extends AbstractADTabbox } } + /** + * Edit selected detail tab + * @param row + * @param formView + */ protected void onEditDetail(int row, boolean formView) { int oldIndex = selectedIndex; @@ -318,6 +327,7 @@ public class CompositeADTabbox extends AbstractADTabbox } } + @Override protected Component doCreatePart(Component parent) { layout = new Vlayout(); @@ -550,15 +560,18 @@ public class CompositeADTabbox extends AbstractADTabbox /** * Return the selected Tab Panel */ + @Override public IADTabpanel getSelectedTabpanel() { return tabPanelList.isEmpty() ? null : tabPanelList.get(selectedIndex); } + @Override public int getSelectedIndex() { return selectedIndex; } + @Override public void setSelectionEventListener(EventListener listener) { selectionListener = listener; } @@ -575,8 +588,8 @@ public class CompositeADTabbox extends AbstractADTabbox newTabpanel.setVisible(true); headerTab = newTabpanel; - layout.getChildren().clear(); - layout.appendChild(headerTab); + if (headerTab.getParent() != layout) + layout.appendChild(headerTab); //set state headerTab.setDetailPaneMode(false); @@ -643,7 +656,8 @@ public class CompositeADTabbox extends AbstractADTabbox if (tabPanel.isActivated() && !tabPanel.isGridView()) { tabPanel.switchRowPresentation(); } - if (tabPanel.getParent() != null) tabPanel.detach(); + if (tabPanel.getParent() != null) + tabPanel.setVisible(false); } tabPanel.setDetailPaneMode(true); detailPane.setADTabpanel(tabIndex, tabPanel, tabLabel, enable.booleanValue()); @@ -797,6 +811,7 @@ public class CompositeADTabbox extends AbstractADTabbox return breadCrumb; } + @Override public Component getComponent() { return layout; } @@ -875,6 +890,10 @@ public class CompositeADTabbox extends AbstractADTabbox } } + /** + * + * @return true if selected detail tab have been activated + */ public boolean isDetailActivated() { if (headerTab instanceof ADTabpanel) { ADTabpanel atp = (ADTabpanel) headerTab; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/GridTabRowRenderer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/GridTabRowRenderer.java index 78acc12192..0af5116ab4 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/GridTabRowRenderer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/GridTabRowRenderer.java @@ -51,12 +51,14 @@ import org.compiere.util.Env; import org.compiere.util.Msg; import org.compiere.util.Util; import org.zkoss.zk.au.out.AuScript; +import org.zkoss.zk.ui.AbstractComponent; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.HtmlBasedComponent; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.sys.ComponentCtrl; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Cell; import org.zkoss.zul.Grid; @@ -169,13 +171,18 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt } } + /** + * + * @param field + * @return column index, -1 if not found + */ public int getColumnIndex(GridField field) { GridField[] fields = gridPanel.getFields(); for(int i = 0; i < fields.length; i++) { if (fields[i] == field) return i; } - return 0; + return -1; } private Component createReadonlyCheckbox(Object value) { @@ -342,9 +349,6 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt final int MAX_TEXT_LENGTH = MSysConfig.getIntValue(MSysConfig.MAX_TEXT_LENGTH_ON_GRID_VIEW,MAX_TEXT_LENGTH_DEFAULT,Env.getAD_Client_ID(Env.getCtx())); if (text != null && text.length() > MAX_TEXT_LENGTH) display = text.substring(0, MAX_TEXT_LENGTH - 3) + "..."; - // since 5.0.8, the org.zkoss.zhtml.Text is encoded by default -// if (display != null) -// display = XMLs.encodeText(display); label.setValue(display); if (text != null && text.length() > MAX_TEXT_LENGTH) label.setTooltiptext(text); @@ -539,11 +543,14 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt if (readOnlyEditor != null) { readOnlyEditors.put(gridPanelFields[i], readOnlyEditor); } - - editor.getComponent().setWidgetOverride("fieldHeader", HelpController.escapeJavascriptContent(gridPanelFields[i].getHeader())); - editor.getComponent().setWidgetOverride("fieldDescription", HelpController.escapeJavascriptContent(gridPanelFields[i].getDescription())); - editor.getComponent().setWidgetOverride("fieldHelp", HelpController.escapeJavascriptContent(gridPanelFields[i].getHelp())); - editor.getComponent().setWidgetListener("onFocus", "zWatch.fire('onFieldTooltip', this, null, this.fieldHeader(), this.fieldDescription(), this.fieldHelp());"); + + if (editor.getComponent() instanceof AbstractComponent) { + editor.getComponent().setWidgetOverride("fieldHeader", HelpController.escapeJavascriptContent(gridPanelFields[i].getHeader())); + editor.getComponent().setWidgetOverride("fieldDescription", HelpController.escapeJavascriptContent(gridPanelFields[i].getDescription())); + editor.getComponent().setWidgetOverride("fieldHelp", HelpController.escapeJavascriptContent(gridPanelFields[i].getHelp())); + editor.getComponent().setWidgetListener("onFocus", "zWatch.fire('onFieldTooltip', this, null, this.fieldHeader(), this.fieldDescription(), this.fieldHelp());"); + ((AbstractComponent)editor.getComponent()).addCallback(ComponentCtrl.AFTER_PAGE_DETACHED, (t) -> {((AbstractComponent)t).setWidgetListener("onFocus", null);}); + } // Default Focus if (defaultFocusField == null && gridPanelFields[i].isDefaultFocus()) @@ -778,6 +785,7 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt /** * @see RowRendererExt#getControls() */ + @Override public int getControls() { return DETACH_ON_RENDER; } @@ -785,6 +793,7 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt /** * @see RowRendererExt#newCell(Row) */ + @Override public Component newCell(Row row) { return null; } @@ -792,6 +801,7 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt /** * @see RowRendererExt#newRow(Grid) */ + @Override public Row newRow(Grid grid) { return null; } @@ -799,18 +809,21 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt /** * @see RendererCtrl#doCatch(Throwable) */ + @Override public void doCatch(Throwable ex) throws Throwable { } /** * @see RendererCtrl#doFinally() */ + @Override public void doFinally() { } /** * @see RendererCtrl#doTry() */ + @Override public void doTry() { } @@ -847,6 +860,10 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt } } + /** + * + * @param toFocus + */ protected void focusToEditor(WEditor toFocus) { Component c = toFocus.getComponent(); if (c instanceof EditorBox) { @@ -915,7 +932,7 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt } /** - * @return boolean + * @return true if it is in edit mode, false otherwise */ public boolean isEditing() { return editing; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AEnv.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AEnv.java index 5d6cd5296b..d243c65555 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AEnv.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AEnv.java @@ -80,6 +80,7 @@ import org.zkoss.zk.ui.Execution; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zul.impl.InputElement; import com.lowagie.text.DocumentException; @@ -874,4 +875,20 @@ public final class AEnv } return false; } + + /** + * Workaround for detached HTML input element leak + * @param c + */ + public static void detachInputElement(Component c) { + if (c instanceof InputElement) { + c.detach(); + } + if (c.getChildren().size() > 0) { + Component[] childs = c.getChildren().toArray(new Component[0]); + for(Component c1 : childs) { + detachInputElement(c1); + } + } + } } // AEnv diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Combobox.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Combobox.java index 89fab02309..e8fea7d65c 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Combobox.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Combobox.java @@ -23,6 +23,7 @@ import org.adempiere.webui.AdempiereIdGenerator; import org.adempiere.webui.LayoutUtils; import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.ui.IdSpace; +import org.zkoss.zk.ui.Page; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.util.Clients; @@ -172,15 +173,6 @@ public class Combobox extends org.zkoss.zul.Combobox implements IdSpace return item.getValue().equals(value); } - //TODO: Find zk6 replacement - /** Returns RS_NO_WIDTH|RS_NO_HEIGHT. - */ - /* - protected int getRealStyleFlags() { - return super.getRealStyleFlags() & 0x0006; - } - */ - //http://jira.idempiere.com/browse/IDEMPIERE-443 //undocumented api hack to ensure onSelect always fire for mouse selection public void clearLastSel() { @@ -196,4 +188,10 @@ public class Combobox extends org.zkoss.zul.Combobox implements IdSpace String script = "(function(me){let id='#'+me.uuid+'-pp .z-comboitem-selected';let selected=zk($(id));if(selected.jq.length==1)selected.scrollIntoView();})(this)"; setWidgetListener("onKeyUp", script); } + + @Override + public void onPageDetached(Page page) { + setWidgetListener("onKeyUp", null); + super.onPageDetached(page); + } } \ No newline at end of file diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tab.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tab.java index 457fe9029f..ecbe201460 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tab.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/Tab.java @@ -22,6 +22,7 @@ import java.util.HashSet; import java.util.Set; import org.adempiere.webui.adwindow.ADWindow; +import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.util.ManageImageCache; import org.compiere.model.MImage; @@ -31,6 +32,8 @@ import org.compiere.util.Env; import org.compiere.util.Util; import org.zkoss.image.Image; import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.event.SelectEvent; import org.zkoss.zul.Include; @@ -180,16 +183,27 @@ public class Tab extends org.zkoss.zul.Tab ((Tabbox)getTabbox()).removeTabFromActiveSeq(this); } + //Workaround for detached HTML input element leak + if (panel != null) { + Executions.schedule(getDesktop(), e -> panel.detach(), new Event("onCloseLinkedPanel")); + } + detach(); if (panel != null) { + //Workaround for detached HTML input element leak + if (panel.getChildren().size() > 0) { + Component[] childs = panel.getChildren().toArray(new Component[0]); + for(Component c : childs) { + AEnv.detachInputElement(c); + } + } // B60-ZK-1160: Exception when closing tab with included content // Must clean up included content before detaching tab panel Component include = panel.getFirstChild(); if (include instanceof Include) { include.detach(); } - panel.detach(); } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java index 6455b96988..3f67fdf265 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WSearchEditor.java @@ -922,6 +922,12 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value } } } + + @Override + public void onPageDetached(Page page) { + setWidgetListener("onChange", null); + super.onPageDetached(page); + } } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WStringEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WStringEditor.java index 23342f42f2..baf0cf83b9 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WStringEditor.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WStringEditor.java @@ -35,10 +35,12 @@ import org.adempiere.webui.window.WTextEditorDialog; import org.compiere.model.GridField; import org.compiere.model.I_R_MailText; import org.compiere.util.DisplayType; +import org.zkoss.zk.ui.AbstractComponent; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.sys.ComponentCtrl; /** * @@ -188,6 +190,8 @@ public class WStringEditor extends WEditor implements ContextMenuListener if (gridField != null) getComponent().setPlaceholder(gridField.getPlaceholder()); } + + getComponent().addCallback(ComponentCtrl.AFTER_PAGE_DETACHED, t -> ((AbstractComponent)t).setWidgetListener("onBind", null)); } public void onEvent(Event event) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoProductWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoProductWindow.java index ad6d2d0b91..7dfc0854e3 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoProductWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoProductWindow.java @@ -1,6 +1,27 @@ -/** - * - */ +/*********************************************************************** + * This file is part of iDempiere ERP Open Source * + * http://www.idempiere.org * + * * + * Copyright (C) Contributors * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301, USA. * + * * + * Contributors: * + * - hengsin * + **********************************************************************/ package org.adempiere.webui.info; import java.sql.PreparedStatement; @@ -195,7 +216,6 @@ public class InfoProductWindow extends InfoWindow { warehouseTbl.setShowTotals(true); warehouseTbl.autoSize(); warehouseTbl.setwListBoxName("AD_InfoWindow_UU|"+ infoWindow.getAD_InfoWindow_UU() +"|stock"); -// warehouseTbl.getModel().addTableModelListener(this); ColumnInfo[] s_layoutSubstitute = new ColumnInfo[]{ new ColumnInfo(Msg.translate(Env.getCtx(), "Warehouse"), "orgname", String.class, true, "orgname"), @@ -214,7 +234,6 @@ public class InfoProductWindow extends InfoWindow { substituteTbl.setMultiSelection(false); substituteTbl.autoSize(); substituteTbl.setwListBoxName("AD_InfoWindow_UU|"+ infoWindow.getAD_InfoWindow_UU() + "|substitute"); -// substituteTbl.getModel().addTableModelListener(this); ColumnInfo[] s_layoutRelated = new ColumnInfo[]{ new ColumnInfo(Msg.translate(Env.getCtx(), "Warehouse"), "orgname", String.class, true, "orgname"), @@ -274,7 +293,6 @@ public class InfoProductWindow extends InfoWindow { productpriceTbl.setMultiSelection(false); productpriceTbl.autoSize(); productpriceTbl.setwListBoxName("AD_InfoWindow_UU|" + infoWindow.getAD_InfoWindow_UU() + "|price"); -// productpriceTbl.getModel().addTableModelListener(this); tabbedPane = new Tabbox(); ZKUpdateUtil.setHeight(tabbedPane, "100%"); @@ -415,6 +433,9 @@ public class InfoProductWindow extends InfoWindow { m_tableAtp.repaint(); } + /** + * handle on click event for product attribute + */ protected void onPAttributeClick() { Integer productInteger = getSelectedRowKey(); if (productInteger == null) { @@ -443,6 +464,10 @@ public class InfoProductWindow extends InfoWindow { }); } + /** + * + * @return label for selected warehouse parameter + */ protected String getSelectedWarehouseLabel() { for(WEditor editor : editors) { if (editor.getGridField() != null && editor.getGridField().getColumnName().equals("M_Warehouse_ID")) { @@ -456,6 +481,10 @@ public class InfoProductWindow extends InfoWindow { return ""; } + /** + * + * @return id for selected price list version parameter + */ protected int getSelectedPriceListVersionId() { for(WEditor editor : editors) { if (editor.getGridField() != null && editor.getGridField().getColumnName().equals("M_PriceList_Version_ID")) { @@ -469,6 +498,10 @@ public class InfoProductWindow extends InfoWindow { return 0; } + /** + * + * @return id for selected warehouse parameter + */ protected int getSelectedWarehouseId() { for(WEditor editor : editors) { if (editor.getGridField() != null && editor.getGridField().getColumnName().equals("M_Warehouse_ID")) { @@ -636,6 +669,8 @@ public class InfoProductWindow extends InfoWindow { /** * Refresh Query + * @param M_Warehouse_ID + * @param M_PriceList_Version_ID */ protected void refresh(int M_Warehouse_ID, int M_PriceList_Version_ID) { @@ -719,7 +754,7 @@ public class InfoProductWindow extends InfoWindow { // Elaine 2008/11/26 /** - * Query ATP + * Query Avaiable to promise (ATP) * @param m_M_Warehouse_ID * @param m_M_Product_ID */ @@ -873,6 +908,9 @@ public class InfoProductWindow extends InfoWindow { m_tableAtp.setData(model, columnNames); } // initAtpTab + /** + * @return true if show detail of ATP + */ public boolean isShowDetailATP() { return chbShowDetailAtp.isChecked(); } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java index 8077791b86..94ed6a239d 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java @@ -1,6 +1,24 @@ -/** - * - */ +/*********************************************************************** + * This file is part of iDempiere ERP Open Source * + * http://www.idempiere.org * + * * + * Copyright (C) Contributors * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301, USA. * + **********************************************************************/ package org.adempiere.webui.info; import java.io.File; @@ -128,6 +146,7 @@ import org.zkoss.zul.South; import org.zkoss.zul.Space; import org.zkoss.zul.Vbox; import org.zkoss.zul.Vlayout; +import org.zkoss.zul.event.ZulEvents; import org.zkoss.zul.impl.InputElement; /** @@ -155,9 +174,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL protected Properties infoContext; /** embedded Panel **/ - Tabbox embeddedPane = new Tabbox(); - ArrayList embeddedWinList = new ArrayList (); - Map relatedMap = new HashMap<>(); + protected Tabbox embeddedPane = new Tabbox(); + protected ArrayList embeddedWinList = new ArrayList (); + protected Map relatedMap = new HashMap<>(); /** Max Length of Fields */ public static final int FIELDLENGTH = 20; @@ -579,6 +598,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } } + /** + * process query value from input element + */ protected void processQueryValue() { isQueryByUser = true; for (int i = 0; i < identifiers.size(); i++) { @@ -650,6 +672,10 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } } + /** + * load info window definition + * @return true if loaded ok + */ protected boolean loadInfoDefinition() { if (infoWindow != null) { String tableName = null; @@ -790,7 +816,10 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } } - //private InfoColumnVO[] topinfoColumns;//infoWindow.getInfoColumns(tableInfos); + /** + * load related info + * @return true if loaded ok + */ protected boolean loadInfoRelatedTabs() { if (infoWindow == null) return false; @@ -891,6 +920,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL return true; } + /** + * setup list box and construct sql query clause + */ protected void prepareTable() { List list = new ArrayList(); String keyTableAlias = tableInfos[0].getSynonym() != null && tableInfos[0].getSynonym().trim().length() > 0 @@ -970,6 +1002,13 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL prepareTable(columnInfos, infoWindow.getFromClause(), p_whereClause, infoWindow.getOrderByClause()); } + /** + * + * @param tableInfos + * @param gridField + * @param infoColumn + * @return {@link ColumnInfo} + */ protected ColumnInfo createLookupColumnInfo(TableInfo[] tableInfos, GridField gridField, InfoColumnVO infoColumn) { String columnName = gridField.getColumnName(); @@ -1186,6 +1225,11 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL return sql; } + /** + * + * @param gridField + * @return {@link InfoColumnVO} if found, null otherwise + */ protected InfoColumnVO findInfoColumn(GridField gridField) { for(int i = 0; i < gridFields.size(); i++) { if (gridFields.get(i) == gridField) { @@ -1195,6 +1239,11 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL return null; } + /** + * + * @param gridField + * @return {@link InfoColumnVO} if found, null otherwise + */ protected InfoColumnVO findInfoColumnParameter(GridField gridField) { for (Integer i : parameterTree.keySet()) { List list = parameterTree.get(i); @@ -1279,6 +1328,15 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } + /** + * + * @param editor + * @param infoColumnVO + * @param pstmt + * @param parameterIndex current parameter index + * @return current parameter index + * @throws SQLException + */ protected int setParameter(WEditor editor, InfoColumnVO infoColumnVO, PreparedStatement pstmt, int parameterIndex) throws SQLException { if(editor == null) return parameterIndex; @@ -1437,6 +1495,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } + /** + * layout window UI elements + */ protected void renderWindow() { // Load User Def @@ -1497,8 +1558,22 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL cbbProcess.setDisabled(true); } // IDEMPIERE-1334 end + + paging = new Paging(); + paging.setPageSize(pageSize); + paging.setTotalSize(0); + paging.setDetailed(true); + paging.addEventListener(ZulEvents.ON_PAGING, this); + paging.setActivePage(0); + pageNo = 0; + insertPagingComponent(); + paging.setVisible(false); } + /** + * layout footer + * @param south + */ protected void renderFooter(South south) { southBody = new Vbox(); ZKUpdateUtil.setHflex(southBody, "1"); @@ -1509,11 +1584,16 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL southBody.appendChild(statusBar); } + @Override protected void insertPagingComponent() { southBody.insertBefore(paging, southBody.getFirstChild()); layout.invalidate(); } + /** + * layout center content pane + * @param center + */ protected void renderContentPane(Center center) { Div div = new Div(); div.setStyle("width :100%; height: 100%"); @@ -1554,15 +1634,26 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL center.appendChild(inner); } + /** + * layout query parameter pane + * @param north + */ protected void renderParameterPane(North north) { createParameterPanel(); north.appendChild(parameterGrid); } + /** + * create query parameter panel + */ protected void createParameterPanel() { layoutParameterGrid(false); } + /** + * layout query parameter panel + * @param update + */ protected void layoutParameterGrid(boolean update) { if (!update) { parameterGrid = GridFactory.newGridLayout(); @@ -1659,6 +1750,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL dynamicDisplay(null); } + /** + * evaluate display logic for input parameters + */ protected void evalDisplayLogic() { int idx = 0; for(WEditor editor : editors) { @@ -1684,7 +1778,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL /** * Add Selection Column to first Tab - * @param infoColumn + * @param infoColumn * @param mField field **/ protected void addSelectionColumn(InfoColumnVO infoColumn, GridField mField, GridField mField2) @@ -1765,6 +1859,11 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } // addSelectionColumn + /** + * add search parameter + * @param editor + * @param editor2 + */ protected void addSearchParameter(WEditor editor, WEditor editor2) { Label label = editor.getLabel(); Component fieldEditor = editor.getComponent(); @@ -1835,6 +1934,10 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL panel.appendChild(outerParent); } + /** + * + * @return number of columns for parameter grid + */ protected int getNoOfParameterColumns() { if (ClientInfo.maxWidth(ClientInfo.SMALL_WIDTH-1)) return 2; @@ -1844,6 +1947,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL return 6; } + /** + * create checkbox for AND + */ protected void createAndCheckbox() { checkAND = new Checkbox(); checkAND.setLabel(Msg.getMsg(Env.getCtx(), "SearchAND", true)); @@ -1856,6 +1962,11 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL checkAND.addEventListener(Events.ON_CHECK, this); } + /** + * + * @param columnName + * @return column index, -1 if not found + */ protected int findColumnIndex(String columnName) { for(int i = 0; i < columnInfos.length; i++) { GridField field = columnInfos[i].getGridField(); @@ -1995,6 +2106,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } + /** + * Post query event if all editor with IsQueryAfterChange=True have been populated + */ protected void postQueryAfterChangeEvent() { if (Executions.getCurrent().getAttribute(ON_USER_QUERY_ATTR) != null) return; @@ -2013,6 +2127,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL onUserQuery(); } + /** + * @param editor + */ protected void dynamicDisplay(WEditor editor) { validateField(editor); evalDisplayLogic(); @@ -2043,7 +2160,8 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL otherEditor.dynamicDisplay(); } } - + + @Override public void onEvent(Event event) { if (event.getName().equals(Events.ON_FOCUS) && event.getTarget() != null && @@ -2134,11 +2252,13 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL onQueryCallback (null); - if (paging != null) - paging.setParent(null); layout.invalidate(); } + /** + * + * @param editor + */ protected void resetParameters(WEditor editor) { if(editor == null) return; @@ -2172,6 +2292,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } } + /** + * handle on client info event + */ protected void onClientInfo() { int t = getNoOfParameterColumns(); if (t > 0 && noOfParameterColumn > 0 && t != noOfParameterColumn) { @@ -2275,7 +2398,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } // testCount /** Return true if there is an 'IsActive' criteria */ - boolean hasIsActiveEditor() { + protected boolean hasIsActiveEditor() { for (WEditor editor : editors) { if (editor.getGridField() != null && "IsActive".equals(editor.getGridField().getColumnName())) { return true; @@ -2288,7 +2411,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL * author xolali IDEMPIERE-1045 * getInfoColumnslayout(MInfoWindow info) * @param info - * @return + * @return list of {@link ColumnInfo} */ public ArrayList getInfoColumnslayout(MInfoWindow info){ @@ -2531,7 +2654,13 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } // Edit Callback method and original values management - + /** + * + * @param row + * @param editingColumn + * @param editingValue + * @return {@link Properties} + */ public Properties getRowaAsCtx(int row, int editingColumn, Object editingValue) { ListModelTable model = contentPanel.getModel(); @@ -2597,6 +2726,14 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL return ctx; } + /** + * + * @param event + * @param rowIndex + * @param colIndex + * @param editor + * @param field + */ public void onCellEditCallback(ValueChangeEvent event, int rowIndex, int colIndex, WEditor editor, GridField field) { Object val = event.getNewValue(); @@ -2643,7 +2780,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } String msg = Msg.translate(ctx, sbError.toString()); - Dialog.error(0, "ValidationError", msg); // TODO messaggio + Dialog.error(0, "ValidationError", msg); } else changeIsValid = true; @@ -2652,7 +2789,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL { log.log(Level.SEVERE, "Error executing validation SQL: " + validationSQL, e); - Dialog.error(0, "Error", validationSQL); // TODO messaggio + Dialog.error(0, "Error", validationSQL); changeIsValid = false; } } @@ -2679,6 +2816,10 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } } + /** + * + * @param rowIndex + */ protected void restoreOriginalValues(int rowIndex) { Integer viewIdKey = getColumnValue(rowIndex); @@ -2696,6 +2837,10 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } } + /** + * + * @param rowIndex + */ protected void cacheOriginalValues(int rowIndex) { Integer viewIdKey = getColumnValue(rowIndex); @@ -2845,7 +2990,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } // F3P: Export function - + /** + * init export button + */ protected void initExport() { exportButton = ButtonFactory.createNamedButton("Export", false, true); @@ -2856,6 +3003,9 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL confirmPanel.addComponentsLeft(exportButton); } + /** + * enable/disable export button + */ protected void enableExportButton() { if(exportButton == null) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java index 8d0a390d1c..91624a7065 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java @@ -189,7 +189,16 @@ public abstract class InfoPanel extends Window implements EventListener, */ protected boolean isRequeryByRunSuccessProcess = false; - + /** + * + * @param WindowNo + * @param tableName + * @param keyColumn + * @param value + * @param multiSelection + * @param whereClause + * @return {@link InfoPanel} + */ public static InfoPanel create (int WindowNo, String tableName, String keyColumn, String value, boolean multiSelection, String whereClause) @@ -232,6 +241,15 @@ public abstract class InfoPanel extends Window implements EventListener, this(WindowNo, tableName, keyColumn, multipleSelection, whereClause, true); } + /** + * + * @param WindowNo + * @param tableName + * @param keyColumn + * @param multipleSelection + * @param whereClause + * @param lookup + */ protected InfoPanel (int WindowNo, String tableName, String keyColumn,boolean multipleSelection, String whereClause, boolean lookup){ @@ -239,6 +257,16 @@ public abstract class InfoPanel extends Window implements EventListener, lookup, 0); } + /** + * + * @param WindowNo + * @param tableName + * @param keyColumn + * @param multipleSelection + * @param whereClause + * @param lookup + * @param ADInfoWindowID + */ protected InfoPanel (int WindowNo, String tableName, String keyColumn,boolean multipleSelection, String whereClause, boolean lookup, int ADInfoWindowID) @@ -309,6 +337,9 @@ public abstract class InfoPanel extends Window implements EventListener, addEventListener(Events.ON_CANCEL, e -> onCancel()); } // InfoPanel + /** + * parse query value from calling input element + */ protected void parseQueryValue() { if (Util.isEmpty(queryValue, true)) return; @@ -421,7 +452,6 @@ public abstract class InfoPanel extends Window implements EventListener, if (isLookup()) addEventListener(Events.ON_CANCEL, this); contentPanel.setOddRowSclass(null); -// contentPanel.setSizedByContent(true); contentPanel.setWidgetAttribute(AdempiereWebUI.WIDGET_INSTANCE_NAME, "infoListbox"); contentPanel.addEventListener("onAfterRender", this); contentPanel.setSclass("z-word-nowrap"); @@ -630,6 +660,13 @@ public abstract class InfoPanel extends Window implements EventListener, btnDeSelectAll.setEnabled(selectedCount > 0); } // setStatusDB + /** + * set up list box and construct sql clause + * @param layout + * @param from + * @param where + * @param orderBy + */ protected void prepareTable (ColumnInfo[] layout, String from, String where, @@ -647,7 +684,6 @@ public abstract class InfoPanel extends Window implements EventListener, m_sqlCount = "SELECT COUNT(*) FROM " + from + " WHERE " + where; // m_sqlOrder = ""; -// m_sqlUserOrder = ""; if (orderBy != null && orderBy.trim().length() > 0) m_sqlOrder = " ORDER BY " + orderBy; } // prepareTable @@ -866,6 +902,9 @@ public abstract class InfoPanel extends Window implements EventListener, } + /** + * render list box items + */ protected void renderItems() { if (m_count > 0) @@ -884,6 +923,7 @@ public abstract class InfoPanel extends Window implements EventListener, { paging.setTotalSize(m_count); paging.setActivePage(0); + paging.setVisible(true); } List subList = readLine(0, pageSize); model = new ListModelTable(subList); @@ -997,6 +1037,10 @@ public abstract class InfoPanel extends Window implements EventListener, return MSysConfig.getBooleanValue(MSysConfig.ZK_INFO_AUTO_HIDE_EMPTY_COLUMNS, false, Env.getAD_Client_ID(Env.getCtx())); } + /** + * update info window status text + * @param no + */ protected void updateStatusBar (int no){ setStatusLine((no == Integer.MAX_VALUE?"?":Integer.toString(no)) + " " + Msg.getMsg(Env.getCtx(), "SearchRows_EnterQuery"), false); setStatusDB(no == Integer.MAX_VALUE?"?":Integer.toString(no)); @@ -1223,6 +1267,13 @@ public abstract class InfoPanel extends Window implements EventListener, return (int)overValue; } + + /** + * build sql clause with paging + * @param start + * @param end + * @return sql clause + */ protected String buildDataSQL(int start, int end) { String dataSql; String dynWhere = getSQLWhere(); @@ -1337,10 +1388,18 @@ public abstract class InfoPanel extends Window implements EventListener, contentPanel.addEventListener(Events.ON_SELECT, this); } + /** + * add paging component for list box + */ protected void insertPagingComponent() { contentPanel.getParent().insertBefore(paging, contentPanel.getNextSibling()); } + /** + * + * @param p_layout + * @return column headers + */ public Vector getColumnHeader(ColumnInfo[] p_layout) { Vector columnHeader = new Vector(); @@ -1436,7 +1495,6 @@ public abstract class InfoPanel extends Window implements EventListener, if (!m_ok) // did not press OK { contentPanel = null; - this.detach(); return; } @@ -1511,6 +1569,7 @@ public abstract class InfoPanel extends Window implements EventListener, /** * Save selected id, viewID of all process to map viewIDMap to save into T_Selection + * @param infoCulumnId */ public Collection getSaveKeys (int infoCulumnId){ // clear result from prev time @@ -1836,7 +1895,9 @@ public abstract class InfoPanel extends Window implements EventListener, return p_keyColumn; } // getKeyColumn - + /** + * @return list of events + */ public String[] getEvents() { return InfoPanel.lISTENER_EVENTS; @@ -1977,6 +2038,7 @@ public abstract class InfoPanel extends Window implements EventListener, return m_SO_Window_ID; } // getAD_Window_ID + @Override public void onEvent(Event event) { if (event == null){ @@ -2189,6 +2251,9 @@ public abstract class InfoPanel extends Window implements EventListener, } } // onEvent + /** + * handle cancel event + */ protected void onCancel() { m_cancel = true; dispose(false); @@ -2264,7 +2329,7 @@ public abstract class InfoPanel extends Window implements EventListener, protected void resetParameters() { } - void preRunProcess (Integer processId){ + protected void preRunProcess (Integer processId){ // disable all control button when run process enableButtons(false); // call run process in next request to disable all button control @@ -2568,6 +2633,11 @@ public abstract class InfoPanel extends Window implements EventListener, } } } + + /** + * handle echo from query event + * @param event null to indicate reset instead of echo from query event + */ public void onQueryCallback(Event event) { try @@ -2610,6 +2680,9 @@ public abstract class InfoPanel extends Window implements EventListener, */ protected void bindInfoProcess (){} + /** + * handle ok event + */ protected void onOk() { if (!contentPanel.getChildren().isEmpty() && getSelectedRowInfo().size() > 0) @@ -2618,6 +2691,9 @@ public abstract class InfoPanel extends Window implements EventListener, } } + /** + * handle double click on row event + */ protected void onDoubleClick() { if (isLookup()) @@ -2631,11 +2707,15 @@ public abstract class InfoPanel extends Window implements EventListener, } + @Override public void tableChanged(WTableModelEvent event) { enableButtons(); } + /** + * zoom to record + */ public void zoom() { Integer recordId = contentPanel.getSelectedRowKey(); @@ -2743,6 +2823,10 @@ public abstract class InfoPanel extends Window implements EventListener, */ protected void newRecordAction (){} + /** + * + * @param listener + */ public void addValueChangeListener(ValueChangeListener listener) { if (listener == null) @@ -2753,6 +2837,10 @@ public abstract class InfoPanel extends Window implements EventListener, listeners.add(listener); } + /** + * + * @param event + */ public void fireValueChange(ValueChangeEvent event) { for (ValueChangeListener listener : listeners) @@ -2774,9 +2862,20 @@ public abstract class InfoPanel extends Window implements EventListener, saveSelection(); } if (Window.MODE_EMBEDDED.equals(getAttribute(Window.MODE_KEY))) + { SessionManager.getAppDesktop().closeActiveWindow(); + } else - this.detach(); + { + //Workaround for detached HTML input element leak + if (getChildren().size() > 0) { + Component[] childs = getChildren().toArray(new Component[0]); + for(Component c : childs) { + AEnv.detachInputElement(c); + } + } + Executions.schedule(getDesktop(), e -> this.detach(), new Event("onAsyncDetach")); + } } // dispose private void saveWlistBoxColumnWidth(Component comp){ @@ -2789,8 +2888,12 @@ public abstract class InfoPanel extends Window implements EventListener, for(Component child:list){ saveWlistBoxColumnWidth(child); } - } + } + /** + * @param cmpr {@link WListItemRenderer.ColumnComparator} + * @param ascending + */ public void sort(Comparator cmpr, boolean ascending) { updateListSelected(); WListItemRenderer.ColumnComparator lsc = (WListItemRenderer.ColumnComparator) cmpr; @@ -2813,11 +2916,18 @@ public abstract class InfoPanel extends Window implements EventListener, renderItems(); } + /** + * + * @return true if it is a lookup dialog + */ public boolean isLookup() { return m_lookup; } + /** + * scroll selected row into view + */ public void scrollToSelectedRow() { if (contentPanel != null && contentPanel.getSelectedIndex() >= 0) { @@ -2833,18 +2943,35 @@ public abstract class InfoPanel extends Window implements EventListener, return "natural"; } + /** + * + * @return window no + */ public int getWindowNo() { return p_WindowNo; } + /** + * + * @return row count + */ public int getRowCount() { return contentPanel.getRowCount(); } + /** + * + * @return first row key/id + */ public Integer getFirstRowKey() { return contentPanel.getFirstRowKey(); } + /** + * + * @param row + * @return row key/id + */ public Integer getRowKeyAt(int row) { return contentPanel.getRowKeyAt(row); } @@ -2870,6 +2997,10 @@ public abstract class InfoPanel extends Window implements EventListener, return cacheEnd; } + /** + * + * @return true if using database paging feature + */ protected boolean isUseDatabasePaging() { return m_useDatabasePaging; } @@ -2903,16 +3034,24 @@ public abstract class InfoPanel extends Window implements EventListener, /** * field call this info panel as search editor * null in case info window open in stand-alone window (from menu, fav,...) - * @return + * @return {@link GridField} */ public GridField getGridfield() { return m_gridfield; } + /** + * + * @param m_gridfield + */ public void setGridfield(GridField m_gridfield) { this.m_gridfield = m_gridfield; } + /** + * + * @return page size (number of rows per page) + */ public int getPageSize() { return pageSize; } @@ -2933,6 +3072,10 @@ public abstract class InfoPanel extends Window implements EventListener, this.m_closeAfterExecutionOfProcess = closeAfterExecutionOfProcess; } + /** + * + * @param multipleSelection + */ public void setMultipleSelection(boolean multipleSelection) { p_multipleSelection = multipleSelection; if (btnSelectAll != null) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/LoginPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/LoginPanel.java index fab594bd21..f638a56f97 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/LoginPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/LoginPanel.java @@ -76,6 +76,7 @@ import org.zkoss.zhtml.Td; import org.zkoss.zhtml.Tr; import org.zkoss.zk.au.out.AuFocus; import org.zkoss.zk.au.out.AuScript; +import org.zkoss.zk.ui.AbstractComponent; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Session; @@ -83,6 +84,7 @@ import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.sys.ComponentCtrl; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.A; import org.zkoss.zul.Checkbox; @@ -346,6 +348,7 @@ public class LoginPanel extends Window implements EventListener pnlButtons.addActionListener(this); Button okBtn = pnlButtons.getButton(ConfirmPanel.A_OK); okBtn.setWidgetListener("onClick", "zAu.cmd0.showBusy(null)"); + okBtn.addCallback(ComponentCtrl.AFTER_PAGE_DETACHED, t -> ((AbstractComponent)t).setWidgetListener("onClick", null)); Button helpButton = pnlButtons.createButton(ConfirmPanel.A_HELP); helpButton.addEventListener(Events.ON_CLICK, this); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/RolePanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/RolePanel.java index c105385a1e..e26d908eec 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/RolePanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/RolePanel.java @@ -58,12 +58,14 @@ import org.zkoss.zhtml.Td; import org.zkoss.zhtml.Tr; import org.zkoss.zk.au.out.AuFocus; import org.zkoss.zk.au.out.AuScript; +import org.zkoss.zk.ui.AbstractComponent; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.event.Deferrable; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.sys.ComponentCtrl; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Comboitem; import org.zkoss.zul.Div; @@ -275,6 +277,7 @@ public class RolePanel extends Window implements EventListener, Deferrabl pnlButtons.addActionListener(this); Button okBtn = pnlButtons.getButton(ConfirmPanel.A_OK); okBtn.setWidgetListener("onClick", "zAu.cmd0.showBusy(null)"); + okBtn.addCallback(ComponentCtrl.AFTER_PAGE_DETACHED, t -> ((AbstractComponent)t).setWidgetListener("onClick", null)); Button helpButton = pnlButtons.createButton(ConfirmPanel.A_HELP); helpButton.addEventListener(Events.ON_CLICK, this); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java index cbb5caf93e..02ad5d8d4d 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/FindWindow.java @@ -2940,20 +2940,18 @@ public class FindWindow extends Window implements EventListener, ValueCha } } - - public void dispose() { - log.config(""); - // Find SQL DB.close(m_pstmt); m_pstmt = null; // - super.dispose(); - + setVisible(false); isvalid = false; + + //simulate real dispose/detach + Events.sendEvent(this, new Event(DialogEvents.ON_WINDOW_CLOSE, this, null)); } // dispose /** @@ -3408,9 +3406,7 @@ public class FindWindow extends Window implements EventListener, ValueCha setAttribute(ON_POST_VISIBLE_ATTR, Boolean.TRUE); Events.echoEvent("OnPostVisible", this, null); } - } else { - //auto detach - detach(); + isvalid = true; } return ret; } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/LoginWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/LoginWindow.java index d0294fbe27..8c17a56528 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/LoginWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/LoginWindow.java @@ -52,6 +52,7 @@ import org.compiere.util.Util; import org.zkoss.util.Locales; import org.zkoss.web.Attributes; import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.Page; import org.zkoss.zk.ui.Session; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; @@ -300,4 +301,10 @@ public class LoginWindow extends FWindow implements EventListener pnlRole.setChangeRole(true); pnlRole.changeRole(ctx); } + + @Override + public void onPageDetached(Page page) { + setWidgetListener("onOK", null); + super.onPageDetached(page); + } }