Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Undo Operations

by artist (Parson)
on Nov 14, 2003 at 16:23 UTC ( [id://307089]=perlquestion: print w/replies, xml ) Need Help??

artist has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,
In many applications I see 'Undo' feature. For example Microsoft Word or Photoshop or even Emacs editor. How I can achieve the similar effect in Perl? For example see the following code.

#!/usr/local/bin/perl use Data::Dumper; my $hash = { a => 21, b => 32, c => 43 }; my $array = [ 11,12,13,14]; foreach (1..3){ perform_operationX(); print_data(); } cancel_last_operationX(2); sub perform_operationX { my $letter = chr(97+ int rand(10)); my $number = int rand(100); $hash->{$letter} = $number; shift @$array; } sub print_data{ print Dumper($hash,$array); } sub cancel_last_operationX { my $number_of_operations = shift; ......... UNDO CODE ............. }
In order to achieve this if we have to save the state of the previous operation how do we do it? An reading/code/material/module etc would be useful.

Thank You
{Artist}

Replies are listed 'Best First'.
Re: Undo Operations
by Corion (Patriarch) on Nov 14, 2003 at 16:36 UTC

    The only discussion I have seen of this feature is the Gang of Four book on Design Patterns. They call it the "Action Pattern" there, and the idea is quite simple :

    In your program, you have (named) actions, that the user can execute, for example in Word, insert a character, insert a word, insert a range, delete a character, delete a word, delete a range. Cutting and pasting text can be modeled as deleting and inserting of several words and characters. Every Action is put into a list, which will be called the "undo list" for obvious reasons. Now, inverting an action is very simple for insert and delete actions, and if you take an object oriented approach, you can simply make it that every action knows how to undo itself.

    These actions must be wedged inbetween the model and the controler if you have an MVC approach. If you don't have an MVC approach, I have no idea how you will find all the possible locations where you need to put special registering code.

    Note that the undo list and the code needed for it also makes your application very easily scriptable, as a script is nothing more than a saved "do"-list - you just need a way to tell your actions whether they should do or undo themselves.

    perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web
Re: Undo Operations
by IlyaM (Parson) on Nov 14, 2003 at 16:36 UTC
Re: Undo Operations
by TomDLux (Vicar) on Nov 14, 2003 at 17:46 UTC

    I know of three approaches to UnDo. Depending on your application, one of these may be better suited than the others.

    • Each time the user makes a change, save a backup copy of the work-in-progress before making the change. In a graphics program, you might save a copy of the image prior to the change in contrast, prior to the blurring, prior to the image rotation. These backups are large and memory-expensive, so you would only keep a small number, say the last three. Most of the time, the important aspect is to be able to undo the last step, thus encouraging exp[erimentation. On the plus side, undo is a trivial operation, simply swap the displayed image and the backup image, and enable the ReDo button.
    • Keep a list of the operations performed. This is a natural for object-oriented graphics. To drop a change, drop the last item on the list. If an object is moved, you have a choice between creating it in its original location and then moving it, or modifying the original creation point, but appending at the end of the performance list an invisible entry with the information needed to revert to the original location. The list is gentler on your memory usage than keeping entire images, but in typical memory/cpu trade-off, it can sometimes require a lot of proceessing to generate the final image.
    • Solution two is not suitable for a word processor storing War and Peace. Instead, keep a list of nodes which specify how to UnDo/ReDo. This works well for a word processor, where it is possible to undo both insert 'Praise the Lord!' at position 65535 and delete 'Praise the Lord!' from position 65535, but not for a graphics program, where there is not an inverse operation for blurring. Generally, this approach is good for an undo list longer than supported than Solution one, yet shorter than Solution two. You might implement a list of a dozen or a hundred entries, or back to the most recent Save.

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re: Undo Operations
by hmerrill (Friar) on Nov 14, 2003 at 16:47 UTC
    If you need an 'undo' feature, the typical thought that comes to my mind is:
    1. make a *before* copy of the data 2. let the user make changes to the data 3. if changes were made, ask the user if he/she wants to keep those changes 4. if user wants to keep changes, move or copy the new data to the *current* data if user does not want to keep changes, move or copy *before* data to *current* data
    That's kind of a simplistic method, but I think it achieves the goal. Is that what you were looking for?

    Hope this helps.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://307089]
Approved by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2024-04-23 23:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found