org.zkoss.zk.ui.sys.StubComponent Maven / Gradle / Ivy
/* StubComponent.java
Purpose:
Description:
History:
Thu Jul 29 08:45:27 TST 2010, Created by tomyeh
Copyright (C) 2010 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.zk.ui.sys;
import org.zkoss.zk.au.AuRequest;
import org.zkoss.zk.ui.AbstractComponent;
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.event.StubEvent;
import org.zkoss.zk.ui.ext.Native;
import org.zkoss.zk.ui.ext.Scope;
/**
* A stub component is a 'degenerated' component that does not maintain
* the states at the server. Rather, the states are maintained at the
* peer widget (running at the client).
*
* Application isn't really aware the existence of a stub component.
* Rather, it is used by ZK Loader to minimize the footprint, if
* it found a component doesn't have to maintain the states at the server
* after rendered.
* For example, {@link org.zkoss.zk.ui.HtmlNativeComponent} and stub-only components
* will degenerate to {@link StubComponent} or {@link StubsComponent} after rendered.
* Refer {@link Component#setStubonly} for details about a stub-only component.
*
*
A component that wants to degenerate to a stub component usually
* invoke {@link #replace} after {@link #redraw} is called.
*
* @author tomyeh
* @since 6.0.0
*/
public class StubComponent extends AbstractComponent {
public StubComponent() {
super(true); //a dummy component definition (replace() will correct it)
}
/** Returns ID of the given UUID, or null if not found or no ID assigned.
* It assumes the given UUID belonged to one of the component being
* merged into this component.
*
Notice that it searches all descendants of this component.
*/
public String getId(String uuid) {
if (uuid.equals(getUuid()))
return id0(getId()); //null if not found or no ID assigned
return getIdFromChild(this, uuid);
}
private static String getIdFromChild(Component comp, String uuid) {
for (Component child = comp.getFirstChild(); child != null; child = child.getNextSibling()) {
if (child instanceof StubComponent) {
String id = ((StubComponent) child).getId(uuid); //recursive
if (id != null)
return id;
} else {
if (uuid.equals(child.getUuid()))
return id0(child.getId());
String id = getIdFromChild(child, uuid);
if (id != null)
return id;
}
}
return null;
}
private static String id0(String id) {
return id != null && id.length() > 0 ? id : null;
}
//super//
/** Replace the specified component with this component in
* the component tree. In other words, the parent of the given
* component will become the parent of this components, so
* are siblings and children. Furthermore, comp will be detached
* at the end.
*
*
Notice that the replacement won't change anything at the client.
* A stub component assumes there is a full-functional widget
* running at the client to handle everything.
*
* @param comp the component. In this implementation it supports
* only derived classes of {@link AbstractComponent}.
* @param bFellow whether to add this component to the map of fellows
* if it is assigned with an ID. If false, the component (comp) cannot
* be retrieved back even with an ID.
* @param bListener whether to retain the event listeners and handlers.
* If true, the event listeners and handlers, if any, will be registered
* to this stub component. In other words, the event will be processed.
* However, it is a stub component, rather than the original one.
* I means the event is the most generic format: an instance of
* {@link org.zkoss.zk.ui.event.Event} (rather than MouseEvent or others).
* @param bChildren whether to have the children of the given component.
* If false, this component won't have any children, and all UUID of children
* reference back to this component.
* If true, the given component's children will belong to this component.
* @exception IllegalStateException if this component has a parent,
* sibling or child.
*/
public void replace(Component comp, boolean bFellow, boolean bListener, boolean bChildren) {
super.replace(comp, bFellow, bListener, bChildren);
}
/** Returns the widget class, "#stub".
*/
public String getWidgetClass() {
return "#stub";
}
public void service(AuRequest request, boolean everError) {
Events.postEvent(StubEvent.getStubEvent(request));
}
public void service(Event event, Scope scope) throws Exception {
if (event instanceof StubEvent) {
EventListenerMap map = ((ComponentCtrl) this).getEventListenerMap();
if (map != null) {
map.service(event, scope, this, ((StubEvent) event).getCommand());
} else
postToNonStubAncestor((StubEvent) event);
} else {
super.service(event, scope);
}
}
/** Post event to the non-stub ancestor. */
/*package*/ void postToNonStubAncestor(StubEvent event) {
Component target = event.getTarget();
while (target instanceof Native || target instanceof StubComponent) {
target = target.getParent();
}
if (target != null)
Events.postEvent(new StubEvent(event, target));
}
}