Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 36493 Details for
Bug 131440
[Model Decoration] Problems with current support for model element decoration
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Updated path
patch131440.txt (text/plain), 108.85 KB, created by
Michael Valenta
on 2006-03-17 10:44:05 EST
(
hide
)
Description:
Updated path
Filename:
MIME Type:
Creator:
Michael Valenta
Created:
2006-03-17 10:44:05 EST
Size:
108.85 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.jdt.ui >Index: ui/org/eclipse/jdt/internal/ui/packageview/WorkingSetAwareContentProvider.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/packageview/WorkingSetAwareContentProvider.java,v >retrieving revision 1.13 >diff -u -r1.13 WorkingSetAwareContentProvider.java >--- ui/org/eclipse/jdt/internal/ui/packageview/WorkingSetAwareContentProvider.java 14 Mar 2006 15:05:34 -0000 1.13 >+++ ui/org/eclipse/jdt/internal/ui/packageview/WorkingSetAwareContentProvider.java 17 Mar 2006 15:40:32 -0000 >@@ -220,6 +220,8 @@ > toRefresh.add(newValue); > } else if (IWorkingSetManager.CHANGE_WORKING_SET_NAME_CHANGE.equals(property)) { > toRefresh.add(newValue); >+ } else if (WorkingSetModel.CHANGE_WORKING_SET_TEAM_DECORATION.equals(property)) { >+ toRefresh.add(newValue); > } > postRefresh(toRefresh, true); > } >Index: ui/org/eclipse/jdt/internal/ui/workingsets/WorkingSetModel.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/workingsets/WorkingSetModel.java,v >retrieving revision 1.17 >diff -u -r1.17 WorkingSetModel.java >--- ui/org/eclipse/jdt/internal/ui/workingsets/WorkingSetModel.java 15 Mar 2006 10:34:47 -0000 1.17 >+++ ui/org/eclipse/jdt/internal/ui/workingsets/WorkingSetModel.java 17 Mar 2006 15:40:32 -0000 >@@ -19,10 +19,15 @@ > import java.util.List; > import java.util.Map; > >+import org.eclipse.core.runtime.CoreException; > import org.eclipse.core.runtime.IAdaptable; > import org.eclipse.core.runtime.ListenerList; > > import org.eclipse.core.resources.IResource; >+import org.eclipse.core.resources.IResourceChangeEvent; >+import org.eclipse.core.resources.IResourceChangeListener; >+import org.eclipse.core.resources.IResourceDelta; >+import org.eclipse.core.resources.ResourcesPlugin; > > import org.eclipse.jface.util.IPropertyChangeListener; > import org.eclipse.jface.util.PropertyChangeEvent; >@@ -35,11 +40,19 @@ > import org.eclipse.ui.IWorkingSetUpdater; > import org.eclipse.ui.PlatformUI; > >+import org.eclipse.team.ui.mapping.ITeamStateChangeEvent; >+import org.eclipse.team.ui.mapping.ITeamStateChangeListener; >+import org.eclipse.team.ui.mapping.ITeamStateDescription; >+import org.eclipse.team.ui.mapping.ITeamStateProvider; >+import org.eclipse.team.ui.mapping.SynchronizationStateTester; >+ > import org.eclipse.jdt.internal.corext.Assert; > > public class WorkingSetModel { > > public static final String CHANGE_WORKING_SET_MODEL_CONTENT= "workingSetModelChanged"; //$NON-NLS-1$ >+ >+ public static final String CHANGE_WORKING_SET_TEAM_DECORATION= "workingSetTamDecorationChanged"; //$NON-NLS-1$ > > public static final IElementComparer COMPARER= new WorkingSetComparar(); > >@@ -57,6 +70,11 @@ > private ElementMapper fElementMapper= new ElementMapper(); > > private boolean fConfigured; >+ >+ private SynchronizationStateTester fSyncStateTester; >+ private ITeamStateChangeListener fTeamListener; >+ private IResourceChangeListener fResourceListener; >+ private Map fTeamState = new HashMap(); > > private static class WorkingSetComparar implements IElementComparer { > public boolean equals(Object o1, Object o2) { >@@ -248,9 +266,34 @@ > }; > PlatformUI.getWorkbench().getWorkingSetManager().addPropertyChangeListener(fWorkingSetManagerListener); > fLocalWorkingSetManager.addPropertyChangeListener(fWorkingSetManagerListener); >+ fSyncStateTester = new SynchronizationStateTester() { >+ public void elementDecorated(Object element, ITeamStateDescription description) { >+ if (element instanceof IWorkingSet) { >+ IWorkingSet set = (IWorkingSet) element; >+ // Record the state that was decorated so we will avoid >+ // unnecessary label updates >+ fTeamState.put(set, description); >+ } >+ super.elementDecorated(element, description); >+ } >+ }; >+ fTeamListener = new ITeamStateChangeListener() { >+ public void teamStateChanged(ITeamStateChangeEvent event) { >+ handeTeamStateChange(event); >+ } >+ }; >+ fResourceListener = new IResourceChangeListener() { >+ public void resourceChanged(IResourceChangeEvent event) { >+ handleResourceChange(event.getDelta()); >+ } >+ }; >+ fSyncStateTester.getTeamStateProvider().addDecoratedStateChangeListener(fTeamListener); >+ ResourcesPlugin.getWorkspace().addResourceChangeListener(fResourceListener, IResourceChangeEvent.POST_CHANGE); > } > > public void dispose() { >+ fSyncStateTester.getTeamStateProvider().removeDecoratedStateChangeListener(fTeamListener); >+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(fResourceListener); > if (fWorkingSetManagerListener != null) { > PlatformUI.getWorkbench().getWorkingSetManager().removePropertyChangeListener(fWorkingSetManagerListener); > fLocalWorkingSetManager.removePropertyChangeListener(fWorkingSetManagerListener); >@@ -349,6 +392,7 @@ > > public void setActiveWorkingSets(IWorkingSet[] workingSets) { > fActiveWorkingSets= new ArrayList(Arrays.asList(workingSets)); >+ fTeamState.clear(); > fElementMapper.rebuild(getActiveWorkingSets()); > fOthersWorkingSetUpdater.updateElements(); > fireEvent(new PropertyChangeEvent(this, CHANGE_WORKING_SET_MODEL_CONTENT, null, null)); >@@ -436,4 +480,88 @@ > public boolean isActiveWorkingSet(IWorkingSet changedWorkingSet) { > return fActiveWorkingSets.contains(changedWorkingSet); > } >-} >\ No newline at end of file >+ >+ protected void handeTeamStateChange(ITeamStateChangeEvent event) { >+ for (Iterator iter = fActiveWorkingSets.iterator(); iter.hasNext();) { >+ IWorkingSet set = (IWorkingSet) iter.next(); >+ if (hasPotentialChanges(event, set) && hasRealChanges(set)) >+ fireEvent(new PropertyChangeEvent(WorkingSetModel.this, CHANGE_WORKING_SET_TEAM_DECORATION, null, null)); >+ } >+ } >+ >+ protected void handleResourceChange(IResourceDelta delta) { >+ for (Iterator iter = fActiveWorkingSets.iterator(); iter.hasNext();) { >+ IWorkingSet set = (IWorkingSet) iter.next(); >+ if (hasPotentialChanges(delta, set) && hasRealChanges(set)) { >+ fireEvent(new PropertyChangeEvent(WorkingSetModel.this, CHANGE_WORKING_SET_TEAM_DECORATION, null, null)); >+ } >+ } >+ } >+ >+ private boolean hasRealChanges(IWorkingSet set) { >+ try { >+ ITeamStateProvider decoratedStateProvider = fSyncStateTester.getTeamStateProvider(); >+ if (decoratedStateProvider.isDecorationEnabled(set)) { >+ ITeamStateDescription desc = decoratedStateProvider.getStateDescription(set, >+ ITeamStateProvider.USE_DECORATED_STATE_MASK, null /* use decorated properties */, null /* no progress */); >+ ITeamStateDescription oldDesc = (ITeamStateDescription)fTeamState.get(set); >+ if (oldDesc == desc) >+ return false; >+ boolean changed = (oldDesc == null && desc != null) >+ || (desc == null && oldDesc != null) >+ || (!desc.equals(oldDesc)); >+ if (desc == null) { >+ fTeamState.remove(set); >+ } else { >+ fTeamState.put(set, desc); >+ } >+ return changed; >+ } else { >+ if (fTeamState.containsKey(set)) { >+ fTeamState.remove(set); >+ return true; >+ } >+ } >+ } catch (CoreException e) { >+ // TODO Auto-generated catch block >+ e.printStackTrace(); >+ } >+ return false; >+ } >+ >+ private boolean hasPotentialChanges(IResourceDelta delta, IWorkingSet set) { >+ IAdaptable[] elements = set.getElements(); >+ for (int i = 0; i < elements.length; i++) { >+ IAdaptable adaptable = elements[i]; >+ IResource resource = (IResource)adaptable.getAdapter(IResource.class); >+ if (resource != null) { >+ IResourceDelta memberDelta = delta.findMember(resource.getFullPath()); >+ if (isChangeOfInterest(memberDelta)) { >+ return true; >+ } >+ } >+ } >+ return false; >+ } >+ >+ private boolean isChangeOfInterest(IResourceDelta memberDelta) { >+ if (memberDelta != null >+ && (memberDelta.getKind() & (IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED)) > 0) { >+ // TODO: Should exclude marker and sync deltas (and possibly others) >+ return true; >+ } >+ return false; >+ } >+ >+ private boolean hasPotentialChanges(ITeamStateChangeEvent event, IWorkingSet set) { >+ IAdaptable[] elements = set.getElements(); >+ for (int i = 0; i < elements.length; i++) { >+ IAdaptable adaptable = elements[i]; >+ IResource resource = (IResource)adaptable.getAdapter(IResource.class); >+ if (resource != null && event.hasChange(resource)) { >+ return true; >+ } >+ } >+ return false; >+ } >+} >#P org.eclipse.team.ui >Index: plugin.xml >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.team.ui/plugin.xml,v >retrieving revision 1.168 >diff -u -r1.168 plugin.xml >--- plugin.xml 16 Mar 2006 21:31:55 -0000 1.168 >+++ plugin.xml 17 Mar 2006 15:40:33 -0000 >@@ -335,6 +335,11 @@ > <adapter type="org.eclipse.team.ui.mapping.ISynchronizationCompareAdapter"/> > <adapter type="org.eclipse.team.core.mapping.ISynchronizationScopeParticipantFactory"/> > </factory> >+ <factory >+ adaptableType="org.eclipse.team.core.RepositoryProviderType" >+ class="org.eclipse.team.internal.ui.TeamAdapterFactory"> >+ <adapter type="org.eclipse.team.ui.mapping.ITeamStateProvider"/> >+ </factory> > </extension> > <extension > point="org.eclipse.ui.navigator.navigatorContent"> >Index: src/org/eclipse/team/internal/ui/TeamAdapterFactory.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamAdapterFactory.java,v >retrieving revision 1.18 >diff -u -r1.18 TeamAdapterFactory.java >--- src/org/eclipse/team/internal/ui/TeamAdapterFactory.java 10 Feb 2006 02:48:44 -0000 1.18 >+++ src/org/eclipse/team/internal/ui/TeamAdapterFactory.java 17 Mar 2006 15:40:33 -0000 >@@ -13,14 +13,15 @@ > import org.eclipse.compare.structuremergeviewer.DiffNode; > import org.eclipse.core.resources.mapping.ModelProvider; > import org.eclipse.core.runtime.IAdapterFactory; >+import org.eclipse.team.core.RepositoryProviderType; > import org.eclipse.team.core.mapping.IResourceMappingMerger; > import org.eclipse.team.core.mapping.ISynchronizationScopeParticipantFactory; > import org.eclipse.team.internal.ui.mapping.*; > import org.eclipse.team.internal.ui.synchronize.DiffNodeWorkbenchAdapter; >-import org.eclipse.team.ui.mapping.*; >+import org.eclipse.team.ui.mapping.ITeamStateProvider; >+import org.eclipse.team.ui.mapping.ISynchronizationCompareAdapter; > import org.eclipse.ui.model.IWorkbenchAdapter; > >- > public class TeamAdapterFactory implements IAdapterFactory { > > private DiffNodeWorkbenchAdapter diffNodeAdapter = new DiffNodeWorkbenchAdapter(); >@@ -48,6 +49,10 @@ > if (adaptableObject instanceof ModelProvider && adapterType == ISynchronizationCompareAdapter.class) { > return COMPARE_ADAPTER; > } >+ if (adaptableObject instanceof RepositoryProviderType && adapterType == ITeamStateProvider.class) { >+ RepositoryProviderType rpt = (RepositoryProviderType) adaptableObject; >+ return TeamUIPlugin.getPlugin().getDecoratedStateProvider(rpt); >+ } > return null; > } > >@@ -55,8 +60,12 @@ > * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList() > */ > public Class[] getAdapterList() { >- return new Class[] { IWorkbenchAdapter.class, >- IResourceMappingMerger.class, ISynchronizationCompareAdapter.class, >- ISynchronizationScopeParticipantFactory.class }; >+ return new Class[] { >+ IWorkbenchAdapter.class, >+ IResourceMappingMerger.class, >+ ISynchronizationCompareAdapter.class, >+ ISynchronizationScopeParticipantFactory.class, >+ ITeamStateProvider.class >+ }; > } > } >Index: src/org/eclipse/team/internal/ui/TeamUIPlugin.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIPlugin.java,v >retrieving revision 1.72 >diff -u -r1.72 TeamUIPlugin.java >--- src/org/eclipse/team/internal/ui/TeamUIPlugin.java 23 Feb 2006 21:54:44 -0000 1.72 >+++ src/org/eclipse/team/internal/ui/TeamUIPlugin.java 17 Mar 2006 15:40:33 -0000 >@@ -27,12 +27,18 @@ > import org.eclipse.swt.custom.BusyIndicator; > import org.eclipse.swt.graphics.Image; > import org.eclipse.swt.widgets.Display; >+import org.eclipse.team.core.RepositoryProviderType; >+import org.eclipse.team.core.subscribers.Subscriber; > import org.eclipse.team.internal.ui.mapping.StreamMergerDelegate; >+import org.eclipse.team.internal.ui.mapping.WorkspaceTeamStateProvider; > import org.eclipse.team.internal.ui.synchronize.SynchronizeManager; > import org.eclipse.team.internal.ui.synchronize.TeamSynchronizingPerspective; > import org.eclipse.team.internal.ui.synchronize.actions.GlobalRefreshAction; > import org.eclipse.team.ui.ISharedImages; > import org.eclipse.team.ui.TeamUI; >+import org.eclipse.team.ui.mapping.ITeamStateProvider; >+import org.eclipse.team.ui.synchronize.TeamStateProvider; >+import org.eclipse.team.ui.synchronize.SubscriberTeamStateProvider; > import org.eclipse.ui.*; > import org.eclipse.ui.plugin.AbstractUIPlugin; > import org.osgi.framework.Bundle; >@@ -58,6 +64,10 @@ > > private Hashtable imageDescriptors = new Hashtable(20); > >+ private WorkspaceTeamStateProvider provider; >+ >+ private Map decoratedStateProviders = new HashMap(); >+ > /** > * Creates a new TeamUIPlugin. > */ >@@ -217,6 +227,13 @@ > } finally { > super.stop(context); > } >+ if (provider != null) { >+ provider.dispose(); >+ } >+ for (Iterator iter = decoratedStateProviders.values().iterator(); iter.hasNext();) { >+ SubscriberTeamStateProvider sdsp = (SubscriberTeamStateProvider) iter.next(); >+ sdsp.dispose(); >+ } > } > > /** >@@ -385,4 +402,29 @@ > public org.osgi.service.prefs.Preferences getInstancePreferences() { > return new InstanceScope().getNode(getBundle().getSymbolicName()); > } >+ >+ public synchronized TeamStateProvider getDecoratedStateProvider(RepositoryProviderType rpt) { >+ TeamStateProvider provider = (TeamStateProvider)decoratedStateProviders.get(rpt.getID()); >+ if (provider != null) >+ return provider; >+ Subscriber subscriber = rpt.getSubscriber(); >+ if (subscriber != null) { >+ provider = new SubscriberTeamStateProvider(subscriber); >+ decoratedStateProviders.put(rpt.getID(), provider); >+ return provider; >+ } >+ return null; >+ } >+ >+ /** >+ * Return a decorated state provider that delegates to the appropriate team >+ * provider. >+ * @return a decorated state provider that delegates to the appropriate team >+ * provider >+ */ >+ public synchronized ITeamStateProvider getDecoratedStateProvider() { >+ if (provider == null) >+ provider = new WorkspaceTeamStateProvider(); >+ return provider; >+ } > } >Index: src/org/eclipse/team/ui/mapping/SynchronizationStateTester.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.team.ui/src/org/eclipse/team/ui/mapping/SynchronizationStateTester.java,v >retrieving revision 1.8 >diff -u -r1.8 SynchronizationStateTester.java >--- src/org/eclipse/team/ui/mapping/SynchronizationStateTester.java 30 Jan 2006 15:56:32 -0000 1.8 >+++ src/org/eclipse/team/ui/mapping/SynchronizationStateTester.java 17 Mar 2006 15:40:33 -0000 >@@ -10,51 +10,40 @@ > *******************************************************************************/ > package org.eclipse.team.ui.mapping; > >-import java.util.HashSet; >-import java.util.Set; >- >-import org.eclipse.core.resources.*; >-import org.eclipse.core.resources.mapping.*; >+import org.eclipse.core.resources.IResourceChangeListener; >+import org.eclipse.core.resources.IWorkspace; >+import org.eclipse.core.resources.mapping.ResourceMapping; > import org.eclipse.core.runtime.CoreException; > import org.eclipse.core.runtime.IProgressMonitor; > import org.eclipse.jface.viewers.IDecorationContext; >-import org.eclipse.team.core.RepositoryProvider; >-import org.eclipse.team.core.Team; > import org.eclipse.team.core.diff.IDiff; >-import org.eclipse.team.core.diff.IThreeWayDiff; > import org.eclipse.team.core.subscribers.Subscriber; >-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.internal.ui.TeamUIPlugin; > import org.eclipse.ui.IDecoratorManager; >-import org.eclipse.ui.PlatformUI; > > /** > * A state change tester is used by logical models to communicate the > * synchronization state of their logical model elements to >- * the lightweight label decorators of team providers. >+ * the lightweight label decorator of a team provider. > * <p> > * There are two different types of elements being decorated: those > * that have a one-to-one mapping to a resource and those that do not. > * Those that do should adapt to their corresponding resource. Doing > * so will ensure that label updates occur when the state of that > * resource changes (i.e. the team provider will generate label updates >- * for those resources and the modle can translate them to appropriate >+ * for those resources and the model can translate them to appropriate > * label updates of their model elements). > * <p> > * 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. > * <p> > * 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 team state provider >+ * ({@link #getTeamStateProvider()}. > * <p> > * Decoration enablement changes and decoration configuration changes > * are handled by the {@link IDecoratorManager#update(String)} API. >@@ -63,98 +52,37 @@ > * be used to determine if an element will receive team decorations. > * If decoration is disabled. team state changes on the element can > * be ignored. >+ * <p> >+ * Clients may subclass this class. > * > * @since 3.2 > * @see IWorkspace#addResourceChangeListener(IResourceChangeListener) > * @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()); >- } >- >- /** >- * Create a tester that obtains the synchroniation state >- * from the given subscriber. >- * @param subscriber the subscriber >- */ >- public SynchronizationStateTester(Subscriber subscriber) { >- this.subscriber = subscriber; >- } >- >- /** >- * 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 final boolean isDecorationEnabled(Object element) { >- ResourceMapping mapping = Utils.getResourceMapping(element); >- if (mapping != null) { >- IProject[] projects = mapping.getProjects(); >- return internalIsDecorationEnabled(projects); >- } >- return false; >+ super(); > } > > /** >- * Return the mask that indicates what state the appropriate team decorator >- * is capable of decorating. The state is determined by querying the >- * <code>org.eclipse.team.ui.teamDecorators</code> extension point. >- * >- * <p> >- * The state mask can consist of the following flags: >- * <ul> >- * <li>The diff kinds of {@link IDiff#ADD}, {@link IDiff#REMOVE} >- * and {@link IDiff#CHANGE}. >- * <li>The directions {@link IThreeWayDiff#INCOMING} and >- * {@link IThreeWayDiff#OUTGOING}. >- * </ul> >- * For convenience sake, if there are no kind flags but there is at least >- * one direction flag then all kinds are assumed. >- * >- * @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 final int getDecoratedStateMask(Object element) { >- ResourceMapping mapping = Utils.getResourceMapping(element); >- if (mapping != null) { >- IProject[] projects = mapping.getProjects(); >- return internalGetDecoratedStateMask(projects); >- } >- return 0; >- } >- >- /** > * Return whether state decoration is enabled for the context > * to which this tester is associated. If <code>true</code> >- * is returned, team decorators will use the state methods provided >+ * 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 <code>false</code> >- * is returned, team decorators will not decorate the elements with any >+ * 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, >@@ -164,6 +92,26 @@ > public boolean isStateDecorationEnabled() { > return true; > } >+ >+ /** >+ * Return whether decoration is enabled for the given model element in the >+ * context to which this tester is associated. By default, the value >+ * returned from {@link #isStateDecorationEnabled()} is used but subclasses >+ * may override to disable decoration of particular elements. >+ * <p> >+ * A team decorator should call this method before decorating a model >+ * element. If the method returns <code>true</code>, 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 boolean isDecorationEnabled(Object element) { >+ return isStateDecorationEnabled(); >+ } > > /** > * Return the synchronization state of the given element. Only the portion >@@ -171,8 +119,8 @@ > * returned. By default, this method calls > * {@link Subscriber#getState(ResourceMapping, int, IProgressMonitor)}. > * <p> >- * Team decorators will use this method to detemine how to decorate the >- * provided element. The {@link #getDecoratedStateMask(Object)} returns the >+ * A team decorator will use this method to determine how to decorate the >+ * provided element. The {@link ITeamStateProvider#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. > * When the team decorator invokes this method, it will pass the stateMask that >@@ -186,10 +134,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. > * <li>The subclasses wishes to provide a more accurate change description for a model > * element that represents only a portion of the file. In this case, the subclass can >- * use the remote file contents available from the subscriber to determine whether >+ * use the remote file contents available from the provider to determine the proper >+ * state for the element. > * </ol> > * > * @param element the model element >@@ -198,122 +147,36 @@ > * @param monitor a progress monitor > * @return the synchronization state of the given element > * @throws CoreException >- * @see Subscriber#getState(ResourceMapping, int, IProgressMonitor) > */ > public int getState(Object element, int stateMask, IProgressMonitor monitor) throws CoreException { >- ResourceMapping mapping = Utils.getResourceMapping(element); >- if (mapping != null) { >- try { >- return subscriber.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 0; >+ ITeamStateDescription desc = getTeamStateProvider().getStateDescription(element, stateMask, new String[0], monitor); >+ if (desc != null) >+ return desc.getStateFlags(); >+ return IDiff.NO_CHANGE; > } > > /** >- * Return whether the given element is supervised. To determine this, the >- * element is adapted to a resource mapping and, using the mapping's >- * traversals, the subcriber is consulted to determine if the element is supervised. >- * An element is supervised if all the resources covered by it's traversals are >- * supervised. >- * @see Subscriber#isSupervised(org.eclipse.core.resources.IResource) >- * >- * @param element the element being tested >- * @return whether the given element is supervisied. >- * @throws CoreException if an error occurres >+ * Return a team state provider that delegates to the appropriate team >+ * provider. >+ * @return a team state provider that delegates to the appropriate team >+ * provider > */ >- public final boolean isSupervised(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 (subscriber.isSupervised(resource)) >- return true; >- } >- } >- } >- return false; >+ public final ITeamStateProvider getTeamStateProvider() { >+ return TeamUIPlugin.getPlugin().getDecoratedStateProvider(); > } >- >+ > /** >- * Return the subscriber associated with this tester. >- * @return the subscriber associated with this tester. >+ * A callback to the tester made from the team decorator to notify the >+ * tester that the given element has been decorated with the given state. >+ * The purpose of the callback is to allow the owner of the tester to >+ * cache the decorated state in order to detect whether a future state >+ * change requires a label update for the element. >+ * @param element the element that was decorated >+ * @param description a description of the decorated state of the element > */ >- public Subscriber getSubscriber() { >- return subscriber; >- } >- >- 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 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()]); >+ public void elementDecorated(Object element, ITeamStateDescription description) { >+ // do nothing by default > } > >- 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 String getProviderId(IProject project) { >- RepositoryProvider provider = RepositoryProvider.getProvider(project); >- if (provider != null) >- return provider.getID(); >- return null; >- } > >- private boolean internalIsDecorationEnabled(String providerId) { >- String decoratorId = getDecoratorId(providerId); >- if (decoratorId != null) { >- return PlatformUI.getWorkbench().getDecoratorManager().getEnabled(decoratorId); >- } >- return false; >- } >- >- private int internalGetDecoratedStateMask(String providerId) { >- TeamDecoratorDescription decoratorDescription = TeamDecoratorManager.getInstance().getDecoratorDescription(providerId); >- if (decoratorDescription != null) >- return decoratorDescription.getDecoratedDirectionFlags(); >- return 0; >- } >- >- 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/TeamStateDescription.java >=================================================================== >RCS file: src/org/eclipse/team/ui/synchronize/TeamStateDescription.java >diff -N src/org/eclipse/team/ui/synchronize/TeamStateDescription.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/team/ui/synchronize/TeamStateDescription.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,130 @@ >+/******************************************************************************* >+ * 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.HashMap; >+import java.util.Map; >+ >+import org.eclipse.team.core.diff.IThreeWayDiff; >+import org.eclipse.team.core.diff.provider.Diff; >+import org.eclipse.team.ui.mapping.ITeamStateDescription; >+ >+/** >+ * An implementation of {@link ITeamStateDescription}. >+ * <p> >+ * This class may be subclassed by clients. >+ * @since 3.2 >+ */ >+public class TeamStateDescription implements ITeamStateDescription { >+ >+ private int state; >+ private Map properties = new HashMap(); >+ >+ /** >+ * Create a description with the given state. >+ * @param state the state >+ */ >+ public TeamStateDescription(int state) { >+ this.state = state; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.IDecoratedStateDescription#getStateFlags() >+ */ >+ public int getStateFlags() { >+ return state; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.IDecoratedStateDescription#getKind() >+ */ >+ public int getKind() { >+ return getStateFlags() & Diff.KIND_MASK; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.IDecoratedStateDescription#getDirection() >+ */ >+ public int getDirection() { >+ return getStateFlags() & IThreeWayDiff.DIRECTION_MASK; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.ITeamStateDescription#getProperties() >+ */ >+ public String[] getPropertyNames() { >+ return (String[]) properties.keySet().toArray(new String[properties.size()]); >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.ITeamStateDescription#getProperty(java.lang.String) >+ */ >+ public Object getProperty(String property) { >+ return properties.get(property); >+ } >+ >+ /** >+ * Set the given property to the given value >+ * @param property the property >+ * @param value the value >+ */ >+ public void setProperty(String property, Object value) { >+ properties.put(property, value); >+ } >+ >+ /* (non-Javadoc) >+ * @see java.lang.Object#equals(java.lang.Object) >+ */ >+ public boolean equals(Object obj) { >+ if (obj instanceof TeamStateDescription) { >+ TeamStateDescription dsd = (TeamStateDescription) obj; >+ if (dsd.getStateFlags() == state) { >+ if (haveSameProperties(this, dsd)) { >+ String[] properties = getPropertyNames(); >+ for (int i = 0; i < properties.length; i++) { >+ String property = properties[i]; >+ Object o1 = this.getProperty(property); >+ Object o2 = dsd.getProperty(property); >+ if (!o1.equals(o2)) { >+ return false; >+ } >+ } >+ return true; >+ } >+ } >+ return false; >+ } >+ return super.equals(obj); >+ } >+ >+ private boolean haveSameProperties(TeamStateDescription d1, TeamStateDescription d2) { >+ String[] p1 = d1.getPropertyNames(); >+ String[] p2 = d2.getPropertyNames(); >+ if (p1.length != p2.length) { >+ return false; >+ } >+ for (int i = 0; i < p1.length; i++) { >+ String s1 = p1[i]; >+ boolean found = false; >+ for (int j = 0; j < p2.length; j++) { >+ String s2 = p2[j]; >+ if (s1.equals(s2)) { >+ found = true; >+ break; >+ } >+ } >+ if (!found) >+ return false; >+ } >+ return true; >+ } >+ >+} >Index: src/org/eclipse/team/internal/ui/mapping/WorkspaceTeamStateProvider.java >=================================================================== >RCS file: src/org/eclipse/team/internal/ui/mapping/WorkspaceTeamStateProvider.java >diff -N src/org/eclipse/team/internal/ui/mapping/WorkspaceTeamStateProvider.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/team/internal/ui/mapping/WorkspaceTeamStateProvider.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,235 @@ >+/******************************************************************************* >+ * 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.internal.ui.mapping; >+ >+import java.util.HashMap; >+import java.util.Map; >+ >+import org.eclipse.core.resources.*; >+import org.eclipse.core.resources.mapping.ResourceMapping; >+import org.eclipse.core.resources.mapping.ResourceMappingContext; >+import org.eclipse.core.runtime.CoreException; >+import org.eclipse.core.runtime.IProgressMonitor; >+import org.eclipse.team.core.RepositoryProvider; >+import org.eclipse.team.core.RepositoryProviderType; >+import org.eclipse.team.internal.core.*; >+import org.eclipse.team.internal.ui.Utils; >+import org.eclipse.team.ui.mapping.*; >+import org.eclipse.team.ui.synchronize.TeamStateProvider; >+ >+/** >+ * A decorated state provider that delegates to the provider for the repository >+ * provider type that is associated with the projects that an element maps to >+ * using the ResourceMapping API. >+ * >+ */ >+public class WorkspaceTeamStateProvider extends TeamStateProvider >+ implements ITeamStateChangeListener, IRepositoryProviderListener, >+ IResourceChangeListener { >+ >+ private Map providers = new HashMap(); >+ >+ public WorkspaceTeamStateProvider() { >+ RepositoryProviderManager.getInstance().addListener(this); >+ ResourcesPlugin.getWorkspace().addResourceChangeListener(this, >+ IResourceChangeEvent.POST_CHANGE); >+ IProject[] allProjects = ResourcesPlugin.getWorkspace().getRoot() >+ .getProjects(); >+ for (int i = 0; i < allProjects.length; i++) { >+ IProject project = allProjects[i]; >+ handleProject(project); >+ } >+ } >+ >+ public void dispose() { >+ RepositoryProviderManager.getInstance().removeListener(this); >+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.DecoratedStateProvider#isDecorationEnabled(java.lang.Object) >+ */ >+ public final boolean isDecorationEnabled(Object element) { >+ ITeamStateProvider provider = getDecoratedStateProvider(element); >+ if (provider != null) >+ return provider.isDecorationEnabled(element); >+ return false; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.DecoratedStateProvider#isDecorated(java.lang.Object) >+ */ >+ public boolean hasDecoratedState(Object element) throws CoreException { >+ ITeamStateProvider provider = getDecoratedStateProvider(element); >+ if (provider != null) >+ provider.hasDecoratedState(element); >+ return false; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.DecoratedStateProvider#getDecoratedStateMask(java.lang.Object) >+ */ >+ public final int getDecoratedStateMask(Object element) { >+ ITeamStateProvider provider = getDecoratedStateProvider(element); >+ if (provider != null) >+ return provider.getDecoratedStateMask(element); >+ return 0; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.ITeamStateProvider#getDecoratedProperties(java.lang.Object) >+ */ >+ public String[] getDecoratedProperties(Object element) { >+ ITeamStateProvider provider = getDecoratedStateProvider(element); >+ if (provider != null) >+ return provider.getDecoratedProperties(element); >+ return new String[0]; >+ } >+ >+ >+ /* (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 { >+ ITeamStateProvider provider = getDecoratedStateProvider(element); >+ if (provider != null) >+ return provider.getStateDescription(element, stateMask, properties, monitor); >+ return null; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.ITeamStateProvider#getResourceMappingContext(java.lang.Object) >+ */ >+ public ResourceMappingContext getResourceMappingContext(Object element) { >+ ITeamStateProvider provider = getDecoratedStateProvider(element); >+ if (provider != null) >+ return provider.getResourceMappingContext(element); >+ return ResourceMappingContext.LOCAL_CONTEXT; >+ } >+ >+ private ITeamStateProvider getDecoratedStateProvider(Object element) { >+ RepositoryProviderType type = getProviderType(element); >+ if (type != null) >+ return (ITeamStateProvider) Utils.getAdapter(type, >+ ITeamStateProvider.class); >+ return null; >+ } >+ >+ private ITeamStateProvider getDecoratedStateProviderForId(String id) { >+ RepositoryProviderType type = getProviderTypeForId(id); >+ if (type != null) >+ return (ITeamStateProvider) Utils.getAdapter(type, >+ ITeamStateProvider.class, true); >+ return null; >+ } >+ >+ private RepositoryProviderType getProviderType(Object element) { >+ ResourceMapping mapping = Utils.getResourceMapping(element); >+ if (mapping != null) { >+ String providerId = getProviderId(mapping.getProjects()); >+ if (providerId != null) >+ return getProviderTypeForId(providerId); >+ } >+ return null; >+ } >+ >+ private String getProviderId(IProject[] projects) { >+ String id = null; >+ for (int i = 0; i < projects.length; i++) { >+ IProject project = projects[i]; >+ String nextId = getProviderId(project); >+ if (id == null) >+ id = nextId; >+ else if (nextId != null && !id.equals(nextId)) >+ return null; >+ } >+ return id; >+ } >+ >+ private String getProviderId(IProject project) { >+ RepositoryProvider provider = RepositoryProvider.getProvider(project); >+ if (provider != null) >+ return provider.getID(); >+ return null; >+ } >+ >+ private RepositoryProviderType getProviderTypeForId(String providerId) { >+ return RepositoryProviderType.getProviderType(providerId); >+ } >+ >+ private void handleProject(IProject project) { >+ if (RepositoryProvider.isShared(project)) { >+ try { >+ String currentId = project >+ .getPersistentProperty(TeamPlugin.PROVIDER_PROP_KEY); >+ if (currentId != null) { >+ listenerForStateChangesForId(currentId); >+ } >+ } catch (CoreException e) { >+ TeamPlugin.log(e); >+ } >+ } >+ } >+ >+ private void listenerForStateChangesForId(String id) { >+ if (!providers.containsKey(id)) { >+ ITeamStateProvider provider = getDecoratedStateProviderForId(id); >+ if (provider != null) { >+ providers.put(id, provider); >+ provider.addDecoratedStateChangeListener(this); >+ } >+ } >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.IDecoratedStateChangeListener#decoratedStateChanged(org.eclipse.team.ui.mapping.IDecoratedStateChangeEvent) >+ */ >+ public void teamStateChanged(ITeamStateChangeEvent event) { >+ fireStateChangeEvent(event); >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.internal.core.IRepositoryProviderListener#providerUnmapped(org.eclipse.core.resources.IProject) >+ */ >+ public void providerUnmapped(IProject project) { >+ // We don't need to worry about this >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.internal.core.IRepositoryProviderListener#providerMapped(org.eclipse.team.core.RepositoryProvider) >+ */ >+ public void providerMapped(RepositoryProvider provider) { >+ String id = provider.getID(); >+ listenerForStateChangesForId(id); >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) >+ */ >+ public void resourceChanged(IResourceChangeEvent event) { >+ IResourceDelta delta = event.getDelta(); >+ IResourceDelta[] projectDeltas = delta >+ .getAffectedChildren(IResourceDelta.ADDED >+ | IResourceDelta.CHANGED); >+ for (int i = 0; i < projectDeltas.length; i++) { >+ IResourceDelta projectDelta = projectDeltas[i]; >+ IResource resource = projectDelta.getResource(); >+ if ((projectDelta.getFlags() & IResourceDelta.OPEN) != 0 >+ && resource.getType() == IResource.PROJECT) { >+ IProject project = (IProject) resource; >+ if (project.isAccessible()) { >+ handleProject(project); >+ } >+ } >+ } >+ } >+} >Index: src/org/eclipse/team/ui/mapping/ITeamStateChangeListener.java >=================================================================== >RCS file: src/org/eclipse/team/ui/mapping/ITeamStateChangeListener.java >diff -N src/org/eclipse/team/ui/mapping/ITeamStateChangeListener.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/team/ui/mapping/ITeamStateChangeListener.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,43 @@ >+/******************************************************************************* >+ * 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 java.util.EventListener; >+ >+import org.eclipse.core.resources.IWorkspace; >+import org.eclipse.team.ui.synchronize.TeamStateProvider; >+ >+/** >+ * A listener registered with an {@link TeamStateProvider} in order to >+ * receive change events when the team state of any >+ * resources change. It is the responsibility of clients to determine if >+ * a label update is required based on the changed resources. >+ * <p> >+ * 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. >+ * <p> >+ * 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. >+ * <p> >+ * 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 >+ * <code>true</code> 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,174 @@ >+/******************************************************************************* >+ * 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 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 >+ * team state provider that uses the subscriber of the type is provided. >+ * <p> >+ * Clients may subclass this class. >+ * >+ * @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 >+ * <code>teamDecorator</code> 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 >+ * <code>teamDecorator</code> 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.ITeamStateProvider#addDecoratedStateChangeListener(org.eclipse.team.ui.mapping.ITeamStateChangeListener) >+ */ >+ public void addDecoratedStateChangeListener(ITeamStateChangeListener listener) { >+ listeners.add(listener); >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.team.ui.mapping.ITeamStateProvider#removeDecoratedStateChangeListener(org.eclipse.team.ui.mapping.ITeamStateChangeListener) >+ */ >+ public void removeDecoratedStateChangeListener(ITeamStateChangeListener listener) { >+ listeners.remove(listener); >+ } >+ >+ /** >+ * Fire the change event to all listeners. >+ * @param event the change event >+ */ >+ protected final 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,151 @@ >+/******************************************************************************* >+ * 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}. >+ * <p> >+ * 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 final 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.ITeamStateProvider#getStateDescription(java.lang.Object, int, java.lang.String[], 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.ITeamStateProvider#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 final Subscriber getSubscriber() { >+ return subscriber; >+ } >+ >+ /** >+ * Called when the provider is no longer needed. This method stops listening >+ * to the subscriber. Subclasses may extend this method but must call this >+ * method if they do. >+ */ >+ 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,175 @@ >+/******************************************************************************* >+ * 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. >+ * <p> >+ * 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. >+ * >+ * <p> >+ * The state mask can consist of the following standard flags: >+ * <ul> >+ * <li>The diff kinds of {@link IDiff#ADD}, {@link IDiff#REMOVE} and >+ * {@link IDiff#CHANGE}. >+ * <li>The directions {@link IThreeWayDiff#INCOMING} and >+ * {@link IThreeWayDiff#OUTGOING}. >+ * </ul> >+ * For convenience sake, if there are no kind flags but there is at least >+ * one direction flag then all kinds are assumed. >+ * <p> >+ * 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 <code>null</code> >+ * is return if the element is not decorated or if decoration is disabled. >+ * Only the portion of the synchronization state covered by >+ * <code>stateMask</code> is returned. The <code>stateMask</code> should >+ * be {@link #USE_DECORATED_STATE_MASK} or the mask returned from >+ * {@link #getDecoratedStateMask(Object)} and the requested properties >+ * should be <code>null</code> 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 >+ * <code>null</code> if the decorated properties are desired >+ * @param monitor >+ * a progress monitor >+ * @return the state for the given element or <code>null</code> >+ * @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. >+ * Adding the same listener more than once has no effect. >+ * >+ * @param listener >+ * the listener >+ */ >+ public void addDecoratedStateChangeListener( >+ ITeamStateChangeListener listener); >+ >+ /** >+ * Remove the decorated state change listener to the provider. >+ * Removing a listener that is not registered has no effect. >+ * >+ * @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,124 @@ >+/******************************************************************************* >+ * 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}. >+ * <p> >+ * This class is not intended to be subclassed by clients. >+ * >+ * @since 3.2 >+ */ >+public class TeamStateChangeEvent implements ITeamStateChangeEvent { >+ >+ private Set changes = new HashSet(); >+ private Set addedRoots = new HashSet(); >+ private Set removedRoots = new HashSet(); >+ >+ public TeamStateChangeEvent() { >+ super(); >+ } >+ >+ /** >+ * 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,90 @@ >+/******************************************************************************* >+ * 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. >+ * <p> >+ * 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 <code>stateMask</code> 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[] getPropertyNames(); >+ >+ /** >+ * Return the value associated with the given property. A <code>null</code> >+ * is returned if the property has no value. >+ * @param property the property >+ * @return the value associated with the given property or <code>null</code> >+ */ >+ public abstract Object getProperty(String property); >+ >+ /** >+ * Return whether this state description is equal the to given object. >+ * Clients should use this method to test whether two state >+ * descriptions are equal. >+ * @param object the object >+ * @return whether this state description is equal the to given object >+ */ >+ public boolean equals(Object object); >+ >+} >#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 17 Mar 2006 15:40:34 -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 17 Mar 2006 15:40:34 -0000 >@@ -1550,6 +1550,11 @@ > class="org.eclipse.team.internal.ccvs.ui.model.CVSAdapterFactory"> > <adapter type="org.eclipse.team.ui.mapping.ISynchronizationCompareAdapter"/> > </factory> >+ <factory >+ adaptableType="org.eclipse.team.internal.ccvs.core.CVSTeamProviderType" >+ class="org.eclipse.team.internal.ccvs.ui.model.CVSAdapterFactory"> >+ <adapter type="org.eclipse.team.ui.mapping.ITeamStateProvider"/> >+ </factory> > </extension> > <extension > point="org.eclipse.team.ui.teamDecorators"> >Index: src/org/eclipse/team/internal/ccvs/ui/CVSDecoration.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSDecoration.java,v >retrieving revision 1.17 >diff -u -r1.17 CVSDecoration.java >--- src/org/eclipse/team/internal/ccvs/ui/CVSDecoration.java 16 Mar 2006 21:55:58 -0000 1.17 >+++ src/org/eclipse/team/internal/ccvs/ui/CVSDecoration.java 17 Mar 2006 15:40:34 -0000 >@@ -20,11 +20,13 @@ > import org.eclipse.jface.resource.ImageDescriptor; > import org.eclipse.jface.viewers.IDecoration; > import org.eclipse.swt.graphics.*; >+import org.eclipse.team.core.diff.IThreeWayDiff; > import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation; > import org.eclipse.team.internal.ccvs.ui.repo.RepositoryManager; > import org.eclipse.team.internal.ccvs.ui.repo.RepositoryRoot; > import org.eclipse.team.internal.ui.TeamUIPlugin; > import org.eclipse.team.ui.ISharedImages; >+import org.eclipse.team.ui.synchronize.TeamStateDescription; > import org.eclipse.ui.PlatformUI; > import org.eclipse.ui.themes.ITheme; > >@@ -75,6 +77,7 @@ > private String repository; > private ICVSRepositoryLocation location; > private String keywordSubstitution; >+ private int stateFlags; > > // Text formatters > private String fileFormatter; >@@ -93,7 +96,7 @@ > // List of preferences used to configure the decorations that > // are applied. > private Preferences preferences; >- >+ > /* > * Define a cached image descriptor which only creates the image data once > */ >@@ -288,6 +291,8 @@ > if (isWatchEditEnabled() && resourceType == IResource.FILE && !isReadOnly() && isHasRemote()) { > return edited; > } >+ if (needsMerge) >+ return merged; > // show checked in > if (preferences.getBoolean(ICVSUIConstants.PREF_SHOW_HASREMOTE_DECORATION) && isHasRemote()) { > if ((resourceType == IResource.FOLDER || resourceType == IResource.PROJECT) && isVirtualFolder()) { >@@ -295,8 +300,6 @@ > } > return checkedIn; > } >- if (needsMerge) >- return merged; > > //nothing matched > return null; >@@ -431,4 +434,34 @@ > public void setVirtualFolder(boolean virtualFolder) { > this.virtualFolder = virtualFolder; > } >+ >+ public void setStateFlags(int stateFlags) { >+ this.stateFlags = stateFlags; >+ if ((stateFlags & IThreeWayDiff.OUTGOING) != 0) { >+ setDirty(true); >+ } >+ } >+ >+ public TeamStateDescription asTeamStateDescription(String[] properties) { >+ TeamStateDescription desc = new CVSTeamStateDescription(stateFlags); >+ Object o = computeImage(); >+ if (o != null && isRequestedProperty(properties, CVSTeamStateDescription.PROP_RESOURCE_STATE)) { >+ desc.setProperty(CVSTeamStateDescription.PROP_RESOURCE_STATE, o); >+ } >+ if (tag != null && isRequestedProperty(properties, CVSTeamStateDescription.PROP_TAG)) { >+ desc.setProperty(CVSTeamStateDescription.PROP_TAG, tag); >+ } >+ return desc; >+ } >+ >+ private boolean isRequestedProperty(String[] properties, String property) { >+ if (properties == null) >+ return true; >+ for (int i = 0; i < properties.length; i++) { >+ String string = properties[i]; >+ if (string.equals(property)) >+ return true; >+ } >+ return false; >+ } > } >Index: src/org/eclipse/team/internal/ccvs/ui/CVSLightweightDecorator.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSLightweightDecorator.java,v >retrieving revision 1.66 >diff -u -r1.66 CVSLightweightDecorator.java >--- src/org/eclipse/team/internal/ccvs/ui/CVSLightweightDecorator.java 30 Jan 2006 15:56:44 -0000 1.66 >+++ src/org/eclipse/team/internal/ccvs/ui/CVSLightweightDecorator.java 17 Mar 2006 15:40:34 -0000 >@@ -15,7 +15,7 @@ > import java.util.*; > > import org.eclipse.core.resources.*; >-import org.eclipse.core.resources.mapping.ResourceMapping; >+import org.eclipse.core.resources.mapping.*; > import org.eclipse.core.runtime.*; > import org.eclipse.jface.preference.IPreferenceStore; > import org.eclipse.jface.util.IPropertyChangeListener; >@@ -162,7 +162,7 @@ > handleException(element, e); > } catch (IllegalStateException e) { > // This is thrown by Core if the workspace is in an illegal state >- // If we are not active, ignore it. Otherwise, propogate it. >+ // If we are not active, ignore it. Otherwise, propagate it. > // (see bug 78303) > if (Platform.getBundle(CVSUIPlugin.ID).getState() == Bundle.ACTIVE) { > throw e; >@@ -170,7 +170,7 @@ > } > } > >- private IResource getResource(Object element) { >+ private static IResource getResource(Object element) { > if (element instanceof ResourceMapping) { > element = ((ResourceMapping) element).getModelObject(); > } >@@ -191,27 +191,41 @@ > return false; > } > >- private CVSDecoration decorate(Object element, SynchronizationStateTester tester) throws CoreException { >+ public static CVSDecoration decorate(Object element, SynchronizationStateTester tester) throws CoreException { > IPreferenceStore store = CVSUIPlugin.getPlugin().getPreferenceStore(); > CVSDecoration result = new CVSDecoration(); > > // First, decorate the synchronization state >- if (tester.isStateDecorationEnabled()) { >- if (tester.isSupervised(element)) { >+ int state = IDiff.NO_CHANGE; >+ if (tester.isDecorationEnabled(element)) { >+ if (isSupervised(element)) { > result.setHasRemote(true); >- int state = tester.getState(element, >+ state = tester.getState(element, > store.getBoolean(ICVSUIConstants.PREF_CALCULATE_DIRTY) > ? IDiff.ADD | IDiff.REMOVE | IDiff.CHANGE | IThreeWayDiff.OUTGOING > : 0, > new NullProgressMonitor()); >- if ((state & IThreeWayDiff.OUTGOING) != 0) { >- result.setDirty(true); >- } >+ result.setStateFlags(state); > } else { > result.setIgnored(true); > } > } > >+ // Tag >+ if (!result.isIgnored()) { >+ CVSTag tag = getTagToShow(element); >+ if (tag != null) { >+ String name = tag.getName(); >+ if (tag.getType() == CVSTag.DATE) { >+ Date date = tag.asDate(); >+ if (date != null) { >+ name = decorateFormatter.format(date); >+ } >+ } >+ result.setTag(name); >+ } >+ } >+ > // If the element adapts to a single resource, add additional decorations > IResource resource = getResource(element); > if (resource == null) { >@@ -219,9 +233,37 @@ > } else { > decorate(resource, result); > } >+ tester.elementDecorated(element, result.asTeamStateDescription(null)); > return result; > } > >+ private static boolean isSupervised(Object element) throws CoreException { >+ IResource[] resources = getTraversalRoots(element); >+ for (int i = 0; i < resources.length; i++) { >+ IResource resource = resources[i]; >+ if (getSubscriber().isSupervised(resource)) >+ return true; >+ } >+ return false; >+ } >+ >+ private static IResource[] getTraversalRoots(Object element) throws CoreException { >+ Set result = new HashSet(); >+ 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]; >+ result.add(resource); >+ } >+ } >+ } >+ return (IResource[]) result.toArray(new IResource[result.size()]); >+ } >+ > private static void decorate(IResource resource, CVSDecoration cvsDecoration) throws CVSException { > IPreferenceStore store = CVSUIPlugin.getPlugin().getPreferenceStore(); > ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(resource); >@@ -250,18 +292,6 @@ > // Has a remote > //cvsDecoration.setHasRemote(CVSWorkspaceRoot.hasRemote(resource)); > } >- // Tag >- CVSTag tag = getTagToShow(resource); >- if (tag != null) { >- String name = tag.getName(); >- if (tag.getType() == CVSTag.DATE) { >- Date date = tag.asDate(); >- if (date != null) { >- name = decorateFormatter.format(date); >- } >- } >- cvsDecoration.setTag(name); >- } > // Is a new resource > if (store.getBoolean(ICVSUIConstants.PREF_SHOW_NEWRESOURCE_DECORATION)) { > if (cvsResource.exists()) { >@@ -333,6 +363,37 @@ > cvsDecoration.setWatchEditEnabled(provider.isWatchEditEnabled()); > } > >+ protected static CVSTag getTagToShow(Object element) throws CoreException { >+ IResource r = getResource(element); >+ if (r != null) >+ return getTagToShow(r); >+ IResource[] resources = getTraversalRoots(element); >+ boolean first = true; >+ CVSTag tag = null; >+ for (int i = 0; i < resources.length; i++) { >+ IResource resource = resources[i]; >+ if (getSubscriber().isSupervised(resource)) { >+ CVSTag nextTag = getTagToShow(resource); >+ if (first) { >+ tag = nextTag; >+ first = false; >+ } else if (!equals(tag, nextTag)) { >+ return null; >+ } >+ >+ } >+ } >+ return tag; >+ } >+ >+ private static boolean equals(CVSTag tag, CVSTag nextTag) { >+ if (tag == nextTag) >+ return true; >+ if (tag == null || nextTag == null) >+ return false; >+ return tag.getName().equals(nextTag.getName()); >+ } >+ > /** > * Only show the tag if the resources tag is different than the parents. Or else, tag > * names will clutter the text decorations. >Index: src/org/eclipse/team/internal/ccvs/ui/CVSTeamStateDescription.java >=================================================================== >RCS file: src/org/eclipse/team/internal/ccvs/ui/CVSTeamStateDescription.java >diff -N src/org/eclipse/team/internal/ccvs/ui/CVSTeamStateDescription.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/team/internal/ccvs/ui/CVSTeamStateDescription.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,31 @@ >+/******************************************************************************* >+ * 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.internal.ccvs.ui; >+ >+import org.eclipse.team.ui.synchronize.TeamStateDescription; >+ >+/** >+ * A state description for the CVS decorations. We only need to >+ * enumerate the states that can be associated with model >+ * elements that don't have a one-to-one mapping to resources >+ */ >+public class CVSTeamStateDescription extends TeamStateDescription { >+ >+ /** >+ * Property representing the image overlay >+ */ >+ public static final String PROP_RESOURCE_STATE = "resourceState"; //$NON-NLS-1$ >+ public static final String PROP_TAG = "tag"; //$NON-NLS-1$ >+ >+ public CVSTeamStateDescription(int state) { >+ super(state); >+ } >+} >Index: src/org/eclipse/team/internal/ccvs/ui/CVSTeamStateProvider.java >=================================================================== >RCS file: src/org/eclipse/team/internal/ccvs/ui/CVSTeamStateProvider.java >diff -N src/org/eclipse/team/internal/ccvs/ui/CVSTeamStateProvider.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/team/internal/ccvs/ui/CVSTeamStateProvider.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,39 @@ >+/******************************************************************************* >+ * 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.internal.ccvs.ui; >+ >+import org.eclipse.core.runtime.CoreException; >+import org.eclipse.core.runtime.IProgressMonitor; >+import org.eclipse.team.core.subscribers.Subscriber; >+import org.eclipse.team.ui.mapping.*; >+import org.eclipse.team.ui.synchronize.SubscriberTeamStateProvider; >+ >+public class CVSTeamStateProvider extends SubscriberTeamStateProvider { >+ >+ public CVSTeamStateProvider(Subscriber subscriber) { >+ super(subscriber); >+ } >+ >+ public ITeamStateDescription getStateDescription(Object element, final int requestedStateMask, String[] properties, IProgressMonitor monitor) throws CoreException { >+ if (properties != null && properties.length == 0) { >+ return new CVSTeamStateDescription(getSynchronizationState(element, requestedStateMask, monitor)); >+ } >+ CVSDecoration d = CVSLightweightDecorator.decorate(element, new SynchronizationStateTester() { >+ public int getState(Object element, int stateMask, IProgressMonitor monitor) throws CoreException { >+ if (requestedStateMask != USE_DECORATED_STATE_MASK) { >+ stateMask = requestedStateMask & stateMask; >+ } >+ return getSynchronizationState(element, requestedStateMask & stateMask, monitor); >+ } >+ }); >+ return d.asTeamStateDescription(properties); >+ } >+} >#P org.eclipse.team.core >Index: src/org/eclipse/team/internal/core/mapping/WorkspaceSubscriber.java >=================================================================== >RCS file: src/org/eclipse/team/internal/core/mapping/WorkspaceSubscriber.java >diff -N src/org/eclipse/team/internal/core/mapping/WorkspaceSubscriber.java >--- src/org/eclipse/team/internal/core/mapping/WorkspaceSubscriber.java 10 Feb 2006 16:54:23 -0000 1.8 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,350 +0,0 @@ >-/******************************************************************************* >- * 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.internal.core.mapping; >- >-import java.util.*; >- >-import org.eclipse.core.resources.*; >-import org.eclipse.core.resources.mapping.ResourceMapping; >-import org.eclipse.core.resources.mapping.ResourceTraversal; >-import org.eclipse.core.runtime.*; >-import org.eclipse.team.core.*; >-import org.eclipse.team.core.diff.IDiff; >-import org.eclipse.team.core.diff.IDiffVisitor; >-import org.eclipse.team.core.subscribers.*; >-import org.eclipse.team.core.synchronize.SyncInfo; >-import org.eclipse.team.core.synchronize.SyncInfoSet; >-import org.eclipse.team.core.variants.IResourceVariant; >-import org.eclipse.team.core.variants.IResourceVariantComparator; >-import org.eclipse.team.internal.core.*; >- >-/** >- * A workspace subscriber is a special subscriber tat delegates to >- * the subscribers associated with each project through the >- * {@link RepositoryProvider} API. >- * @since 3.2 >- */ >-public class WorkspaceSubscriber extends Subscriber implements ISubscriberChangeListener, IRepositoryProviderListener, IResourceChangeListener { >- >- private static WorkspaceSubscriber instance; >- private Map projects = new HashMap(); >- >- public static synchronized WorkspaceSubscriber getInstance() { >- if (instance == null) { >- instance = new WorkspaceSubscriber(); >- } >- return instance; >- } >- >- public WorkspaceSubscriber() { >- // Add subscribers for all projects that have them >- RepositoryProviderManager.getInstance().addListener(this); >- ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); >- IProject[] allProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); >- for (int i = 0; i < allProjects.length; i++) { >- IProject project = allProjects[i]; >- handleProject(project); >- } >- } >- >- private void handleProject(IProject project) { >- if (RepositoryProvider.isShared(project)) { >- try { >- String currentId = project.getPersistentProperty(TeamPlugin.PROVIDER_PROP_KEY); >- if (currentId != null) { >- RepositoryProviderType type = RepositoryProviderType.getProviderType(currentId); >- if (type != null) { >- Subscriber subscriber = type.getSubscriber(); >- if (subscriber != null) { >- subscriber.addListener(this); >- projects.put(project, subscriber); >- } >- } >- } >- } catch (CoreException e) { >- TeamPlugin.log(e); >- } >- } >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#getName() >- */ >- public String getName() { >- return Messages.WorkspaceSubscriber_0; >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#isSupervised(org.eclipse.core.resources.IResource) >- */ >- public boolean isSupervised(IResource resource) throws TeamException { >- Subscriber subscriber = getSubscriber(resource); >- if (subscriber != null) >- return subscriber.isSupervised(resource); >- return false; >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#members(org.eclipse.core.resources.IResource) >- */ >- public IResource[] members(IResource resource) throws TeamException { >- Subscriber subscriber = getSubscriber(resource); >- if (subscriber != null) >- return subscriber.members(resource); >- if (resource instanceof IContainer) { >- IContainer container = (IContainer) resource; >- try { >- return container.members(); >- } catch (CoreException e) { >- throw TeamException.asTeamException(e); >- } >- } >- return new IResource[0]; >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#roots() >- */ >- public IResource[] roots() { >- return (IProject[]) projects.keySet().toArray(new IProject[projects.size()]); >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#getDiff(org.eclipse.core.resources.IResource) >- */ >- public IDiff getDiff(IResource resource) throws CoreException { >- Subscriber subscriber = getSubscriber(resource); >- if (subscriber != null) >- return subscriber.getDiff(resource); >- return super.getDiff(resource); >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#getSyncInfo(org.eclipse.core.resources.IResource) >- */ >- public SyncInfo getSyncInfo(IResource resource) throws TeamException { >- Subscriber subscriber = getSubscriber(resource); >- if (subscriber != null) >- return subscriber.getSyncInfo(resource); >- return null; >- } >- >- /** >- * Return a dummy comparator. The comparator should not be used by clients. >- * >- * @see org.eclipse.team.core.subscribers.Subscriber#getResourceComparator() >- */ >- public IResourceVariantComparator getResourceComparator() { >- return new IResourceVariantComparator() { >- public boolean isThreeWay() { >- return true; >- } >- public boolean compare(IResourceVariant base, IResourceVariant remote) { >- return false; >- } >- public boolean compare(IResource local, IResourceVariant remote) { >- return false; >- } >- >- }; >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#refresh(org.eclipse.core.resources.mapping.ResourceTraversal[], org.eclipse.core.runtime.IProgressMonitor) >- */ >- public void refresh(ResourceTraversal[] traversals, IProgressMonitor monitor) throws TeamException { >- try { >- List errors = new ArrayList(); >- Subscriber[] subscribers = getSubscribers(); >- monitor.beginTask(null, subscribers.length * 100); >- for (int i = 0; i < subscribers.length; i++) { >- Subscriber subscriber = subscribers[i]; >- try { >- subscriber.refresh(traversals, Policy.subMonitorFor(monitor, 100)); >- } catch (TeamException e) { >- errors.add(e); >- } >- } >- try { >- handleErrors((CoreException[]) errors.toArray(new CoreException[errors.size()])); >- } catch (CoreException e) { >- throw TeamException.asTeamException(e); >- } >- } finally { >- monitor.done(); >- } >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#refresh(org.eclipse.core.resources.IResource[], int, org.eclipse.core.runtime.IProgressMonitor) >- */ >- public void refresh(IResource[] resources, int depth, >- IProgressMonitor monitor) throws TeamException { >- refresh(new ResourceTraversal[] { new ResourceTraversal(resources, depth, IResource.NONE)}, monitor); >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#accept(org.eclipse.core.resources.mapping.ResourceTraversal[], org.eclipse.team.core.diff.IDiffVisitor) >- */ >- public void accept(ResourceTraversal[] traversals, IDiffVisitor visitor) throws CoreException { >- List errors = new ArrayList(); >- Subscriber[] subscribers = getSubscribers(); >- for (int i = 0; i < subscribers.length; i++) { >- Subscriber subscriber = subscribers[i]; >- try { >- subscriber.accept(traversals, visitor); >- } catch (CoreException e) { >- errors.add(e); >- } >- } >- handleErrors((CoreException[]) errors.toArray(new CoreException[errors.size()])); >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#accept(org.eclipse.core.resources.IResource[], int, org.eclipse.team.core.diff.IDiffVisitor) >- */ >- public void accept(IResource[] resources, int depth, IDiffVisitor visitor) throws CoreException { >- accept(new ResourceTraversal[] { new ResourceTraversal(resources, depth, IResource.NONE)}, visitor); >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#getState(org.eclipse.core.resources.mapping.ResourceMapping, int, org.eclipse.core.runtime.IProgressMonitor) >- */ >- public int getState(ResourceMapping mapping, int stateMask, IProgressMonitor monitor) throws CoreException { >- int state = 0; >- try { >- List errors = new ArrayList(); >- Subscriber[] subscribers = getSubscribers(mapping.getProjects()); >- monitor.beginTask(null, subscribers.length * 100); >- for (int i = 0; i < subscribers.length; i++) { >- Subscriber subscriber = subscribers[i]; >- try { >- int subscriberState = subscriber.getState(mapping, stateMask, Policy.subMonitorFor(monitor, 100)); >- state |= subscriberState; >- } catch (TeamException e) { >- errors.add(e); >- } >- } >- handleErrors((CoreException[]) errors.toArray(new CoreException[errors.size()])); >- } finally { >- monitor.done(); >- } >- return state & stateMask; >- } >- >- private Subscriber[] getSubscribers(IProject[] projects) { >- for (int i = 0; i < projects.length; i++) { >- IProject project = projects[i]; >- if (!this.projects.containsKey(project)) { >- handleProject(project); >- } >- } >- return getSubscribers(); >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.Subscriber#collectOutOfSync(org.eclipse.core.resources.IResource[], int, org.eclipse.team.core.synchronize.SyncInfoSet, org.eclipse.core.runtime.IProgressMonitor) >- */ >- public void collectOutOfSync(IResource[] resources, int depth, SyncInfoSet set, IProgressMonitor monitor) { >- try { >- Subscriber[] subscribers = getSubscribers(); >- monitor.beginTask(null, subscribers.length * 100); >- for (int i = 0; i < subscribers.length; i++) { >- Subscriber subscriber = subscribers[i]; >- subscriber.collectOutOfSync(resources, depth, set, Policy.subMonitorFor(monitor, 100)); >- } >- } finally { >- monitor.done(); >- } >- } >- >- private Subscriber[] getSubscribers() { >- Set result = new HashSet(); >- for (Iterator iter = projects.values().iterator(); iter.hasNext();) { >- Subscriber subscriber = (Subscriber) iter.next(); >- result.add(subscriber); >- } >- return (Subscriber[]) result.toArray(new Subscriber[result.size()]); >- } >- >- /* >- * Return the subscriber for the given resource if the resource >- * is in the scope of this subscriber. >- */ >- private Subscriber getSubscriber(IResource resource) { >- return (Subscriber)projects.get(resource.getProject()); >- } >- >- private void handleErrors(CoreException[] exceptions) throws CoreException { >- if (exceptions.length == 0) >- return; >- if (exceptions.length == 1) >- throw exceptions[0]; >- MultiStatus result = new MultiStatus(TeamPlugin.ID, 0, Messages.WorkspaceSubscriber_1, null); >- for (int i = 0; i < exceptions.length; i++) { >- CoreException exception = exceptions[i]; >- IStatus status = new Status( >- exception.getStatus().getSeverity(), >- exception.getStatus().getPlugin(), >- exception.getStatus().getCode(), >- exception.getStatus().getMessage(), >- exception); >- result.add(status); >- } >- throw new TeamException(result); >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.core.subscribers.ISubscriberChangeListener#subscriberResourceChanged(org.eclipse.team.core.subscribers.ISubscriberChangeEvent[]) >- */ >- public void subscriberResourceChanged(ISubscriberChangeEvent[] deltas) { >- fireTeamResourceChange(deltas); >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.internal.core.IRepositoryProviderListener#providerMapped(org.eclipse.team.core.RepositoryProvider) >- */ >- public void providerMapped(RepositoryProvider provider) { >- // Record the subscriber. No need to fire an event since the subscriber should >- Subscriber subscriber = provider.getSubscriber(); >- if (subscriber != null) >- projects.put(provider.getProject(), subscriber); >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.team.internal.core.IRepositoryProviderListener#providerUnmapped(org.eclipse.core.resources.IProject) >- */ >- public void providerUnmapped(IProject project) { >- // We'll remove the project. No need to fire an event since the subscriber should have done that >- projects.remove(project); >- } >- >- /* (non-Javadoc) >- * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) >- */ >- public void resourceChanged(IResourceChangeEvent event) { >- IResourceDelta delta = event.getDelta(); >- IResourceDelta[] projectDeltas = delta.getAffectedChildren(IResourceDelta.ADDED | IResourceDelta.CHANGED); >- for (int i = 0; i < projectDeltas.length; i++) { >- IResourceDelta projectDelta = projectDeltas[i]; >- IResource resource = projectDelta.getResource(); >- if ((projectDelta.getFlags() & IResourceDelta.OPEN) != 0 >- && resource.getType() == IResource.PROJECT) { >- IProject project = (IProject)resource; >- if (project.isAccessible()) { >- handleProject(project); >- } else { >- projects.remove(project); >- } >- } >- } >- } >-} >Index: src/org/eclipse/team/core/Team.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.team.core/src/org/eclipse/team/core/Team.java,v >retrieving revision 1.59 >diff -u -r1.59 Team.java >--- src/org/eclipse/team/core/Team.java 31 Jan 2006 15:35:51 -0000 1.59 >+++ src/org/eclipse/team/core/Team.java 17 Mar 2006 15:40:36 -0000 >@@ -18,9 +18,7 @@ > import org.eclipse.core.runtime.Preferences.PropertyChangeEvent; > import org.eclipse.core.runtime.content.IContentType; > import org.eclipse.team.core.mapping.IStorageMerger; >-import org.eclipse.team.core.subscribers.Subscriber; > import org.eclipse.team.internal.core.*; >-import org.eclipse.team.internal.core.mapping.WorkspaceSubscriber; > > /** > * The Team class provides a global point of reference for the global ignore set >@@ -457,19 +455,6 @@ > return fFileContentManager; > } > >- /** >- * Returns a subscriber that provides access to the synchronization state >- * of the workspace for those projects that provide it. >- * >- * @return a subscriber that provides access to the synchronization state >- * of the workspace. >- * >- * @since 3.2 >- */ >- public static Subscriber getWorkspaceSubscriber() { >- return WorkspaceSubscriber.getInstance(); >- } >- > /** > * Creates a storage merger for the given content type. > * If no storage merger is registered for the given content type <code>null</code> is returned.
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 131440
:
36419
| 36493