[comp.sys.mac] MacApp's undo ability.

pgtrubey@watlion.UUCP (03/09/87)

Somebody a while back mentioned something about extending MacApp
to allow for multiple undo operations as opposed to just being
able to undo the latest command.

Is there a reason why this wasn't implemented in MacApp? 

It seems to me that it wouldn't be too hard given the current MacApp
framework.  Instead of MacApp <Commit>ing the last command before
<Doit>ing the current one, why couldn't it keep all the commands 
on a stack and thus it could successively undo each operation.
I guess as you undid commands, you would have to keep another stack
to be able to redo each command.

The only problem that I see is when to <Commit> the commands.  You could
either allow a maximum undo stack, or you could commit commands only when
something like a file save was being performed.

Is this resonable, or have I overlooked something?
-- 
Phil Trubey      
pgtrubey@watlion.UUCP  !{allegra,clyde,decvax,ihnp4}!watmath!watlion!pgtrubey
pgtrubey%watlion%waterloo.csnet@csnet-relay.ARPA
pgtrubey%watlion@waterloo.CSNET

wetter@tybalt.caltech.edu.UUCP (03/11/87)

In article <7932@watlion.UUCP> pgtrubey@watlion.UUCP writes:
>Somebody a while back mentioned something about extending MacApp
>to allow for multiple undo operations as opposed to just being
>able to undo the latest command.
>
>
>It seems to me that it wouldn't be too hard given the current MacApp
>framework.  Instead of MacApp <Commit>ing the last command before
><Doit>ing the current one, why couldn't it keep all the commands 
>on a stack and thus it could successively undo each operation.
>I guess as you undid commands, you would have to keep another stack
>to be able to redo each command.

    Another way to do this would be two have another method "Uncommit". This 
method would perform an undo for a command already commited. This also requires
that there be an undo data stack to handle the data the command needs to 
uncommit. This is assuming the command is freed after it is committed. The 
alternative is to have a lot of command objects sitting in your heap (yech).>

>The only problem that I see is when to <Commit> the commands.  You could
>either allow a maximum undo stack, or you could commit commands only when
>something like a file save was being performed.

  A rational limit for a command stack would be from 2-4 (>4 might cause 
innumerable side effects between undos. if you undo a change to a deleted object
do you undo the delete too?). Also needed would be another menu command. Undo #
since undo toggles between undo and redo. What about if the user only wants
to undo one of the commands on the stack? Should there be four commands
undo "commandname" X 4? I'm not sure this is worth the trouble.

     Good luck.   Pierce Wetter.

Magnet, n.: Something acted upon by magnetism

Magnetism, n.: Something acting upon a magnet.

The two definition immediately foregoing are condensed from the works
of one thousand eminent scientists, who have illuminated the subject
with a great white light, to the inexpressible advancement of human
knowledge.
		-- Ambrose Bierce, "The Devil's Dictionary"

--------------------------------------------

wetter@tybalt.caltech.edu

--------------------------------------------

jww@sdcsvax.UUCP (03/12/87)

I believe the reason is that multi-level undo is not the standard
interface, a top requirement for MacApp.

If you want multi-level undo, you need to define an interface for
multi-level undo.  You probably ought to make 'undo' a compound 
menu or call a dialog box with a list of choices to be undone.
-- 
	Joel West
	{ucbvax,ihnp4}!sdcsvax!jww	(ihnp4!gould9!joel once I fix news)
	jww@sdcsvax.ucsd.edu	if you must

lsr@apple.UUCP (03/13/87)

In article <7932@watlion.UUCP> pgtrubey@watlion.UUCP writes:
>Somebody a while back mentioned something about extending MacApp
>to allow for multiple undo operations as opposed to just being
>able to undo the latest command.
>
>Is there a reason why this wasn't implemented in MacApp? 

Mostly complexity of implementation in MacApp and complexity of programming
with that model.  Also, there was no user interface defined for multiple
levels of Undo.

We tried to provide an Undo framework that could be extended to support
multiple-level Undo if a programmer wanted it.  There are methods one could
override in order to save multiple command objects.

>The only problem that I see is when to <Commit> the commands.  You could
>either allow a maximum undo stack, or you could commit commands only when
>something like a file save was being performed.

A lot depends on the implementation of the command.

Commit is usually implemented for commands that postpone changing the
internal data structures until the last minute.  But the application
displays the data structure as if it had been changed.

For example, if you take an entire word processor document and change it to
bold, then it is impractical to remember all the previous style changes in
order to undo the command.  Instead, you show the user the document as if it
was bold, but don't change the data structures until the command is
committed.

In the case of saving multiple commands, your application has to be able to
apply multiple changes to its data structures.  (The user might have done
bold, then italic.)  

If you only save a limited number of command objects, then you could call
Commit when one of the command objects "falls off the end", just before it
is freed.

One complication is that some operations (e.g., Save) would require that
all pending commands be committed.  This is for convenience, since
committing all the commands brings the data structures up-to-date, so that
they can be written out to disk.  


-- 
Larry Rosenstein

Object Specialist
Apple Computer

AppleLink: Rosenstein1
UUCP:  {sun, voder, nsc, mtxinu, dual}!apple!lsr
CSNET: lsr@Apple.CSNET

lsr@apple.UUCP (03/13/87)

In article <1999@cit-vax.Caltech.Edu> wetter@tybalt.caltech.edu.UUCP (Pierce T. Wetter) writes:
>
>    Another way to do this would be two have another method "Uncommit". This 
>method would perform an undo for a command already commited. This also requires

In general, this would not work.  The main reason for a command object
having a Commit method is that saving the state necessary to undo the
command is impractical.  

Consider MacDraw.  You select 1,000 objects and change their fills to
white.  To remember the fill pattern of all the objects would require about
as much memory as the entire document.  

Instead, you "make believe" the objects are white, but don't change the data
structures until the command is committed.  Once it was committed, there
would be no way to uncommit it, for the same reason as above.

>  A rational limit for a command stack would be from 2-4 (>4 might cause 
>innumerable side effects between undos. if you undo a change to a deleted object
>do you undo the delete too?). Also needed would be another menu command. Undo #
>since undo toggles between undo and redo. What about if the user only wants
>to undo one of the commands on the stack? Should there be four commands
>undo "commandname" X 4? I'm not sure this is worth the trouble.

As long as the number of saved commands is >1, you have this problem.  The
easiest thing to do is to undo commands in the reverse order in which they
were done.  You could then add a separate Redo command that repeats the
commands in the original order.  

Now this is not always what the user wants to do.  S/he might have decided
that clearing that object 15 minutes ago was a mistake and wants to get it
back, but still wants to keep the rest of the changes made in the past 15
minutes.  

That is a very tricky problem, both from a user interface point of view and
from a programming point of view.  For more information about it, look at
the article "US&R: A New Framework for Redoing" by Jeffrey Vitter; IEEE
Software, October 1984.  US&R stands for Undo, Skip, and Redo.  This
mechanism gives users the maximum flexibility in undoing and reordering
commands.

-- 
Larry Rosenstein

Object Specialist
Apple Computer

AppleLink: Rosenstein1
UUCP:  {sun, voder, nsc, mtxinu, dual}!apple!lsr
CSNET: lsr@Apple.CSNET