Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2010 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 org.eclipse.core.resources.mapping.*; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.action.*; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.*; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.*; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.mapping.*; import org.eclipse.team.internal.ui.TeamUIPlugin; import org.eclipse.team.internal.ui.Utils; import org.eclipse.team.internal.ui.synchronize.AbstractTreeViewerAdvisor; import org.eclipse.team.internal.ui.synchronize.SynchronizePageConfiguration; import org.eclipse.team.ui.TeamUI; import org.eclipse.team.ui.mapping.*; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.ModelSynchronizeParticipant; import org.eclipse.ui.*; import org.eclipse.ui.actions.ActionContext; import org.eclipse.ui.navigator.*; import org.eclipse.ui.part.IPageSite; /** * Provides a Common Navigator based viewer for use by a {@link ModelSynchronizePage}. */ public class CommonViewerAdvisor extends AbstractTreeViewerAdvisor implements INavigatorContentServiceListener, IEmptyTreeListener, IPropertyChangeListener { public static final class NavigableCommonViewer extends CommonViewer implements ITreeViewerAccessor { private final IEmptyTreeListener listener; private boolean empty; private NavigableCommonViewer(String id, Composite parent, int style, IEmptyTreeListener listener) { super(id, parent, style); this.listener = listener; } public void createChildren(TreeItem item) { super.createChildren(item); } public void openSelection() { fireOpen(new OpenEvent(this, getSelection())); } protected void internalRefresh(Object element, boolean updateLabels) { TreePath[] expanded = getVisibleExpandedPaths(); super.internalRefresh(element, updateLabels); setExpandedTreePaths(expanded); checkForEmptyViewer(); } protected void internalRemove(Object parent, Object[] elements) { super.internalRemove(parent, elements); if (parent == getInput()) checkForEmptyViewer(); } protected void internalRemove(Object[] elements) { super.internalRemove(elements); checkForEmptyViewer(); } protected void internalAdd(Widget widget, Object parentElement, Object[] childElements) { super.internalAdd(widget, parentElement, childElements); if (empty) { empty = false; listener.notEmpty(this); } } protected void inputChanged(Object input, Object oldInput) { super.inputChanged(input, oldInput); checkForEmptyViewer(); } private void checkForEmptyViewer() { Object input = getInput(); if (input != null) { Widget w = findItem(input); Item[] children = getChildren(w); if (children.length == 0) { if (!empty) { empty = true; listener.treeEmpty(this); } return; } } empty = false; if (listener != null) listener.notEmpty(this); } public boolean isEmpty() { return empty; } protected void initDragAndDrop() { getNavigatorContentService().getDnDService().bindDragAssistant(new ResourceDragAdapterAssistant()); super.initDragAndDrop(); } /** * Gets the expanded elements that are visible to the user. An expanded * element is only visible if the parent is expanded. * * @return the visible expanded elements * @since 2.0 */ public TreePath[] getVisibleExpandedPaths() { ArrayList v = new ArrayList(); internalCollectVisibleExpanded(v, getControl()); return (TreePath[]) v.toArray(new TreePath[v.size()]); } private void internalCollectVisibleExpanded(ArrayList result, Widget widget) { Item[] items = getChildren(widget); for (int i = 0; i < items.length; i++) { Item item = items[i]; if (getExpanded(item)) { TreePath path = getTreePathFromItem(item); if (path != null) { result.add(path); } //Only recurse if it is expanded - if //not then the children aren't visible internalCollectVisibleExpanded(result, item); } } } } /** * Subclass of SubActionBars that manages the contributions from the common action service */ private class CommonSubActionBars extends SubActionBars { public CommonSubActionBars(IActionBars parent) { super(parent); } public void setGlobalActionHandler(String actionID, IAction handler) { if (handler == null) { // Only remove the handler if it was set if (getGlobalActionHandler(actionID) != null) { getParent().setGlobalActionHandler(actionID, null); super.setGlobalActionHandler(actionID, null); } } else { // Only set the action handler if the parent doesn't if (getParent().getGlobalActionHandler(actionID) != null) { TeamUIPlugin.log(new TeamException( NLS.bind("Conflicting attempt to set action id {0} detected", actionID))); //$NON-NLS-1$ return; } super.setGlobalActionHandler(actionID, handler); } } public void clearGlobalActionHandlers() { // When cleared, also remove the ids from the parent Map handlers = getGlobalActionHandlers(); if (handlers != null) { Set keys = handlers.keySet(); Iterator iter = keys.iterator(); while (iter.hasNext()) { String actionId = (String) iter.next(); getParent().setGlobalActionHandler(actionId, null); } } super.clearGlobalActionHandlers(); } public void updateActionBars() { // On update, push all or action handlers into our parent Map newActionHandlers = getGlobalActionHandlers(); if (newActionHandlers != null) { Set keys = newActionHandlers.entrySet(); Iterator iter = keys.iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); getParent().setGlobalActionHandler((String) entry.getKey(), (IAction) entry.getValue()); } } super.updateActionBars(); } } public static final String TEAM_NAVIGATOR_CONTENT = "org.eclipse.team.ui.navigatorViewer"; //$NON-NLS-1$ private static final String PROP_ACTION_SERVICE_ACTION_BARS = "org.eclipse.team.ui.actionServiceActionBars"; //$NON-NLS-1$ private Set extensions = new HashSet(); private NavigatorActionService actionService; private IEmptyTreeListener emptyTreeListener; /** * Create a common viewer * @param parent the parent composite of the common viewer * @param configuration the configuration for the viewer * @return a newly created common viewer */ private static CommonViewer createViewer(Composite parent, final ISynchronizePageConfiguration configuration, IEmptyTreeListener listener) { final CommonViewer v = new NavigableCommonViewer(configuration.getViewerId(), parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL, listener); v.setSorter(new CommonViewerSorter()); v.setSorter(new TeamViewerSorter((CommonViewerSorter) v.getSorter())); ISynchronizationScope scope = getScope(configuration); bindTeamContentProviders(v); scope.addScopeChangeListener(new ISynchronizationScopeChangeListener() { public void scopeChanged(final ISynchronizationScope scope, ResourceMapping[] newMappings, ResourceTraversal[] newTraversals) { enableContentProviders(v, configuration); Utils.asyncExec(new Runnable() { public void run() { v.refresh(); } }, v); } }); enableContentProviders(v, configuration); configuration.getSite().setSelectionProvider(v); return v; } private static void enableContentProviders(CommonViewer v, ISynchronizePageConfiguration configuration) { v.getNavigatorContentService().getActivationService() .activateExtensions(getEnabledContentProviders(configuration), true); } private static String[] getEnabledContentProviders(ISynchronizePageConfiguration configuration) { String visibleModel = (String) configuration .getProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER); if (visibleModel != null && !visibleModel.equals(ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE)) { ITeamContentProviderDescriptor desc = TeamUI.getTeamContentProviderManager() .getDescriptor(visibleModel); if (desc != null && desc.isEnabled()) return new String[] { desc.getContentExtensionId() }; } configuration.setProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER, ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE); ModelSynchronizeParticipant participant = (ModelSynchronizeParticipant) configuration.getParticipant(); ModelProvider[] providers = participant.getEnabledModelProviders(); Set result = new HashSet(); Object property = configuration.getProperty(ITeamContentProviderManager.PROP_PAGE_LAYOUT); boolean isFlatLayout = property != null && property.equals(ITeamContentProviderManager.FLAT_LAYOUT); for (int i = 0; i < providers.length; i++) { ModelProvider provider = providers[i]; ITeamContentProviderDescriptor desc = TeamUI.getTeamContentProviderManager() .getDescriptor(provider.getId()); if (desc != null && desc.isEnabled() && (!isFlatLayout || desc.isFlatLayoutSupported())) result.add(desc.getContentExtensionId()); } return (String[]) result.toArray(new String[result.size()]); } private static void bindTeamContentProviders(CommonViewer v) { ITeamContentProviderManager teamContentProviderManager = TeamUI.getTeamContentProviderManager(); ITeamContentProviderDescriptor[] descriptors = teamContentProviderManager.getDescriptors(); Set toBind = new HashSet(); for (int i = 0; i < descriptors.length; i++) { ITeamContentProviderDescriptor descriptor = descriptors[i]; toBind.add(descriptor.getContentExtensionId()); } v.getNavigatorContentService().bindExtensions((String[]) toBind.toArray(new String[toBind.size()]), true); } private static ISynchronizationScope getScope(ISynchronizePageConfiguration configuration) { return (ISynchronizationScope) configuration .getProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_SCOPE); } /** * Create the advisor using the given configuration * @param parent the parent * @param configuration the configuration */ public CommonViewerAdvisor(Composite parent, ISynchronizePageConfiguration configuration) { super(configuration); final CommonViewer viewer = CommonViewerAdvisor.createViewer(parent, configuration, this); TeamUI.getTeamContentProviderManager().addPropertyChangeListener(this); configuration.addPropertyChangeListener(this); GridData data = new GridData(GridData.FILL_BOTH); viewer.getControl().setLayoutData(data); viewer.getNavigatorContentService().addListener(this); initializeViewer(viewer); IBaseLabelProvider provider = viewer.getLabelProvider(); if (provider instanceof DecoratingLabelProvider) { DecoratingLabelProvider dlp = (DecoratingLabelProvider) provider; ILabelDecorator decorator = ((SynchronizePageConfiguration) configuration).getLabelDecorator(); if (decorator != null) { ILabelProvider lp = dlp.getLabelProvider(); dlp = new DecoratingLabelProvider(new DecoratingLabelProvider(lp, decorator), PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()); viewer.setLabelProvider(dlp); } DecorationContext decorationContext = new DecorationContext(); decorationContext.putProperty(SynchronizationStateTester.PROP_TESTER, new SynchronizationStateTester() { public boolean isStateDecorationEnabled() { return false; } }); dlp.setDecorationContext(decorationContext); } else if (provider instanceof DecoratingStyledCellLabelProvider) { DecoratingStyledCellLabelProvider dsclp = (DecoratingStyledCellLabelProvider) provider; ILabelDecorator decorator = ((SynchronizePageConfiguration) configuration).getLabelDecorator(); if (decorator != null) { IStyledLabelProvider slp = dsclp.getStyledStringProvider(); dsclp = new DecoratingStyledCellLabelProvider( new MyDecoratingStyledCellLabelProvider(slp, decorator), PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator(), null); viewer.setLabelProvider(dsclp); } DecorationContext decorationContext = new DecorationContext(); decorationContext.putProperty(SynchronizationStateTester.PROP_TESTER, new SynchronizationStateTester() { public boolean isStateDecorationEnabled() { return false; } }); dsclp.setDecorationContext(decorationContext); } } private class MyDecoratingStyledCellLabelProvider extends DecoratingStyledCellLabelProvider implements IStyledLabelProvider, IFontProvider { private IStyledLabelProvider slp; public MyDecoratingStyledCellLabelProvider(IStyledLabelProvider slp, ILabelDecorator decorator) { super(slp, decorator, null); this.slp = slp; } public StyledString getStyledText(Object element) { return slp.getStyledText(element); } public Font getFont(Object element) { // DelegatingStyledCellLabelProvider does not implement // IFontProvider return super.getFont(element); } } public void setInitialInput() { CommonViewer viewer = (CommonViewer) getViewer(); viewer.setInput(getInitialInput()); viewer.expandToLevel(2); } /* (non-Javadoc) * @see org.eclipse.team.internal.ui.synchronize.StructuredViewerAdvisor#initializeViewer(org.eclipse.jface.viewers.StructuredViewer) */ public void initializeViewer(StructuredViewer viewer) { createActionService((CommonViewer) viewer, getConfiguration()); super.initializeViewer(viewer); } private void createActionService(CommonViewer viewer, ISynchronizePageConfiguration configuration) { ICommonViewerSite commonSite = createCommonViewerSite(viewer, configuration); actionService = new NavigatorActionService(commonSite, viewer, viewer.getNavigatorContentService()); } private ICommonViewerSite createCommonViewerSite(CommonViewer viewer, ISynchronizePageConfiguration configuration) { IWorkbenchSite site = configuration.getSite().getWorkbenchSite(); if (site instanceof IEditorSite) { IEditorSite es = (IEditorSite) site; return CommonViewerSiteFactory.createCommonViewerSite(es); } if (site instanceof IViewSite) { IViewSite vs = (IViewSite) site; return CommonViewerSiteFactory.createCommonViewerSite(vs); } if (site instanceof IPageSite) { IPageSite ps = (IPageSite) site; return CommonViewerSiteFactory.createCommonViewerSite(configuration.getViewerId(), ps); } return CommonViewerSiteFactory.createCommonViewerSite(configuration.getViewerId(), viewer, configuration.getSite().getShell()); } private Object getInitialInput() { String visible = (String) getConfiguration() .getProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER); if (visible != null && !visible.equals(ModelSynchronizeParticipant.ALL_MODEL_PROVIDERS_VISIBLE)) { try { IModelProviderDescriptor desc = ModelProvider.getModelProviderDescriptor(visible); if (desc != null) return desc.getModelProvider(); } catch (CoreException e) { TeamUIPlugin.log(e); } } return getConfiguration().getProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_CONTEXT); } /* (non-Javadoc) * @see org.eclipse.ui.navigator.internal.extensions.INavigatorContentServiceListener#onLoad(org.eclipse.ui.navigator.internal.extensions.NavigatorContentExtension) */ public void onLoad(INavigatorContentExtension anExtension) { extensions.add(anExtension); ISynchronizationContext context = getParticipant().getContext(); anExtension.getStateModel().setProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_SCOPE, context.getScope()); anExtension.getStateModel().setProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_PAGE_CONFIGURATION, getConfiguration()); anExtension.getStateModel().setProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_CONTEXT, context); } private ModelSynchronizeParticipant getParticipant() { return (ModelSynchronizeParticipant) getConfiguration().getParticipant(); } /* (non-Javadoc) * @see org.eclipse.team.internal.ui.synchronize.StructuredViewerAdvisor#getContextMenuId(org.eclipse.jface.viewers.StructuredViewer) */ protected String getContextMenuId(StructuredViewer viewer) { return ((CommonViewer) viewer).getNavigatorContentService().getViewerDescriptor().getPopupMenuId(); } /* (non-Javadoc) * @see org.eclipse.team.internal.ui.synchronize.StructuredViewerAdvisor#registerContextMenu(org.eclipse.jface.viewers.StructuredViewer, org.eclipse.jface.action.MenuManager) */ protected void registerContextMenu(StructuredViewer viewer, MenuManager menuMgr) { actionService.prepareMenuForPlatformContributions(menuMgr, viewer, false); } /* (non-Javadoc) * @see org.eclipse.team.internal.ui.synchronize.StructuredViewerAdvisor#fillContextMenu(org.eclipse.jface.viewers.StructuredViewer, org.eclipse.jface.action.IMenuManager) */ protected void fillContextMenu(StructuredViewer viewer, IMenuManager manager) { // Clear any handlers from the menu if (manager instanceof CommonMenuManager) { CommonMenuManager cmm = (CommonMenuManager) manager; cmm.clearHandlers(); } // Add the actions from the service (which willal so add the groups) ISelection selection = getViewer().getSelection(); actionService.setContext(new ActionContext(selection)); actionService.fillContextMenu(manager); // Add any programmatic menu items super.fillContextMenu(viewer, manager); } /* (non-Javadoc) * @see org.eclipse.team.internal.ui.synchronize.StructuredViewerAdvisor#dispose() */ public void dispose() { TeamUI.getTeamContentProviderManager().removePropertyChangeListener(this); getConfiguration().removePropertyChangeListener(this); actionService.dispose(); super.dispose(); } /* (non-Javadoc) * @see org.eclipse.team.internal.ui.synchronize.StructuredViewerAdvisor#updateActionBars(org.eclipse.jface.viewers.IStructuredSelection) */ protected void updateActionBars(IStructuredSelection selection) { super.updateActionBars(selection); if (!getConfiguration().getSite().isModal()) { actionService.setContext(new ActionContext(selection)); // This is non-standard behavior that is required by the common navigator framework (see bug 122808) SubActionBars subActionBars = (SubActionBars) getConfiguration() .getProperty(PROP_ACTION_SERVICE_ACTION_BARS); if (subActionBars == null) { subActionBars = new CommonSubActionBars(getConfiguration().getSite().getActionBars()); getConfiguration().setProperty(PROP_ACTION_SERVICE_ACTION_BARS, subActionBars); } actionService.fillActionBars(subActionBars); } } /* (non-Javadoc) * @see org.eclipse.team.internal.ui.synchronize.StructuredViewerAdvisor#createContextMenuManager(java.lang.String) */ protected MenuManager createContextMenuManager(String targetID) { return new CommonMenuManager(targetID); } /* (non-Javadoc) * @see org.eclipse.team.internal.ui.synchronize.StructuredViewerAdvisor#addContextMenuGroups(org.eclipse.jface.action.IMenuManager) */ protected void addContextMenuGroups(IMenuManager manager) { // Don't do anything. The groups will be added by the action service } public void addEmptyTreeListener(IEmptyTreeListener emptyTreeListener) { this.emptyTreeListener = emptyTreeListener; } public void treeEmpty(TreeViewer viewer) { if (emptyTreeListener != null) emptyTreeListener.treeEmpty(viewer); } public void notEmpty(TreeViewer viewer) { if (emptyTreeListener != null) emptyTreeListener.notEmpty(viewer); } public void propertyChange(final PropertyChangeEvent event) { if (event.getProperty().equals(ITeamContentProviderManager.PROP_ENABLED_MODEL_PROVIDERS)) { enableContentProviders((CommonViewer) getViewer(), getConfiguration()); } else if (event.getProperty().equals(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER)) { enableContentProviders((CommonViewer) getViewer(), getConfiguration()); final Viewer viewer = getViewer(); Utils.syncExec(new Runnable() { public void run() { Object viewerInput = ModelSynchronizePage.getViewerInput(getConfiguration(), (String) event.getNewValue()); if (viewer != null && viewerInput != null) { viewer.setInput(viewerInput); } } }, (StructuredViewer) viewer); } else if (event.getProperty().equals(ITeamContentProviderManager.PROP_PAGE_LAYOUT)) { // TODO enableContentProviders((CommonViewer) getViewer(), getConfiguration()); } } protected boolean handleDoubleClick(StructuredViewer viewer, DoubleClickEvent event) { if (isOpenable(event.getSelection())) { return true; } return super.handleDoubleClick(viewer, event); } private boolean isOpenable(ISelection selection) { IStructuredSelection ss = (IStructuredSelection) selection; Object object = ss.getFirstElement(); if (object == null) return false; return getParticipant().hasCompareInputFor(object); } protected void expandToNextDiff(Object element) { ((TreeViewer) getViewer()).expandToLevel(element, AbstractTreeViewer.ALL_LEVELS); } }