0

Im trying to create an undoredo manager that doesnt matter on what object you pass in. But I cant figure out how to do this in C#. I would like to do something like a pointer to the Original Object and only change where that pointer is pointing to.

C# code

public class UndoableObject<T> : IUndoableAction
{
    private T UndoObject;
    private T ClonedObject;

    private readonly string _name;
    public string Name
    {
        get { return _name; }
    }

    public UndoableObject(ref T ObjectToUndo, string name)
    {
        _name = name;
        UndoObject = ObjectToUndo;
        ClonedObject = ObjectExtensions.Copy<T>(ObjectToUndo);
    }

    public void Redo()
    {
        T temp = ObjectExtensions.Copy<T>(UndoObject);
        UndoObject = ClonedObject;
        ClonedObject = temp;
    }

    public void Undo()
    {
        T temp = ObjectExtensions.Copy<T>(UndoObject);
        UndoObject = ClonedObject;
        ClonedObject = temp;
    }

}

A C++ implementation of what i would like to happen

template<typename T>
public class UndoableObject : IUndoableAction
{
    private T *UndoObject;
    private T *ClonedObject;

    private string _name;
    public string GetName
    {
        return _name;
    }

    public UndoableObject(T *ObjectToUndo, string name)
    {
        _name = name;
        UndoObject = ObjectToUndo;
        ClonedObject = &ObjectExtensions.Copy(*ObjectToUndo);
    }

    public void Redo()
    {
        T *temp = &ObjectExtensions.Copy(*UndoObject);
        delete UndoObject;
        UndoObject = ClonedObject;
        ClonedObject = temp;
    }

    public void Undo()
    {
        T *temp = &ObjectExtensions.Copy(*UndoObject);
        delete UndoObject;
        UndoObject = ClonedObject;
        ClonedObject = temp;
    }

}

I know there are probably memory leaks in it but i wrote up the c++ without compiling it. Hopefully I made some sense.

  • 1
    And what is the question??? Also your current code is only allowing one undo/redo action, then it won't work anymore, only returning the same object... – cramopy Jun 02 '15 at 17:41
  • Different semantics: In C# you have to implement a deep copy (getting a new handle). In C++ you should just copy by value (do not store a pointer) –  Jun 02 '15 at 17:58
  • In C# `class` types are "refrence types", basically a pointer. In your head any time in C# you use a `.` with a `class` type, replace it with a `->`. so `UndoableObject(ref T ObjectToUndo, string name)` is actually `UndoableObject(T& ObjectToUndo, const string *name)` in C++. If you dropped the `ref` you would get `UndoableObject(T *ObjectToUndo, const string *name)` – Scott Chamberlain Jun 02 '15 at 20:07

1 Answers1

1

Have a look at the following:

//using System;
//using Sytem.Collections.Generic
public class UndoableObject<T>
{
    List<T> _list = new List<T>();
    string _name;
    int _step = 0;

    public UndoableObject(T source, string name)
    {
        _list.Clear();
        _list = new List<T>();
        _list.Add(source);
        _name = name;
        _step = 0;
    }

    public string GetName
    {
        get { return _name; }
    }

    public void Record(T item)
    {
        _list.Add(item);
        _step++;
    }

    public T Undo()
    {
        _step--;
        if (_step >= 0)
        {
            return _list[_step];
        }
        else
        {
            _step = 0;
            return _list[_step];
        }
    }

    public T Redo()
    {
        _step++;
        if (_step < _list.Count)
        {
            return _list[_step];
        }
        else
        {
            _step = _list.Count - 1;
            return _list[_step];
        }
    }
}

Basic Usage:

var pictureBox1 = new PictureBox();
var _bitmap = new Bitmap(300, 300);
var uo = new UndoableObject<Bitmap>(_bitmap, "bitmap");

Undo:

pictureBox1.Image = uo.Undo();

Record:

uo.Record((Bitmap)pictureBox1.Image);

Redo:

pictureBox1.Image = uo.Redo();
cramopy
  • 3,459
  • 6
  • 28
  • 42