📄 abstractcomponent.java
字号:
/* AbstractComponent.java{{IS_NOTE Purpose: Description: History: Mon May 30 21:49:42 2005, Created by tomyeh}}IS_NOTECopyright (C) 2005 Potix Corporation. All Rights Reserved.{{IS_RIGHT This program is distributed under GPL Version 2.0 in the hope that it will be useful, but WITHOUT ANY WARRANTY.}}IS_RIGHT*/package org.zkoss.zk.ui;import java.util.Iterator;import java.util.ListIterator;import java.util.Set;import java.util.HashSet;import java.util.List;import java.util.AbstractSequentialList;import java.util.LinkedList;import java.util.Collection;import java.util.Collections;import java.util.Map;import java.util.HashMap;import java.io.Writer;import java.io.IOException;import org.zkoss.lang.D;import org.zkoss.lang.Classes;import org.zkoss.lang.Objects;import org.zkoss.util.CollectionsX;import org.zkoss.util.logging.Log;import org.zkoss.io.Serializables;import org.zkoss.xml.HTMLs;import org.zkoss.zk.mesg.MZk;import org.zkoss.zk.ui.event.EventListener;import org.zkoss.zk.ui.event.Deferrable;import org.zkoss.zk.ui.event.Event;import org.zkoss.zk.ui.event.ForwardEvent;import org.zkoss.zk.ui.event.Events;import org.zkoss.zk.ui.ext.RawId;import org.zkoss.zk.ui.ext.NonFellow;import org.zkoss.zk.ui.ext.render.ZidRequired;import org.zkoss.zk.ui.render.ComponentRenderer;import org.zkoss.zk.ui.util.ComponentSerializationListener;import org.zkoss.zk.ui.util.ComponentCloneListener;import org.zkoss.zk.ui.sys.ExecutionCtrl;import org.zkoss.zk.ui.sys.ExecutionsCtrl;import org.zkoss.zk.ui.sys.ComponentCtrl;import org.zkoss.zk.ui.sys.ComponentsCtrl;import org.zkoss.zk.ui.sys.PageCtrl;import org.zkoss.zk.ui.sys.DesktopCtrl;import org.zkoss.zk.ui.sys.SessionCtrl;import org.zkoss.zk.ui.sys.WebAppCtrl;import org.zkoss.zk.ui.sys.UiEngine;import org.zkoss.zk.ui.sys.IdGenerator;import org.zkoss.zk.ui.sys.Names;import org.zkoss.zk.ui.metainfo.AnnotationMap;import org.zkoss.zk.ui.metainfo.Annotation;import org.zkoss.zk.ui.metainfo.EventHandlerMap;import org.zkoss.zk.ui.metainfo.ComponentDefinition;import org.zkoss.zk.ui.metainfo.PageDefinition;import org.zkoss.zk.ui.metainfo.LanguageDefinition;import org.zkoss.zk.ui.metainfo.ComponentInfo;import org.zkoss.zk.ui.metainfo.ComponentDefinition;import org.zkoss.zk.ui.metainfo.ComponentDefinitionMap;import org.zkoss.zk.ui.metainfo.DefinitionNotFoundException;import org.zkoss.zk.ui.metainfo.EventHandler;import org.zkoss.zk.ui.metainfo.ZScript;import org.zkoss.zk.ui.impl.ListenerIterator;import org.zkoss.zk.fn.ZkFns;import org.zkoss.zk.au.AuResponse;import org.zkoss.zk.au.out.AuClientInfo;import org.zkoss.zk.scripting.Namespace;import org.zkoss.zk.scripting.Interpreter;import org.zkoss.zk.scripting.util.SimpleNamespace;/** * A skeletal implementation of {@link Component}. Though it is OK * to implement Component from scratch, this class simplifies some of * the chores. * * @author tomyeh */public class AbstractComponentimplements Component, ComponentCtrl, java.io.Serializable {// private static final Log log = Log.lookup(AbstractComponent.class); private static final long serialVersionUID = 20070920L; private transient Page _page; private String _id; private String _uuid; private transient ComponentDefinition _def; /** The mold (default: "default"). */ private String _mold = "default"; /** The info of the ID space, or null if IdSpace is NOT implemented. */ private transient SpaceInfo _spaceInfo; private transient Map _attrs; //don't create it dynamically because _ip bind it at constructor /** A map of event listener: Map(evtnm, EventListener)). */ private transient Map _listeners; /** The extra controls. */ private transient Object _xtrl; /** The list used for {@link #getChildren} only. */ private transient List _apiChildren; private transient AbstractComponent _parent; /** The next sibling. */ private transient AbstractComponent _next; /** The previous sibling. */ private transient AbstractComponent _prev; /** The first child. */ private transient AbstractComponent _first; /** The last child. */ private transient AbstractComponent _last; /** # of children. */ private int _nChild; /** The modification count used to avoid co-modification of _next, _prev.. */ private transient int _modCntChd; /** A set of components that are being removed. * It is used to prevent dead-loop between {@link #removeChild} * and {@link #setParent}. */ private transient Set _rming; /** A set of components that are being added. * It is used to prevent dead-loop between {@link #insertBefore} * and {@link #setParent}. */ private transient Set _adding; /** A map of annotations. Serializable since a component might have * its own annotations. */ private AnnotationMap _annots; /** A map of event handler to handle events. */ private EventHandlerMap _evthds; /** A map of forward conditions: * Map(String orgEvt, [listener, List([target or targetPath,targetEvent])]). */ private transient Map _forwards; /** Whether _annots is shared with other components. */ private transient boolean _annotsShared; /** Whether _evthds is shared with other components. */ private transient boolean _evthdsShared; /** Whether this component is visible. */ private boolean _visible = true; /** Constructs a component with auto-generated ID. */ protected AbstractComponent() { final Execution exec = Executions.getCurrent(); final Object curInfo = ComponentsCtrl.getCurrentInfo(); if (curInfo != null) { ComponentsCtrl.setCurrentInfo((ComponentInfo)null); //to avoid mis-use if (curInfo instanceof ComponentInfo) { final ComponentInfo compInfo = (ComponentInfo)curInfo; _def = compInfo.getComponentDefinition(); addSharedAnnotationMap(_def.getAnnotationMap()); addSharedAnnotationMap(compInfo.getAnnotationMap()); } else { _def = (ComponentDefinition)curInfo; addSharedAnnotationMap(_def.getAnnotationMap()); } } else { _def = lookupDefinition(exec, getClass()); if (_def != null) addSharedAnnotationMap(_def.getAnnotationMap()); else _def = ComponentsCtrl.DUMMY; } init(false); _spaceInfo = this instanceof IdSpace ? new SpaceInfo(this): null;// if (D.ON && log.debugable()) log.debug("Create comp: "+this); } private static final ComponentDefinition lookupDefinition(Execution exec, Class cls) { if (exec != null) { final ExecutionCtrl execCtrl = (ExecutionCtrl)exec; final PageDefinition pgdef = execCtrl.getCurrentPageDefinition(); final Page page = execCtrl.getCurrentPage(); final ComponentDefinition compdef = pgdef != null ? pgdef.getComponentDefinition(cls, true): page != null ? page.getComponentDefinition(cls, true): null; if (compdef != null) return compdef; return lookupDefinitionByDeviceType(exec.getDesktop().getDeviceType(), cls); } for (Iterator it = LanguageDefinition.getDeviceTypes().iterator(); it.hasNext();) { final ComponentDefinition compdef = lookupDefinitionByDeviceType((String)it.next(), cls); if (compdef != null) return compdef; } return null; } private static final ComponentDefinition lookupDefinitionByDeviceType(String deviceType, Class cls) { for (Iterator it = LanguageDefinition.getByDeviceType(deviceType).iterator(); it.hasNext();) { final LanguageDefinition ld = (LanguageDefinition)it.next(); try { return ld.getComponentDefinition(cls); } catch (DefinitionNotFoundException ex) { //ignore } } return null; } /** Initialize for contructor and serialization. * @param cloning whether this method is called by clone() */ private void init(boolean cloning) { _xtrl = newExtraCtrl(); _apiChildren = new AbstractSequentialList() { public int size() { return _nChild; } public ListIterator listIterator(int index) { return new ChildIter(index); } }; if (!cloning) _attrs = new HashMap(4); } /** Adds to the ID spaces, if any, when ID is changed. * Caller has to make sure the uniqueness. */ private static void addToIdSpaces(final Component comp) { if (comp instanceof IdSpace) ((AbstractComponent)comp).bindToIdSpace(comp); final IdSpace is = getSpaceOwnerOfParent(comp); if (is instanceof Component) ((AbstractComponent)is).bindToIdSpace(comp); else if (is != null) ((PageCtrl)is).addFellow(comp); } private static final IdSpace getSpaceOwnerOfParent(Component comp) { final Component parent = comp.getParent(); if (parent != null) return parent.getSpaceOwner(); else return comp.getPage(); } /** Removes from the ID spaces, if any, when ID is changed. */ private static void removeFromIdSpaces(final Component comp) { final AbstractComponent abcomp = (AbstractComponent)comp; final String compId = abcomp._id; if (compId == null || (comp instanceof NonFellow) || ComponentsCtrl.isAutoId(compId)) return; //nothing to do if (comp instanceof IdSpace) abcomp.unbindFromIdSpace(compId); final IdSpace is = getSpaceOwnerOfParent(comp); if (is instanceof Component) ((AbstractComponent)is).unbindFromIdSpace(compId); else if (is != null) ((PageCtrl)is).removeFellow(comp); } /** Checks the uniqueness in ID space when changing ID. */ private static void checkIdSpaces(final AbstractComponent comp, String newId) { if (comp instanceof NonFellow) return; //no need to check if (comp instanceof IdSpace && comp._spaceInfo.fellows.containsKey(newId)) throw new UiException("Not unique in the ID space of "+comp); final IdSpace is = getSpaceOwnerOfParent(comp); if (is instanceof Component) { if (((AbstractComponent)is)._spaceInfo.fellows.containsKey(newId)) throw new UiException("Not unique in the ID space of "+is); } else if (is != null) { if (((PageCtrl)is).hasFellow(newId)) throw new UiException("Not unique in the ID space of "+is); } } /** Adds its descendants to the ID space when parent or page is changed, * excluding comp. */ private static void addToIdSpacesDown(Component comp) { final IdSpace is = getSpaceOwnerOfParent(comp); if (is instanceof Component) addToIdSpacesDown(comp, (Component)is); else if (is != null) addToIdSpacesDown(comp, (PageCtrl)is); } private static void addToIdSpacesDown(Component comp, Component owner) { if (!(comp instanceof NonFellow) && !ComponentsCtrl.isAutoId(comp.getId())) ((AbstractComponent)owner).bindToIdSpace(comp); if (!(comp instanceof IdSpace)) for (Iterator it = comp.getChildren().iterator(); it.hasNext();) addToIdSpacesDown((Component)it.next(), owner); //recursive } private static void addToIdSpacesDown(Component comp, PageCtrl owner) { if (!(comp instanceof NonFellow) && !ComponentsCtrl.isAutoId(comp.getId())) owner.addFellow(comp); if (!(comp instanceof IdSpace)) for (Iterator it = comp.getChildren().iterator(); it.hasNext();) addToIdSpacesDown((Component)it.next(), owner); //recursive } /** Adds its descendants to the ID space when parent or page is changed, * excluding comp. */ private static void removeFromIdSpacesDown(Component comp) { final IdSpace is = getSpaceOwnerOfParent(comp); if (is instanceof Component) removeFromIdSpacesDown(comp, (Component)is); else if (is != null) removeFromIdSpacesDown(comp, (PageCtrl)is); } private static void removeFromIdSpacesDown(Component comp, Component owner) { final String compId = comp.getId(); if (!(comp instanceof NonFellow) && !ComponentsCtrl.isAutoId(compId)) ((AbstractComponent)owner).unbindFromIdSpace(compId); if (!(comp instanceof IdSpace)) for (Iterator it = comp.getChildren().iterator(); it.hasNext();) removeFromIdSpacesDown((Component)it.next(), owner); //recursive } private static void removeFromIdSpacesDown(Component comp, PageCtrl owner) { if (!(comp instanceof NonFellow) && !ComponentsCtrl.isAutoId(comp.getId())) owner.removeFellow(comp); if (!(comp instanceof IdSpace)) for (Iterator it = comp.getChildren().iterator(); it.hasNext();) removeFromIdSpacesDown((Component)it.next(), owner); //recursive } /** Checks the uniqueness in ID space when changing parent. */ private static void checkIdSpacesDown(Component comp, Component newparent) { final IdSpace is = newparent.getSpaceOwner(); if (is instanceof Component) checkIdSpacesDown(comp, ((AbstractComponent)is)._spaceInfo); else if (is != null) checkIdSpacesDown(comp, (PageCtrl)is); } /** Checks comp and its descendants for the specified SpaceInfo. */ private static void checkIdSpacesDown(Component comp, SpaceInfo si) { final String compId = comp.getId(); if (!(comp instanceof NonFellow) && !ComponentsCtrl.isAutoId(compId) && si.fellows.containsKey(compId)) throw new UiException("Not unique in the new ID space: "+compId); if (!(comp instanceof IdSpace)) for (Iterator it = comp.getChildren().iterator(); it.hasNext();) checkIdSpacesDown((Component)it.next(), si); //recursive } /** Checks comp and its descendants for the specified page. */ private static void checkIdSpacesDown(Component comp, PageCtrl pageCtrl) { final String compId = comp.getId(); if (!(comp instanceof NonFellow) && !ComponentsCtrl.isAutoId(compId) && pageCtrl.hasFellow(compId)) throw new UiException("Not unique in the ID space of "+pageCtrl+": "+compId); if (!(comp instanceof IdSpace)) for (Iterator it = comp.getChildren().iterator(); it.hasNext();) checkIdSpacesDown((Component)it.next(), pageCtrl); //recursive } /** Bind comp to this ID space (owned by this component). * Called only if IdSpace is implemented. */ private void bindToIdSpace(Component comp) { final String compId = comp.getId(); _spaceInfo.fellows.put(compId, comp); } /** Unbind comp from this ID space (owned by this component). * Called only if IdSpace is implemented. */ private void unbindFromIdSpace(String compId) { _spaceInfo.fellows.remove(compId); } //-- Extra utlities --// /** Returns the mold URI based on {@link #getMold} * and the molds defined in the component definition * ({@link ComponentDefinition}). * * <p>As of release 3.0.0, it may return a String instance representing * the URI, or a {@link ComponentRenderer} instance responsible for * redrawing. * * <p>Used only for component implementation. */ protected Object getMoldURI() { return _def.getMoldURI(this, getMold()); } /** Returns the UI engine based on {@link #_page}'s getDesktop(). * Don't call this method when _page is null. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -