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
This commit is contained in:
hengsin 2023-01-20 21:46:00 +08:00 committed by GitHub
parent c28655af5f
commit 1a095d2d0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 688 additions and 135 deletions

View File

@ -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<Event>, 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);

View File

@ -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<Row> rowList;
List<Group> allCollapsibleGroups;
protected List<Group> 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<WEditor> editorTaverseCallback) {
editorTraverse(editorTaverseCallback, editors);
editorTraverse(editorTaverseCallback, editors);
}
@Override
@ -2334,6 +2351,10 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer
}
/**
*
* @return {@link AbstractADWindowContenta}
*/
public AbstractADWindowContent getADWindowContent()
{
return windowPanel;

View File

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

View File

@ -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<Event>() {
@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<BreadCrumbLink> parents = breadCrumb.getParentLinks();
@ -856,6 +875,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
/**
* @see ToolbarListener#onFirst()
*/
@Override
public void onFirst()
{
Callback<Boolean> callback = new Callback<Boolean>() {
@ -873,6 +893,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
/**
* @see ToolbarListener#onLast()
*/
@Override
public void onLast()
{
Callback<Boolean> callback = new Callback<Boolean>() {
@ -890,6 +911,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
/**
* @see ToolbarListener#onNext()
*/
@Override
public void onNext()
{
Callback<Boolean> callback = new Callback<Boolean>() {
@ -907,6 +929,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
/**
* @see ToolbarListener#onPrevious()
*/
@Override
public void onPrevious()
{
Callback<Boolean> callback = new Callback<Boolean>() {
@ -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<Boolean> 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<Boolean> callback) {
final Callback<Boolean> postCallback = new Callback<Boolean>() {
@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<Boolean>() {
@ -2555,9 +2573,6 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
});
}
/**
* @param onSaveEvent
*/
private void onSaveCallback(final boolean onSaveEvent, final boolean onNavigationEvent, final Callback<Boolean> 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<Boolean>() {
@ -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()
{

View File

@ -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<Event>() {
@ -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<Event> 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;

View File

@ -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<Object[]>, 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<Object[]>, 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<Object[]>, 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<Object[]>, RowRendererExt
/**
* @see RowRendererExt#getControls()
*/
@Override
public int getControls() {
return DETACH_ON_RENDER;
}
@ -785,6 +793,7 @@ public class GridTabRowRenderer implements RowRenderer<Object[]>, RowRendererExt
/**
* @see RowRendererExt#newCell(Row)
*/
@Override
public Component newCell(Row row) {
return null;
}
@ -792,6 +801,7 @@ public class GridTabRowRenderer implements RowRenderer<Object[]>, RowRendererExt
/**
* @see RowRendererExt#newRow(Grid)
*/
@Override
public Row newRow(Grid grid) {
return null;
}
@ -799,18 +809,21 @@ public class GridTabRowRenderer implements RowRenderer<Object[]>, 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<Object[]>, 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<Object[]>, RowRendererExt
}
/**
* @return boolean
* @return true if it is in edit mode, false otherwise
*/
public boolean isEditing() {
return editing;

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -922,6 +922,12 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value
}
}
}
@Override
public void onPageDetached(Page page) {
setWidgetListener("onChange", null);
super.onPageDetached(page);
}
}
}

View File

@ -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)

View File

@ -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();
}

View File

@ -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 <EmbedWinInfo> embeddedWinList = new ArrayList <EmbedWinInfo>();
Map<Integer, RelatedInfoWindow> relatedMap = new HashMap<>();
protected Tabbox embeddedPane = new Tabbox();
protected ArrayList <EmbedWinInfo> embeddedWinList = new ArrayList <EmbedWinInfo>();
protected Map<Integer, RelatedInfoWindow> 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<ColumnInfo> list = new ArrayList<ColumnInfo>();
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<Object[]> 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<ColumnInfo> 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)

View File

@ -189,7 +189,16 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
*/
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<Event>,
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<Event>,
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<Event>,
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<Event>,
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<Event>,
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<Event>,
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<Event>,
}
/**
* render list box items
*/
protected void renderItems()
{
if (m_count > 0)
@ -884,6 +923,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
{
paging.setTotalSize(m_count);
paging.setActivePage(0);
paging.setVisible(true);
}
List<Object> subList = readLine(0, pageSize);
model = new ListModelTable(subList);
@ -997,6 +1037,10 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
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<Event>,
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<Event>,
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<String> getColumnHeader(ColumnInfo[] p_layout)
{
Vector<String> columnHeader = new Vector<String>();
@ -1436,7 +1495,6 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
if (!m_ok) // did not press OK
{
contentPanel = null;
this.detach();
return;
}
@ -1511,6 +1569,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
/**
* Save selected id, viewID of all process to map viewIDMap to save into T_Selection
* @param infoCulumnId
*/
public Collection<KeyNamePair> getSaveKeys (int infoCulumnId){
// clear result from prev time
@ -1836,7 +1895,9 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
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<Event>,
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<Event>,
}
} // onEvent
/**
* handle cancel event
*/
protected void onCancel() {
m_cancel = true;
dispose(false);
@ -2264,7 +2329,7 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
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<Event>,
}
}
}
/**
* 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<Event>,
*/
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<Event>,
}
}
/**
* handle double click on row event
*/
protected void onDoubleClick()
{
if (isLookup())
@ -2631,11 +2707,15 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
}
@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<Event>,
*/
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<Event>,
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<Event>,
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<Event>,
for(Component child:list){
saveWlistBoxColumnWidth(child);
}
}
}
/**
* @param cmpr {@link WListItemRenderer.ColumnComparator}
* @param ascending
*/
public void sort(Comparator<Object> cmpr, boolean ascending) {
updateListSelected();
WListItemRenderer.ColumnComparator lsc = (WListItemRenderer.ColumnComparator) cmpr;
@ -2813,11 +2916,18 @@ public abstract class InfoPanel extends Window implements EventListener<Event>,
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<Event>,
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<Event>,
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<Event>,
/**
* 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<Event>,
this.m_closeAfterExecutionOfProcess = closeAfterExecutionOfProcess;
}
/**
*
* @param multipleSelection
*/
public void setMultipleSelection(boolean multipleSelection) {
p_multipleSelection = multipleSelection;
if (btnSelectAll != null)

View File

@ -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<Event>
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);

View File

@ -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<Event>, 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);

View File

@ -2940,20 +2940,18 @@ public class FindWindow extends Window implements EventListener<Event>, 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<Event>, ValueCha
setAttribute(ON_POST_VISIBLE_ATTR, Boolean.TRUE);
Events.echoEvent("OnPostVisible", this, null);
}
} else {
//auto detach
detach();
isvalid = true;
}
return ret;
}

View File

@ -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<Event>
pnlRole.setChangeRole(true);
pnlRole.changeRole(ctx);
}
@Override
public void onPageDetached(Page page) {
setWidgetListener("onOK", null);
super.onPageDetached(page);
}
}