diff options
author | Jean Michel-Lemieux | 2004-02-17 03:14:26 +0000 |
---|---|---|
committer | Jean Michel-Lemieux | 2004-02-17 03:14:26 +0000 |
commit | e63e9b5c44d77b9791a0014d5e2139f5f2cb259b (patch) | |
tree | f4374a3b24b3175e1c698f5c25e2ac84e1343290 | |
parent | 8506cae5a4a434acc21083a027010249800e748c (diff) | |
download | eclipse.platform.team-e63e9b5c44d77b9791a0014d5e2139f5f2cb259b.tar.gz eclipse.platform.team-e63e9b5c44d77b9791a0014d5e2139f5f2cb259b.tar.xz eclipse.platform.team-e63e9b5c44d77b9791a0014d5e2139f5f2cb259b.zip |
*** empty log message ***
18 files changed, 356 insertions, 172 deletions
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/TimeoutProgressMonitorDialog.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/TimeoutProgressMonitorDialog.java index 42130ae0e..8f1bb9353 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/TimeoutProgressMonitorDialog.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/TimeoutProgressMonitorDialog.java @@ -39,7 +39,7 @@ public class TimeoutProgressMonitorDialog extends ProgressMonitorDialog { } /* (non-Javadoc) - * Method declared on IRunnableContext. + * Method declared on ITeamRunnableContext. * Runs the given <code>IRunnableWithProgress</code> with the progress monitor for this * progress dialog. The dialog is opened before it is run, and closed after it completes. */ diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/model/CVSModelElement.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/model/CVSModelElement.java index 5fb8cfb18..f7f7e0966 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/model/CVSModelElement.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/model/CVSModelElement.java @@ -46,7 +46,7 @@ public abstract class CVSModelElement implements IWorkbenchAdapter, IAdaptable { /** * Returns the runnableContext. - * @return IRunnableContext + * @return ITeamRunnableContext */ public IRunnableContext getRunnableContext() { if (runnableContext == null) { diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CVSOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CVSOperation.java index 476b4afab..9791e637f 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CVSOperation.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CVSOperation.java @@ -24,6 +24,7 @@ import org.eclipse.team.internal.ccvs.core.CVSStatus; import org.eclipse.team.internal.ccvs.core.util.Assert; import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin; import org.eclipse.team.internal.ccvs.ui.Policy; +import org.eclipse.team.ui.synchronize.subscriber.*; /** @@ -46,7 +47,7 @@ public abstract class CVSOperation implements IRunnableWithProgress { // instance variable used to indicate behavior while prompting for overwrite private boolean confirmOverwrite = true; - ICVSRunnableContext cvsRunnableContext; + ITeamRunnableContext cvsRunnableContext; public CVSOperation(Shell shell) { this.shell = shell; @@ -146,14 +147,14 @@ public abstract class CVSOperation implements IRunnableWithProgress { protected abstract void execute(IProgressMonitor monitor) throws CVSException, InterruptedException; /* - * Return the ICVSRunnableContext which will be used to run the operation. + * Return the ITeamRunnableContext which will be used to run the operation. */ - private ICVSRunnableContext getCVSRunnableContext() { + private ITeamRunnableContext getCVSRunnableContext() { if (cvsRunnableContext == null) { if (canRunAsJob() && areJobsEnabled()) { - return new CVSNonblockingRunnableContext(); + return new JobRunnableContext(); } else { - return new CVSBlockingRunnableContext(shell); + return new ProgressDialogRunnableContext(shell); } } return cvsRunnableContext; @@ -166,7 +167,7 @@ public abstract class CVSOperation implements IRunnableWithProgress { * for testing purposes. * @param cvsRunnableContext */ - public void setCVSRunnableContext(ICVSRunnableContext cvsRunnableContext) { + public void setCVSRunnableContext(ITeamRunnableContext cvsRunnableContext) { this.cvsRunnableContext = cvsRunnableContext; } diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/CVSSubscriberAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/CVSSubscriberAction.java index 1da29b626..d022250c2 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/CVSSubscriberAction.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/CVSSubscriberAction.java @@ -11,12 +11,11 @@ package org.eclipse.team.internal.ccvs.ui.subscriber; import java.lang.reflect.InvocationTargetException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; -import org.eclipse.core.runtime.jobs.*; -import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.team.core.TeamException; @@ -27,11 +26,8 @@ import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer; import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin; import org.eclipse.team.internal.ccvs.ui.Policy; -import org.eclipse.team.internal.ccvs.ui.operations.*; import org.eclipse.team.internal.ui.TeamUIPlugin; import org.eclipse.team.ui.synchronize.subscriber.SubscriberAction; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.IWorkbenchSite; public abstract class CVSSubscriberAction extends SubscriberAction { @@ -126,7 +122,7 @@ public abstract class CVSSubscriberAction extends SubscriberAction { * Sync actions seem to need to be sync-execed to work * @param t */ - protected void handle(Throwable t) { + protected void handle(Exception t) { CVSUIPlugin.openError(getShell(), getErrorTitle(), null, t, CVSUIPlugin.PERFORM_SYNC_EXEC | CVSUIPlugin.LOG_NONTEAM_EXCEPTIONS); } @@ -137,25 +133,6 @@ public abstract class CVSSubscriberAction extends SubscriberAction { protected String getErrorTitle() { return null; } - - /* (non-Javadoc) - * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) - */ - public void run(IAction action) { -// TODO: Saving can change the sync state! How should this be handled? -// boolean result = saveIfNecessary(); -// if (!result) return null; - - SyncInfoSet syncSet = getFilteredSyncInfoSet(getFilteredSyncInfos()); - if (syncSet == null || syncSet.isEmpty()) return; - try { - getCVSRunnableContext().run(getJobName(syncSet), getSchedulingRule(syncSet), true, getRunnable(syncSet)); - } catch (InvocationTargetException e) { - handle(e); - } catch (InterruptedException e) { - // nothing to do; - } - } /** * Return an IRunnableWithProgress that will operate on the given sync set. @@ -189,74 +166,9 @@ public abstract class CVSSubscriberAction extends SubscriberAction { }; } - protected abstract void run(SyncInfoSet syncSet, IProgressMonitor monitor) throws TeamException; - - /* - * Return the ICVSRunnableContext which will be used to run the operation. - */ - private ICVSRunnableContext getCVSRunnableContext() { - if (canRunAsJob() && areJobsEnabled()) { - return new CVSNonblockingRunnableContext() { - protected void schedule(Job job) { - IWorkbenchSite site = null; - IWorkbenchPart part = getTargetPart(); - if(part != null) { - site = part.getSite(); - } - SubscriberAction.schedule(job, site); - } - }; - } else { - return new CVSBlockingRunnableContext(shell); - } - } - - protected boolean areJobsEnabled() { - return true; - } - - /** - * Return the job name to be used if the action can run as a job. - * - * @param syncSet - * @return - */ - protected abstract String getJobName(SyncInfoSet syncSet); - - /** - * Return a scheduling rule that includes all resources that will be operated - * on by the subscriber action. The default behavior is to include all projects - * effected by the operation. Subclasses may override. - * - * @param syncSet - * @return - */ - protected ISchedulingRule getSchedulingRule(SyncInfoSet syncSet) { - IResource[] resources = syncSet.getResources(); - Set set = new HashSet(); - for (int i = 0; i < resources.length; i++) { - IResource resource = resources[i]; - set.add(resource.getProject()); - } - IProject[] projects = (IProject[]) set.toArray(new IProject[set.size()]); - if (projects.length == 1) { - return projects[0]; - } else { - return new MultiRule(projects); - } - } - protected boolean canRunAsJob() { return true; } - - /** - * Filter the sync resource set using action specific criteria or input from the user. - */ - protected SyncInfoSet getFilteredSyncInfoSet(SyncInfo[] selectedResources) { - // If there are conflicts or outgoing changes in the syncSet, we need to warn the user. - return new SyncInfoSet(selectedResources); - } protected void pruneEmptyParents(SyncInfo[] nodes) throws CVSException { // TODO: A more explicit tie in to the pruning mechanism would be prefereable. diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/MergeUpdateAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/MergeUpdateAction.java index f4fd80aba..7294626e8 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/MergeUpdateAction.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/MergeUpdateAction.java @@ -18,7 +18,7 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.core.TeamException; -import org.eclipse.team.core.subscribers.*; +import org.eclipse.team.core.subscribers.Subscriber; import org.eclipse.team.core.synchronize.*; import org.eclipse.team.core.synchronize.FastSyncInfoFilter.OrSyncInfoFilter; import org.eclipse.team.core.synchronize.FastSyncInfoFilter.SyncInfoDirectionFilter; diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/SubscriberCommitAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/SubscriberCommitAction.java index 6a375a51e..71050affd 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/SubscriberCommitAction.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/SubscriberCommitAction.java @@ -45,7 +45,7 @@ public class SubscriberCommitAction extends CVSSubscriberAction { * @see org.eclipse.team.internal.ccvs.ui.subscriber.CVSSubscriberAction#getFilteredSyncInfoSet(org.eclipse.team.internal.ui.sync.views.SyncInfo[]) */ protected SyncInfoSet getFilteredSyncInfoSet(SyncInfo[] selectedResources) { - SyncInfoSet syncSet = super.getFilteredSyncInfoSet(selectedResources); + SyncInfoSet syncSet = new SyncInfoSet(selectedResources); if (!promptForConflictHandling(syncSet)) return null; try { if (!promptForUnaddedHandling(syncSet)) return null; diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/WorkspaceUpdateAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/WorkspaceUpdateAction.java index 0ec55baf5..0a09dee12 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/WorkspaceUpdateAction.java +++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/WorkspaceUpdateAction.java @@ -94,5 +94,12 @@ public class WorkspaceUpdateAction extends SafeUpdateAction { */ protected void updated(IResource[] resources) throws TeamException { // Do nothing + } + + /* (non-Javadoc) + * @see org.eclipse.team.ui.synchronize.subscriber.SubscriberAction#getJobName(org.eclipse.team.core.synchronize.SyncInfoSet) + */ + protected String getJobName(SyncInfoSet syncSet) { + return null; } } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/Utils.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/Utils.java index 20b869000..2d1eb24af 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/Utils.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/Utils.java @@ -15,6 +15,8 @@ import java.util.*; import java.util.List; import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.structuremergeviewer.IDiffContainer; +import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.*; import org.eclipse.jface.action.IAction; @@ -429,4 +431,33 @@ public class Utils { } return (SyncInfo[]) result.toArray(new SyncInfo[result.size()]); } + + /** + * This method returns all out-of-sync SyncInfos that are in the current + * selection. + * + * @return the list of selected sync infos + */ + public static IDiffElement[] getDiffNodes(Object[] selected) { + Set result = new HashSet(); + for (int i = 0; i < selected.length; i++) { + Object object = selected[i]; + if(object instanceof IDiffElement) { + collectAllNodes((IDiffElement)object, result); + } + } + return (IDiffElement[]) result.toArray(new IDiffElement[result.size()]); + } + + private static void collectAllNodes(IDiffElement element, Set nodes) { + if(element.getKind() != SyncInfo.IN_SYNC) { + nodes.add(element); + } + if(element instanceof IDiffContainer) { + IDiffElement[] children = ((IDiffContainer)element).getChildren(); + for (int i = 0; i < children.length; i++) { + collectAllNodes(children[i], nodes); + } + } + } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ICVSRunnableContext.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/ITeamRunnableContext.java index 7e72aa83c..d3ba489f1 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ICVSRunnableContext.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/ITeamRunnableContext.java @@ -8,7 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ -package org.eclipse.team.internal.ccvs.ui.operations; +package org.eclipse.team.ui.synchronize.subscriber; import java.lang.reflect.InvocationTargetException; @@ -23,7 +23,7 @@ import org.eclipse.swt.widgets.Shell; * 2) whether the operation modifies the workspace * 3) what shell the operation should use to display info to the user */ -public interface ICVSRunnableContext { +public interface ITeamRunnableContext { /** * Run the given runnable in the context of the receiver. By default, the diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CVSNonblockingRunnableContext.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/JobRunnableContext.java index dc8ee0e79..e152147a3 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CVSNonblockingRunnableContext.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/JobRunnableContext.java @@ -8,37 +8,32 @@ * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ -package org.eclipse.team.internal.ccvs.ui.operations; +package org.eclipse.team.ui.synchronize.subscriber; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.resources.WorkspaceJob; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.IJobChangeListener; -import org.eclipse.core.runtime.jobs.ISchedulingRule; -import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.*; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; -import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.core.TeamException; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; /** * This runnable context executes it's operation in the context of a background job. */ -public class CVSNonblockingRunnableContext implements ICVSRunnableContext { +public class JobRunnableContext implements ITeamRunnableContext { private IJobChangeListener listener; - public CVSNonblockingRunnableContext() { + public JobRunnableContext() { this(null); } - public CVSNonblockingRunnableContext(IJobChangeListener listener) { + public JobRunnableContext(IJobChangeListener listener) { this.listener = listener; } @@ -46,7 +41,7 @@ public class CVSNonblockingRunnableContext implements ICVSRunnableContext { try { runnable.run(monitor); } catch (InvocationTargetException e) { - return CVSException.wrapException(e).getStatus(); + return TeamException.asTeamException(e).getStatus(); } catch (InterruptedException e) { return Status.OK_STATUS; } @@ -56,7 +51,7 @@ public class CVSNonblockingRunnableContext implements ICVSRunnableContext { protected Job getBasicJob(String title, final IRunnableWithProgress runnable) { return new Job(title) { public IStatus run(IProgressMonitor monitor) { - return CVSNonblockingRunnableContext.this.run(runnable, monitor); + return JobRunnableContext.this.run(runnable, monitor); } }; } @@ -64,13 +59,13 @@ public class CVSNonblockingRunnableContext implements ICVSRunnableContext { protected Job getWorkspaceJob(String title, final IRunnableWithProgress runnable) { return new WorkspaceJob(title) { public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { - return CVSNonblockingRunnableContext.this.run(runnable, monitor); + return JobRunnableContext.this.run(runnable, monitor); } }; } /* (non-Javadoc) - * @see org.eclipse.team.internal.ccvs.ui.operations.ICVSRunnableContext#run(java.lang.String, boolean, org.eclipse.jface.operation.IRunnableWithProgress) + * @see org.eclipse.team.internal.ccvs.ui.operations.ITeamRunnableContext#run(java.lang.String, boolean, org.eclipse.jface.operation.IRunnableWithProgress) */ public void run(String title, ISchedulingRule schedulingRule, boolean postponeBuild, IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException { Job job; @@ -93,7 +88,7 @@ public class CVSNonblockingRunnableContext implements ICVSRunnableContext { } /* (non-Javadoc) - * @see org.eclipse.team.internal.ccvs.ui.operations.ICVSRunnableContext#getShell() + * @see org.eclipse.team.internal.ccvs.ui.operations.ITeamRunnableContext#getShell() */ public Shell getShell() { final Shell[] newShell = new Shell[] { null }; diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CVSBlockingRunnableContext.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/ProgressDialogRunnableContext.java index a36b164df..c9cbfad6a 100644 --- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/CVSBlockingRunnableContext.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/ProgressDialogRunnableContext.java @@ -8,7 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ -package org.eclipse.team.internal.ccvs.ui.operations; +package org.eclipse.team.ui.synchronize.subscriber; import java.lang.reflect.InvocationTargetException; @@ -20,7 +20,7 @@ import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.widgets.Shell; -import org.eclipse.team.internal.ccvs.ui.Policy; +import org.eclipse.team.internal.ui.Policy; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.progress.IProgressService; @@ -28,12 +28,12 @@ import org.eclipse.ui.progress.IProgressService; * This CVS runnable context blocks the UI and can therfore have a shell assigned to * it (since the shell won't be closed by the user before the runnable completes. */ -public class CVSBlockingRunnableContext implements ICVSRunnableContext { +public class ProgressDialogRunnableContext implements ITeamRunnableContext { private Shell shell; private IRunnableContext runnableContext; - public CVSBlockingRunnableContext(Shell shell) { + public ProgressDialogRunnableContext(Shell shell) { this.shell = shell; } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/RefreshAction.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/RefreshAction.java index 7eeb49c61..62a1d1724 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/RefreshAction.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/RefreshAction.java @@ -69,6 +69,7 @@ public class RefreshAction extends Action { group.beginTask("Refreshing " + description, 100); job.setProgressGroup(group, 70); collector.setProgressGroup(group, 30); + SubscriberAction.schedule(job, site); job.addJobChangeListener(new JobChangeAdapter() { public void done(IJobChangeEvent event) { diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/SubscriberAction.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/SubscriberAction.java index d196dbd35..92d6beb99 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/SubscriberAction.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/subscriber/SubscriberAction.java @@ -10,32 +10,82 @@ *******************************************************************************/ package org.eclipse.team.ui.synchronize.subscriber; -import java.util.ArrayList; -import java.util.List; +import java.lang.reflect.InvocationTargetException; +import java.util.*; -import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.compare.structuremergeviewer.IDiffElement; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.jobs.*; import org.eclipse.jface.action.IAction; +import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.core.TeamException; -import org.eclipse.team.core.synchronize.FastSyncInfoFilter; -import org.eclipse.team.core.synchronize.SyncInfo; +import org.eclipse.team.core.synchronize.*; import org.eclipse.team.internal.ui.Utils; import org.eclipse.team.internal.ui.actions.TeamAction; +import org.eclipse.team.ui.synchronize.viewers.IBusyWorkbenchAdapter; import org.eclipse.team.ui.synchronize.viewers.SyncInfoDiffNode; import org.eclipse.ui.*; import org.eclipse.ui.progress.IWorkbenchSiteProgressService; /** - * This is an abstract superclass for actions associated with a - * {@link SubscriberParticipant}. It provides helper methods to - * access and filter selections that contain {@link ITeamSubscriberParticipantNode} - * instances. + * This action provides utilities for performing operations on diff elements + * contained in a selection. + * 1. provides scheduling action via workbench part (provide feedback via view) + * 2. provides selection filtering + * 3. provides support for running action in background or foreground + * 4. provides support for locking workspace resources + * 5. * <p> * It is optional for SubscriberParticipant actions to subclass. * </p> * @since 3.0 */ public abstract class SubscriberAction extends TeamAction implements IViewActionDelegate, IEditorActionDelegate { + + private IDiffElement[] filteredDiffElements = null; + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) + */ + public final void run(IAction action) { + // TODO: Saving can change the sync state! How should this be handled? + // boolean result = saveIfNecessary(); + // if (!result) return null; + SyncInfoSet syncSet = new SyncInfoSet(getFilteredSyncInfos()); + if (syncSet == null || syncSet.isEmpty()) return; + try { + getRunnableContext().run(getJobName(syncSet), getSchedulingRule(syncSet), true, getRunnable(syncSet)); + } catch (InvocationTargetException e) { + handle(e); + } catch (InterruptedException e) { + // nothing to do; + } + } + + /** + * Return the job name to be used if the action can run as a job. + * + * @param syncSet + * @return + */ + protected abstract String getJobName(SyncInfoSet syncSet); + + /** + * Subsclasses must override to provide behavior for the action. + * @param syncSet the set of filtered sync info objects on which to perform the action. + * @param monitor a progress monitor, or <code>null</code> if progress + * reporting and cancellation are not desired + * @throws TeamException if something went wrong running the action + */ + protected abstract void run(SyncInfoSet syncSet, IProgressMonitor monitor) throws TeamException; + + protected void handle(Exception e) { + Utils.handle(e); + } /** * This method returns all instances of SyncInfo that are in the current @@ -44,8 +94,8 @@ public abstract class SubscriberAction extends TeamAction implements IViewAction * * @return the selected resources */ - protected SyncInfo[] getSyncInfos() { - return Utils.getSyncInfos(((IStructuredSelection)selection).toArray()); + protected IDiffElement[] getDiffElements() { + return Utils.getDiffNodes(((IStructuredSelection)selection).toArray()); } /** @@ -56,36 +106,52 @@ public abstract class SubscriberAction extends TeamAction implements IViewAction * @see org.eclipse.team.internal.ui.actions.TeamAction#isEnabled() */ protected boolean isEnabled() throws TeamException { - return (getFilteredSyncInfos().length > 0); + return (getFilteredDiffElements().length > 0); } /** - * Return true if the action should be enabled for the given SyncInfo. - * Default behavior is to use a SyncInfoFilter to determine if the action - * is enabled. - * - * @param info - * @return + * Default filter includes all out-of-sync elements in the current + * selection. + * @return a sync info filter which selects all out-of-sync resources. */ - protected boolean select(SyncInfo info) { - return info != null && getSyncInfoFilter().select(info); - } - protected FastSyncInfoFilter getSyncInfoFilter() { return new FastSyncInfoFilter(); } /** + * Return the selected diff element for which this action is enabled. + * @return the list of selected diff elements for which this action is enabled. + */ + protected IDiffElement[] getFilteredDiffElements() { + if (filteredDiffElements == null) { + IDiffElement[] elements = getDiffElements(); + List filtered = new ArrayList(); + for (int i = 0; i < elements.length; i++) { + IDiffElement e = elements[i]; + if (e instanceof SyncInfoDiffNode) { + SyncInfo info = ((SyncInfoDiffNode) e).getSyncInfo(); + if (info != null && getSyncInfoFilter().select(info)) { + filtered.add(e); + } + } + } + filteredDiffElements = (IDiffElement[]) filtered.toArray(new IDiffElement[filtered.size()]); + } + return filteredDiffElements; + } + + /** * Return the selected SyncInfo for which this action is enabled. - * @return + * @return the selected SyncInfo for which this action is enabled. */ protected SyncInfo[] getFilteredSyncInfos() { - SyncInfo[] infos = getSyncInfos(); + IDiffElement[] elements = getFilteredDiffElements(); List filtered = new ArrayList(); - for (int i = 0; i < infos.length; i++) { - SyncInfo info = infos[i]; - if (select(info)) - filtered.add(info); + for (int i = 0; i < elements.length; i++) { + IDiffElement e = elements[i]; + if (e instanceof SyncInfoDiffNode) { + filtered.add(((SyncInfoDiffNode)e).getSyncInfo()); + } } return (SyncInfo[]) filtered.toArray(new SyncInfo[filtered.size()]); } @@ -96,11 +162,16 @@ public abstract class SubscriberAction extends TeamAction implements IViewAction public void setActiveEditor(IAction action, IEditorPart targetEditor) { setActivePart(action, targetEditor); } - - public void updateWorkingState(SyncInfoDiffNode[] nodes, boolean working) { - for (int i = 0; i < nodes.length; i++) { - SyncInfoDiffNode node = nodes[i]; - node.setWorking(working); + + public void markBusy(IDiffElement[] elements, boolean isBusy) { + for (int i = 0; i < elements.length; i++) { + IDiffElement e = elements[i]; + if(e instanceof IAdaptable) { + IBusyWorkbenchAdapter busyAdapter = (IBusyWorkbenchAdapter) ((IAdaptable)e).getAdapter(IBusyWorkbenchAdapter.class); + if(busyAdapter != null) { + busyAdapter.setBusy(e, isBusy); + } + } } } @@ -114,4 +185,72 @@ public abstract class SubscriberAction extends TeamAction implements IViewAction } job.schedule(); } + + /* + * Return the ITeamRunnableContext which will be used to run the operation. + */ + private ITeamRunnableContext getRunnableContext() { + if (canRunAsJob()) { + // mark resources that will be affected by job + markBusy(getFilteredDiffElements(), true); + // register to unmark when job is finished + IJobChangeListener listener = new JobChangeAdapter() { + public void done(IJobChangeEvent event) { + markBusy(getFilteredDiffElements(), false); + } + }; + return new JobRunnableContext(listener) { + // schedule via view + protected void schedule(Job job) { + IWorkbenchSite site = null; + IWorkbenchPart part = getTargetPart(); + if(part != null) { + site = part.getSite(); + } + SubscriberAction.schedule(job, site); + } + }; + } else { + return new ProgressDialogRunnableContext(shell); + } + } + + protected boolean canRunAsJob() { + return false; + } + + /** + * Return a scheduling rule that includes all resources that will be operated + * on by the subscriber action. The default behavior is to include all projects + * effected by the operation. Subclasses may override. + * + * @param syncSet + * @return + */ + protected ISchedulingRule getSchedulingRule(SyncInfoSet syncSet) { + IResource[] resources = syncSet.getResources(); + Set set = new HashSet(); + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + set.add(resource.getProject()); + } + IProject[] projects = (IProject[]) set.toArray(new IProject[set.size()]); + if (projects.length == 1) { + return projects[0]; + } else { + return new MultiRule(projects); + } + } + + public IRunnableWithProgress getRunnable(final SyncInfoSet syncSet) { + return new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + try { + SubscriberAction.this.run(syncSet, monitor); + } catch (TeamException e) { + throw new InvocationTargetException(e); + } + } + }; + } } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/IBusyWorkbenchAdapter.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/IBusyWorkbenchAdapter.java new file mode 100644 index 000000000..960b2926f --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/IBusyWorkbenchAdapter.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.ui.synchronize.viewers; + +public interface IBusyWorkbenchAdapter { + public void setBusy(Object element, boolean isBusy); + public boolean isBusy(Object element); +} diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoDiffNode.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoDiffNode.java index ec6f018cc..080cf4861 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoDiffNode.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoDiffNode.java @@ -20,10 +20,12 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.*; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.synchronize.*; import org.eclipse.team.internal.core.Assert; import org.eclipse.team.internal.ui.Policy; +import org.eclipse.team.internal.ui.TeamUIPlugin; import org.eclipse.team.internal.ui.synchronize.compare.LocalResourceTypedElement; import org.eclipse.team.internal.ui.synchronize.compare.RemoteResourceTypedElement; import org.eclipse.ui.model.IWorkbenchAdapter; @@ -45,13 +47,19 @@ import org.eclipse.ui.model.IWorkbenchAdapter; * @see DiffTreeViewer * @see Differencer */ -public class SyncInfoDiffNode extends DiffNode implements IAdaptable, IWorkbenchAdapter { +public class SyncInfoDiffNode extends DiffNode implements IAdaptable, IWorkbenchAdapter, IBusyWorkbenchAdapter { private SyncInfoTree syncSet; private IResource resource; private Set workingChildren = new HashSet(); - private boolean working = false; + private boolean nodeIsBusy = false; + private ListenerList listeners; + + /** + * Property constant indicating the mode of a page has changed. + */ + public static final String P_BUSY_ELEMENT = TeamUIPlugin.ID + ".P_NODE_ISBUSY"; //$NON-NLS-1$ /** * Create an ITypedElement for the given local resource. The returned ITypedElement @@ -174,6 +182,8 @@ public class SyncInfoDiffNode extends DiffNode implements IAdaptable, IWorkbench public Object getAdapter(Class adapter) { if(adapter == IWorkbenchAdapter.class) { return this; + } else if(adapter == IBusyWorkbenchAdapter.class) { + return this; } return null; } @@ -261,12 +271,12 @@ public class SyncInfoDiffNode extends DiffNode implements IAdaptable, IWorkbench /** Track nodes that are being worked on **/ - public boolean isWorking() { - return working || ! workingChildren.isEmpty(); + public boolean isBusy(Object element) { + return nodeIsBusy || ! workingChildren.isEmpty(); } - public void setWorking(boolean working) { - this.working = working; + public void setBusy(Object element, boolean isBusy) { + this.nodeIsBusy = isBusy; IDiffContainer parent = getParent(); while (parent != null) { if(parent instanceof SyncInfoDiffNode) { @@ -274,15 +284,55 @@ public class SyncInfoDiffNode extends DiffNode implements IAdaptable, IWorkbench } parent = parent.getParent(); } + fireChange(P_BUSY_ELEMENT); } public void updateWorkingChild(SyncInfoDiffNode node) { - if(node.isWorking()) { + if(node.isBusy(node)) { workingChildren.add(node); } else { workingChildren.remove(node); } } + + /** + * Registers a listener for changes of this <code>ICompareInput</code>. + * Has no effect if an identical listener is already registered. + * + * @param listener the listener to add + */ + public void addPropertyChangeListener(IPropertyChangeListener listener) { + if (listeners == null) + listeners= new ListenerList(); + listeners.add(listener); + } + + /** + * Unregisters a <code>ICompareInput</code> listener. + * Has no effect if listener is not registered. + * + * @param listener the listener to remove + */ + public void removePropertyInputChangeListener(IPropertyChangeListener listener) { + if (listeners != null) { + listeners.remove(listener); + if (listeners.isEmpty()) + listeners= null; + } + } + + /** + * Sends out notification that a change has occured on the <code>ICompareInput</code>. + */ + protected void fireChange(String property) { + if (listeners != null) { + Object[] l= listeners.getListeners(); + for (int i= 0; i < l.length; i++) { + PropertyChangeEvent event = new PropertyChangeEvent(this, property, null, null); + ((IPropertyChangeListener) l[i]).propertyChange(event); + } + } + } /** WorkbenchAdapter methods **/ diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoLabelProvider.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoLabelProvider.java index 57871f68d..a8efa5323 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoLabelProvider.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoLabelProvider.java @@ -115,7 +115,7 @@ public class SyncInfoLabelProvider extends LabelProvider implements IColorProvid public Color getForeground(Object element) { if (element instanceof SyncInfoDiffNode) { SyncInfoDiffNode node = (SyncInfoDiffNode)element; - if(node.isWorking()) { + if(node.isBusy(node)) { return WorkbenchColors.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW); } } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoSetViewerInput.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoSetViewerInput.java index b0187edd5..e0b9e956b 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoSetViewerInput.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoSetViewerInput.java @@ -17,6 +17,8 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.swt.custom.BusyIndicator; @@ -42,7 +44,7 @@ import org.eclipse.team.internal.ui.TeamUIPlugin; * * @since 3.0 */ -public class SyncInfoSetViewerInput extends SyncInfoDiffNode implements ISyncInfoSetChangeListener { +public class SyncInfoSetViewerInput extends SyncInfoDiffNode implements ISyncInfoSetChangeListener, IPropertyChangeListener { // During updates we keep track of the parent elements that need their // labels updated. This is required to support displaying information in a @@ -199,6 +201,7 @@ public class SyncInfoSetViewerInput extends SyncInfoDiffNode implements ISyncInf protected SyncInfoDiffNode createModelObject(DiffNode parent, IResource resource) { SyncInfoTree set = parent instanceof SyncInfoDiffNode ? ((SyncInfoDiffNode) parent).getSyncInfoTree() : getSyncInfoTree(); SyncInfoDiffNode node = new SyncInfoDiffNode(parent, set, resource); + node.addPropertyChangeListener(this); addToViewer(node); return node; } @@ -455,4 +458,33 @@ public class SyncInfoSetViewerInput extends SyncInfoDiffNode implements ISyncInf public void syncInfoSetErrors(SyncInfoSet set, ITeamStatus[] errors, IProgressMonitor monitor) { // TODO Auto-generated method stub } + + /* (non-Javadoc) + * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + String prop = event.getProperty(); + if(prop.equals(SyncInfoDiffNode.P_BUSY_ELEMENT)) { + List labelUpdates = new ArrayList(); + SyncInfoDiffNode node = (SyncInfoDiffNode)event.getSource(); + boolean isBusy = node.isBusy(node); + labelUpdates.add(node); + IDiffContainer parent = node.getParent(); + while (parent != null) { + if(parent instanceof IBusyWorkbenchAdapter) { + IBusyWorkbenchAdapter busy = (IBusyWorkbenchAdapter)parent; + if(busy.isBusy(busy) != isBusy) { + labelUpdates.add(parent); + } + } + parent = parent.getParent(); + } + + // update labels + if (canUpdateViewer()) { + AbstractTreeViewer tree = getTreeViewer(); + tree.update(labelUpdates.toArray(new Object[labelUpdates.size()]), null); + } + } + } } diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/HeadlessCVSRunnableContext.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/HeadlessCVSRunnableContext.java index b36f43c8b..da0db8944 100644 --- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/HeadlessCVSRunnableContext.java +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/ui/HeadlessCVSRunnableContext.java @@ -17,10 +17,10 @@ import org.eclipse.core.runtime.jobs.IJobChangeListener; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.widgets.Shell; -import org.eclipse.team.internal.ccvs.ui.operations.CVSNonblockingRunnableContext; -import org.eclipse.team.internal.ccvs.ui.operations.ICVSRunnableContext; +import org.eclipse.team.ui.synchronize.subscriber.JobRunnableContext; +import org.eclipse.team.ui.synchronize.subscriber.ITeamRunnableContext; -public class HeadlessCVSRunnableContext implements ICVSRunnableContext { +public class HeadlessCVSRunnableContext implements ITeamRunnableContext { private boolean background; private IJobChangeListener listener; @@ -34,7 +34,7 @@ public class HeadlessCVSRunnableContext implements ICVSRunnableContext { } /* (non-Javadoc) - * @see org.eclipse.team.internal.ccvs.ui.operations.ICVSRunnableContext#run(java.lang.String, org.eclipse.core.runtime.jobs.ISchedulingRule, org.eclipse.jface.operation.IRunnableWithProgress) + * @see org.eclipse.team.internal.ccvs.ui.operations.ITeamRunnableContext#run(java.lang.String, org.eclipse.core.runtime.jobs.ISchedulingRule, org.eclipse.jface.operation.IRunnableWithProgress) */ public void run( String title, @@ -43,14 +43,14 @@ public class HeadlessCVSRunnableContext implements ICVSRunnableContext { throws InvocationTargetException, InterruptedException { if (listener != null) { - new CVSNonblockingRunnableContext(listener).run("Headless Job", null, true, runnable); + new JobRunnableContext(listener).run("Headless Job", null, true, runnable); } else { runnable.run(new NullProgressMonitor()); } } /* (non-Javadoc) - * @see org.eclipse.team.internal.ccvs.ui.operations.ICVSRunnableContext#getShell() + * @see org.eclipse.team.internal.ccvs.ui.operations.ITeamRunnableContext#getShell() */ public Shell getShell() { return null; |