001/**
002 * 
003 */
004package plugins.tutorial.undo;
005
006import icy.math.ArrayMath;
007import icy.plugin.abstract_.PluginActionable;
008import icy.sequence.Sequence;
009import icy.sequence.edit.AbstractSequenceEdit;
010import icy.type.collection.array.Array1DUtil;
011
012import javax.swing.undo.CannotRedoException;
013import javax.swing.undo.CannotUndoException;
014
015/**
016 * This plugin demonstrate how to use the Undo framework with 'redo' operation support.
017 * 
018 * @author Stephane
019 */
020public class AdvancedUndo extends PluginActionable
021{
022    /**
023     * Create the Undoable operation class
024     * 
025     * @author Stephane
026     */
027    class DivideOperation extends AbstractSequenceEdit
028    {
029        final double divisor;
030
031        public DivideOperation(Sequence sequence, double divisor)
032        {
033            super(sequence, "Divide intensity");
034
035            this.divisor = divisor;
036            // consider the operation as "not done" by default
037            hasBeenDone = false;
038        }
039
040        @Override
041        public void undo() throws CannotUndoException
042        {
043            super.undo();
044
045            final Sequence seq = getSequence();
046            final Object data = seq.getDataXY(0, 0, 0);
047
048            // convert to double
049            final double[] doubleArray = Array1DUtil.arrayToDoubleArray(data, seq.isSignedDataType());
050            // multiply intensity by 2
051            ArrayMath.multiply(doubleArray, 2d, doubleArray);
052            // copy data back to image
053            Array1DUtil.doubleArrayToArray(doubleArray, data);
054            // notify sequence we changed its data
055            seq.dataChanged();
056        }
057
058        @Override
059        public void redo() throws CannotRedoException
060        {
061            super.redo();
062
063            final Sequence seq = getSequence();
064            final Object data = seq.getDataXY(0, 0, 0);
065
066            // convert to double
067            final double[] doubleArray = Array1DUtil.arrayToDoubleArray(data, seq.isSignedDataType());
068            // divide intensity by 2
069            ArrayMath.divide(doubleArray, 2d, doubleArray);
070            // copy data back to image, note that here we can loss information (double --> whatever
071            // type conversion) so the redo operation won't correctly restore original data
072            Array1DUtil.doubleArrayToArray(doubleArray, data);
073            // notify sequence we changed its data
074            seq.dataChanged();
075        }
076    }
077
078    @Override
079    public void run()
080    {
081        final Sequence seq = getActiveSequence();
082
083        if (seq != null)
084        {
085            final Object data = seq.getDataXY(0, 0, 0);
086
087            // have some data here ?
088            if (data != null)
089            {
090                final DivideOperation op = new DivideOperation(seq, 2d);
091
092                // execute operation
093                op.redo();
094                // add as undoable edit
095                seq.addUndoableEdit(op);
096            }
097        }
098    }
099}