IDEMPIERE-762 Zk: Grid line editing enhancement.

This commit is contained in:
Heng Sin Low 2013-03-18 15:23:07 +08:00
parent 5e30569fc8
commit fc083ca2d8
8 changed files with 217 additions and 41 deletions

View File

@ -114,7 +114,7 @@ import org.zkoss.zul.impl.XulElement;
* @author Low Heng Sin
*/
public class ADTabpanel extends Div implements Evaluatee, EventListener<Event>,
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();
}
}

View File

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

View File

@ -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,9 +1946,18 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
if(result)
{
adTabbox.getSelectedGridTab().dataRefreshAll(true, true);
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();
}
}
}
});
}

View File

@ -258,8 +258,7 @@ public class DetailPane extends Panel implements EventListener<Event>, IdSpace {
button.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
@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<Event>, IdSpace {
}
return null;
}
public void onNew() throws Exception {
Event openEvent = new Event(ON_NEW_EVENT, DetailPane.this);
eventListener.onEvent(openEvent);
}
}

View File

@ -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<Object[]>, 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<Object[]>, 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<Object[]>, 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<Object[]>, 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<Object[]>, RowRendererExt
}
}
if (toFocus != null) {
focusToEditor(toFocus);
} else if (firstEditor != null) {
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();
}
Clients.response(new AuFocus(c));
} 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();
((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));
}
}
}

View File

@ -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<Event>, IdSpace
public class GridView extends Vbox implements EventListener<Event>, 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<Event>, 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<Event>, IdSpace
setFocusToField(columnOnClick);
columnOnClick = null;
} else {
renderer.setFocusToEditor();
renderer.focusToFirstEditor();
}
} else {
focusToRow(row);
@ -610,7 +612,7 @@ public class GridView extends Vbox implements EventListener<Event>, IdSpace
setFocusToField(columnOnClick);
columnOnClick = null;
} else {
renderer.setFocusToEditor();
renderer.focusToFirstEditor();
}
} else {
focusToRow(row);
@ -631,7 +633,7 @@ public class GridView extends Vbox implements EventListener<Event>, 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<Event>, 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<Event>, 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<Event>, 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<Event>, IdSpace
}
public void onEditCurrentRow() {
onEditCurrentRow(null);
}
public void onEditCurrentRow(Event event) {
if (!renderer.isEditing()) {
Row currentRow = renderer.getCurrentRow();
if (currentRow == null || currentRow.getParent() == null || !currentRow.isVisible()) {
if (event == null) {
Events.postEvent("onEditCurrentRow", this, null);
}
} else {
renderer.editCurrentRow();
renderer.setFocusToEditor();
renderer.focusToFirstEditor();
}
}
}
@Override
public void focusToFirstEditor() {
if (renderer.isEditing()) {
renderer.focusToFirstEditor();
}
}
@Override
public void focusToNextEditor(WEditor ref) {
if (renderer.isEditing()) {
renderer.focusToNextEditor(ref);
}
}
}

View File

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

View File

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