beginNewTransaction and Values

I’m setting values and I’ve assigned an undoManager. Problem is, every time I undo, everything since the last beginNewTransaction undoes, not just the last user action.

I think that I only need to use beginNewTransaction when I am setting parameters via code - it seems like everything a control sets should always call beginNewTransaction, or we need a better way to group transactions.

Is there a common workaround to this?


I usually start a timer for maybe 1 second when a change is made, and let the timer start a new transaction. That way streams of continuous changes keep restarting the timer, and only when the user pauses does a transaction get registered.

Hmm. But even then some user actions will get lumped together that they may not want?

Wouldn’t you say this seems like a bodge, and that it’s extra work (and timer and code execution) for the 90%, where the 10% is cases where actions need to be undone or done together?

Wouldn’t an ‘end transaction’ or similar work better?


Edit - plus if I have different values, I’m going to be scattering timers and begins around my code so that any of them will trigger a begin.

No, it’s not a bodge! I’d say it’s exactly what you expect to happen - lump together events that happen in quick succession, and have transactions when there’s a pause in activity. Your use-case may be different, but this pattern has always worked very well for things I’ve done.

So… if I wait for a pause in activity, then start a new transaction, what does the next undo get? The previous transaction?

FYI - a begintransaction with “” instead of String::empty seems to bork the system. Maybe an assertion is needed?

Yes, if you haven’t added any UndoableActions to the current transaction. Otherwise the current transaction will be undone.

I presume this is why you need to specify the name at the start of the transaction, there is no real end to a transaction, just current and previous (unless you’ve already undone some that can then be redone of course.)

I can’t see how that could possibly be the case… String::empty and “” are exactly equivalent when passed to that method. When you say it broke, what actually happened, and in what context?

When I used “” no undo’s happened, and changing to empty fixed it. Could that maybe affect the canUndo () that I was using to enable the command?

No… I really think you must be mis-diagnosing that one - there’s no way it could behave any differently.

Yes, I guess I was. Undo is now intermittant - sometimes new actions don’t seem undoable, it varies from run to run. At a guess, some values don’t have the undomanager, or something crazy, but that’s almost impossible - it’s set from a global shared variable (yeah yeah).

Will have to dig.


Hi Bruce. Any chance your undo transaction is causing an undoable action to occur? It’s been awhile since I ran into the problem so I might not be recalling exactly but I do recall having a situation where undoing would cause a valuetree listener to be invoked which would then perform an undoable action, which subsequently borked the undo state. Maybe you have something like that happening?

Well, it’s all Values, using the juce controls having their Value linked to my Values. And yes, there’s ValueTree::Listeners - that’s the point in this design, to do something when the user moves a control.

I’ll look for that issue - Undoable actions wrecking the undo state, thanks Graeme.

I thought I was using this all for its intended purpose. :x


Well UndoManager::perform does have a reentrancy check for catching what I described, and a simple test here verifies that it does work. If there was a bug with it I would have reported it so in my case it’s unlikely that there was a failure of that. But it was something like I described anyway, I’m sorry I can’t remember exactly what it was.

Thanks. I’ll look. I need to work out some vagaries of Values anyway. They’re deceptively simple, until something is odd.