Undo Function for my Tool


#1

Hi,

at the moment I’m working on a tool to visualize data. The tool is able to save and restore the data when you click the “Save” button. But that function only saves the then prepared and calculated data, not all the settings in various menus or temporary variables.
Now I want to create a function that I can call whenever the user made a significant change. My dream would be to dump the complete RAM at that moment and later, when the user decides to undo his previous (5 or less) actions, load that data.
Is something like that possible?

Max


#2

Ovbiously I mean is there a clean way to do it?

If not I could create a class where all variables are stored and save an instance of that class in an ArrayList…
I want to die.


#3

There is not a clean way to do it.

You should create a class where all the variables are stored and save an instance of that class in an ArrayList.


Actually, depending on your data, you might be able to record not a snapshot of the entire data set, but rather just what the last 5 changes made to it were. Example: Let’s say the user does the following six actions:

  1. Set redness from 180 to 90.
  2. Adjust size from 30 to 160.
  3. Turn up volume by 154%.
  4. Recombobulate the entire data set.
  5. Pull the latest weather info from an external site.
  6. Scribble a doodle over the UI.

To undo 6, you’d just need to redraw the UI without it.
To roll back 5, you’d need that full copy of the previous data. Yikes.
To undo 4, you’d need a backup of that data. Everyone knows that you can’t de-recombobulate something (it’s a one-way operation).

Those are the cases where you’d be backing things with a class, probably.

But for the first three, they are just value changes. You need not record the entire data set, just the fact that “volume”, “size”, and “redness” were what were changed, and the amounts they were previously.


#4

I tried this now but it only stores a reference so when I change a value also the stored value is changed. Do you know how to fix that?
It’s similar to the arrayCopy problem…

Variables var = new Variables();
ArrayList<Variables> = new ArrayList<Variables>();

void setup() {

}

void draw() {
  println(var.value);
}

class Variables {
  int value = 0;
}

void mousePressed() {
  var.value++;
}

void keyPressed() {
  if (key == 's') {
    var_list.add(var);
    println("stored @ " + (var_list.size()-1));
  } else if (key == 'u') {
    if (var_list.size() != 0) {
      var = new Variables();
      var = var_list.get((var_list.size()-1));
      println("undone to " + (var_list.size()-1));
    }
  }
}

You can use the debugger to see the value in the ArrayList changeing aswell…


#5

Yeah, I see your problem. Add a deepCopy method to you class that creates a clone of the class, not a reference to it. Working example:

Variables var = new Variables();
ArrayList<Variables> var_list= new ArrayList<Variables>();

void setup() {
  size(400, 400);
}

void draw() {
  background(0);
  stroke(255);
  text(var.value, 20, 20);
}

class Variables {
  int value = 0;
  Variables deepCopy() {
    Variables clone = new Variables();
    clone.value = value;
    return clone;
  }
}

void mousePressed() {
  var.value++;
}

void keyPressed() {
  if (key == 's') {
    var_list.add(var.deepCopy());
    println("stored value " + var.value + " at position " + (var_list.size()-1) );
  } else if (key == 'u') {
    if (var_list.size() > 0) {
      var = var_list.get((var_list.size()-1));
      var_list.remove((var_list.size()-1));
      println( "" );
      println("restored the value of " + var.value + " from stored position " + (var_list.size()) );
      println( "new stored size is " + (var_list.size()) );
    } else {
      println( "" );
      println( "can't undo - no more stored values" );
    }
  }
}

#6

Yeah that’s what I figured out too.

Here are some parts for different variable types in case someone wants to do something similar:

// an int / float / single variable
this.X_MIN = v.X_MIN;

// a float array
this.supports_xparallel = new float[v.supports_xparallel.length];
arrayCopy(v.supports_xparallel, this.supports_xparallel);

// a multi dimensional array (this is not perfect but it works)
this.iso_line_points = new float[v.iso_line_points.length][v.iso_line_points[0].length][v.iso_line_points[0][0].length];
for (int a = 0; a < v.iso_line_points.length; a++) {
  for (int b = 0; b < v.iso_line_points[a].length; b++) {
    for (int c = 0; c < v.iso_line_points[a][b].length; c++) {
      this.iso_line_points[a][b][c] = v.iso_line_points[a][b][c];
    }
  }
}

// an arrayList
this.data.clear();
for (int i = 0; i < v.data.size(); i++) {
  this.data.add(v.data.get(i));
}

#7