📄 abstractcomponent.java
字号:
//assert D.OFF || _parent == null || _parent.getPage() == page; //detach final boolean bRoot = _parent == null; if (_page != null) { if (bRoot) ((PageCtrl)_page).removeRoot(this); if (page == null) { ((DesktopCtrl)_desktop).removeComponent(this); _desktop = null; } } final Page oldpage = _page; _page = page; //attach if (_page != null) { if (bRoot) ((PageCtrl)_page).addRoot(this); //Not depends on uuid if (oldpage == null) { _desktop = _page.getDesktop(); final boolean anonymous = ComponentsCtrl.AUTO_ID_PREFIX.equals(_uuid); if (anonymous || _desktop.getComponentByUuidIfAny(_uuid) != null) { if (!anonymous) getThisUiEngine().addUuidChanged(this, true); //called before uuid is changed //stupid but no better way to find a correct UUID yet //also, it is rare so performance not an issue do { _uuid = nextUuid(_desktop); } while (_desktop.getComponentByUuidIfAny(_uuid) != null); if (D.ON && log.finerable()) log.finer("Uuid changed: "+this); } ((DesktopCtrl)_desktop).addComponent(this); //depends on uuid } } if (_spaceInfo != null && _parent == null) _spaceInfo.ns.setParent( page != null ? page.getNamespace(): null); //process all children recursively for (final Iterator it = _children.iterator(); it.hasNext();) { final Object child = it.next(); ((AbstractComponent)child).setPage0(page); //recursive } } public final String getId() { return _id; } public void setId(String id) { if (id == null || id.length() == 0) throw new UiException("ID cannot be empty"); if (!_id.equals(id)) { if (Variables.isReserved(id) || ComponentsCtrl.isAutoId(id)) throw new UiException("Invalid ID: "+id+". Cause: reserved words not allowed: "+Variables.getReservedNames()); final boolean rawId = this instanceof RawId; if (rawId && _desktop != null && _desktop.getComponentByUuidIfAny(id) != null) throw new UiException("Replicated ID is not allowed for "+getClass()+": "+id+"\nNote: HTML/WML tags, ID must be unique"); checkIdSpaces(this, id); removeFromIdSpaces(this); if (rawId) { //we have to change UUID if (_desktop != null) { getThisUiEngine().addUuidChanged(this, false); //called before uuid is changed ((DesktopCtrl)_desktop).removeComponent(this); } else { final UiEngine eng = getCurrentUiEngine(); if (eng != null) eng.addUuidChanged(this, true); } _uuid = _id = id; if (_desktop != null) { ((DesktopCtrl)_desktop).addComponent(this); if (_parent != null && isTransparent(this)) _parent.invalidate(); addMoved(this, _parent, _page, _page); } } else { _id = id; } addToIdSpaces(this); final Object xc = getExtraCtrl(); if ((xc instanceof ZidRequired) && ((ZidRequired)xc).isZidRequired()) smartUpdate("z.zid", _id); } } private static boolean isTransparent(Component comp) { final Object xc = ((ComponentCtrl)comp).getExtraCtrl(); return (xc instanceof Transparent) && ((Transparent)xc).isTransparent(); } public final String getUuid() { return _uuid; } public final IdSpace getSpaceOwner() { Component p = this; do { if (p instanceof IdSpace) return (IdSpace)p; } while ((p = p.getParent()) != null); return _page; } public Component getFellow(String compId) { if (this instanceof IdSpace) { final Component comp = (Component)_spaceInfo.fellows.get(compId); if (comp == null) if (compId != null && ComponentsCtrl.isAutoId(compId)) throw new ComponentNotFoundException(MZk.AUTO_ID_NOT_LOCATABLE, compId); else throw new ComponentNotFoundException("Fellow component not found: "+compId); return comp; } final IdSpace idspace = getSpaceOwner(); if (idspace == null) throw new ComponentNotFoundException("This component doesn't belong to any ID space: "+this); return idspace.getFellow(compId); } public Component getFellowIfAny(String compId) { if (this instanceof IdSpace) return (Component)_spaceInfo.fellows.get(compId); final IdSpace idspace = getSpaceOwner(); return idspace == null ? null: idspace.getFellowIfAny(compId); } public Map getAttributes(int scope) { switch (scope) { case SPACE_SCOPE: if (this instanceof IdSpace) return _spaceInfo.attrs; final IdSpace idspace = getSpaceOwner(); return idspace instanceof Page ? ((Page)idspace).getAttributes(): idspace == null ? Collections.EMPTY_MAP: ((Component)idspace).getAttributes(SPACE_SCOPE); case PAGE_SCOPE: return _page != null ? _page.getAttributes(): Collections.EMPTY_MAP; case DESKTOP_SCOPE: return _desktop != null ? _desktop.getAttributes(): Collections.EMPTY_MAP; case SESSION_SCOPE: return _desktop != null ? _desktop.getSession().getAttributes(): Collections.EMPTY_MAP; case APPLICATION_SCOPE: return _desktop != null ? _desktop.getWebApp().getAttributes(): Collections.EMPTY_MAP; case COMPONENT_SCOPE: return _attrs; case REQUEST_SCOPE: final Execution exec = getExecution(); if (exec != null) return exec.getAttributes(); //fall thru default: return Collections.EMPTY_MAP; } } private final Execution getExecution() { return _desktop != null ? _desktop.getExecution(): Executions.getCurrent(); } public Object getAttribute(String name, int scope) { return getAttributes(scope).get(name); } public Object setAttribute(String name, Object value, int scope) { if (value != null) { final Map attrs = getAttributes(scope); if (attrs == Collections.EMPTY_MAP) throw new IllegalStateException("This component, "+this +", doesn't belong to the "+Components.scopeToString(scope)+" scope"); return attrs.put(name, value); } else { return removeAttribute(name, scope); } } public Object removeAttribute(String name, int scope) { final Map attrs = getAttributes(scope); if (attrs == Collections.EMPTY_MAP) throw new IllegalStateException("This component doesn't belong to any ID space: "+this); return attrs.remove(name); } public final Map getAttributes() { return _attrs; } public final Object getAttribute(String name) { return _attrs.get(name); } public final Object setAttribute(String name, Object value) { return value != null ? _attrs.put(name, value): _attrs.remove(name); } public final Object removeAttribute(String name) { return _attrs.remove(name); } public void setVariable(String name, Object val, boolean local) { getNamespace().setVariable(name, val, local); } public Object getVariable(String name, boolean local) { return getNamespace().getVariable(name, local); } public void unsetVariable(String name) { getNamespace().unsetVariable(name); } public Component getParent() { return _parent; } public void setParent(Component parent) { if (_parent == parent) return; //nothing changed final boolean idSpaceChanged; if (parent != null) { if (Components.isAncestor(this, parent)) throw new UiException("A child cannot be a parent of its ancestor: "+this); if (!parent.isChildable()) throw new UiException(parent+" doesn't allow any child"); final Page newpage = parent.getPage(); if (newpage != null && newpage.getDesktop() != _desktop && _desktop != null) throw new UiException("The new parent must be in the same desktop: "+parent); //Not allow developers to access two desktops simutaneously idSpaceChanged = parent.getSpaceOwner() != (_parent != null ? _parent.getSpaceOwner(): _page); if (idSpaceChanged) checkIdSpacesDown(this, parent); } else { idSpaceChanged = _page != null; } if (_parent != null && isTransparent(this)) _parent.invalidate(); if (idSpaceChanged) removeFromIdSpacesDown(this); final Component oldparent = _parent; if (_parent != null) { _parent = null; //update first to avoid loop back oldparent.removeChild(this); //spec: removeChild must be called } else { if (_page != null) ((PageCtrl)_page).removeRoot(this); //Not depends on uuid } if (parent != null) { _parent = parent; //update first to avoid loop back //We could use _parent.getChildren().contains instead, but //the following statement is much faster if a lot of children if (!((AbstractComponent)_parent)._newChildren.contains(this)) parent.appendChild(this); } //if parent == null, assume no page at all (so no addRoot) final Page newpg = _parent != null ? _parent.getPage(): null; addMoved(this, oldparent, _page, newpg); //Not depends on UUID setPage0(newpg); //UUID might be changed here if (_spaceInfo != null) //ID space owner _spaceInfo.ns.setParent( _parent != null ? _parent.getNamespace(): null); if (idSpaceChanged) addToIdSpacesDown(this); //called after setPage checkRootEvents(null); } /** Default: return true (allows to have children). */ public boolean isChildable() { return true; } public boolean insertBefore(Component newChild, Component refChild) { if (newChild == null) throw new UiException("newChild is null"); boolean found = false; if (_modChildByIter) { _modChildByIter = false; //avoid dead loop } else { boolean added = false; for (ListIterator it = _children.listIterator(); it.hasNext();) { final Object o = it.next(); if (o == newChild) { if (!added) { if (!it.hasNext()) return false; //last if (it.next() == refChild) return false; //same position it.previous(); it.previous(); it.next(); //restore cursor } it.remove(); found = true; if (added || refChild == null) break; //done } else if (o == refChild) { it.previous(); it.add(newChild); it.next(); added = true; if (found) break; //done } } if (!added) _children.add(newChild); } final AbstractComponent nc = (AbstractComponent)newChild; if (found) { //re-order if (isTransparent(newChild)) invalidate(); addMoved(newChild, nc._parent, nc._page, _page); //Not to use getPage and getParent to avoid calling user's codes //if they override them } else { //new added if (nc._parent != this) { //avoid loop back _newChildren.add(newChild); //used by setParent to avoid loop back try { newChild.setParent(this); //call addMoved, setPage0... } finally { _newChildren.remove(newChild); } } onChildAdded(newChild); } return true; } /** Appends a child to the end of all children. * It calls {@link #insertBefore} with refChild to be null. * Derives cannot override this method, and they shall override * {@link #insertBefore} instead. */ public final boolean appendChild(Component child) { //Yes, final; see below return insertBefore(child, null); //NOTE: we must go thru insertBefore //such that deriving is easy to override } public boolean removeChild(Component child) { if (child == null) throw new UiException("child must be specified"); if (_modChildByIter || _children.remove(child)) { _modChildByIter = false; //avoid dead loop if (child.getParent() != null) //avoid loop back child.setParent(null); onChildRemoved(child); //to invalidate itself if necessary return true; } else { return false; } } public List getChildren() { return _modChildren; } /** Returns the root of the specified component. */ public Component getRoot() { for (Component comp = this;;) { final Component parent = comp.getParent(); if (parent == null) return comp; comp = parent; } } public boolean isVisible() { return _visible; } public boolean setVisible(boolean visible) { final boolean old = _visible; if (old != visible) { _visible = visible; if (!isTransparent(this)) smartUpdate("visibility", _visible); } return old; } public void invalidate() { if (_page != null) { getThisUiEngine().addInvalidate(this); //always add even though _parent.invalidate might be called //reason: Transparent relationship might be changed if (_parent != null && isTransparent(this)) _parent.invalidate(); //Note: UiEngine will handle transparent, but we still //handle it here to simplify codes that handles transparent //in AbstractComponent } } public void response(String key, AuResponse response) { //if response depends on nothing, it must be generated if (_page != null || (_desktop != null && response.getDepends() == null)) getThisUiEngine().addResponse(key, response); } public void smartUpdate(String attr, String value) { if (_parent != null && isTransparent(this)) throw new IllegalStateException("A transparent component cannot use smartUpdate: "+attr+'='+value); if (_page != null) getThisUiEngine().addSmartUpdate(this, attr, value); } /** A special smart-update that update a value in int. */ public void smartUpdate(String attr, int value) { smartUpdate(attr, Integer.toString(value)); } /** A special smart-update that update a value in boolean. */ public void smartUpdate(String attr, boolean value) { smartUpdate(attr, Boolean.toString(value)); } public void detach() { if (getParent() != null) setParent(null); else setPage(null); } /** Default: does nothing. */ public void onChildAdded(Component child) { } /** Default: does nothing. */ public void onChildRemoved(Component child) { } /** Default: null (no propagation at all). */ public Component getPropagatee(String evtnm) { return null; } /** * Default: "default" */ public final String getMold() { return _mold; } public void setMold(String mold) { if (mold == null || mold.length() == 0) mold = "default"; if (!Objects.equals(_mold, mold)) { if (!_mill.hasMold(mold)) throw new UiException("Unknown mold: "+mold +", while allowed include "+_mill.getMoldNames()); _mold = mold;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -