/zkbind/src/org/zkoss/bind/impl/ChildrenBindingListDataListener.java
Java | 137 lines | 111 code | 8 blank | 18 comment | 38 complexity | 566183332a5a5c740b95d5a270a510f6 MD5 | raw file
Possible License(s): LGPL-2.1
- /* ChildrenBindingListDataListener.java
- Purpose:
-
- Description:
-
- History:
- 2015/01/16 Created by James Chu
- Copyright (C) 2015 Potix Corporation. All Rights Reserved.
- */
- package org.zkoss.bind.impl;
- import java.util.List;
- import org.zkoss.bind.BindContext;
- import org.zkoss.bind.Converter;
- import org.zkoss.bind.sys.BinderCtrl;
- import org.zkoss.bind.xel.zel.BindELContext;
- import org.zkoss.zk.ui.Component;
- import org.zkoss.zk.ui.UiException;
- import org.zkoss.zul.ListModel;
- import org.zkoss.zul.event.ListDataEvent;
- import org.zkoss.zul.event.ListDataListener;
- /**
- * listen the model data onChange event (support list model in children binding)
- * @author James Chu
- * @since 8.0.0
- */
- public class ChildrenBindingListDataListener implements ListDataListener, java.io.Serializable {
- private static final long serialVersionUID = 20150116151900L;
- private final Component _owner;
- private final BindContext _ctx;
- private final Converter<?, ListModel<?>, Component> _conv;
- public ChildrenBindingListDataListener(Component comp, BindContext ctx,
- Converter<?, ListModel<?>, Component> conv) {
- this._owner = comp;
- this._ctx = ctx;
- this._conv = conv;
- }
- public void onChange(ListDataEvent event) {
- onListModelDataChange(new ChildrenBindingListModelDataEvent(event));
- }
- @SuppressWarnings("unchecked")
- private void onListModelDataChange(ListDataEvent event) {
- final ListModel<?> model = event.getModel();
- int type = event.getType();
- int index0 = event.getIndex0();
- int index1 = event.getIndex1();
- List<Component[]> cbrCompsList = (List<Component[]>) _owner
- .getAttribute(BinderCtrl.CHILDREN_BINDING_RENDERED_COMPONENTS);
- int oldsz = cbrCompsList == null ? 0 : cbrCompsList.size();
- int newsz = model.getSize();
- boolean refreshOwnerCBAttr = false;
- if (type == ListDataEvent.INTERVAL_ADDED) {
- int addedCount = index1 - index0 + 1;
- if ((newsz - oldsz) < 0)
- throw new UiException("Adding causes a smaller list?");
- else if ((oldsz + addedCount) != newsz) { //check live data changed
- index0 = oldsz;
- index1 = newsz - 1;
- }
- renderModelData(model, index0, index1);
- } else if (type == ListDataEvent.CONTENTS_CHANGED) {
- if (index0 >= 0 && index1 >= 0) {
- renderModelData(model, index0, index1);
- cbrCompsList = (List<Component[]>) _owner.getAttribute(BinderCtrl.CHILDREN_BINDING_RENDERED_COMPONENTS);
- int count = (index1 - index0) + 1;
- //remove old
- int oIndex = index1 + 1;
- for (int i = 0; i < count; i++) {
- Component[] oldComps = cbrCompsList.get(oIndex);
- for (Component oc : oldComps)
- oc.detach();
- cbrCompsList.remove(oIndex);
- }
- refreshOwnerCBAttr = true;
- } else //sync model
- syncModel(model);
- } else if (type == ListDataEvent.INTERVAL_REMOVED) {
- if (oldsz - newsz < 0)
- throw new UiException("Removal causes a larger list?");
- if (cbrCompsList != null) {
- for (int i = index0; i <= index1; i++) {
- Component[] oldComps = cbrCompsList.get(index0);
- if (oldComps != null) {
- for (Component oc : oldComps) {
- oc.detach();
- }
- }
- cbrCompsList.remove(index0);
- }
- }
- refreshOwnerCBAttr = true;
- }
- if (refreshOwnerCBAttr)
- _owner.setAttribute(BinderCtrl.CHILDREN_BINDING_RENDERED_COMPONENTS, cbrCompsList);
- }
- @SuppressWarnings("unchecked")
- private void syncModel(ListModel<?> model) {
- //clear all
- List<Component[]> cbrCompsList = (List<Component[]>) _owner
- .getAttribute(BinderCtrl.CHILDREN_BINDING_RENDERED_COMPONENTS);
- if (cbrCompsList != null) {
- _owner.removeAttribute(BinderCtrl.CHILDREN_BINDING_RENDERED_COMPONENTS);
- for (Component[] oldComps : cbrCompsList) {
- if (oldComps != null) {
- for (Component oc : oldComps) {
- oc.detach();
- }
- }
- }
- }
- renderModelData(model, 0, model.getSize() - 1);
- }
- @SuppressWarnings("unchecked")
- private void renderModelData(ListModel<?> model, int from, int to) {
- BindChildRenderer renderer = new BindChildRenderer();
- if (_conv != null) {
- List<Object> data = (List<Object>) _conv.coerceToUi(model, _owner, _ctx);
- BindELContext.addModel(_owner, data);
- if (data != null) {
- int size = data.size();
- if (to >= size)
- to = size - 1;
- for (int i = from; i <= to; i++)
- renderer.render(_owner, data.get(i), i, size, true);
- }
- }
- }
- }