/* StubsComponent.java
Purpose:
Description:
History:
Sat Jun 4 21:24:11 TST 2011, Created by tomyeh
Copyright (C) 2011 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.zk.ui.sys;
import java.util.LinkedList;
import java.util.List;
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.StubEvent;
import org.zkoss.zk.ui.ext.Scope;
/**
* Represents a tree of {@link StubComponent} that are merged into
* a single component.
*
* @author tomyeh
* @since 6.0.0
*/
public class StubsComponent extends StubComponent {
private String[] _uuids;
/** [0]: uuid, [1]: id */
private String[][] _idmap;
/** [0]: uuid, [1]: EventListenerMap. */
private Object[][] _evtmap;
/** Called when this component replaced the given component,
* and the children of the given component shall be 'merged' to this component.
* @param replaced the component that this component will replace.
* @exception IllegalStateException if this method has been called twice
* (we can modify the algorithm to support but not worth).
*/
public void onChildrenMerged(Component replaced, boolean bListener) {
if (_uuids != null)
throw new IllegalStateException("called twice");
final List<String> uuids = new LinkedList<String>();
final List<String[]> idmap = new LinkedList<String[]>();
final List<Object[]> evtmap = bListener ? new LinkedList<Object[]>() : null;
final Page page = getPage();
mapChildren(page != null ? (DesktopCtrl) page.getDesktop() : null, uuids, idmap, evtmap, replaced);
_uuids = uuids.toArray(new String[uuids.size()]);
_idmap = !idmap.isEmpty() ? idmap.toArray(new String[idmap.size()][]) : null;
_evtmap = evtmap != null && !evtmap.isEmpty() ? evtmap.toArray(new Object[evtmap.size()][]) : null;
}
private void mapChildren(DesktopCtrl desktopCtrl, List<String> uuids, List<String[]> idmap, List<Object[]> evtmap,
Component comp) {
for (Component p = comp.getFirstChild(); p != null; p = p.getNextSibling()) {
if (p instanceof StubsComponent) {
final String[] kiduuids = ((StubsComponent) p)._uuids;
if (kiduuids != null)
for (String uuid : kiduuids) {
uuids.add(uuid);
if (desktopCtrl != null)
desktopCtrl.mapComponent(uuid, this);
}
final String[][] kidids = ((StubsComponent) p)._idmap;
if (kidids != null)
for (String[] idinf : kidids)
idmap.add(idinf);
if (evtmap != null) {
final Object[][] kidevts = ((StubsComponent) p)._evtmap;
if (kidevts != null)
for (Object[] evtinf : kidevts)
evtmap.add(evtinf);
}
}
final String uuid = p.getUuid();
uuids.add(uuid);
if (desktopCtrl != null)
desktopCtrl.mapComponent(uuid, this);
final String id = p.getId();
if (id != null && id.length() > 0)
idmap.add(new String[] { uuid, id });
if (evtmap != null) {
EventListenerMap em = ((ComponentCtrl) p).getEventListenerMap();
if (em != null)
evtmap.add(new Object[] { uuid, em });
}
mapChildren(desktopCtrl, uuids, idmap, evtmap, p); //recursive
}
}
//--super--//
public String getId(String uuid) {
if (_idmap != null)
for (String[] idinf : _idmap)
if (uuid.equals(idinf[0]))
return idinf[1];
return super.getId(uuid);
}
public void onPageAttached(Page newpage, Page oldpage) {
super.onPageAttached(newpage, oldpage);
if (newpage != null) {
final DesktopCtrl desktopCtrl = (DesktopCtrl) newpage.getDesktop();
for (String uuid : _uuids)
desktopCtrl.mapComponent(uuid, this);
}
}
public void onPageDetached(Page page) {
super.onPageDetached(page);
final DesktopCtrl desktopCtrl = (DesktopCtrl) page.getDesktop();
for (String uuid : _uuids)
desktopCtrl.mapComponent(uuid, null);
}
public void service(Event event, Scope scope) throws Exception {
final StubEvent stubevt = event instanceof StubEvent ? (StubEvent) event : null;
final String uuid = stubevt != null ? stubevt.getUuid() : null;
if (uuid == null || uuid.equals(getUuid())) {
super.service(event, scope);
} else if (_evtmap != null) {
for (Object[] evtinf : _evtmap) {
if (uuid.equals(evtinf[0])) { //matched
((EventListenerMap) evtinf[1]).service(event, scope, this, stubevt.getCommand());
break; //done
}
}
postToNonStubAncestor(stubevt);
}
}
/** Returns the widget class, "#stubs".
*/
public String getWidgetClass() {
return "#stubs";
}
/** {@link StubsComponent} represents a collection of {@link StubComponent},
* so it does not allow any child.
*/
protected boolean isChildable() {
return false;
}
public String toString() {
final StringBuffer sb = new StringBuffer(super.toString());
if (_uuids != null) {
sb.append('(');
for (int j = 0; j < _uuids.length; ++j) {
if (j != 0)
sb.append(", ");
sb.append(_uuids[j]);
}
sb.append(')');
}
if (_idmap != null) {
sb.append('(');
for (int j = 0; j < _idmap.length; ++j) {
if (j != 0)
sb.append(", ");
sb.append(_idmap[j][0]).append('=').append(_idmap[j][1]);
}
sb.append(')');
}
return sb.toString();
}
}