/** ShadowElementsCtrl.java. Purpose: Description: History: 2:24:33 PM Oct 29, 2014, Created by jumperchen Copyright (C) 2014 Potix Corporation. All Rights Reserved. */ package org.zkoss.zk.ui.sys; import java.util.LinkedList; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.ShadowElement; import org.zkoss.zk.ui.ShadowElementCtrl; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.util.Template; /** * Utilities for implementing components. (Internal use only) * * @author jumperchen * @since 8.0.0 */ public class ShadowElementsCtrl { private static final ThreadLocal<Object> _shadowInfo = new ThreadLocal<Object>(); private static final ThreadLocal<Object> _distributedIndexInfo = new ThreadLocal<Object>(); /** Sets the current shadow element, which is used only by * {@link org.zkoss.zk.ui.sys.UiEngine} to communicate with * {@link org.zkoss.zk.ui.HtmlShadowElement}. * <p>Used only internally. */ public static final void setCurrentInfo(Object shadowInfo) { _shadowInfo.set(shadowInfo); } /** Returns the current shadow element, which is used only by * {@link org.zkoss.zk.ui.sys.UiEngine} to communicate with * {@link org.zkoss.zk.ui.HtmlShadowElement}. * <p>Used only internally. */ public static final Object getCurrentInfo() { return _shadowInfo.get(); } /** Sets the current distributed index info, which is used only by * {@link org.zkoss.zk.ui.HtmlShadowElement}. * <p>Used only internally. */ public static final void setDistributedIndexInfo(Object indexMapInfo) { _distributedIndexInfo.set(indexMapInfo); } /** Returns the current distributed index info, which is used only by * {@link org.zkoss.zk.ui.HtmlShadowElement}. * <p>Used only internally. */ public static final Object getDistributedIndexInfo() { return _distributedIndexInfo.get(); } /** * Returns the component array filter out shadows if any. (Most often used * for the component developer to invoke * {@link Template#create(Component, Component, org.zkoss.xel.VariableResolver, org.zkoss.zk.ui.util.Composer)} * by themselves and invoke this to filter out shadows. */ public static final Component[] filterOutShadows(Component[] shadows) { if (shadows == null || shadows.length == 0) return shadows; int length = shadows.length; // fixed ZK-3046 //to force init and load for (Component shadow : shadows) { if (shadow instanceof ShadowElement) { ShadowElement se = (ShadowElement) shadow; if (se.getDistributedChildren().isEmpty()) { if (((ShadowElementCtrl) se).isDynamicValue()) { Events.sendEvent(new Event("onBindInit", (Component) se)); Events.sendEvent(new Event("onBindingReady", (Component) se)); } } } } if (length == 1) { if (shadows[0] instanceof ShadowElement) { ShadowElement se = ((ShadowElement) shadows[0]); return se.getDistributedChildren().toArray(new Component[0]); } } else { Component parent = null; Component start = null; if (shadows[0] instanceof ShadowElementCtrl) { ShadowElementCtrl se = ((ShadowElementCtrl) shadows[0]); start = se.getFirstInsertion(); } else { start = shadows[0]; parent = start.getParent(); } if (parent instanceof ComponentCtrl) { ComponentCtrl pCtrl = (ComponentCtrl) parent; if (pCtrl.getShadowRoots().isEmpty()) return shadows; // no shadow available here, we can skip the filter. } // the following code will filter the shadow element if any. Component end = shadows[length - 1]; if (end instanceof ShadowElementCtrl) { ShadowElementCtrl se = (ShadowElementCtrl) end; end = se.getLastInsertion(); } LinkedList<Component> list = new LinkedList<Component>(); while (start != null) { list.add(start); if (start == end) break; start = start.getNextSibling(); } return list.toArray(new Component[0]); } return shadows; } }