Using the undo manager on repeated events


#1

When using the undomanager with the knob controlled by the mouse I do:

void mouseDown(const MouseEvent& e)
{
  um->beginNewTransaction();
  um->perform(new Foo());
}

void mouseDrag(const MouseEvent& e)
{
  um->undoCurrentTransactionOnly();
  um->perform(new Foo());
}

void mouseUp(const MouseEvent& e)
{
  um->beginNewTransaction();
}

Now I want to do the same thing for a midi knob. But there is no equivalent to mouseDown() or mouseUp()

Any idea how to do this?

I was thinking of starting a new named transaction, then on each midi message, check if the last transaction has the correct name, and if it does, undoCurrentTransactionOnly() and then perform().

But I’m not really sure how to tell when the knob stops turning, I don’t want to use a timer, since the user may have already started doing something else.

Any ideas?


#2

Is it a Slider? If so, you can catch the sliderDragStarted() and ended events (which I seem to remember adding for exactly this purpose…)


#3

No, its an actualy physical knob on a piece of hardware.


#4

ah, sorry - I should probably have read your post more carefully!

That is a bit tricky, isn’t it. What would be nice would be if the last transaction had a timestamp - then you could merge the new one with the last if it is the same type and happens within a certain time period.

How about if we add a method to the UndoManager to return a list of the UndoableActions in the current transaction. Then you can scan through them, do a dynamic cast to see if they’re the right type, and you can add a timestamp to your action class to see when they happened. Then if there aren’t any other rogue actions in the list caused by the user doing something else, you can undo.

Here’s my suggestion for such a method - shout if it works (or if I’ve missed the point again!)

void UndoManager::getActionsInCurrentTransaction (Array <const UndoableAction*>& actionsFound) const
{
    const OwnedArray <UndoableAction>* const commandSet = transactions [nextIndex - 1];

    if (commandSet != 0 && ! newTransaction)
    {
        for (int i = 0; i < commandSet->size(); ++i)
            actionsFound.add (commandSet->getUnchecked(i));
    }
}

#5