| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.team.ui.synchronize; |
| |
| import org.eclipse.compare.CompareConfiguration; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.PlatformObject; |
| import org.eclipse.jface.preference.PreferencePage; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.viewers.IBasicPropertyConstants; |
| import org.eclipse.team.core.TeamException; |
| import org.eclipse.team.core.synchronize.SyncInfo; |
| import org.eclipse.team.internal.ui.IHelpContextIds; |
| import org.eclipse.team.internal.ui.PropertyChangeHandler; |
| import org.eclipse.team.internal.ui.TeamUIMessages; |
| import org.eclipse.team.internal.ui.Utils; |
| import org.eclipse.team.internal.ui.preferences.SyncViewerPreferencePage; |
| import org.eclipse.team.internal.ui.registry.SynchronizeParticipantDescriptor; |
| import org.eclipse.team.internal.ui.synchronize.SyncInfoModelElement; |
| import org.eclipse.team.internal.ui.synchronize.SynchronizePageConfiguration; |
| import org.eclipse.team.ui.TeamImages; |
| import org.eclipse.ui.IMemento; |
| import org.eclipse.ui.PartInitException; |
| |
| /** |
| * This class is the abstract base class for all synchronize view participants. Clients must subclass |
| * this class instead of directly implementing {@link ISynchronizeParticipant}. |
| * <p> |
| * This class provides lifecycle support and hooks for configuration of synchronize view pages. |
| * </p> |
| * @see ISynchronizeParticipant |
| * @since 3.0 |
| */ |
| public abstract class AbstractSynchronizeParticipant extends PlatformObject implements ISynchronizeParticipant { |
| |
| /** |
| * Property key used in the property change event fired when the pinned |
| * state of a participant changes. |
| */ |
| public static final String P_PINNED = "org.eclipse.team.pinned"; //$NON-NLS-1$ |
| |
| /** |
| * Property key used in the property change event fired when the |
| * participants refresh schedule changes. |
| * @since 3.2 |
| */ |
| public static final String P_SCHEDULED = "org.eclipse.team.schedule"; //$NON-NLS-1$ |
| |
| // key for persisting the pinned state of a participant |
| private final static String CTX_PINNED = "root"; //$NON-NLS-1$ |
| |
| // property listeners |
| private PropertyChangeHandler fChangeHandler; |
| |
| private String fName; |
| private String fId; |
| private String fSecondaryId; |
| private boolean pinned; |
| private ImageDescriptor fImageDescriptor; |
| private String fHelpContextId; |
| protected IConfigurationElement configElement; |
| |
| /** |
| * Default constructor is a no-op. Subclasses that are persistable must support a no-arg constructor |
| * and |
| */ |
| public AbstractSynchronizeParticipant() { |
| } |
| |
| @Override |
| public String getName() { |
| return fName; |
| } |
| |
| @Override |
| public ImageDescriptor getImageDescriptor() { |
| return fImageDescriptor; |
| } |
| |
| @Override |
| public String getId() { |
| return fId; |
| } |
| |
| @Override |
| public String getSecondaryId() { |
| return fSecondaryId; |
| } |
| |
| /** |
| * Returns the help context id of this participant or value of |
| * <code>IHelpContextIds.SYNC_VIEW</code> when no specific id has been |
| * provided. |
| * |
| * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#getHelpContextId() |
| * @see org.eclipse.team.internal.ui.IHelpContextIds#SYNC_VIEW |
| * @since 3.5 |
| * @nooverride This method is not intended to be re-implemented or extended |
| * by clients. |
| */ |
| @Override |
| public String getHelpContextId() { |
| return fHelpContextId == null ? IHelpContextIds.SYNC_VIEW |
| : fHelpContextId; |
| } |
| |
| @Override |
| public final void setPinned(boolean pinned) { |
| this.pinned = pinned; |
| pinned(pinned); |
| firePropertyChange(this, P_PINNED, Boolean.valueOf(!pinned), Boolean.valueOf(pinned)); |
| } |
| |
| @Override |
| public final boolean isPinned() { |
| return pinned; |
| } |
| |
| /** |
| * Called when the pinned state is changed. Allows subclasses to react to pin state changes. |
| * |
| * @param pinned whether the participant is pinned. |
| */ |
| protected void pinned(boolean pinned) { |
| // Subclasses can re-act to changes in the pinned state |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if(obj == this) return true; |
| if( ! (obj instanceof ISynchronizeParticipant)) return false; |
| ISynchronizeParticipant other = (ISynchronizeParticipant)obj; |
| return getId().equals(other.getId()) && Utils.equalObject(getSecondaryId(), other.getSecondaryId()); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Utils.getKey(getId(), getSecondaryId()).hashCode(); |
| } |
| |
| /** |
| * Return whether this participant can be refreshed. Participants that can |
| * be refreshed may have a Synchronize menu item contributed to their context menu |
| * and can also be refreshed from the Synchronize drop-down toolbar item. |
| * When refreshed from the toolbar item, the {@link ISynchronizeParticipant#run(org.eclipse.ui.IWorkbenchPart)} |
| * method is called. |
| * @return whether this participant can be refreshed |
| */ |
| public boolean doesSupportSynchronize() { |
| return true; |
| } |
| |
| @Override |
| public synchronized void addPropertyChangeListener(IPropertyChangeListener listener) { |
| if (fChangeHandler == null) { |
| fChangeHandler = new PropertyChangeHandler(); |
| } |
| fChangeHandler.addPropertyChangeListener(listener); |
| } |
| |
| @Override |
| public void removePropertyChangeListener(IPropertyChangeListener listener) { |
| if (fChangeHandler != null) { |
| fChangeHandler.removePropertyChangeListener(listener); |
| } |
| } |
| |
| /** |
| * Notify all listeners that the given property has changed. |
| * |
| * @param source the object on which a property has changed |
| * @param property identifier of the property that has changed |
| * @param oldValue the old value of the property, or <code>null</code> |
| * @param newValue the new value of the property, or <code>null</code> |
| */ |
| public void firePropertyChange(Object source, String property, Object oldValue, Object newValue) { |
| if (fChangeHandler == null) { |
| return; |
| } |
| fChangeHandler.firePropertyChange(source, property, oldValue, newValue); |
| } |
| |
| @Override |
| public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { |
| // Save config element. |
| configElement = config; |
| |
| // Id |
| fId = config.getAttribute("id"); //$NON-NLS-1$ |
| |
| // Title. |
| fName = config.getAttribute("name"); //$NON-NLS-1$ |
| if (fName == null) { |
| fName = "Unknown"; //$NON-NLS-1$ |
| } |
| |
| // Icon. |
| String strIcon = config.getAttribute("icon"); //$NON-NLS-1$ |
| if (strIcon != null) { |
| fImageDescriptor = TeamImages.getImageDescriptorFromExtension(configElement.getDeclaringExtension(), strIcon); |
| } |
| |
| // Help Context Id. |
| fHelpContextId = configElement |
| .getAttribute(SynchronizeParticipantDescriptor.ATT_HELP_CONTEXT_ID); |
| } |
| |
| protected void setInitializationData(ISynchronizeParticipantDescriptor descriptor) throws CoreException { |
| if(descriptor instanceof SynchronizeParticipantDescriptor) { |
| setInitializationData(((SynchronizeParticipantDescriptor)descriptor).getConfigurationElement(), null, null); |
| } else { |
| throw new TeamException(TeamUIMessages.AbstractSynchronizeParticipant_4); |
| } |
| } |
| |
| /** |
| * Sets the name of this participant to the specified value and notifies |
| * property listeners of the change. |
| * |
| * @param name the new name |
| */ |
| protected void setName(String name) { |
| String old = fName; |
| fName = name; |
| firePropertyChange(this, IBasicPropertyConstants.P_TEXT, old, name); |
| } |
| |
| /** |
| * Sets the image descriptor for this participant to the specified value and |
| * notifies property listeners of the change. |
| * |
| * @param imageDescriptor the new image descriptor |
| */ |
| protected void setImageDescriptor(ImageDescriptor imageDescriptor) { |
| ImageDescriptor old = fImageDescriptor; |
| fImageDescriptor = imageDescriptor; |
| firePropertyChange(this, IBasicPropertyConstants.P_IMAGE, old, imageDescriptor); |
| } |
| |
| /** |
| * Sets the secondary id for this participant. |
| * |
| * @param secondaryId the secondary id for this participant. |
| */ |
| protected void setSecondaryId(String secondaryId) { |
| this.fSecondaryId = secondaryId; |
| } |
| |
| /** |
| * Classes that are persisted must override this method and perform |
| * the following initialization. |
| * <pre> |
| * super.init(secondaryId, memento); |
| * try { |
| * ISynchronizeParticipantDescriptor descriptor = TeamUI.getSynchronizeManager().getParticipantDescriptor(PARTICIPANT_ID); |
| * setInitializationData(descriptor); |
| * } catch (CoreException e) { |
| * TeamUIPlugin.log(e); |
| * } |
| * </pre> |
| * where <code>PARTICIPANT_ID</code> is the id of the participant as defined in the plugin manifest. |
| * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#init(String, org.eclipse.ui.IMemento) |
| */ |
| @Override |
| public void init(String secondaryId, IMemento memento) throws PartInitException { |
| setSecondaryId(secondaryId); |
| pinned = Boolean.valueOf(memento.getString(CTX_PINNED)).booleanValue(); |
| } |
| |
| @Override |
| public void saveState(IMemento memento) { |
| memento.putString(CTX_PINNED, Boolean.toString(pinned)); |
| } |
| |
| @Override |
| public final ISynchronizePageConfiguration createPageConfiguration() { |
| SynchronizePageConfiguration configuration = new SynchronizePageConfiguration(this); |
| if (isViewerContributionsSupported()) { |
| configuration.setProperty(ISynchronizePageConfiguration.P_OBJECT_CONTRIBUTION_ID, getId()); |
| } |
| initializeConfiguration(configuration); |
| return configuration; |
| } |
| |
| /** |
| * This method is invoked after a page configuration is created but before it is returned by the |
| * <code>createPageConfiguration</code> method. Subclasses can implement this method to |
| * tailor the configuration in ways appropriate to the participant. |
| * |
| * @param configuration the newly create page configuration |
| */ |
| protected abstract void initializeConfiguration(ISynchronizePageConfiguration configuration); |
| |
| /** |
| * Default implementation will update the labels in the given configuration using |
| * information from the provided element if it adapts to <code>SyncInfo</code>. |
| * It will also cache the contents for the remote and base if the element is |
| * sync info based. |
| * @param element the sync model element whose contents are about to be displayed to the user |
| * in a compare editor or compare dialog |
| * @param config the compare configuration that will be used to configure the compare editor or dialog |
| * @param monitor a progress monitor that can be used if contacting a server to prepare the element and configuration |
| * @throws TeamException if an error occurred that should prevent the display of the compare editor containing |
| * the element |
| * |
| * @since 3.1 |
| * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#prepareCompareInput(org.eclipse.team.ui.synchronize.ISynchronizeModelElement, org.eclipse.compare.CompareConfiguration, org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| @Override |
| public void prepareCompareInput(ISynchronizeModelElement element, CompareConfiguration config, IProgressMonitor monitor) throws TeamException { |
| SyncInfo sync = getSyncInfo(element); |
| if (sync != null) |
| Utils.updateLabels(sync, config, monitor); |
| if (element instanceof SyncInfoModelElement) { |
| SyncInfoModelElement node = (SyncInfoModelElement)element; |
| (node).cacheContents(monitor); |
| } |
| } |
| |
| /* |
| * Get the sync info node from the element using the adaptable mechanism. |
| * A <code>null</code> is returned if the element doesn't have a sync info |
| * @param element the sync model element |
| * @return the sync info for the element or <code>null</code> |
| */ |
| private SyncInfo getSyncInfo(ISynchronizeModelElement element) { |
| if (element instanceof IAdaptable) { |
| return ((IAdaptable)element).getAdapter(SyncInfo.class); |
| } |
| return null; |
| } |
| |
| @Override |
| public PreferencePage[] getPreferencePages() { |
| return new PreferencePage[] { new SyncViewerPreferencePage() }; |
| } |
| |
| /** |
| * Return whether this participant supports the contribution of actions to |
| * the context menu by contributing a <code>viewerContribution</code> |
| * to the <code>org.eclipse.ui.popupMenus</code> extension point. By default, |
| * <code>false</code> is returned. If a subclasses overrides to return <code>true</code>, |
| * the <code>id</code> of the participant is used as the <code>targetId</code>. Here is |
| * an extension that could be added to the plugin manifest to contribute an action to |
| * the context menu for a participant |
| * |
| * <pre> |
| * <extension point="org.eclipse.ui.popupMenus"> |
| * <viewerContribution |
| * id="org.eclipse.team.cvs.ui.viewContributionId" |
| * targetID="org.eclipse.team.cvs.ui.cvsworkspace-participant"> |
| * <action |
| * label="Add" |
| * menubarPath="additions" |
| * tooltip="Add a file to CVS version control" |
| * class="org.eclipse.team.internal.ccvs.ui.actions.AddAction" |
| * helpContextId="org.eclipse.team.cvs.ui.workspace_subscriber_add" |
| * id="org.eclipse.team.ccvs.ui.CVSWorkspaceSubscriber.add"> |
| * </action> |
| * </viewerContribution> |
| * </extension> |
| * </pre> |
| * |
| * |
| * @return whether this participant supports the contribution of actions to |
| * the context menu using the <code>org.eclipse.ui.popupMenus</code> extension point |
| * @since 3.1 |
| */ |
| protected boolean isViewerContributionsSupported() { |
| return false; |
| } |
| } |