Java tutorial
/******************************************************************************* * Copyright (c) 2006, 2012 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.*; import java.util.List; import org.eclipse.core.resources.mapping.*; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.jobs.*; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.preference.PreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.eclipse.team.core.diff.*; import org.eclipse.team.core.mapping.ISynchronizationContext; import org.eclipse.team.core.mapping.ISynchronizationScope; import org.eclipse.team.internal.core.subscribers.SubscriberDiffTreeEventHandler; import org.eclipse.team.internal.ui.*; import org.eclipse.team.internal.ui.synchronize.*; import org.eclipse.team.ui.ISharedImages; import org.eclipse.team.ui.TeamUI; import org.eclipse.team.ui.mapping.*; import org.eclipse.team.ui.synchronize.*; import org.eclipse.ui.forms.events.HyperlinkAdapter; import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.Hyperlink; public class DiffTreeChangesSection extends ForwardingChangesSection implements IDiffChangeListener, IPropertyChangeListener, IEmptyTreeListener { private ISynchronizationContext context; private IStatus[] errors; private boolean showingError; private JobChangeAdapter jobChangeListener; public interface ITraversalFactory { ResourceTraversal[] getTraversals(ISynchronizationScope scope); } public DiffTreeChangesSection(Composite parent, AbstractSynchronizePage page, ISynchronizePageConfiguration configuration) { super(parent, page, configuration); context = (ISynchronizationContext) configuration .getProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_CONTEXT); context.getDiffTree().addDiffChangeListener(this); getConfiguration().addPropertyChangeListener(this); jobChangeListener = new JobChangeAdapter() { public void running(IJobChangeEvent event) { if (isJobOfInterest(event.getJob())) { if (context.getDiffTree().isEmpty()) calculateDescription(); } } private boolean isJobOfInterest(Job job) { if (job.belongsTo(getConfiguration().getParticipant())) return true; SubscriberDiffTreeEventHandler handler = getHandler(); if (handler != null && handler.getEventHandlerJob() == job) return true; return false; } public void done(IJobChangeEvent event) { if (isJobOfInterest(event.getJob())) { if (context.getDiffTree().isEmpty()) calculateDescription(); } } }; Job.getJobManager().addJobChangeListener(jobChangeListener); } public void dispose() { context.getDiffTree().removeDiffChangeListener(this); getConfiguration().removePropertyChangeListener(this); Job.getJobManager().removeJobChangeListener(jobChangeListener); super.dispose(); } protected int getChangesCount() { return context.getDiffTree().size(); } protected long getChangesInMode(int candidateMode) { long numChanges; long numConflicts = context.getDiffTree().countFor(IThreeWayDiff.CONFLICTING, IThreeWayDiff.DIRECTION_MASK); switch (candidateMode) { case ISynchronizePageConfiguration.CONFLICTING_MODE: numChanges = numConflicts; break; case ISynchronizePageConfiguration.OUTGOING_MODE: numChanges = numConflicts + context.getDiffTree().countFor(IThreeWayDiff.OUTGOING, IThreeWayDiff.DIRECTION_MASK); break; case ISynchronizePageConfiguration.INCOMING_MODE: numChanges = numConflicts + context.getDiffTree().countFor(IThreeWayDiff.INCOMING, IThreeWayDiff.DIRECTION_MASK); break; case ISynchronizePageConfiguration.BOTH_MODE: numChanges = numConflicts + context.getDiffTree().countFor(IThreeWayDiff.INCOMING, IThreeWayDiff.DIRECTION_MASK) + context.getDiffTree().countFor(IThreeWayDiff.OUTGOING, IThreeWayDiff.DIRECTION_MASK); break; default: numChanges = 0; break; } return numChanges; } protected boolean hasChangesInMode(String id, ISynchronizationCompareAdapter adapter, int candidateMode) { switch (candidateMode) { case ISynchronizePageConfiguration.CONFLICTING_MODE: return hasChangesFor(id, adapter, context, new int[] { IThreeWayDiff.CONFLICTING }, IThreeWayDiff.DIRECTION_MASK); case ISynchronizePageConfiguration.OUTGOING_MODE: return hasChangesFor(id, adapter, context, new int[] { IThreeWayDiff.CONFLICTING, IThreeWayDiff.OUTGOING }, IThreeWayDiff.DIRECTION_MASK); case ISynchronizePageConfiguration.INCOMING_MODE: return hasChangesFor(id, adapter, context, new int[] { IThreeWayDiff.CONFLICTING, IThreeWayDiff.INCOMING }, IThreeWayDiff.DIRECTION_MASK); case ISynchronizePageConfiguration.BOTH_MODE: return hasChangesFor(id, adapter, context, new int[] { IThreeWayDiff.CONFLICTING, IThreeWayDiff.INCOMING, IThreeWayDiff.OUTGOING }, IThreeWayDiff.DIRECTION_MASK); } return false; } private boolean hasChangesFor(String id, ISynchronizationCompareAdapter adapter, ISynchronizationContext context, int[] states, int mask) { ITraversalFactory factory = (ITraversalFactory) Utils.getAdapter(adapter, ITraversalFactory.class); ResourceTraversal[] traversals; if (factory == null) { traversals = context.getScope().getTraversals(id); } else { traversals = factory.getTraversals(context.getScope()); } return (context.getDiffTree().hasMatchingDiffs(traversals, FastDiffFilter.getStateFilter(states, mask))); } protected long getVisibleChangesCount() { ISynchronizePageConfiguration configuration = getConfiguration(); if (configuration.getComparisonType() == ISynchronizePageConfiguration.TWO_WAY) { return context.getDiffTree().size(); } int currentMode = configuration.getMode(); String id = (String) configuration.getProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER); if (id != null && !id.equals(ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE)) { try { IModelProviderDescriptor desc = ModelProvider.getModelProviderDescriptor(id); ISynchronizationCompareAdapter adapter = Utils.getCompareAdapter(desc.getModelProvider()); if (adapter != null) { return hasChangesInMode(desc.getId(), adapter, getConfiguration().getMode()) ? -1 : 0; } } catch (CoreException e) { TeamUIPlugin.log(e); } // Use the view state to indicate whether there are visible changes return isViewerEmpty() ? 0 : -1; } return getChangesInMode(currentMode); } protected int getCandidateMode() { SynchronizePageConfiguration configuration = (SynchronizePageConfiguration) getConfiguration(); long outgoingChanges = context.getDiffTree().countFor(IThreeWayDiff.OUTGOING, IThreeWayDiff.DIRECTION_MASK); if (outgoingChanges > 0) { if (configuration.isModeSupported(ISynchronizePageConfiguration.OUTGOING_MODE)) { return ISynchronizePageConfiguration.OUTGOING_MODE; } if (configuration.isModeSupported(ISynchronizePageConfiguration.BOTH_MODE)) { return ISynchronizePageConfiguration.BOTH_MODE; } } long incomingChanges = context.getDiffTree().countFor(IThreeWayDiff.INCOMING, IThreeWayDiff.DIRECTION_MASK); if (incomingChanges > 0) { if (configuration.isModeSupported(ISynchronizePageConfiguration.INCOMING_MODE)) { return ISynchronizePageConfiguration.INCOMING_MODE; } if (configuration.isModeSupported(ISynchronizePageConfiguration.BOTH_MODE)) { return ISynchronizePageConfiguration.BOTH_MODE; } } return configuration.getMode(); } public void diffsChanged(IDiffChangeEvent event, IProgressMonitor monitor) { IStatus[] errors = event.getErrors(); if (errors.length > 0) { this.errors = errors; } calculateDescription(); } /* (non-Javadoc) * @see org.eclipse.team.core.diff.IDiffChangeListener#propertyChanged(int, org.eclipse.core.runtime.IPath[]) */ public void propertyChanged(IDiffTree tree, int property, IPath[] paths) { // Do nothing } public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(ISynchronizePageConfiguration.P_MODE) || event.getProperty().equals(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER)) { calculateDescription(); } } protected Composite getEmptyChangesComposite(Composite parent) { if (context.getDiffTree().isEmpty()) { SubscriberDiffTreeEventHandler handler = getHandler(); if (handler != null && handler.getState() == SubscriberDiffTreeEventHandler.STATE_STARTED) { // The context has not been initialized yet return getInitializationPane(parent); } if (isRefreshRunning() || (handler != null && handler.getEventHandlerJob().getState() != Job.NONE)) { return getInitializingMessagePane(parent); } } else { ISynchronizePageConfiguration configuration = getConfiguration(); String id = (String) configuration.getProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER); if (id == null) id = ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER; if (id.equals(ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE)) { if (getChangesInMode(getConfiguration().getMode()) > 0 && isAtLeastOneProviderDisabled()) { // There are changes in this mode but they are not visible so enable // all providers return createEnableParticipantModelProvidersPane(parent); } } else { // A particular model is active so we need to look for a model that has changes in this // same mode before offering to change modes. ModelProvider[] providers = findModelsWithChangesInMode(getConfiguration().getMode()); ModelProvider currentProvider = null; for (int i = 0; i < providers.length; i++) { ModelProvider provider = providers[i]; if (isEnabled(provider)) { if (provider.getDescriptor().getId().equals(id)) { currentProvider = provider; } else { return getPointerToModel(parent, provider, id); } } } if (currentProvider != null || providers.length > 0) { // The current provider has changes but the view is empty // or there is a disabled provider with changes // This is an error so offer to enable and show all models return createEnableParticipantModelProvidersPane(parent); } } } return super.getEmptyChangesComposite(parent); } private boolean isAtLeastOneProviderDisabled() { ModelProvider[] providers = findModelsWithChangesInMode(getConfiguration().getMode()); for (int i = 0; i < providers.length; i++) { ModelProvider provider = providers[i]; if (!isEnabled(provider)) { return true; } } return false; } private ModelProvider[] findModelsWithChangesInMode(int mode) { ModelProvider[] providers = context.getScope().getModelProviders(); providers = ModelOperation.sortByExtension(providers); List result = new ArrayList(); for (int i = 0; i < providers.length; i++) { ModelProvider provider = providers[i]; ISynchronizationCompareAdapter adapter = Utils.getCompareAdapter(provider); if (adapter != null) { boolean hasChanges = hasChangesInMode(provider.getId(), adapter, getConfiguration().getMode()); if (hasChanges) { result.add(provider); } } } return (ModelProvider[]) result.toArray(new ModelProvider[result.size()]); } private boolean isEnabled(ModelProvider provider) { ITeamContentProviderDescriptor desc = TeamUI.getTeamContentProviderManager() .getDescriptor(provider.getId()); return (desc != null && desc.isEnabled()); } private Composite createEnableParticipantModelProvidersPane(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setBackground(getListBackgroundColor()); GridLayout layout = new GridLayout(); layout.numColumns = 2; composite.setLayout(layout); GridData data = new GridData(GridData.FILL_BOTH); data.grabExcessVerticalSpace = true; composite.setLayoutData(data); String message; int changesCount = getChangesCount(); if (changesCount == 1) { message = TeamUIMessages.DiffTreeChangesSection_8; } else { message = NLS.bind(TeamUIMessages.DiffTreeChangesSection_9, new Integer(changesCount)); } final ITeamContentProviderDescriptor[] descriptors = getEnabledContentDescriptors(); if (descriptors.length == 0) message = NLS.bind(TeamUIMessages.DiffTreeChangesSection_10, message); else message = NLS.bind(TeamUIMessages.DiffTreeChangesSection_11, message); createDescriptionLabel(composite, message); Label warning = new Label(composite, SWT.NONE); warning.setImage(TeamUIPlugin.getPlugin().getImage(ISharedImages.IMG_WARNING_OVR)); Hyperlink link = getForms().createHyperlink(composite, TeamUIMessages.DiffTreeChangesSection_12, SWT.WRAP); link.addHyperlinkListener(new HyperlinkAdapter() { public void linkActivated(HyperlinkEvent e) { ModelSynchronizeParticipant participant = (ModelSynchronizeParticipant) getConfiguration() .getParticipant(); ModelProvider[] providers = participant.getEnabledModelProviders(); Set toEnable = new HashSet(); toEnable.addAll(Arrays.asList(descriptors)); for (int i = 0; i < providers.length; i++) { ModelProvider provider = providers[i]; ITeamContentProviderDescriptor desc = TeamUI.getTeamContentProviderManager() .getDescriptor(provider.getId()); if (desc != null && !desc.isEnabled()) { toEnable.add(desc); } } TeamUI.getTeamContentProviderManager() .setEnabledDescriptors((ITeamContentProviderDescriptor[]) toEnable .toArray(new ITeamContentProviderDescriptor[toEnable.size()])); getConfiguration().setProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER, ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE); } }); getForms().getHyperlinkGroup().add(link); return composite; } private ITeamContentProviderDescriptor[] getEnabledContentDescriptors() { ModelSynchronizeParticipant participant = (ModelSynchronizeParticipant) getConfiguration().getParticipant(); ModelProvider[] providers = participant.getEnabledModelProviders(); Set result = new HashSet(); for (int i = 0; i < providers.length; i++) { ModelProvider provider = providers[i]; ITeamContentProviderDescriptor desc = TeamUI.getTeamContentProviderManager() .getDescriptor(provider.getId()); if (desc != null && desc.isEnabled()) result.add(desc); } return (ITeamContentProviderDescriptor[]) result.toArray(new ITeamContentProviderDescriptor[result.size()]); } private Composite getInitializationPane(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setBackground(getListBackgroundColor()); GridLayout layout = new GridLayout(); layout.numColumns = 2; composite.setLayout(layout); GridData data = new GridData(GridData.FILL_BOTH); data.grabExcessVerticalSpace = true; composite.setLayoutData(data); createDescriptionLabel(composite, NLS.bind(TeamUIMessages.DiffTreeChangesSection_3, new String[] { Utils .shortenText(SynchronizeView.MAX_NAME_LENGTH, getConfiguration().getParticipant().getName()) })); final boolean[] remember = new boolean[] { false }; final PreferenceStore store = (PreferenceStore) getConfiguration() .getProperty(StartupPreferencePage.STARTUP_PREFERENCES); Hyperlink link = getForms().createHyperlink(composite, TeamUIMessages.DiffTreeChangesSection_4, SWT.WRAP); link.addHyperlinkListener(new HyperlinkAdapter() { public void linkActivated(HyperlinkEvent e) { if (remember[0] && store != null) { store.putValue(StartupPreferencePage.PROP_STARTUP_ACTION, StartupPreferencePage.STARTUP_ACTION_POPULATE); } getHandler().initializeIfNeeded(); } }); getForms().getHyperlinkGroup().add(link); link = getForms().createHyperlink(composite, TeamUIMessages.DiffTreeChangesSection_5, SWT.WRAP); link.addHyperlinkListener(new HyperlinkAdapter() { public void linkActivated(HyperlinkEvent e) { if (remember[0] && store != null) { store.putValue(StartupPreferencePage.PROP_STARTUP_ACTION, StartupPreferencePage.STARTUP_ACTION_SYNCHRONIZE); } getConfiguration().getParticipant().run(getConfiguration().getSite().getPart()); } }); getForms().getHyperlinkGroup().add(link); if (store != null) { final Button rememberButton = getForms().createButton(composite, TeamUIMessages.DiffTreeChangesSection_14, SWT.CHECK); rememberButton.setToolTipText(TeamUIMessages.DiffTreeChangesSection_14); data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = 2; data.horizontalIndent = 5; data.verticalIndent = 5; data.widthHint = 100; rememberButton.setLayoutData(data); rememberButton.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { remember[0] = rememberButton.getSelection(); } public void widgetDefaultSelected(SelectionEvent e) { // Do nothing } }); } return composite; } private Composite getInitializingMessagePane(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setBackground(getListBackgroundColor()); GridLayout layout = new GridLayout(); layout.numColumns = 2; composite.setLayout(layout); GridData data = new GridData(GridData.FILL_BOTH); data.grabExcessVerticalSpace = true; composite.setLayoutData(data); if (isRefreshRunning()) { createDescriptionLabel(composite, NLS.bind(TeamUIMessages.DiffTreeChangesSection_6, new String[] { Utils.shortenText(SynchronizeView.MAX_NAME_LENGTH, getConfiguration().getParticipant().getName()) })); } else { createDescriptionLabel(composite, NLS.bind(TeamUIMessages.DiffTreeChangesSection_7, new String[] { Utils.shortenText(SynchronizeView.MAX_NAME_LENGTH, getConfiguration().getParticipant().getName()) })); } return composite; } private boolean isRefreshRunning() { return Job.getJobManager().find(getConfiguration().getParticipant()).length > 0; } private SubscriberDiffTreeEventHandler getHandler() { return (SubscriberDiffTreeEventHandler) Utils.getAdapter(context, SubscriberDiffTreeEventHandler.class); } private Composite getPointerToModel(Composite parent, final ModelProvider provider, String oldId) { Composite composite = new Composite(parent, SWT.NONE); composite.setBackground(getListBackgroundColor()); GridLayout layout = new GridLayout(); layout.numColumns = 2; composite.setLayout(layout); GridData data = new GridData(GridData.FILL_BOTH); data.grabExcessVerticalSpace = true; composite.setLayoutData(data); IModelProviderDescriptor oldDesc = ModelProvider.getModelProviderDescriptor(oldId); String message; String modeToString = Utils.modeToString(getConfiguration().getMode()); message = NLS.bind(TeamUIMessages.DiffTreeChangesSection_0, new String[] { provider.getDescriptor().getLabel(), modeToString }); message = NLS.bind(TeamUIMessages.DiffTreeChangesSection_1, new String[] { modeToString, oldDesc.getLabel(), message }); createDescriptionLabel(composite, message); Label warning = new Label(composite, SWT.NONE); warning.setImage(TeamUIPlugin.getPlugin().getImage(ISharedImages.IMG_WARNING_OVR)); Hyperlink link = getForms().createHyperlink(composite, NLS.bind(TeamUIMessages.DiffTreeChangesSection_2, new String[] { provider.getDescriptor().getLabel() }), SWT.WRAP); link.addHyperlinkListener(new HyperlinkAdapter() { public void linkActivated(HyperlinkEvent e) { getConfiguration().setProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER, provider.getDescriptor().getId()); } }); getForms().getHyperlinkGroup().add(link); new Label(composite, SWT.NONE); Hyperlink link2 = getForms().createHyperlink(composite, TeamUIMessages.DiffTreeChangesSection_13, SWT.WRAP); link2.addHyperlinkListener(new HyperlinkAdapter() { public void linkActivated(HyperlinkEvent e) { getConfiguration().setProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER, ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE); } }); getForms().getHyperlinkGroup().add(link2); return composite; } public void treeEmpty(TreeViewer viewer) { handleEmptyViewer(); } private void handleEmptyViewer() { // Override stand behavior to do our best to show something TeamUIPlugin.getStandardDisplay().asyncExec(new Runnable() { public void run() { if (!getContainer().isDisposed()) updatePage(getEmptyChangesComposite(getContainer())); } }); } protected void calculateDescription() { if (errors != null && errors.length > 0) { if (!showingError) { TeamUIPlugin.getStandardDisplay().asyncExec(new Runnable() { public void run() { updatePage(getErrorComposite(getContainer())); showingError = true; } }); } return; } showingError = false; if (isViewerEmpty()) { handleEmptyViewer(); } else { super.calculateDescription(); } } private boolean isViewerEmpty() { Viewer v = getPage().getViewer(); if (v instanceof CommonViewerAdvisor.NavigableCommonViewer) { CommonViewerAdvisor.NavigableCommonViewer cv = (CommonViewerAdvisor.NavigableCommonViewer) v; return cv.isEmpty(); } return false; } public void notEmpty(TreeViewer viewer) { calculateDescription(); } private Composite getErrorComposite(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setBackground(getListBackgroundColor()); GridLayout layout = new GridLayout(); layout.numColumns = 2; composite.setLayout(layout); GridData data = new GridData(GridData.FILL_BOTH); data.grabExcessVerticalSpace = true; composite.setLayoutData(data); createDescriptionLabel(composite, NLS.bind(TeamUIMessages.ChangesSection_10, new String[] { Utils .shortenText(SynchronizeView.MAX_NAME_LENGTH, getConfiguration().getParticipant().getName()) })); Hyperlink link = getForms().createHyperlink(composite, TeamUIMessages.ChangesSection_8, SWT.WRAP); link.addHyperlinkListener(new HyperlinkAdapter() { public void linkActivated(HyperlinkEvent e) { showErrors(); } }); getForms().getHyperlinkGroup().add(link); link = getForms().createHyperlink(composite, TeamUIMessages.ChangesSection_9, SWT.WRAP); link.addHyperlinkListener(new HyperlinkAdapter() { public void linkActivated(HyperlinkEvent e) { errors = null; calculateDescription(); SubscriberDiffTreeEventHandler handler = getHandler(); if (handler != null) handler.initializeIfNeeded(); else getConfiguration().getParticipant().run(getConfiguration().getSite().getPart()); } }); getForms().getHyperlinkGroup().add(link); return composite; } /* private */ void showErrors() { if (errors != null) { IStatus[] status = errors; String title = TeamUIMessages.ChangesSection_11; if (status.length == 1) { ErrorDialog.openError(getShell(), title, status[0].getMessage(), status[0]); } else { MultiStatus multi = new MultiStatus(TeamUIPlugin.ID, 0, status, TeamUIMessages.ChangesSection_12, null); ErrorDialog.openError(getShell(), title, null, multi); } } } }