Undo grouping problem

  • I'm trying to set up the following situation:

    I start creating an object that will require multiple user actions to
    create. I want each action to be undoable during the object's
    creation phase, but once the object is created I want an undo to
    completely remove the object (and redo would completely recreate it).

    I start off calling beginUndoGrouping before the new object is added
    to the document, and register an undo action that will remove the
    object.
    at each phase or creation I register an undo action that will back
    that phase out.
    when the object is complete I call endUndoGrouping.

    This seems to work for the outside case, that is, after the object is
    completely created it will remove (or re-create) the entire object.

    During object creation though I get the message: undo: NSUndoManager
    0x31aae0 is in invalid state, undo was called with too many nested
    undo groups.

    What am I missing here?

    Matt Brandt
    <mattb...>
  • Hello Matt,

    > I start creating an object that will require multiple user actions
    > to create. I want each action to be undoable during the object's
    > creation phase, but once the object is created I want an undo to
    > completely remove the object (and redo would completely recreate it).

    I'm not sure because I'm a cocoa-newbie, but I would have tried the
    following (no idea if it works):

    1. While you create your object in single steps, put the undo-
    operations UNGROUPED on the stack.
    -> You should be able to undo every single step while you create it.

    2. Once your object is complete, you remove the previous single undo-
    operations for your object with [undo
    removeAllActionsWithTarget:yourObject];. Directly after that, you put
    the whole bunch of single undo-operations back on the stack, but this
    time you put them in an undo-group with:

    [undo beginUndoGrouping];
      [[undo prepareWithInvocationTarget:yourObject] doSingleStep];
      [[undo prepareWithInvocationTarget:yourObject] doAnotherSingleStep];
      [[undo prepareWithInvocationTarget:yourObject]
    doATotallyOtherSingleStep];
    [undo endUndoGrouping];

    -> You should now be able to undo the whole object with one click.

    If someone knows how to do it easier (or if my solution is totally
    wrong...) I'm interested in it too, because at the time I'm doing my
    first attempts with the undo manager...

    Jens Beuckenhauer
    <beuckenhauer...>
  • On Dec 30, 2006, at 1:18 AM, <pocahontius...> wrote:

    > 1. While you create your object in single steps, put the undo-
    > operations UNGROUPED on the stack.
    > -> You should be able to undo every single step while you create it.
    >
    > 2. Once your object is complete, you remove the previous single
    > undo-operations for your object with [undo
    > removeAllActionsWithTarget:yourObject];. Directly after that, you
    > put the whole bunch of single undo-operations back on the stack,
    > but this time you put them in an undo-group with:
    >
    > [undo beginUndoGrouping];
    > [[undo prepareWithInvocationTarget:yourObject] doSingleStep];
    > [[undo prepareWithInvocationTarget:yourObject] doAnotherSingleStep];
    > [[undo prepareWithInvocationTarget:yourObject]
    > doATotallyOtherSingleStep];
    > [undo endUndoGrouping];
    >
    > -> You should now be able to undo the whole object with one click.
    >

    This an interesting idea, but I would need to create a separate owner
    for grouped objects, or they will all get removed when I go to group
    the next creation group. Sort of a kludge, but it seems doable.

    There must be a more elegant method though...

    Matt Brandt
    <mattb...>
  • Hi Matt,

    On 2006-12-30, at 17:23, Matt Brandt wrote:

    > I start off calling beginUndoGrouping[...]
    >
    > What am I missing here?

    You can't use undo groupings like that; you can't undo whilst still
    in a grouping. The way I'd do this is to subclass NSUndoManager and
    add another grouping level, like [undoManager beginUndoBatch] or
    something. Then when -undo is called, call [super undo] for each
    action added to the batch. It feels slightly more complicated than
    this, though.

    Jonathon Mah
    <me...>
  • On Dec 30, 2006, at 10:16 PM, Jonathon Mah wrote:

    > You can't use undo groupings like that; you can't undo whilst still
    > in a grouping. The way I'd do this is to subclass NSUndoManager and
    > add another grouping level, like [undoManager beginUndoBatch] or
    > something. Then when -undo is called, call [super undo] for each
    > action added to the batch. It feels slightly more complicated than
    > this, though.

    That seems like a pretty good solution. It seems odd that this sort
    of thing wouldn't be taken care of by the standard NSUndoManager
    though. I didn't think what I was trying to do was all that weird...

    Thanks for the idea.

    Matt Brandt
    <mattb...>
previous month december 2006 next month
MTWTFSS
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Go to today