/******************************************************************************* * Copyright (c) 2000, 2010, 2012 IBM Corporation, Gerhardt Informatics Kft. 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 * Gerhardt Informatics Kft. - GEFGWT port *******************************************************************************/ package org.eclipse.gef.ui.properties; import org.eclipse.gef.commands.Command; import org.eclipse.gef.internal.GEFMessages; import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.properties.IPropertySource2; import com.ibm.icu.text.MessageFormat; /** * A command used to set or reset the value of a property. * * @author pshah * @author anyssen * * @since 3.7 * */ public class SetPropertyValueCommand extends Command { /** * Value constant to indicate that the property is to be reset to its * default value during execute/redo and undo. */ protected static final Object DEFAULT_VALUE = new Object(); /** the value to set for the property */ private Object newValue; /** the old value of the property prior to executing this command */ private Object oldValue; /** the id of the property whose value has to be set */ private Object propertyId; /** the property source whose property has to be set */ private IPropertySource propertySource; /** * Constructs a new {@link SetPropertyValueCommand}. * * @param propertyLabel * A label to identify the property whose value is set by this * command. * @param propertySource * The property source which provides the property, whose value * is to be set. * @param propertyId * The id of the property whose value is to be set. * @param newValue * The new value to set for the property or * {@link #DEFAULT_VALUE} to indicate that the property should be * reset. * @since 3.7 */ public SetPropertyValueCommand(String propertyLabel, IPropertySource propertySource, Object propertyId, Object newValue) { super(MessageFormat.format(GEFMessages.SetPropertyValueCommand_Label, new Object[] { propertyLabel }).trim()); this.propertySource = propertySource; this.propertyId = propertyId; this.newValue = newValue; } /** * @see org.eclipse.gef.commands.Command#canExecute() */ public boolean canExecute() { if (propertySource == null || propertyId == null) { return false; } if (newValue == DEFAULT_VALUE) { // we may only reset a property to its default value if it supports // the notion of a default value and it does not already have this // value boolean canExecute = propertySource.isPropertySet(propertyId); if (propertySource instanceof IPropertySource2) { canExecute &= (((IPropertySource2) propertySource) .isPropertyResettable(propertyId)); } return canExecute; } return true; } /** * @see org.eclipse.gef.commands.Command#execute() */ public void execute() { /* * Fix for bug #54250 IPropertySource.isPropertySet(String) returns * false both when there is no default value, and when there is a * default value and the property is set to that value. To correctly * determine if a reset should be done during undo, we compare the * return value of isPropertySet(String) before and after * setPropertyValue(...) is invoked. If they are different (it must have * been false before and true after -- it cannot be the other way * around), then that means we need to reset. */ boolean wasPropertySet = propertySource.isPropertySet(propertyId); oldValue = unwrapValue(propertySource.getPropertyValue(propertyId)); // set value of property to new value or reset the value, if specified if (newValue == DEFAULT_VALUE) { propertySource.resetPropertyValue(propertyId); } else { propertySource.setPropertyValue(propertyId, unwrapValue(newValue)); } // check if property was set to its default value before (so it will // have to be resetted during undo); note that if the new value is // DEFAULT_VALUE the old value may not have been the default value as // well, as the command would not be executable in this case. if (propertySource instanceof IPropertySource2) { if (!wasPropertySet && ((IPropertySource2) propertySource) .isPropertyResettable(propertyId)) { oldValue = DEFAULT_VALUE; } } else { if (!wasPropertySet && propertySource.isPropertySet(propertyId)) { oldValue = DEFAULT_VALUE; } } } /** * Returns the new value to be set for the property when executing or * redoing. * * @return the new value or {@link #DEFAULT_VALUE} to indicate that the * default value should be set as the new value. * @since 3.7 */ protected Object getNewValue() { return newValue; } /** * After the command has been executed or redone, returns the old value of * the property or {@link #DEFAULT_VALUE} if the property did not have a * value before. * * @return the old value of the property or {@link #DEFAULT_VALUE}. * @since 3.7 */ protected Object getOldValue() { return oldValue; } /** * Returns the id by which to identify the property whose value is to be * set. * * @return the id of the property whose value is to be set. * @since 3.7 */ protected Object getPropertyId() { return propertyId; } /** * Returns the {@link IPropertySource} which provides the property, whose * value is to be set. * * @return the {@link IPropertySource} which provides the property. * @since 3.7 */ protected IPropertySource getPropertySource() { return propertySource; } /** * @see org.eclipse.gef.commands.Command#redo() */ public void redo() { execute(); } /** * @see org.eclipse.gef.commands.Command#undo() */ public void undo() { if (oldValue == DEFAULT_VALUE) { propertySource.resetPropertyValue(propertyId); } else { propertySource.setPropertyValue(propertyId, oldValue); } } private Object unwrapValue(Object value) { if (value instanceof IPropertySource) return ((IPropertySource) value).getEditableValue(); return value; } }