DynamicWorkingSetUpdater.java
package com.codeaffine.extras.workingset.internal;
import static com.codeaffine.extras.workingset.internal.DynamicWorkingSet.ID;
import static java.lang.Boolean.TRUE;
import static java.util.Collections.synchronizedSet;
import static org.eclipse.core.resources.IResourceChangeEvent.POST_CHANGE;
import static org.eclipse.core.resources.IResourceDelta.ADDED;
import static org.eclipse.core.resources.IResourceDelta.CHANGED;
import static org.eclipse.core.resources.IResourceDelta.REMOVED;
import static org.eclipse.ui.IWorkingSetManager.CHANGE_WORKING_SET_ADD;
import static org.eclipse.ui.IWorkingSetManager.CHANGE_WORKING_SET_NAME_CHANGE;
import static org.eclipse.ui.IWorkingSetManager.CHANGE_WORKING_SET_REMOVE;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IProject;
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.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.IWorkingSetUpdater;
import org.eclipse.ui.PlatformUI;
public class DynamicWorkingSetUpdater
implements IWorkingSetUpdater, IPropertyChangeListener, IResourceChangeListener
{
private final IWorkingSetManager workingSetManager;
private final IWorkspace workspace;
private final ThreadLocal<Boolean> inPropertyChange;
private final Set<IWorkingSet> workingSets;
public DynamicWorkingSetUpdater() {
workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
workspace = ResourcesPlugin.getWorkspace();
inPropertyChange = new ThreadLocal<>();
workingSets = synchronizedSet( new HashSet<IWorkingSet>() );
initialize();
}
private void initialize() {
workingSetManager.addPropertyChangeListener( this );
workspace.addResourceChangeListener( this, POST_CHANGE );
}
@Override
public void add( IWorkingSet workingSet ) {
update( workingSet );
workingSets.add( workingSet );
}
@Override
public boolean remove( IWorkingSet workingSet ) {
return workingSets.remove( workingSet );
}
@Override
public boolean contains( IWorkingSet workingSet ) {
return workingSets.contains( workingSet );
}
@Override
public void dispose() {
workspace.removeResourceChangeListener( this );
workingSetManager.removePropertyChangeListener( this );
workingSets.clear();
}
@Override
public void propertyChange( PropertyChangeEvent event ) {
if( inPropertyChange.get() == null ) {
inPropertyChange.set( TRUE );
try {
handlePropertyChange( event );
} finally {
inPropertyChange.remove();
}
}
}
@Override
public void resourceChanged( IResourceChangeEvent event ) {
if( event.getDelta() != null && isUpdateNeeded( event ) ) {
update();
}
}
private void handlePropertyChange( PropertyChangeEvent event ) {
if( isWorkingSetAddEvent( event ) ) {
add( getWorkingSet( event ) );
} else if( isWorkingSetNameChangeEvent( event ) ) {
update( getWorkingSet( event ) );
} else if( isWorkingSetRemoveEvent( event ) ) {
remove( getWorkingSet( event ) );
}
}
private boolean isUpdateNeeded( IResourceChangeEvent event ) {
ResourceDeltaVisitor visitor = new ResourceDeltaVisitor();
try {
event.getDelta().accept( visitor );
} catch( CoreException ce ) {
throw new RuntimeException( ce );
}
return visitor.isUpdateNeeded();
}
private void update() {
for( IWorkingSet workingSet : workingSets.toArray( new IWorkingSet[ 0 ] ) ) {
update( workingSet );
}
}
private static void update( IWorkingSet workingSet ) {
new WorkingSetContentUpdater( workingSet ).updateElements();
}
private static boolean isWorkingSetAddEvent( PropertyChangeEvent event ) {
return CHANGE_WORKING_SET_ADD.equals( event.getProperty() ) && isDynamicWorkingSet( event );
}
private static boolean isWorkingSetRemoveEvent( PropertyChangeEvent event ) {
return CHANGE_WORKING_SET_REMOVE.equals( event.getProperty() ) && isDynamicWorkingSet( event );
}
private static boolean isWorkingSetNameChangeEvent( PropertyChangeEvent event ) {
return CHANGE_WORKING_SET_NAME_CHANGE.equals( event.getProperty() ) && isDynamicWorkingSet( event );
}
private static boolean isDynamicWorkingSet( PropertyChangeEvent event ) {
IWorkingSet workingSet = getWorkingSet( event );
return ID.equals( workingSet.getId() );
}
private static IWorkingSet getWorkingSet( PropertyChangeEvent event ) {
IWorkingSet result = ( IWorkingSet )event.getNewValue();
if( result == null ) {
result = ( IWorkingSet )event.getOldValue();
}
return result;
}
private class ResourceDeltaVisitor implements IResourceDeltaVisitor {
private boolean updateNeeded;
@Override
public boolean visit( IResourceDelta delta ) throws CoreException {
updateNeeded = isProjectChange( delta );
return !updateNeeded;
}
private boolean isProjectChange( IResourceDelta delta ) {
int kind = delta.getKind();
IResource resource = delta.getResource();
return ( kind == ADDED || kind == CHANGED || kind == REMOVED ) && resource instanceof IProject;
}
boolean isUpdateNeeded() {
return updateNeeded;
}
}
}