/*******************************************************************************
* Copyright (c) 2006-2013 The RCP Company 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:
* The RCP Company - initial API and implementation
*******************************************************************************/
package com.rcpcompany.uibindings.internal.handlers;
import java.util.Map;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.ui.ISourceProviderListener;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.commands.IElementUpdater;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.menus.UIElement;
import org.eclipse.ui.services.IServiceLocator;
import org.eclipse.ui.services.ISourceProviderService;
import com.rcpcompany.uibindings.Constants;
import com.rcpcompany.uibindings.IValueBinding;
import com.rcpcompany.uibindings.internal.Activator;
import com.rcpcompany.uibindings.internal.sourceProviders.BindingSourceProvider;
import com.rcpcompany.utils.logging.LogUtils;
/**
* Handler for the commands <code>com.rcpcompany.uibindings.commands.UseDefaultValue</code>.
* <p>
* Keeps track of the current binding and updates the state appropriately.
*
* @author Tonny Madsen, The RCP Company
*/
public class UseDefaultValueHandler extends AbstractHandler implements IHandler, IElementUpdater {
/**
* The binding source provider...
*/
private final BindingSourceProvider myProvider;
/**
* The current "checked" state of the handler.
*/
private boolean myIsUnset = false;
/**
* The current "is unsettable" state of the handler. Use to set the name.
*/
private boolean myIsUnsettable;
/**
* Listener that tracks the {@link EObject#eIsSet(org.eclipse.emf.ecore.EStructuralFeature)}
* state of the current binding when {@link Constants#SOURCES_ACTIVE_BINDING} is
* <code>true</code>.
*/
private final ISourceProviderListener myProviderListener = new ISourceProviderListener() {
@Override
public void sourceChanged(int sourcePriority, String sourceName, Object sourceValue) {
if (sourceName.equals(Constants.SOURCES_ACTIVE_BINDING)) {
updateHandlerState();
}
}
@Override
public void sourceChanged(int sourcePriority, Map sourceValuesByName) {
if (sourceValuesByName.containsKey(Constants.SOURCES_ACTIVE_BINDING)) {
updateHandlerState();
}
}
};
/**
* The global command service.
*/
private final ICommandService myCommandService;
/**
* Constructs and returns a new handler.
*/
public UseDefaultValueHandler() {
final IServiceLocator locator = PlatformUI.getWorkbench();
final ISourceProviderService sourceProviders = (ISourceProviderService) locator
.getService(ISourceProviderService.class);
myCommandService = (ICommandService) locator.getService(ICommandService.class);
myProvider = (BindingSourceProvider) sourceProviders.getSourceProvider(Constants.SOURCES_ACTIVE_BINDING);
myProvider.addSourceProviderListener(myProviderListener);
}
/**
* Calculates any new {@link #myIsUnset} and {@link #myIsUnsettable}.
*/
protected void updateHandlerState() {
final Map<String, Object> currentState = myProvider.getCurrentState();
final Object b = currentState.get(Constants.SOURCES_ACTIVE_BINDING);
if (!(b instanceof IValueBinding)) return;
final IValueBinding binding = (IValueBinding) b;
final EStructuralFeature feature = binding.getModelFeature();
if (feature == null) {
setHandlerState(false, false);
return;
}
final EObject obj = binding.getModelObject();
if (obj == null) {
setHandlerState(false, feature.isUnsettable());
return;
}
setHandlerState(!obj.eIsSet(feature), feature.isUnsettable());
}
/**
* Sets the new value of {@link #myIsUnset}.
*
* @param newIsUnset the new state
* @param newIsUnsettable TODO
*/
protected void setHandlerState(boolean newIsUnset, boolean newIsUnsettable) {
if (myIsUnset == newIsUnset && myIsUnsettable == newIsUnsettable) return;
myIsUnset = newIsUnset;
myIsUnsettable = newIsUnsettable;
myCommandService.refreshElements(Constants.USE_DEFAULT_TOGGLE_COMMAND, null);
}
@Override
public void dispose() {
myProvider.removeSourceProviderListener(myProviderListener);
super.dispose();
}
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
if (Activator.getDefault().TRACE_HANDLERS) {
LogUtils.debug(this, "");
}
final IValueBinding binding = (IValueBinding) HandlerUtil.getVariableChecked(event,
Constants.SOURCES_ACTIVE_BINDING);
if (binding == null) return null;
final EObject obj = binding.getModelObject();
final EStructuralFeature feature = binding.getModelFeature();
if (obj == null || feature == null) return null;
final Object value;
if (obj.eIsSet(feature)) {
value = SetCommand.UNSET_VALUE;
} else {
value = obj.eGet(feature);
}
final Command command = SetCommand.create(binding.getEditingDomain(), obj, feature, value);
binding.getEditingDomain().getCommandStack().execute(command);
updateHandlerState();
return null;
}
@Override
public void updateElement(UIElement element, Map parameters) {
String name = null;
if (myIsUnset) {
name = "Set as Normal Attribute";
} else {
if (myIsUnsettable) {
name = "Set to Default";
} else {
name = "Use Default Value";
}
}
element.setText(name);
element.setChecked(myIsUnset);
}
}