/* * Copyright (c) 2008 Stiftung Deutsches Elektronen-Synchrotron, * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY. * * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS. * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION, * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM */ package org.csstudio.sds.ui.internal.properties.view; import java.text.MessageFormat; import java.util.EventObject; import org.csstudio.sds.ui.internal.commands.SetDynamicsDescriptorCommand; import org.csstudio.sds.ui.internal.localization.Messages; import org.eclipse.gef.commands.CommandStack; import org.eclipse.gef.commands.CommandStackListener; import org.eclipse.gef.commands.CompoundCommand; import org.eclipse.gef.commands.ForwardUndoCompoundCommand; /** * <p> * UndoablePropertySheetEntry provides undo support for changes made to * IPropertySources by the {@link PropertySheetViewer}. Clients can construct a * {@link PropertySheetPage} and use this class as the root entry. All changes * made to property sources displayed on that page will be done using the * provided command stack. * <p> * <b>NOTE:</b> If you intend to use an IPropertySourceProvider for a * PropertySheetPage whose root entry is an instance of of * UndoablePropertySheetEntry, you should set the IPropertySourceProvider on * that root entry, rather than the PropertySheetPage. */ public final class UndoablePropertySheetEntry extends PropertySheetEntry { /** * A command stack listener. */ private CommandStackListener _commandStackListener; /** * A command stack. */ private CommandStack _stack; /** * Private default constructor. */ private UndoablePropertySheetEntry() { } /** * Constructs the root entry using the given command stack. * * @param stack * the command stack * @since 3.1 */ public UndoablePropertySheetEntry(final CommandStack stack) { setCommandStack(stack); } /** * {@inheritDoc} */ @Override protected PropertySheetEntry createChildEntry() { return new UndoablePropertySheetEntry(); } /** * {@inheritDoc} */ @Override public void dispose() { if (_stack != null) { _stack.removeCommandStackListener(_commandStackListener); } super.dispose(); } /** * Gets the command stack. * * @return the command stack */ CommandStack getCommandStack() { // only the root has, and is listening too, the command stack if (getParent() != null) { return ((UndoablePropertySheetEntry) getParent()).getCommandStack(); } return _stack; } /** * {@inheritDoc} */ @Override public void resetPropertyValue() { CompoundCommand cc = new CompoundCommand(); ResetValueCommand restoreCmd; if (getParent() == null) { // root does not have a default value return; } // Use our parent's values to reset our values. boolean change = false; Object[] objects = getParent().getValues(); for (int i = 0; i < objects.length; i++) { IPropertySource source = getPropertySource(objects[i]); if (source.isPropertySet(getDescriptor().getId())) { // source.resetPropertyValue(getDescriptor()getId()); restoreCmd = new ResetValueCommand(); restoreCmd.setTarget(source); restoreCmd.setPropertyId(getDescriptor().getId()); cc.add(restoreCmd); change = true; } } if (change) { getCommandStack().execute(cc); refreshFromRoot(); } } /** * Sets the command stack. * * @param stack * the command stack */ void setCommandStack(final CommandStack stack) { this._stack = stack; _commandStackListener = new CommandStackListener() { @Override public void commandStackChanged(final EventObject e) { refreshFromRoot(); } }; stack.addCommandStackListener(_commandStackListener); } /** * {@inheritDoc} */ @Override protected void valueChanged(final PropertySheetEntry child) { valueChanged((UndoablePropertySheetEntry) child, new ForwardUndoCompoundCommand(MessageFormat.format( Messages.SetPropertyValueCommand_label, new Object[] { child.getDescriptor().getDisplayName(), child.getValues().length }).trim())); } /** * Called, when a value is changed. * * @param child * the child property sheet entry * @param command * a compound command, which should collect the single * SetValueCommands, when multiple properties are changed in one * step */ void valueChanged(final UndoablePropertySheetEntry child, final CompoundCommand command) { CompoundCommand cc = new CompoundCommand(); command.add(cc); SetValueCommand setCommand; for (int i = 0; i < getValues().length; i++) { setCommand = new SetValueCommand(child.getDisplayName(), child .getDescriptor().getId(), child.getValues()[i], getPropertySource(getValues()[i])); cc.add(setCommand); } // inform our parent if (getParent() != null) { ((UndoablePropertySheetEntry) getParent()).valueChanged(this, command); } else { // I am the root entry _stack.execute(command); } } /** * {@inheritDoc} */ @Override protected void dynamicDescriptorChanged(final PropertySheetEntry child) { dynamicDescriptorChanged((UndoablePropertySheetEntry) child, new ForwardUndoCompoundCommand(MessageFormat.format( Messages.SetDynamicsDescriptorCommand_label, new Object[] { child.getDescriptor().getDisplayName(), child.getValues().length }).trim())); } /** * Called, when a dynamics descriptor is changed. * * @param child * the child property sheet entry * @param command * a compound command, which should collect the single * SetValueCommands, when multiple properties are changed in one * step */ void dynamicDescriptorChanged(final UndoablePropertySheetEntry child, final CompoundCommand command) { CompoundCommand cc = new CompoundCommand(); command.add(cc); SetDynamicsDescriptorCommand setCommand; for (int i = 0; i < getValues().length; i++) { setCommand = new SetDynamicsDescriptorCommand(child .getDisplayName(), child.getDescriptor().getId(), child .getDynamicsDescriptor(i), getPropertySource(getValues()[i])); cc.add(setCommand); } // inform our parent if (getParent() != null) { ((UndoablePropertySheetEntry) getParent()).valueChanged(this, command); } else { // I am the root entry _stack.execute(command); } } }