Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.zkoss.bind.impl.BindChildRenderer Maven / Gradle / Ivy
/* BindChildRenderer.java
Purpose:
Description:
History:
2012/1/2 Created by Dennis Chen
Copyright (C) 2011 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.bind.impl;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.zkoss.bind.Binder;
import org.zkoss.bind.sys.BinderCtrl;
import org.zkoss.bind.sys.TemplateResolver;
import org.zkoss.bind.xel.zel.BindELContext;
import org.zkoss.zel.PropertyNotFoundException;
import org.zkoss.zel.PropertyNotWritableException;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.sys.ShadowElementsCtrl;
import org.zkoss.zk.ui.util.ForEachStatus;
import org.zkoss.zk.ui.util.Template;
import org.zkoss.zul.Label;
import org.zkoss.zul.ListModel;
/**
* to renderer children of component
* @author dennis
* @since 6.0.0
*/
public class BindChildRenderer extends AbstractRenderer {
private static final long serialVersionUID = 1L;
public BindChildRenderer() {
setAttributeName(AnnotateBinderHelper.CHILDREN_KEY);
}
public void render(final Component owner, final Object data, final int index, final int size) {
render(owner, data, index, size, false);
}
@SuppressWarnings("unchecked")
public void render(final Component owner, final Object data, final int index, final int size,
final boolean isListModel) {
final Template tm = resolveTemplate(owner, owner, data, index, size, "children");
if (tm == null) {
Label l = new Label(data == null ? "" : data.toString());
l.setParent(owner);
addChildrenBindingRenderedComps(owner, new Component[] { l }, index);
return;
}
final ForEachStatus iterStatus = new ChildrenBindingForEachStatus(index, data, size); //provide iteration status in this context
final String var = (String) tm.getParameters().get("var");
final String varnm = var == null ? EACH_VAR : var; //var is not specified, default to "each"
final String itervar = (String) tm.getParameters().get(STATUS_ATTR);
final String itervarnm = itervar == null ? (var == null ? EACH_STATUS_VAR : varnm + STATUS_POST_VAR) : itervar; //provide default value if not specified
//bug 1188, EL when nested var and itervar
Object oldVar = owner.getAttribute(varnm);
Object oldIter = owner.getAttribute(itervarnm);
owner.setAttribute(varnm, data);
owner.setAttribute(itervarnm, iterStatus);
// For bug ZK-2552
Component insertBefore = null;
List cbrCompsList = (List) owner
.getAttribute(BinderCtrl.CHILDREN_BINDING_RENDERED_COMPONENTS);
if (cbrCompsList != null) {
int newIndex = 0;
int steps = 0;
for (Component[] cmps : cbrCompsList) {
if (steps++ >= index)
break;
newIndex += cmps.length;
}
if (owner.getChildren().size() > newIndex) {
insertBefore = owner.getChildren().get(newIndex);
}
}
final Component[] items = ShadowElementsCtrl.filterOutShadows(tm.create(owner, insertBefore, null, null));
// Bug ZK-2789: do not use setAttribute when actually trying to removeAttribute
if (oldVar != null) {
owner.setAttribute(varnm, oldVar);
} else {
owner.removeAttribute(varnm);
}
if (oldIter != null) {
owner.setAttribute(itervarnm, oldIter);
} else {
owner.removeAttribute(itervarnm);
}
boolean templateTracked = false;
//ZK-2545 - Children binding support list model
if (isListModel)
addChildrenBindingRenderedComps(owner, items, index);
for (final Component comp : items) {
comp.setAttribute(BinderCtrl.VAR, varnm);
// ZK-2552
comp.setAttribute(AbstractRenderer.IS_TEMPLATE_MODEL_ENABLED_ATTR, true);
comp.setAttribute(AbstractRenderer.CURRENT_INDEX_RESOLVER_ATTR, new IndirectBinding(data) {
public Binder getBinder() {
return BinderUtil.getBinder(comp, true);
}
public Component getComponent() {
return comp;
}
protected ListModel getModel() {
return null;
}
public void setValue(BindELContext ctx, Object value) {
Collection> collection = (Collection>) owner.getAttribute(BindELContext.getModelName(owner));
if (collection instanceof List>) {
List list = (List) collection;
int index = list.indexOf(data);
try {
list.set(index, value);
setData(value);
} catch (UnsupportedOperationException e) {
throw new PropertyNotWritableException(e);
} catch (IndexOutOfBoundsException e) {
throw new PropertyNotFoundException(e);
}
}
}
});
addItemReference(owner, comp, index, varnm); //kept the reference to the data, before ON_BIND_INIT
comp.setAttribute(itervarnm, iterStatus);
//add template dependency
if (!templateTracked) {
//ZK-1787 When the viewModel tell binder to reload a list, the other component that bind a bean in the list will reload again
//move TEMPLATE_OBJECT (was set in resoloveTemplate) to current for check in addTemplateTracking
Object obj = owner.removeAttribute(TemplateResolver.TEMPLATE_OBJECT);
// Bug ZK-2789: do not use setAttribute when actually trying to removeAttribute
if (obj != null) {
comp.setAttribute(TemplateResolver.TEMPLATE_OBJECT, obj);
} else {
comp.removeAttribute(TemplateResolver.TEMPLATE_OBJECT);
}
addTemplateTracking(owner, comp, data, index, size);
templateTracked = true;
}
//to force init and load
Events.sendEvent(new Event(BinderCtrl.ON_BIND_INIT, comp));
}
}
private void addChildrenBindingRenderedComps(final Component owner, Component[] items, int index) {
List cbrCompsList = (List) owner
.getAttribute(BinderCtrl.CHILDREN_BINDING_RENDERED_COMPONENTS);
if (cbrCompsList == null)
cbrCompsList = new LinkedList();
cbrCompsList.add(index, items);
owner.setAttribute(BinderCtrl.CHILDREN_BINDING_RENDERED_COMPONENTS, cbrCompsList);
}
private class ChildrenBindingForEachStatus extends AbstractForEachStatus {
private static final long serialVersionUID = 1L;
private int index;
private transient Object data;
private Integer size;
public ChildrenBindingForEachStatus(int index, Object data, Integer size) {
this.index = index;
this.data = data;
this.size = size;
}
public int getIndex() {
return index;
}
public Object getCurrent() {
return data;
}
public Integer getEnd() {
return size;
}
}
}