I have an image processing app and I intend to implement a functionality that will let a user undo and redo image operations. For this, I chose a List data structure where when user performs an image operation, I add the result bitmap to this List. When user clicks undo button then what I do is I use an index to return the Bitmap that got added last to the list and for redo I just return the Bitmap in the next index. The code works in undoing operations until it reaches the last index and returns an index out of bounds exception despite handling that with some custom logic that checks if index is less than 0 and resets it to 0. The same problem occurs when the user tries to redo past the last item on the list. Below is my code and thanks in advance.
//in class declaration of the list object
private List<Bitmap> Queue = new List<Bitmap>() ;
//index to help the user perform undo and redo operations
private int indexer = 0;
The index declared above is updated to point to the last Bitmap in the List like below
//image operation
//add image to list
Queue.Add(bitmap);
//point to the last image in the list
indexer = Queue.Count-1;
Now the event handler that executed the undo operation looks like below.
case Resource.Id.action_do:
//check if the lost contains at least one image
if(Queue.Count > 0){
//handle undo past 0
if(indexer < 0){
//reset
indexer = 0;
}else{
indexer -= 1;
}
//update the image to UI
var bmp = Queue.ElementAt(indexer);
pictureBox1.SetImageBitmap(bmp);
}
break;
Whilst the redo command is executed like below
case Resource.Id.action_redo:
if(Queue.Count > 0) {
if(indexer > Queue.Count){
indexer = Queue.Count-1;
}else{
indexer += 1;
}
}
break;
How to I make it return the Bitmap at index 0 if it's going to the negative side and make it return the Bitmap at the last index if user is trying to redo past the last bitmap on the collection?
if(indexer < 0){
//reset
indexer = 0;
}else{
indexer -= 1;
}
What will happen if the index is zero? It is not less than zero, so you will subtract one, resulting in a negative indexer resulting in your error. Changing the check to to <=
should fix the issue. You are not posting your redo-logic, but it might have a similar error.
I would recommend disabling the undo button if index <= 0
and the redo button if index >= Queue.Count-1
. Do note that these cases can occur simultaneously.
I would encourage you to learn how to use the debugger. That should make problems like this fairly obvious. Either just "break on exception", and check what the variables values after the error has occurred. Or place a break point at some suitable place, and step thru the code, verifying that it behaves as you expect it to.
You will also need to be careful when you undo something and then perform another action, since this should clear any redo-actions. Using separate undo and redo stack instead of a common list may make all of this significantly easier.
Note that just keeping a bitmap will likely be fairly limited in what operations you can support. You would often want to model changes as a user-visible stack of modifications, so the user can change parameters without needing to undo and redo all subsequent work. For this you will need a more complex undo/redo model.