⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uivisualizer.java

📁 非常接近C/S操作方式的Java Ajax框架-ZK 用ZK框架使你的B/S应用程序更漂亮更易操作。 官网:www.zkoss.org
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* UiVisualizer.java{{IS_NOTE	Purpose:			Description:			History:		Tue Jun 14 10:57:48     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.impl;import java.util.Iterator;import java.util.ListIterator;import java.util.Collection;import java.util.Collections;import java.util.List;import java.util.LinkedList;import java.util.Set;import java.util.LinkedHashSet;import java.util.HashSet;import java.util.Map;import java.util.LinkedHashMap;import java.util.HashMap;import java.util.Arrays;import java.io.StringWriter;import java.io.IOException;import org.zkoss.lang.D;import org.zkoss.lang.Objects;import org.zkoss.util.logging.Log;import org.zkoss.zk.ui.Desktop;import org.zkoss.zk.ui.Page;import org.zkoss.zk.ui.Component;import org.zkoss.zk.ui.Components;import org.zkoss.zk.ui.Execution;import org.zkoss.zk.ui.UiException;import org.zkoss.zk.ui.ext.render.Transparent;import org.zkoss.zk.ui.ext.render.Cropper;import org.zkoss.zk.ui.ext.render.ChildChangedAware;import org.zkoss.zk.ui.ext.render.MultiBranch;import org.zkoss.zk.ui.sys.Visualizer;import org.zkoss.zk.ui.sys.DesktopCtrl;import org.zkoss.zk.ui.sys.PageCtrl;import org.zkoss.zk.ui.sys.ComponentCtrl;import org.zkoss.zk.ui.sys.AbortingReason;import org.zkoss.zk.au.*;/** * An implementation of {@link Visualizer} that works with * {@link UiEngineImpl}. * * @author tomyeh *//*package*/ class UiVisualizer implements Visualizer {	private static final Log log = Log.lookup(UiVisualizer.class);	/** The first exec info that causes a chain of executions (never null).	 */	private final UiVisualizer _1stec;	/** The associated execution. */	private final Execution _exec;	/** A set of invalidated pages. */	private Set _pgInvalid;	/** A set of removed pages. */	private Set _pgRemoved;	/** A set of invalidated components  (Component). */	private final Set _invalidated = new LinkedHashSet(37);	/** A map of smart updates (Component comp, Map(String name, TimedValue(comp,name,value))). */	private final Map _smartUpdated = new HashMap(53); //we use TimedValue for better sequence control	/** A set of new attached components. */	private final Set _attached = new LinkedHashSet(37);	/** A set of moved components (parent changed or page changed). */	private final Set _moved = new LinkedHashSet(37);	/** A map of components whose UUID is changed (Component, UUID). */	private Map _idChgd;	/** A map of responses being added(Component/Page, Map(key, List/TimedValue(AuResponse))). */	private Map _responses;	/** A stack of components that are including new pages (and then	 * become the owner of the new page, if any).	 */	private final List _owners;	/** Time stamp for smart update and responses (see {@link TimedValue}). */	private int _timed;	/** if not null, it means the current executing is aborting	 * and the content is reason to aborting. Its interpretation depends	 * on {@link org.zkoss.zk.ui.sys.UiEngine}.	 */	private AbortingReason _aborting;	/** Whether the first execution (_1stec) is for async-update. */	private final boolean _1stau;	/**	 * Creates a root execution (without parent).	 * In other words, it must be the first execution in the current request.	 *	 * @param asyncUpdate whether this exec is for async-update	 */	public UiVisualizer(Execution exec, boolean asyncUpdate) {		_exec = exec;		_1stec = this;		_1stau = asyncUpdate;		_owners = new LinkedList();	}	/**	 * Creates the following execution.	 * The first execution must use {@link #UiVisualizer(Execution, boolean)}	 */	public UiVisualizer(UiVisualizer parent, Execution exec) {		_exec = exec;		_1stec = parent._1stec;		_1stau = parent._1stau;		_owners = null;	}	//-- Visualizer --//	public final Execution getExecution() {		return _exec;	}	public final boolean isEverAsyncUpdate() {		return _1stau;	}	public final boolean addToFirstAsyncUpdate(List responses) {		if (!_1stau) return false;		if (D.ON && log.finerable()) log.finer("Add to 1st au: "+responses);		for (Iterator it = responses.iterator(); it.hasNext();)			_1stec.addResponse(null, (AuResponse)it.next());		return true;	}	//-- update/redraw --//	/** Invalidates the whole page.	 */	public void addInvalidate(Page page) {		if (!_exec.isAsyncUpdate(page))			return; //nothing to do		if (_pgInvalid == null)			_pgInvalid = new LinkedHashSet(7);		_pgInvalid.add(page);	}	/** Adds an invalidated component. Once invalidated, all invocations	 * to {@link #addSmartUpdate} are ignored in this execution.	 */	public void addInvalidate(Component comp) {		if (!_exec.isAsyncUpdate(comp.getPage()))			return; //nothing to do		if (_invalidated.add(comp))			_smartUpdated.remove(comp);	}	/** Smart updates a component's attribute.	 * Meaningful only if {@link #addInvalidate(Component)} is not called in this	 * execution	 */	public void addSmartUpdate(Component comp, String attr, String value) {		if (!_exec.isAsyncUpdate(comp.getPage()) || _invalidated.contains(comp))			return; //nothing to do		Map respmap = (Map)_smartUpdated.get(comp);		if (respmap == null)			_smartUpdated.put(comp, respmap = new HashMap());		respmap.put(attr, new TimedValue(_timed++, comp, attr, value));	}	/** Called to update (redraw) a component, when a component is moved.	 * If a component's page or parent is changed, this method need to be	 * called only once for the top one.	 *	 * @param oldparent the parent before moved	 * @param oldpg the page before moved	 * @param newpg the page after moved	 */	public void addMoved(Component comp, Component oldparent, Page oldpg, Page newpg) {		if ((newpg == null && !_exec.isAsyncUpdate(oldpg)) //detach from loading pg		|| (oldpg == null && !_exec.isAsyncUpdate(newpg))) //attach to loading pg			return; //to avoid redundant AuRemove		if (oldpg == null && !_moved.contains(comp)) { //new attached			_attached.add(comp);				//note: we cannot examine _exec.isAsyncUpdate here because				//comp.getPage might be ready when this method is called		} else {			if (_moved.add(comp)) { //first time added				//Due to the performance of Cropper.getAvailableAtClient				//usually not good, so we count on isCropper only				//In other words, this algorithm might redraw something that don't				//need to, but has better performance if no redudant redrawing				if (oldparent != null) {					final Object xc = ((ComponentCtrl)oldparent).getExtraCtrl();					if ((xc instanceof Cropper) && ((Cropper)xc).isCropper())						_invalidated.add(oldparent);				}			}			_attached.remove(comp);		}	}	/** Called before changing the component's UUID.	 *	 * @param addOnlyMoved if true, it is added only if it was moved	 * before (see {@link #addMoved}).	 */	public void addUuidChanged(Component comp, boolean addOnlyMoved) {		if ((!addOnlyMoved || _moved.contains(comp))		&& (_idChgd == null || !_idChgd.containsKey(comp))) {			if (_idChgd == null) _idChgd = new LinkedHashMap(23);			_idChgd.put(comp, comp.getUuid());		}	}	/** Adds a response directly (which will be returned when	 * {@link #getResponses} is called).	 *	 * <p>If the response is component-dependent, {@link AuResponse#getDepends}	 * must return a component. And, if the component is removed, the response	 * is removed, too.	 *	 * @param key could be anything. The second invocation of this method	 * in the same execution with the same key will override the previous one.	 */	public void addResponse(String key, AuResponse response) {		if (response == null)			throw new IllegalArgumentException();		if (_responses == null)			_responses = new HashMap();		final Object depends = response.getDepends(); //Page or Component		Map respmap = (Map)_responses.get(depends);		if (respmap == null)			_responses.put(depends, respmap = new HashMap());		final TimedValue tval = new TimedValue(_timed++, response);		if (key != null) {			respmap.put(key, tval);		} else {			List resps = (List)respmap.get(null);			if (resps == null)				respmap.put(null, resps = new LinkedList());			resps.add(tval); //don't overwrite		}	}	/** Process {@link Cropper}.	 *	 * <p>Note: it is too late to handle the moved/removed components here,	 * since we don't know their old parent now!	 * Rather, we handle it in {@link #addMoved}.	 *	 * @return whether any new invalidated is added	 */	private boolean doCrop() {		final Map cropping = new HashMap();		boolean invAdded = crop(_attached, cropping, true, false);		invAdded = crop(_smartUpdated.keySet(), cropping, false, false) || invAdded;		if (_responses != null)			invAdded = crop(_responses.keySet(), cropping, false, true) || invAdded;		invAdded = crop(_invalidated, cropping, false, false) || invAdded;			//crop invalidate as the last step since new invalidated might be added		return invAdded;	}	/** Crop attached and moved.	 *	 * @return whether any new invalidated is added	 */	private boolean crop(Set coll, Map cropping, boolean bAttached,	boolean bResponse) {		Set newInvalid = null;		for (Iterator it = coll.iterator(); it.hasNext();) {			final Object o = it.next();			if (!(o instanceof Component))				continue;			final Component comp = (Component)o;			if (!_exec.isAsyncUpdate(comp.getPage())) {				if (!bResponse) it.remove(); //just in case				continue;			}			for (Component p, c = comp; (p = c.getParent()) != null; c = p) {				final Set avail = getAvailableAtClient(p, cropping);				if (avail != null) {					if (bAttached)  {						if (avail.contains(c)) {							if (c != comp)								continue; //not direct child, do as if not cropper							//don't add to _invalidate directly since coll might							//be _invalidate							if (newInvalid == null)								newInvalid = new HashSet();							newInvalid.add(p);						}						it.remove();						break;					} else if (!avail.contains(c)) {						it.remove();						break;					}				}			}		}		return newInvalid != null && _invalidated.addAll(newInvalid);	}	private static Set getAvailableAtClient(Component comp, Map cropping) {		final Object xc = ((ComponentCtrl)comp).getExtraCtrl();		if (xc instanceof Cropper) {			//we don't need to check isCropper first since its component's job			//to ensure the consistency			Set set = (Set)cropping.get(comp);			if (set != null)				return set != Collections.EMPTY_SET ? set: null;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -