From fc083ca2d891ea96afcb585e7b115a6a7b945a9a Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Mon, 18 Mar 2013 15:23:07 +0800 Subject: [PATCH] IDEMPIERE-762 Zk: Grid line editing enhancement. --- .../adempiere/webui/adwindow/ADTabpanel.java | 49 ++++++++++---- .../webui/adwindow/ADWindowToolbar.java | 6 ++ .../adwindow/AbstractADWindowContent.java | 12 +++- .../adempiere/webui/adwindow/DetailPane.java | 8 ++- .../webui/adwindow/GridTabRowRenderer.java | 67 ++++++++++++++----- .../adempiere/webui/adwindow/GridView.java | 61 ++++++++++++++--- .../webui/adwindow/IFieldEditorContainer.java | 34 ++++++++++ .../adempiere/webui/editor/WSearchEditor.java | 21 ++++++ 8 files changed, 217 insertions(+), 41 deletions(-) create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/IFieldEditorContainer.java 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 bb0b298f29..f112f6f80a 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 @@ -114,7 +114,7 @@ import org.zkoss.zul.impl.XulElement; * @author Low Heng Sin */ public class ADTabpanel extends Div implements Evaluatee, EventListener, -DataStatusListener, IADTabpanel, IdSpace +DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer { private static final String ON_SAVE_OPEN_PREFERENCE_EVENT = "onSaveOpenPreference"; @@ -923,7 +923,7 @@ DataStatusListener, IADTabpanel, IdSpace } else { if (activate) { formContainer.setVisible(activate); - setFocusToField(); + focusToFirstEditor(); } } @@ -938,7 +938,8 @@ DataStatusListener, IADTabpanel, IdSpace /** * set focus to first active editor */ - private void setFocusToField() { + @Override + public void focusToFirstEditor() { WEditor toFocus = null; for (WEditor editor : editors) { if (editor.isHasFocus() && editor.isVisible() && editor.getComponent().getParent() != null) { @@ -954,14 +955,7 @@ DataStatusListener, IADTabpanel, IdSpace } } if (toFocus != null) { - Component c = toFocus.getComponent(); - if (c instanceof EditorBox) { - c = ((EditorBox)c).getTextbox(); - } else if (c instanceof NumberBox) { - c = ((NumberBox)c).getDecimalbox(); - } - - Clients.response(new AuFocus(c)); + focusToEditor(toFocus); } } @@ -1302,7 +1296,7 @@ DataStatusListener, IADTabpanel, IdSpace @Override public void focus() { if (formContainer.isVisible()) - this.setFocusToField(); + this.focusToFirstEditor(); else listPanel.focus(); } @@ -1477,5 +1471,36 @@ DataStatusListener, IADTabpanel, IdSpace return detailPane != null && detailPane.getTabcount() > 0; } + + /** + * set focus to next readwrite editor from ref + * @param ref + */ + @Override + public void focusToNextEditor(WEditor ref) { + boolean found = false; + for (WEditor editor : editors) { + if (editor == ref) { + found = true; + continue; + } + if (found) { + if (editor.isVisible() && editor.isReadWrite()) { + focusToEditor(editor); + break; + } + } + } + } + + protected void focusToEditor(WEditor toFocus) { + Component c = toFocus.getComponent(); + if (c instanceof EditorBox) { + c = ((EditorBox)c).getTextbox(); + } else if (c instanceof NumberBox) { + c = ((NumberBox)c).getDecimalbox(); + } + ((HtmlBasedComponent)c).focus(); + } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADWindowToolbar.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADWindowToolbar.java index b4658dbd6e..8770cedd46 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADWindowToolbar.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADWindowToolbar.java @@ -44,12 +44,14 @@ import org.compiere.util.CLogger; import org.compiere.util.Env; import org.compiere.util.Msg; import org.zkoss.image.AImage; +import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Page; 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.event.KeyEvent; +import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Space; /** @@ -504,6 +506,10 @@ public class ADWindowToolbar extends FToolbar implements EventListener keyEvent.stopPropagation(); if (!btn.isDisabled() && btn.isVisible()) { Events.sendEvent(btn, new Event(Events.ON_CLICK, btn)); + //client side script to close combobox popup + String script = "var w=zk.Widget.$('#" + btn.getUuid()+"'); " + + "zWatch.fire('onFloatUp', w);"; + Clients.response(new AuScript(script)); } } } 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 ef4a7b74b2..823d1d8b5e 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 @@ -1916,6 +1916,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements } if (dirtyTabpanel != null && dirtyTabpanel.getGridTab().isDetail()) { + Executions.getCurrent().setAttribute("adtabpane.saved", dirtyTabpanel); dirtyTabpanel.getGridTab().refreshParentTabs(); } @@ -1945,7 +1946,16 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements if(result) { adTabbox.getSelectedGridTab().dataRefreshAll(true, true); - onNew(); + IADTabpanel dirtyTabpanel = (IADTabpanel) Executions.getCurrent().removeAttribute("adtabpane.saved"); + if (dirtyTabpanel != null && dirtyTabpanel.getGridTab().isDetail()) { + try { + adTabbox.getSelectedTabpanel().getDetailPane().onNew(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + onNew(); + } } } }); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/DetailPane.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/DetailPane.java index 5b3a724dd3..0db103c340 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/DetailPane.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/DetailPane.java @@ -258,8 +258,7 @@ public class DetailPane extends Panel implements EventListener, IdSpace { button.addEventListener(Events.ON_CLICK, new EventListener() { @Override public void onEvent(Event event) throws Exception { - Event openEvent = new Event(ON_NEW_EVENT, DetailPane.this); - eventListener.onEvent(openEvent); + onNew(); } }); button.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "New"))); @@ -709,4 +708,9 @@ public class DetailPane extends Panel implements EventListener, IdSpace { } return null; } + + public void onNew() throws Exception { + Event openEvent = new Event(ON_NEW_EVENT, DetailPane.this); + eventListener.onEvent(openEvent); + } } 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 3bfb49e0c7..675e22df16 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 @@ -17,6 +17,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Properties; import org.adempiere.util.GridRowCtx; import org.adempiere.webui.component.Checkbox; @@ -37,7 +38,6 @@ import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.Msg; import org.compiere.util.Util; -import org.zkoss.zk.au.out.AuFocus; import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.HtmlBasedComponent; @@ -397,6 +397,8 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt else if (DisplayType.isNumeric(gridPanelFields[i].getDisplayType())) { divStyle = CELL_DIV_STYLE_ALIGN_RIGHT; } + GridRowCtx ctx = new GridRowCtx(Env.getCtx(), gridTab, rowIndex); + component.setVisible(gridPanelFields[i].isDisplayed(ctx, true)); } div.setStyle(divStyle); div.setWidth("100%"); @@ -498,8 +500,12 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt popupMenu.addContextElement((XulElement) editor.getComponent()); } + + Properties ctx = isDetailPane() ? new GridRowCtx(Env.getCtx(), gridTab, gridTab.getCurrentRow()) + : gridPanelFields[i].getVO().ctx; //check context - if (!gridPanelFields[i].isDisplayedGrid()) + if (!gridPanelFields[i].isDisplayedGrid() || + !gridPanelFields[i].isDisplayed(ctx, true)) { editor.setVisible(false); } @@ -514,6 +520,17 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt } } + private boolean isDetailPane() { + Component parent = grid.getParent(); + while (parent != null) { + if (parent instanceof DetailPane) { + return true; + } + parent = parent.getParent(); + } + return false; + } + /** * @see RowRendererExt#getControls() */ @@ -556,7 +573,7 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt /** * set focus to first active editor */ - public void setFocusToEditor() { + public void focusToFirstEditor() { if (currentRow != null && currentRow.getParent() != null) { WEditor toFocus = null; WEditor firstEditor = null; @@ -575,21 +592,39 @@ public class GridTabRowRenderer implements RowRenderer, RowRendererExt } } if (toFocus != null) { - Component c = toFocus.getComponent(); - if (c instanceof EditorBox) { - c = ((EditorBox)c).getTextbox(); - } else if (c instanceof NumberBox) { - c = ((NumberBox)c).getDecimalbox(); - } - Clients.response(new AuFocus(c)); + focusToEditor(toFocus); } else if (firstEditor != null) { - Component c = firstEditor.getComponent(); - if (c instanceof EditorBox) { - c = ((EditorBox)c).getTextbox(); - } else if (c instanceof NumberBox) { - c = ((NumberBox)c).getDecimalbox(); + focusToEditor(firstEditor); + } + } + } + + protected void focusToEditor(WEditor toFocus) { + Component c = toFocus.getComponent(); + if (c instanceof EditorBox) { + c = ((EditorBox)c).getTextbox(); + } else if (c instanceof NumberBox) { + c = ((NumberBox)c).getDecimalbox(); + } + ((HtmlBasedComponent)c).focus(); + } + + /** + * set focus to next readwrite editor from ref + * @param ref + */ + public void focusToNextEditor(WEditor ref) { + boolean found = false; + for (WEditor editor : getEditors()) { + if (editor == ref) { + found = true; + continue; + } + if (found) { + if (editor.isVisible() && editor.isReadWrite()) { + focusToEditor(editor); + break; } - Clients.response(new AuFocus(c)); } } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/GridView.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/GridView.java index e85bc7d073..112600919a 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/GridView.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/GridView.java @@ -18,10 +18,12 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Properties; import javax.swing.table.AbstractTableModel; import org.adempiere.model.MTabCustomization; +import org.adempiere.util.GridRowCtx; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.component.Columns; import org.adempiere.webui.component.EditorBox; @@ -60,7 +62,7 @@ import org.zkoss.zul.event.ZulEvents; * @author Low Heng Sin * */ -public class GridView extends Vbox implements EventListener, IdSpace +public class GridView extends Vbox implements EventListener, IdSpace, IFieldEditorContainer { private static final String HEADER_GRID_STYLE = "border: none; margin:0; padding: 0;"; @@ -529,7 +531,7 @@ public class GridView extends Vbox implements EventListener, IdSpace if (columnName != null && columnName.trim().length() > 0) setFocusToField(columnName); else - renderer.setFocusToEditor(); + renderer.focusToFirstEditor(); } } else @@ -587,7 +589,7 @@ public class GridView extends Vbox implements EventListener, IdSpace setFocusToField(columnOnClick); columnOnClick = null; } else { - renderer.setFocusToEditor(); + renderer.focusToFirstEditor(); } } else { focusToRow(row); @@ -610,7 +612,7 @@ public class GridView extends Vbox implements EventListener, IdSpace setFocusToField(columnOnClick); columnOnClick = null; } else { - renderer.setFocusToEditor(); + renderer.focusToFirstEditor(); } } else { focusToRow(row); @@ -631,7 +633,7 @@ public class GridView extends Vbox implements EventListener, IdSpace setFocusToField(columnOnClick); columnOnClick = null; } else { - renderer.setFocusToEditor(); + renderer.focusToFirstEditor(); } } else { Component cmp = null; @@ -744,11 +746,25 @@ public class GridView extends Vbox implements EventListener, IdSpace comp.setReadWrite(rw); } - comp.setVisible(mField.isDisplayedGrid()); + Properties ctx = isDetailPane() ? new GridRowCtx(Env.getCtx(), gridTab, gridTab.getCurrentRow()) + : mField.getVO().ctx; + + comp.setVisible(mField.isDisplayedGrid() && mField.isDisplayed(ctx, true)); } } } + private boolean isDetailPane() { + Component parent = this.getParent(); + while (parent != null) { + if (parent instanceof DetailPane) { + return true; + } + parent = parent.getParent(); + } + return false; + } + /** * * @param windowNo @@ -760,7 +776,7 @@ public class GridView extends Vbox implements EventListener, IdSpace @Override public void focus() { if (renderer != null && renderer.isEditing()) { - renderer.setFocusToEditor(); + renderer.focusToFirstEditor(); } } @@ -770,7 +786,7 @@ public class GridView extends Vbox implements EventListener, IdSpace public boolean onEnterKey() { if (!modeless && renderer != null && !renderer.isEditing()) { renderer.editCurrentRow(); - renderer.setFocusToEditor(); + renderer.focusToFirstEditor(); return true; } return false; @@ -827,9 +843,34 @@ public class GridView extends Vbox implements EventListener, IdSpace } public void onEditCurrentRow() { + onEditCurrentRow(null); + } + + public void onEditCurrentRow(Event event) { if (!renderer.isEditing()) { - renderer.editCurrentRow(); - renderer.setFocusToEditor(); + Row currentRow = renderer.getCurrentRow(); + if (currentRow == null || currentRow.getParent() == null || !currentRow.isVisible()) { + if (event == null) { + Events.postEvent("onEditCurrentRow", this, null); + } + } else { + renderer.editCurrentRow(); + renderer.focusToFirstEditor(); + } + } + } + + @Override + public void focusToFirstEditor() { + if (renderer.isEditing()) { + renderer.focusToFirstEditor(); + } + } + + @Override + public void focusToNextEditor(WEditor ref) { + if (renderer.isEditing()) { + renderer.focusToNextEditor(ref); } } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/IFieldEditorContainer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/IFieldEditorContainer.java new file mode 100644 index 0000000000..98f86995c8 --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/IFieldEditorContainer.java @@ -0,0 +1,34 @@ +/****************************************************************************** + * Copyright (C) 2013 Heng Sin Low * + * Copyright (C) 2013 Trek Global * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.webui.adwindow; + +import org.adempiere.webui.editor.WEditor; + +/** + * + * @author hengsin + * + */ +public interface IFieldEditorContainer { + /** + * focus to first field editor + */ + public void focusToFirstEditor(); + + /** + * focus to next field editor from ref + * @param ref + */ + public void focusToNextEditor(WEditor ref); +} 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 8f136150d4..791d13eddb 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 @@ -29,6 +29,7 @@ import java.util.logging.Level; import org.adempiere.util.Callback; import org.adempiere.webui.ValuePreference; import org.adempiere.webui.adwindow.ADWindow; +import org.adempiere.webui.adwindow.IFieldEditorContainer; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.component.Searchbox; import org.adempiere.webui.event.ContextMenuEvent; @@ -55,11 +56,14 @@ import org.compiere.util.DB; import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.Util; +import org.zkoss.zk.au.out.AuScript; +import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Page; 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.util.Clients; /** * Search Editor for web UI. @@ -405,6 +409,22 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value actionCombo(new Integer(id)); // data binding + Searchbox comp = getComponent(); + Component parent = comp.getParent(); + while (parent != null) { + if (parent instanceof IFieldEditorContainer) { + ((IFieldEditorContainer) parent).focusToNextEditor(this); + break; + } + parent = parent.getParent(); + } + + //safety check: if focus is going no where, focus back to self + String uid = getComponent().getTextbox().getUuid(); + String script = "setTimeout(function(){try{var e = zk.Widget.$('#" + uid + + "').$n(); if (jq(':focus').size() == 0) e.focus();} catch(error){}}, 100);"; + Clients.response(new AuScript(script)); + resetButtonState(); } // actionText @@ -563,6 +583,7 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value { if (log.isLoggable(Level.CONFIG)) log.config(getColumnName() + " - Result = null (not cancelled)"); } + getComponent().getTextbox().focus(); } }); ip.setId(ip.getTitle()+"_"+ip.getWindowNo());