* For those elements that do not have a one-to-one mapping to resources, * the model must do extra work. The purpose of this class is to allow * the model to decide when a label update for a logical model element is * required and to communicate the dirty state of their logical model - * elements to the team decorator. For logical model elements, the team decorator - * will only decorate based on the supervised state and the dirty state. - * This class provides methods for determining both of these so that - * logical models can track whether a label update is required for a - * model element. + * elements to the team decorator. *
* Model providers need to re-evaluate the state of a * model element whenever a change in the resources occurs by listening - * to both resource deltas and subscriber change events. + * to both resource deltas and change events from the decorated state provider + * ({@link #getDecoratedStateProvider()}. *
* Decoration enablement changes and decoration configuration changes
* are handled by the {@link IDecoratorManager#update(String)} API.
@@ -69,100 +59,72 @@
* @see Subscriber#addListener(org.eclipse.team.core.subscribers.ISubscriberChangeListener)
*/
public class SynchronizationStateTester {
-
+
/**
* Constant that is used as the property key on an {@link IDecorationContext}.
* If a context passed to a team decorator has this property, the associated
- * state tester will be used by the deocator to determine whether elements
+ * state tester will be used by the decorator to determine whether elements
* have an outgoing change.
*/
public static final String PROP_TESTER = "org.eclipse.team.ui.syncStateTester"; //$NON-NLS-1$
- private Subscriber subscriber;
-
/**
- * Create a tester that uses the workspace subscriber to
- * obtain the synchronization state of resources.
- * @see Team#getWorkspaceSubscriber()
+ * Create a synchronization state tester.
*/
public SynchronizationStateTester() {
- this(Team.getWorkspaceSubscriber());
+ super();
}
/**
- * Create a tester that obtains the synchroniation state
- * from the given subscriber.
- * @param subscriber the subscriber
+ * Return whether state decoration is enabled for the context
+ * to which this tester is associated. If true
+ * is returned, a team decorator will use the state methods provided
+ * on this class to calculate the synchronization state of model
+ * elements for the purpose of decoration. If false
+ * is returned, a team decorator will not decorate the elements with any
+ * synchronization related decorations. Subclasses will want to disable
+ * state decoration if state decoration is being provided another way
+ * (e.g. by a {@link SynchronizationLabelProvider}). By default,
+ * true
is returned. Subclasses may override.
+ * @return whether state decoration is enabled
*/
- public SynchronizationStateTester(Subscriber subscriber) {
- this.subscriber = subscriber;
+ public boolean isStateDecorationEnabled() {
+ return true;
}
-
+
/**
* Return whether decoration is enabled for the given
- * model element. If decoration is not enabled, the model
- * does not need to fire label change events when the team state
- * of the element changes.
+ * model element in the context to which this tester is associated.
+ * By default, the enablement state from the provider returned
+ * from {@link #getDecoratedStateProvider()} is used but subclasses
+ * may override to disable decoration of particular elements.
+ *
+ * A team decorator should call this method before decorating a model element.
+ * If the method returns true
, no team state decorations should be applied
+ * to the model element. Otherwise, the {@link #getState(Object, int, IProgressMonitor)}
+ * should be consulted in order to determine what state to decorate.
* @param element the model element
* @return whether decoration is enabled for the given
* model element
*/
- public final boolean isDecorationEnabled(Object element) {
- ResourceMapping mapping = Utils.getResourceMapping(element);
- if (mapping != null) {
- IProject[] projects = mapping.getProjects();
- return internalIsDecorationEnabled(projects);
- }
- return false;
+ public boolean isDecorationEnabled(Object element) {
+ return isStateDecorationEnabled()
+ && getDecoratedStateProvider().isDecorationEnabled(element);
}
/**
* Return the mask that indicates what state the appropriate team decorator
- * is capable of decorating. The state is determined by querying the
- * org.eclipse.team.ui.teamDecorators
extension point.
- *
- *
- * The state mask can consist of the following flags: - *
true
- * is returned, team decorators will use the state methods provided
- * on this class to calculate the synchronization state of model
- * elements for the purpose of decoration. If false
- * is returned, team decorators will not decorate the elements with any
- * synchronization related decorations. Subclasses will want to disable
- * state decoration if state decoration is being provided another way
- * (e.g. by a {@link SynchronizationLabelProvider}). By default,
- * true
is returned. Subclasses may override.
- * @return whether state decoration is enabled
- */
- public boolean isStateDecorationEnabled() {
- return true;
+ return getDecoratedStateProvider().getDecoratedStateMask(element);
}
/**
@@ -171,7 +133,7 @@
* returned. By default, this method calls
* {@link Subscriber#getState(ResourceMapping, int, IProgressMonitor)}.
* - * Team decorators will use this method to detemine how to decorate the + * A team decorator will use this method to determine how to decorate the * provided element. The {@link #getDecoratedStateMask(Object)} returns the * state that the corresponding team decorator is capable of decorating but * the decorator may be configured to decorate only a portion of that state. @@ -186,10 +148,11 @@ * decorated state of a model element changes. In this case the subclass * can override this method to record the stateMask and returned state. It can * use this recorded information to determine whether local changes or subscriber changes - * result in a change in the deocrated sstate of the model element. + * result in a change in the decorated state of the model element. *
+ * Change events may not be issued if a local change has resulted in a + * synchronization state change. It is up to clients to check whether + * a label update is required for a model element when local resources change + * by using the resource delta mechanism. + *
+ * Clients may implement this interface + * + * @see IWorkspace#addResourceChangeListener(org.eclipse.core.resources.IResourceChangeListener) + * @since 3.2 + */ +public interface ITeamStateChangeListener extends EventListener { + + /** + * Notification that the team state of resources + * has changed. + * @param event the event that describes which resources have changed + */ + public void teamStateChanged(ITeamStateChangeEvent event); + +} Index: src/org/eclipse/team/ui/mapping/ITeamStateChangeEvent.java =================================================================== RCS file: src/org/eclipse/team/ui/mapping/ITeamStateChangeEvent.java diff -N src/org/eclipse/team/ui/mapping/ITeamStateChangeEvent.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/team/ui/mapping/ITeamStateChangeEvent.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2006 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 + *******************************************************************************/ +package org.eclipse.team.ui.mapping; + +import org.eclipse.core.resources.IResource; +import org.eclipse.team.ui.synchronize.TeamStateChangeEvent; + +/** + * A description of the team state changes that have occurred. This event + * indicates the resources for which the team state may have changed. + * However, it may be the case that the state did not actually change. Clients + * that wish to determine if the state ha changed must cache the previous state + * and re-obtain the state when they receive this event. Also, the event may + * not include team state changes that resulted from local changes. Clients should listen + * for resource changes as well. + *
+ * This interface is not intended to be implemented by clients. Clients should
+ * instead use {@link TeamStateChangeEvent}.
+ *
+ * @see ITeamStateChangeListener
+ * @see ITeamStateProvider
+ * @see TeamStateChangeEvent
+ *
+ * @since 3.2
+ */
+public interface ITeamStateChangeEvent {
+
+ /**
+ * Return the set of resources that were previously undecorated
+ * but are now decorated.
+ * @return the set of resources that were previously undecorated
+ * but are now decorated.
+ */
+ public IResource[] getAddedRoots();
+
+ /**
+ * Return the set of resources that were previously decorated
+ * but are now undecorated.
+ * @return the set of resources that were previously decorated
+ * but are now undecorated.
+ */
+ public IResource[] getRemovedRoots();
+
+ /**
+ * Return the set of resources whose decorated state has changed.
+ * @return the set of resources whose decorated state has changed.
+ */
+ public IResource[] getChangedResources();
+
+ /**
+ * Return whether the resource has any state changes. This returns
+ * true
if the resource is included in the set
+ * of changes returned by {@link #getChangedResources()} or
+ * if it is a descendant of a root that is present in a set
+ * returned by {@link #getAddedRoots()} or {@link #getRemovedRoots()}.
+ *
+ * @param resource the resource
+ * @return whether the resource has any state changes
+ */
+ public boolean hasChange(IResource resource);
+
+}
Index: src/org/eclipse/team/ui/synchronize/TeamStateProvider.java
===================================================================
RCS file: src/org/eclipse/team/ui/synchronize/TeamStateProvider.java
diff -N src/org/eclipse/team/ui/synchronize/TeamStateProvider.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/team/ui/synchronize/TeamStateProvider.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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
+ *******************************************************************************/
+package org.eclipse.team.ui.synchronize;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.mapping.ResourceMapping;
+import org.eclipse.core.runtime.*;
+import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.team.core.RepositoryProviderType;
+import org.eclipse.team.internal.ui.Utils;
+import org.eclipse.team.internal.ui.registry.TeamDecoratorDescription;
+import org.eclipse.team.internal.ui.registry.TeamDecoratorManager;
+import org.eclipse.team.ui.mapping.*;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * A decorated state provider is used by the {@link SynchronizationStateTester} to obtain
+ * the decorated synchronization state for model elements. A decorated state provider is
+ * associated with a {@link RepositoryProviderType} using the adaptable mechanism. A default
+ * decoration provider that uses the subscriber of the type is provided.
+ *
+ * @see IAdapterManager
+ * @see RepositoryProviderType
+ * @since 3.2
+ */
+public abstract class TeamStateProvider implements ITeamStateProvider {
+
+ private ListenerList listeners = new ListenerList(ListenerList.IDENTITY);
+
+ /**
+ * Determine if the decorator for the element is enabled by consulting the
+ * teamDecorator
extension point to determine the decorator
+ * id associated with the resources the element maps to. Subclasses may
+ * override.
+ *
+ * @see org.eclipse.team.ui.mapping.ITeamStateProvider#isDecorationEnabled(java.lang.Object)
+ */
+ public boolean isDecorationEnabled(Object element) {
+ ResourceMapping mapping = Utils.getResourceMapping(element);
+ if (mapping != null) {
+ IProject[] projects = mapping.getProjects();
+ return internalIsDecorationEnabled(projects);
+ }
+ return false;
+ }
+
+ /**
+ * Determine the decorated state for the element by consulting the
+ * teamDecorator
extension point to get the decorated state
+ * mask associated with the resources the element maps to. Subclasses may
+ * override.
+ *
+ * @see org.eclipse.team.ui.mapping.ITeamStateProvider#getDecoratedStateMask(java.lang.Object)
+ */
+ public int getDecoratedStateMask(Object element) {
+ ResourceMapping mapping = Utils.getResourceMapping(element);
+ if (mapping != null) {
+ IProject[] projects = mapping.getProjects();
+ return internalGetDecoratedStateMask(projects);
+ }
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.mapping.IDecoratedStateProvider#addDecoratedStateChangeListener(org.eclipse.team.ui.mapping.IDecoratedStateChangeListener)
+ */
+ public void addDecoratedStateChangeListener(ITeamStateChangeListener listener) {
+ listeners.add(listener);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.mapping.IDecoratedStateProvider#removeDecoratedStateChangeListener(org.eclipse.team.ui.mapping.IDecoratedStateChangeListener)
+ */
+ public void removeDecoratedStateChangeListener(ITeamStateChangeListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Fire the change event to all listeners
+ * @param event the change event
+ */
+ protected void fireStateChangeEvent(final ITeamStateChangeEvent event) {
+ Object[] allListeners = listeners.getListeners();
+ for (int i = 0; i < allListeners.length; i++) {
+ final ITeamStateChangeListener listener = (ITeamStateChangeListener)allListeners[i];
+ SafeRunner.run(new ISafeRunnable() {
+ public void run() throws Exception {
+ listener.teamStateChanged(event);
+ }
+ public void handleException(Throwable exception) {
+ // Logged by the runner
+ }
+ });
+ }
+ }
+
+ private int internalGetDecoratedStateMask(IProject[] projects) {
+ int stateMask = 0;
+ String[] providerIds = getProviderIds(projects);
+ for (int i = 0; i < providerIds.length; i++) {
+ String providerId = providerIds[i];
+ stateMask |= internalGetDecoratedStateMask(providerId);
+ }
+ return stateMask;
+ }
+
+ private int internalGetDecoratedStateMask(String providerId) {
+ TeamDecoratorDescription decoratorDescription = TeamDecoratorManager
+ .getInstance().getDecoratorDescription(providerId);
+ if (decoratorDescription != null)
+ return decoratorDescription.getDecoratedDirectionFlags();
+ return 0;
+ }
+
+ private String[] getProviderIds(IProject[] projects) {
+ Set providerIds = new HashSet();
+ for (int i = 0; i < projects.length; i++) {
+ IProject project = projects[i];
+ String id = getProviderId(project);
+ if (id != null)
+ providerIds.add(id);
+ }
+ return (String[]) providerIds.toArray(new String[providerIds.size()]);
+ }
+
+ private String getProviderId(IProject project) {
+ RepositoryProvider provider = RepositoryProvider.getProvider(project);
+ if (provider != null)
+ return provider.getID();
+ return null;
+ }
+
+ private boolean internalIsDecorationEnabled(IProject[] projects) {
+ String[] providerIds = getProviderIds(projects);
+ for (int i = 0; i < providerIds.length; i++) {
+ String providerId = providerIds[i];
+ if (internalIsDecorationEnabled(providerId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean internalIsDecorationEnabled(String providerId) {
+ String decoratorId = getDecoratorId(providerId);
+ if (decoratorId != null) {
+ return PlatformUI.getWorkbench().getDecoratorManager().getEnabled(
+ decoratorId);
+ }
+ return false;
+ }
+
+ private String getDecoratorId(String providerId) {
+ TeamDecoratorDescription decoratorDescription = TeamDecoratorManager
+ .getInstance().getDecoratorDescription(providerId);
+ if (decoratorDescription != null)
+ return decoratorDescription.getDecoratorId();
+ return null;
+ }
+
+}
Index: src/org/eclipse/team/ui/synchronize/SubscriberTeamStateProvider.java
===================================================================
RCS file: src/org/eclipse/team/ui/synchronize/SubscriberTeamStateProvider.java
diff -N src/org/eclipse/team/ui/synchronize/SubscriberTeamStateProvider.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/team/ui/synchronize/SubscriberTeamStateProvider.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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
+ *******************************************************************************/
+package org.eclipse.team.ui.synchronize;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.mapping.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.RepositoryProviderType;
+import org.eclipse.team.core.diff.IDiff;
+import org.eclipse.team.core.subscribers.*;
+import org.eclipse.team.internal.ui.Policy;
+import org.eclipse.team.internal.ui.Utils;
+import org.eclipse.team.ui.mapping.ITeamStateDescription;
+import org.eclipse.team.ui.mapping.ITeamStateProvider;
+
+/**
+ * A team state provider that makes use of a {@link Subscriber} to determine the synchronization
+ * state. Repository provider types that have a subscriber will get one of these free through the adaptable mechanism.
+ * If a repository provider type does not have a subscriber, or it a repository provider type wishes to se a custom
+ * provider, they must adapt their {@link RepositoryProviderType} class to an appropriate {@link ITeamStateProvider}.
+ *
+ * Clients may subclass this class. + * + * @since 3.2 + */ +public class SubscriberTeamStateProvider extends TeamStateProvider implements ISubscriberChangeListener { + + private Subscriber subscriber; + + /** + * Create a provider that determines the synchronization state + * from the subscriber. This method registers this provider as a listener + * on the subscriber in order to know when to fire state change events. + * @param subscriber the subscriber for this provider + */ + public SubscriberTeamStateProvider(Subscriber subscriber) { + this.subscriber = subscriber; + subscriber.addListener(this); + } + + /* (non-Javadoc) + * @see org.eclipse.team.ui.mapping.DecoratedStateProvider#isDecorated(java.lang.Object) + */ + public boolean hasDecoratedState(Object element) throws CoreException { + ResourceMapping mapping = Utils.getResourceMapping(element); + if (mapping != null) { + ResourceTraversal[] traversals = mapping.getTraversals( + ResourceMappingContext.LOCAL_CONTEXT, null); + for (int i = 0; i < traversals.length; i++) { + ResourceTraversal traversal = traversals[i]; + IResource[] resources = traversal.getResources(); + for (int j = 0; j < resources.length; j++) { + IResource resource = resources[j]; + if (getSubscriber().isSupervised(resource)) + return true; + } + } + } + return false; + } + + /** + * Obtain the synchronization state of the element from the subscriber + * using {@link Subscriber#getState(ResourceMapping, int, IProgressMonitor)} + * @param element the element + * @param stateMask the state mask that indicates which state flags are desired + * @param monitor a progress monitor + * @return the synchronization state of the element + * @throws CoreException + */ + protected int getSynchronizationState(Object element, int stateMask, + IProgressMonitor monitor) throws CoreException { + ResourceMapping mapping = Utils.getResourceMapping(element); + if (mapping != null) { + try { + return getSubscriber().getState(mapping, stateMask, monitor); + } catch (CoreException e) { + IProject[] projects = mapping.getProjects(); + for (int i = 0; i < projects.length; i++) { + IProject project = projects[i]; + // Only through the exception if the project for the mapping + // is accessible + if (project.isAccessible()) { + throw e; + } + } + } + } + return IDiff.NO_CHANGE; + } + + /* (non-Javadoc) + * @see org.eclipse.team.ui.mapping.DecoratedStateProvider#getState(java.lang.Object, int, org.eclipse.core.runtime.IProgressMonitor) + */ + public ITeamStateDescription getStateDescription(Object element, int stateMask, + String[] properties, IProgressMonitor monitor) throws CoreException { + monitor = Policy.monitorFor(monitor); + if (stateMask == USE_DECORATED_STATE_MASK) + stateMask = getDecoratedStateMask(element); + return new TeamStateDescription(getSynchronizationState(element, stateMask, monitor)); + } + + /* (non-Javadoc) + * @see org.eclipse.team.ui.mapping.IDecoratedStateProvider#getResourceMappingContext(java.lang.Object) + */ + public ResourceMappingContext getResourceMappingContext(Object element) { + return new SubscriberResourceMappingContext(subscriber, false); + } + + /** + * Return the subscriber associated with this tester. + * + * @return the subscriber associated with this tester. + */ + protected Subscriber getSubscriber() { + return subscriber; + } + + /** + * Called when the provider is no longer needed. This + * method stops listening to the subscriber. + */ + public void dispose() { + subscriber.removeListener(this); + } + + /* (non-Javadoc) + * @see org.eclipse.team.core.subscribers.ISubscriberChangeListener#subscriberResourceChanged(org.eclipse.team.core.subscribers.ISubscriberChangeEvent[]) + */ + public void subscriberResourceChanged(ISubscriberChangeEvent[] deltas) { + fireStateChangeEvent(new TeamStateChangeEvent(deltas)); + } + + /* (non-Javadoc) + * @see org.eclipse.team.ui.mapping.ITeamStateProvider#getDecoratedProperties(java.lang.Object) + */ + public String[] getDecoratedProperties(Object element) { + return new String[0]; + } +} Index: src/org/eclipse/team/ui/mapping/ITeamStateProvider.java =================================================================== RCS file: src/org/eclipse/team/ui/mapping/ITeamStateProvider.java diff -N src/org/eclipse/team/ui/mapping/ITeamStateProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/team/ui/mapping/ITeamStateProvider.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2006 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 + *******************************************************************************/ +package org.eclipse.team.ui.mapping; + +import org.eclipse.core.resources.mapping.RemoteResourceMappingContext; +import org.eclipse.core.resources.mapping.ResourceMappingContext; +import org.eclipse.core.runtime.*; +import org.eclipse.team.core.RepositoryProviderType; +import org.eclipse.team.core.diff.IDiff; +import org.eclipse.team.core.diff.IThreeWayDiff; +import org.eclipse.team.ui.synchronize.TeamStateProvider; +import org.eclipse.team.ui.synchronize.SubscriberTeamStateProvider; + +/** + * A team state provider is used by the {@link SynchronizationStateTester} + * to obtain the team state for model elements. A team + * state provider is associated with a {@link RepositoryProviderType} using the + * adaptable mechanism. A default decoration provider that uses the subscriber + * of the type is provided. + *
+ * This interface is not intended to be implemented by clients. Clients should + * instead subclass {@link TeamStateProvider} or + * {@link SubscriberTeamStateProvider}. + * + * @see IAdapterManager + * @see RepositoryProviderType + * @see RepositoryProviderType#getSubscriber() + * @see TeamStateProvider + * @see SubscriberTeamStateProvider + * @see SynchronizationStateTester + * + * @since 3.2 + */ +public interface ITeamStateProvider { + + /** + * A state mask that can be passed to the {@link #getStateDescription(Object, int, String[], IProgressMonitor)} + * method to indicate that only the decorated state flags are desired. It is equivalent to + * passing he mask returned from {@link #getDecoratedStateMask(Object)}; + */ + public static final int USE_DECORATED_STATE_MASK = -1; + + /** + * Return whether decoration is enabled for the given model element. If + * decoration is not enabled, the model does not need to fire label change + * events when the team state of the element changes. + * + * @param element + * the model element + * @return whether decoration is enabled for the given model element + */ + public boolean isDecorationEnabled(Object element); + + /** + * Return whether the given element has any decorated state. + * + * @param element + * the element being decorated + * @return whether the given element has any decorated state + * @throws CoreException + */ + public boolean hasDecoratedState(Object element) throws CoreException; + + /** + * Return the mask that indicates what state the appropriate team decorator + * is capable of decorating. Clients can used this to obtain the current + * decorated state from + * {@link #getStateDescription(Object, int, String[], IProgressMonitor)} in + * order to determine if the decorated state has changed. + * + *
+ * The state mask can consist of the following standard flags: + *
+ * The mask can also consist of flag bits that are unique to the repository
+ * provider associated with the resources that the element maps to.
+ *
+ * @param element
+ * the model element to be decorated
+ * @return the mask that indicates what state the appropriate team decorator
+ * will decorate
+ * @see IDiff
+ * @see IThreeWayDiff
+ */
+ public int getDecoratedStateMask(Object element);
+
+ /**
+ * Return the set of property identifiers that represent the set of
+ * properties that the team decorator would decorate for the given model
+ * element.
+ *
+ * @param element
+ * the model element to be decorated
+ * @return the set of decorated properties
+ */
+ public String[] getDecoratedProperties(Object element);
+
+ /**
+ * Return the state description for the given element. A null
+ * is return if the element is not decorated or if decoration is disabled.
+ * Only the portion of the synchronization state covered by
+ * stateMask
is returned. The stateMask
should
+ * be {@link #USE_DECORATED_STATE_MASK} or the mask returned from
+ * {@link #getDecoratedStateMask(Object)} and the requested properties
+ * should be null
or the value returned from
+ * {@link #getDecoratedProperties(Object)} if the client wishes to obtain
+ * the current decorated state.
+ *
+ * @param element
+ * the model element
+ * @param stateMask
+ * the mask that identifies which synchronization state flags are
+ * desired if present
+ * @param properties
+ * the set of properties that should be included in the result or
+ * null
if the decorated properties are desired
+ * @param monitor
+ * a progress monitor
+ * @return the state for the given element or null
+ * @throws CoreException
+ */
+ public ITeamStateDescription getStateDescription(Object element,
+ int stateMask, String[] properties, IProgressMonitor monitor)
+ throws CoreException;
+
+ /**
+ * Return a resource mapping context that gives access to the remote state
+ * of the resources associated with the provider. If a
+ * {@link RemoteResourceMappingContext} is returned, then the client may
+ * access the remote state.
+ *
+ * @param element
+ * the element for which remote contents are desired
+ *
+ * @return a resource mapping context that gives access to the remote state
+ * of the resources associated with the provider
+ */
+ public ResourceMappingContext getResourceMappingContext(Object element);
+
+ /**
+ * Add a decorated state change listener to the provider.
+ *
+ * @param listener
+ * the listener
+ */
+ public void addDecoratedStateChangeListener(
+ ITeamStateChangeListener listener);
+
+ /**
+ * Remove the decorated state change listener to the provider.
+ *
+ * @param listener
+ * the listener
+ */
+ public void removeDecoratedStateChangeListener(
+ ITeamStateChangeListener listener);
+
+}
Index: src/org/eclipse/team/ui/synchronize/TeamStateChangeEvent.java
===================================================================
RCS file: src/org/eclipse/team/ui/synchronize/TeamStateChangeEvent.java
diff -N src/org/eclipse/team/ui/synchronize/TeamStateChangeEvent.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/team/ui/synchronize/TeamStateChangeEvent.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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
+ *******************************************************************************/
+package org.eclipse.team.ui.synchronize;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.team.core.subscribers.ISubscriberChangeEvent;
+import org.eclipse.team.ui.mapping.ITeamStateChangeEvent;
+
+/**
+ * An implementation of {@link ITeamStateChangeEvent}.
+ * @since 3.2
+ */
+public class TeamStateChangeEvent implements ITeamStateChangeEvent {
+
+ Set changes = new HashSet();
+ Set addedRoots = new HashSet();
+ Set removedRoots = new HashSet();
+
+ /**
+ * Convenience constructor for creating an event from a subscriber change.
+ * @param deltas the set of subscriber changes
+ */
+ public TeamStateChangeEvent(ISubscriberChangeEvent[] deltas) {
+ for (int i = 0; i < deltas.length; i++) {
+ ISubscriberChangeEvent event = deltas[i];
+ IResource resource = event.getResource();
+ if ((event.getFlags() & ISubscriberChangeEvent.ROOT_ADDED) != 0)
+ rootAdded(resource);
+ if ((event.getFlags() & ISubscriberChangeEvent.ROOT_REMOVED) != 0)
+ rootRemoved(resource);
+ if ((event.getFlags() & ISubscriberChangeEvent.SYNC_CHANGED) != 0)
+ changed(resource);
+ // Indicate that the ancestors may have changed as well
+ while (resource.getType() != IResource.PROJECT) {
+ resource = resource.getParent();
+ changed(resource);
+ }
+ }
+ }
+
+ /**
+ * The given resource has changed state.
+ * @param resource the resource whose state has changed
+ */
+ public void changed(IResource resource) {
+ changes.add(resource);
+ }
+
+ /**
+ * The given root resource has been removed.
+ * @param resource the resource
+ */
+ public void rootRemoved(IResource resource) {
+ removedRoots.add(resource);
+ }
+
+ /**
+ * The given root resource has been added.
+ * @param resource the resource
+ */
+ public void rootAdded(IResource resource) {
+ addedRoots.add(resource);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.mapping.IDecoratedStateChangeEvent#getAddedRoots()
+ */
+ public IResource[] getAddedRoots() {
+ return (IResource[]) addedRoots.toArray(new IResource[addedRoots.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.mapping.IDecoratedStateChangeEvent#getRemovedRoots()
+ */
+ public IResource[] getRemovedRoots() {
+ return (IResource[]) removedRoots.toArray(new IResource[removedRoots.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.mapping.IDecoratedStateChangeEvent#getChangedResources()
+ */
+ public IResource[] getChangedResources() {
+ return (IResource[]) changes.toArray(new IResource[changes.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.ui.mapping.IDecoratedStateChangeEvent#hasChange(org.eclipse.core.resources.IResource)
+ */
+ public boolean hasChange(IResource resource) {
+ if (changes.contains(resource))
+ return true;
+ if (isChildOfChangedRoot(resource)) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isChildOfChangedRoot(IResource resource) {
+ if (resource == null || resource.getType() == IResource.ROOT)
+ return false;
+ if (addedRoots.contains(resource) || removedRoots.contains(resource))
+ return true;
+ return isChildOfChangedRoot(resource.getParent());
+ }
+
+}
Index: src/org/eclipse/team/ui/mapping/ITeamStateDescription.java
===================================================================
RCS file: src/org/eclipse/team/ui/mapping/ITeamStateDescription.java
diff -N src/org/eclipse/team/ui/mapping/ITeamStateDescription.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/team/ui/mapping/ITeamStateDescription.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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
+ *******************************************************************************/
+package org.eclipse.team.ui.mapping;
+
+import org.eclipse.team.core.diff.IDiff;
+import org.eclipse.team.core.diff.IThreeWayDiff;
+import org.eclipse.team.core.mapping.IResourceDiff;
+import org.eclipse.team.ui.synchronize.TeamStateDescription;
+import org.eclipse.team.ui.synchronize.TeamStateProvider;
+
+/**
+ * A description of the the state of a logical model element with respect to a
+ * team repository.
+ *
+ * This interface is not intended to be implemented by clients. Clients that wish
+ * to create a description should use {@link TeamStateDescription}.
+ *
+ * @see TeamStateProvider
+ * @since 3.2
+ */
+public interface ITeamStateDescription {
+
+ /**
+ * Return the synchronization state flags for the element for which this
+ * state description was generated. Only the portion of the synchronization
+ * state covered by stateMask
used when obtaining this
+ * description is returned.
+ *
+ * @return the synchronization state of the given element
+ * @see IDiff
+ * @see IThreeWayDiff
+ * @see IResourceDiff
+ */
+ int getStateFlags();
+
+ /**
+ * Return the portion of the state flags that represent the kind associated
+ * with the element for which this description was generated. See
+ * {@link IDiff#getKind()} for a description of what this value represents.
+ *
+ * @return the kind associated with the element for which this description
+ * was generated
+ */
+ int getKind();
+
+ /**
+ * Return the portion of the state flags that represent the direction
+ * associated with the element for which this description was generated. See
+ * {@link IThreeWayDiff#getDirection()} for a description of what this value
+ * represents.
+ *
+ * @return the direction associated with the element for which this
+ * description was generated
+ */
+ int getDirection();
+
+ /**
+ * Return the properties names for all decorated properties associated with
+ * the element for which this description was generated.
+ *
+ * @return the properties names for all decorated properties
+ */
+ public abstract String[] getProperties();
+
+ /**
+ * Return the value associated with the given property. A null
+ * is returned if the property has no value.
+ * @param property the property
+ * @return the value associated with the given property or null
+ */
+ public abstract Object getProperty(String property);
+
+}
#P org.eclipse.team.cvs.ui
Index: src/org/eclipse/team/internal/ccvs/ui/model/CVSAdapterFactory.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/model/CVSAdapterFactory.java,v
retrieving revision 1.16
diff -u -r1.16 CVSAdapterFactory.java
--- src/org/eclipse/team/internal/ccvs/ui/model/CVSAdapterFactory.java 9 Mar 2006 19:34:56 -0000 1.16
+++ src/org/eclipse/team/internal/ccvs/ui/model/CVSAdapterFactory.java 16 Mar 2006 15:43:30 -0000
@@ -14,19 +14,23 @@
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.ui.CVSHistoryPageSource;
+import org.eclipse.team.internal.ccvs.ui.CVSTeamStateProvider;
import org.eclipse.team.internal.ccvs.ui.repo.RepositoryRoot;
import org.eclipse.team.ui.history.IHistoryPageSource;
import org.eclipse.team.ui.mapping.ISynchronizationCompareAdapter;
+import org.eclipse.team.ui.mapping.ITeamStateProvider;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.progress.IDeferredWorkbenchAdapter;
import org.eclipse.ui.views.properties.IPropertySource;
public class CVSAdapterFactory implements IAdapterFactory {
- private Object fileAdapter = new RemoteFileElement();
- private Object folderAdapter = new RemoteFolderElement();
- private Object rootAdapter = new CVSRepositoryRootElement();
+ private static Object fileAdapter = new RemoteFileElement();
+ private static Object folderAdapter = new RemoteFolderElement();
+ private static Object rootAdapter = new CVSRepositoryRootElement();
- private Object historyParticipant = new CVSHistoryPageSource();
+ private static Object historyParticipant = new CVSHistoryPageSource();
+
+ private static Object teamStateProvider;
// Property cache
private Object cachedPropertyObject = null;
@@ -56,6 +60,14 @@
return historyParticipant;
}
+ if (ITeamStateProvider.class == adapterType) {
+ synchronized (this) {
+ if (teamStateProvider == null)
+ teamStateProvider = new CVSTeamStateProvider(CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber());
+ }
+ return teamStateProvider;
+ }
+
return null;
}
@@ -76,8 +88,11 @@
* Method declared on IAdapterFactory.
*/
public Class[] getAdapterList() {
- return new Class[] {IWorkbenchAdapter.class, IPropertySource.class, IDeferredWorkbenchAdapter.class, IHistoryPageSource.class, ISynchronizationCompareAdapter.class};
+ return new Class[] { IWorkbenchAdapter.class, IPropertySource.class,
+ IDeferredWorkbenchAdapter.class, IHistoryPageSource.class,
+ ISynchronizationCompareAdapter.class, ITeamStateProvider.class };
}
+
/**
* Returns the property source for the given object. Caches
* the result because the property sheet is extremely inefficient,
Index: plugin.xml
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.team.cvs.ui/plugin.xml,v
retrieving revision 1.244
diff -u -r1.244 plugin.xml
--- plugin.xml 14 Mar 2006 14:33:23 -0000 1.244
+++ plugin.xml 16 Mar 2006 15:43:30 -0000
@@ -1550,6 +1550,11 @@
class="org.eclipse.team.internal.ccvs.ui.model.CVSAdapterFactory">
null
is returned.