/******************************************************************************* * Copyright (c) 2011, 2013 Wind River Systems, Inc. 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: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.te.ui.trees; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.eclipse.core.expressions.EvaluationContext; import org.eclipse.core.expressions.EvaluationResult; import org.eclipse.core.expressions.Expression; import org.eclipse.core.expressions.ExpressionConverter; import org.eclipse.core.expressions.IEvaluationContext; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent; import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.tcf.te.ui.interfaces.IViewerCellEditorFactory; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.handlers.IHandlerService; /** * <code>TreeViewerEditorActivationStrategy</code> is a subclass of * <code>ColumnViewerEditorActivationStrategy</code> that parses the extensions of * "org.eclipse.tcf.te.ui.cellEditors" for Target Explorer, creating a map of * <code>IViewerCellEditorFactory</code> with the activation expressions. When requested to judge if * a <code>ColumnViewerEditorActivationEvent</code> triggers the cell editing in method * <code>isEditorActivationEvent</code>, it traverses the map and finds an appropriate cell editor * factory by evaluating its activation expression. If such a factory is found, add the cell editing * support to Target Explorer viewer with it and return true to activate the cell editing. If no * such a factory is found, then return false to deactivate the cell editing. */ public class TreeViewerEditorActivationStrategy extends ColumnViewerEditorActivationStrategy { // The extension point id. private static final String EXTENSION_POINT_ID = "org.eclipse.tcf.te.ui.cellEditors"; //$NON-NLS-1$ // The common viewer's id. String viewerId; // The common viewer to add editing support. TreeViewer viewer; // The registered cell editor factories map. Map<Expression, IViewerCellEditorFactory> factories; /** * Create an instance with the specified viewer id and the common viewer. * * @param viewerId * @param viewer */ public TreeViewerEditorActivationStrategy(String viewerId, TreeViewer viewer) { super(viewer); Assert.isNotNull(viewerId); this.viewerId = viewerId; this.viewer = viewer; loadFactories(); } /* * (non-Javadoc) * @see org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy#isEditorActivationEvent(org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent) */ @Override protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) { IViewerCellEditorFactory factory = getFactory(event); if (factory != null) { // If an appropriate factory is found, initialize the cell editors. viewer.setColumnProperties(factory.getColumnProperties()); viewer.setCellEditors(factory.getCellEditors()); viewer.setCellModifier(factory.getCellModifier()); } return factory != null; } /** * Get an appropriate cell editor factory based on the event and the current * selection in the viewer. * * @param event the event triggering the action * @return The cell editor factory is appropriate. */ private IViewerCellEditorFactory getFactory(ColumnViewerEditorActivationEvent event) { // Prepare the evaluation context. ISelection selection = viewer.getSelection(); IEvaluationContext currentState = ((IHandlerService)PlatformUI.getWorkbench().getService(IHandlerService.class)).getCurrentState(); final EvaluationContext context = new EvaluationContext(currentState, selection); context.addVariable("selection", selection); //$NON-NLS-1$ context.addVariable("event", event); //$NON-NLS-1$ context.setAllowPluginActivation(true); final IViewerCellEditorFactory[] result = new IViewerCellEditorFactory[1]; for (Expression expression : factories.keySet()) { final Expression exp = expression; SafeRunner.run(new SafeRunnable() { @Override public void handleException(Throwable e) { // Ignore exception } @Override public void run() throws Exception { EvaluationResult evaluate = exp.evaluate(context); if (evaluate == EvaluationResult.TRUE) { result[0] = factories.get(exp); } } }); if (result[0] != null) return result[0]; } return null; } /** * Load the currently registered cell editor factories. */ private void loadFactories() { factories = Collections.synchronizedMap(new HashMap<Expression, IViewerCellEditorFactory>()); IExtensionRegistry registry = Platform.getExtensionRegistry(); IExtensionPoint extensionPoint = registry.getExtensionPoint(EXTENSION_POINT_ID); IConfigurationElement[] configurations = extensionPoint.getConfigurationElements(); for (IConfigurationElement configuration : configurations) { String name = configuration.getName(); if ("cellEditor".equals(name)) { //$NON-NLS-1$ if (isApplicable(configuration)) { addFactory(configuration); } } } } /** * If the configuration has a contribution viewer that has the same id with the specified viewerId. * * @param configuration The cellEditor element. * @return true if it has a specified viewer element. */ private boolean isApplicable(IConfigurationElement configuration) { IConfigurationElement[] children = configuration.getChildren("contributeTo"); //$NON-NLS-1$ for(IConfigurationElement child : children) { String viewerId = child.getAttribute("viewerId"); //$NON-NLS-1$ if(this.viewerId.equals(viewerId)) return true; } return false; } /** * Create and add the cell editor factory that is defined in the configuration element * into the map. * @param configuration The configuration element that defines the cell editor factory. */ private void addFactory(final IConfigurationElement configuration) { IConfigurationElement[] children = configuration.getChildren("activation"); //$NON-NLS-1$ Assert.isTrue(children != null && children.length == 1); children = children[0].getChildren(); Assert.isTrue(children != null && children.length == 1); final IConfigurationElement config = children[0]; SafeRunner.run(new SafeRunnable() { @Override public void handleException(Throwable e) { // Ignore exception } @Override public void run() throws Exception { Expression expression = ExpressionConverter.getDefault().perform(config); IViewerCellEditorFactory factory = (IViewerCellEditorFactory) configuration.createExecutableExtension("editorFactory"); //$NON-NLS-1$ if (expression != null && factory != null) { factory.init(viewer); factories.put(expression, factory); } } }); } }