/******************************************************************************* * Copyright (c) 2000, 2009 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.compare.CompareConfiguration; import org.eclipse.core.runtime.*; 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.*; 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}. *

* This class provides lifecycle support and hooks for configuration of synchronize view pages. *

* @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() { } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#getName() */ public String getName() { return fName; } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#getImageDescriptor() */ public ImageDescriptor getImageDescriptor() { return fImageDescriptor; } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#getId() */ public String getId() { return fId; } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#getSecondaryId() */ public String getSecondaryId() { return fSecondaryId; } /** * Returns the help context id of this participant or value of * IHelpContextIds.SYNC_VIEW 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. */ public String getHelpContextId() { return fHelpContextId == null ? IHelpContextIds.SYNC_VIEW : fHelpContextId; } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#setPinned(boolean) */ public final void setPinned(boolean pinned) { this.pinned = pinned; pinned(pinned); firePropertyChange(this, P_PINNED, Boolean.valueOf(!pinned), Boolean.valueOf(pinned)); } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#isPinned() */ 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 } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ 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()); } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ 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; } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#addPropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener) */ public synchronized void addPropertyChangeListener(IPropertyChangeListener listener) { if (fChangeHandler == null) { fChangeHandler = new PropertyChangeHandler(); } fChangeHandler.addPropertyChangeListener(listener); } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#removePropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener) */ 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 null * @param newValue the new value of the property, or null */ public void firePropertyChange(Object source, String property, Object oldValue, Object newValue) { if (fChangeHandler == null) { return; } fChangeHandler.firePropertyChange(source, property, oldValue, newValue); } /* (non-Javadoc) * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object) */ 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. *
	 * 		super.init(secondaryId, memento);
	 * 		try {
	 *			ISynchronizeParticipantDescriptor descriptor = TeamUI.getSynchronizeManager().getParticipantDescriptor(PARTICIPANT_ID);
	 *			setInitializationData(descriptor);
	 *		} catch (CoreException e) {
	 *			TeamUIPlugin.log(e);
	 *		}
	 * 
* where PARTICIPANT_ID 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) */ public void init(String secondaryId, IMemento memento) throws PartInitException { setSecondaryId(secondaryId); pinned = Boolean.valueOf(memento.getString(CTX_PINNED)).booleanValue(); } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#saveState(org.eclipse.ui.IMemento) */ public void saveState(IMemento memento) { memento.putString(CTX_PINNED, Boolean.toString(pinned)); } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#createPageConfiguration() */ 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 * createPageConfiguration 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 SyncInfo. * 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) */ 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 null 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 null */ private SyncInfo getSyncInfo(ISynchronizeModelElement element) { if (element instanceof IAdaptable) { return (SyncInfo)((IAdaptable)element).getAdapter(SyncInfo.class); } return null; } /* (non-Javadoc) * @see org.eclipse.team.ui.synchronize.ISynchronizeParticipant#getPreferencePages() */ public PreferencePage[] getPreferencePages() { return new PreferencePage[] { new SyncViewerPreferencePage() }; } /** * Return whether this participant supports the contribution of actions to * the context menu by contributing a viewerContribution * to the org.eclipse.ui.popupMenus extension point. By default, * false is returned. If a subclasses overrides to return true, * the id of the participant is used as the targetId. Here is * an extension that could be added to the plugin manifest to contribute an action to * the context menu for a participant * *
	 *    <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>
	 * 
* * * @return whether this participant supports the contribution of actions to * the context menu using the org.eclipse.ui.popupMenus extension point * @since 3.1 */ protected boolean isViewerContributionsSupported() { return false; } }