Mercurial > projects > dwt-addons
diff dwtx/core/commands/contexts/ContextManager.d @ 3:6518c18a01f7
eclipse.core package without osgi dependencies
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Wed, 26 Mar 2008 00:57:19 +0100 |
parents | |
children | 04b47443bb01 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/core/commands/contexts/ContextManager.d Wed Mar 26 00:57:19 2008 +0100 @@ -0,0 +1,339 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ + +module dwtx.core.commands.contexts.ContextManager; + +import tango.util.collection.HashSet; +import tango.util.collection.model.Set; +import tango.util.collection.model.SetView; + +import dwtx.core.commands.contexts.IContextListener; +import dwtx.core.commands.contexts.IContextManagerListener; +import dwtx.core.commands.contexts.ContextEvent; +import dwtx.core.commands.contexts.ContextManagerEvent; +import dwtx.core.commands.contexts.Context; +import dwtx.core.commands.common.HandleObjectManager; +import dwtx.core.commands.util.Tracing; +import dwtx.core.internal.commands.util.Util; + +import dwt.dwthelper.utils; + +/** + * <p> + * A context manager tracks the sets of defined and enabled contexts within the + * application. The manager sends notification events to listeners when these + * sets change. It is also possible to retrieve any given context with its + * identifier. + * </p> + * <p> + * This class is not intended to be extended by clients. + * </p> + * + * @since 3.1 + */ +public final class ContextManager : HandleObjectManager, + IContextListener { + + private static const String DEFER_EVENTS = "dwtx.ui.internal.contexts.deferEvents"; //$NON-NLS-1$ + private static const String SEND_EVENTS = "dwtx.ui.internal.contexts.sendEvents"; //$NON-NLS-1$ + + /** + * This flag can be set to <code>true</code> if the context manager should + * print information to <code>System.out</code> when certain boundary + * conditions occur. + */ + public static bool DEBUG = false; + + /** + * The set of active context identifiers. This value may be empty, but it is + * never <code>null</code>. + */ + private Set!(String) activeContextIds; + private static Set!(String) EMPTY_SET; + + // allow the ContextManager to send one event for a larger delta + private bool caching = false; + + private int cachingRef = 0; + + private bool activeContextsChange = false; + + private Set!(String) oldIds = null; + + public this(){ + activeContextIds = new HashSet!(String); + if( EMPTY_SET is null ){ + EMPTY_SET = new HashSet!(String); + } + } + + /** + * Activates a context in this context manager. + * + * @param contextId + * The identifier of the context to activate; must not be + * <code>null</code>. + */ + public final void addActiveContext(String contextId) { + if (DEFER_EVENTS.equals(contextId)) { + cachingRef++; + if (cachingRef is 1 ) { + setEventCaching(true); + } + return; + } else if (SEND_EVENTS.equals(contextId)) { + cachingRef--; + if (cachingRef is 0) { + setEventCaching(false); + } + return; + } + + if (activeContextIds.contains(contextId)) { + return; + } + activeContextsChange = true; + + if (caching) { + activeContextIds.add(contextId); + } else { + Set!(String) previouslyActiveContextIds = activeContextIds.duplicate(); + activeContextIds.add(contextId); + + fireContextManagerChanged(new ContextManagerEvent(this, null, + false, true, previouslyActiveContextIds)); + } + + if (DEBUG) { + Tracing.printTrace("CONTEXTS", SetToString(activeContextIds)); //$NON-NLS-1$ + } + + } + + /** + * Adds a listener to this context manager. The listener will be notified + * when the set of defined contexts changes. This can be used to track the + * global appearance and disappearance of contexts. + * + * @param listener + * The listener to attach; must not be <code>null</code>. + */ + public final void addContextManagerListener( + IContextManagerListener listener) { + addListenerObject(cast(Object)listener); + } + + public final void contextChanged(ContextEvent contextEvent) { + if (contextEvent.isDefinedChanged()) { + Context context = contextEvent.getContext(); + String contextId = context.getId(); + bool contextIdAdded = context.isDefined(); + if (contextIdAdded) { + definedHandleObjects.add(context); + } else { + definedHandleObjects.remove(context); + } + if (isListenerAttached()) { + fireContextManagerChanged(new ContextManagerEvent(this, + contextId, contextIdAdded, false, null)); + } + } + } + + /** + * Notifies all of the listeners to this manager that the set of defined + * context identifiers has changed. + * + * @param event + * The event to send to all of the listeners; must not be + * <code>null</code>. + */ + private final void fireContextManagerChanged(ContextManagerEvent event) { + if (event is null) { + throw new NullPointerException(); + } + + Object[] listeners = getListeners(); + for (int i = 0; i < listeners.length; i++) { + IContextManagerListener listener = cast(IContextManagerListener) listeners[i]; + listener.contextManagerChanged(event); + } + } + + /** + * Returns the set of active context identifiers. + * + * @return The set of active context identifiers; this value may be + * <code>null</code> if no active contexts have been set yet. If + * the set is not <code>null</code>, then it contains only + * instances of <code>String</code>. + */ + public final SetView!(String) getActiveContextIds() { + return /+Collections.unmodifiableSet(+/activeContextIds/+)+/; + } + + /** + * Gets the context with the given identifier. If no such context currently + * exists, then the context will be created (but be undefined). + * + * @param contextId + * The identifier to find; must not be <code>null</code>. + * @return The context with the given identifier; this value will never be + * <code>null</code>, but it might be undefined. + * @see Context + */ + public final Context getContext(String contextId) { + checkId(contextId); + + Context context = cast(Context) handleObjectsById.get(contextId); + if (context is null) { + context = new Context(contextId); + handleObjectsById.add(contextId, context); + context.addContextListener(this); + } + + return context; + } + + /** + * Returns the set of identifiers for those contexts that are defined. + * + * @return The set of defined context identifiers; this value may be empty, + * but it is never <code>null</code>. + */ + public final Set!(String) getDefinedContextIds() { + return getDefinedHandleObjectIds(); + } + + /** + * Returns the those contexts that are defined. + * + * @return The defined contexts; this value may be empty, but it is never + * <code>null</code>. + * @since 3.2 + */ + public final Context[] getDefinedContexts() { + return cast(Context[]) definedHandleObjects + .toArray(/+new Context[definedHandleObjects.size()]+/); + } + + /** + * Deactivates a context in this context manager. + * + * @param contextId + * The identifier of the context to deactivate; must not be + * <code>null</code>. + */ + public final void removeActiveContext(String contextId) { + if (!activeContextIds.contains(contextId)) { + return; + } + + activeContextsChange = true; + if (caching) { + activeContextIds.remove(contextId); + } else { + auto previouslyActiveContextIds = activeContextIds.dup; + activeContextIds.remove(contextId); + + fireContextManagerChanged(new ContextManagerEvent(this, null, + false, true, previouslyActiveContextIds)); + } + + if (DEBUG) { + Tracing.printTrace("CONTEXTS", SetToString(activeContextIds)); //$NON-NLS-1$ + } + } + private String SetToString( Set!(String) set ){ + String s = "["; + foreach( id; set ){ + if( s.length > 1 ) s ~= ", "; + s ~= id; + } + s ~= "]"; + return s; + } + /** + * Removes a listener from this context manager. + * + * @param listener + * The listener to be removed; must not be <code>null</code>. + */ + public final void removeContextManagerListener( + IContextManagerListener listener) { + removeListenerObject(cast(Object)listener); + } + + /** + * Changes the set of active contexts for this context manager. The whole + * set is required so that internal consistency can be maintained and so + * that excessive recomputations do nothing occur. + * + * @param activeContextIds + * The new set of active context identifiers; may be + * <code>null</code>. + */ + public final void setActiveContextIds(Set!(String) activeContextIds) { + if (Util.equals(this.activeContextIds.toArray, activeContextIds.toArray)) { + return; + } + + activeContextsChange = true; + + Set!(String) previouslyActiveContextIds = this.activeContextIds; + if (activeContextIds !is null) { + this.activeContextIds = activeContextIds.duplicate; + } else { + this.activeContextIds = null; + } + + if (DEBUG) { + Tracing.printTrace("CONTEXTS", (activeContextIds is null) ? "none" //$NON-NLS-1$ //$NON-NLS-2$ + : SetToString(activeContextIds)); + } + + if (!caching) { + fireContextManagerChanged(new ContextManagerEvent(this, null, + false, true, previouslyActiveContextIds)); + } + } + + /** + * Set the manager to cache context id changes. + * + * @param cache + * <code>true</code> to turn caching on, <code>false</code> + * to turn caching off and send an event if necessary. + * @since 3.3 + */ + private void setEventCaching(bool cache) { + if (caching is cache) { + return; + } + caching = cache; + bool fireChange = activeContextsChange; + Set!(String) holdOldIds = (oldIds is null? EMPTY_SET : oldIds ); + + if (caching) { + oldIds = activeContextIds.duplicate; + } else { + oldIds = null; + } + activeContextsChange = false; + + if (!caching && fireChange) { + fireContextManagerChanged(new ContextManagerEvent(this, null, + false, true, holdOldIds)); + } + } +}