UndoManager listening


#1

Hi there,

I’m wondering how I can get the UndoManager’s changelistener to only react to undo()/redo() calls?
The changeListenerCallback() seems to be called when values are set (e.g. passing the undomanager to CachedValue::setValue calls).
Right now, I figured that this works but seems hacky:

void Main_VC::UndoListener::changeListenerCallback(ChangeBroadcaster* source)
{
if (auto* undo_man = dynamic_cast<UndoManager*>(source))
{
if (!undo_man->getNumActionsInCurrentTransaction())
{
// react to undo()
}
}
}


#2

What’s the use-case?


#3

Basically just trying to update the UI when the user undos.
The UI reacts to CachedValues which are also fed the undomanager when they are set.
So I wrote the above method in order to make repaint() calls.


#4

Sure, but what are you updating? e.g. a typical example is an undo button which should be disabled if you can’t undo, and that’s easy to do by making it a listener, and then enabling it if undoManager.canUndo() is true.

And if you want to e.g. flash a button to show that an undo operation is happening, the best pattern is not to make it follow changes to the undomanager, but to make it respond to application commands directly.


#5

I see, maybe the pattern i’m using is bad.
I’m working on a grid sequencer where the notes are cachedvalues and stored in a valuetree. I.e. clicking on the grid sets the cachedvalue and calls repaint (manually) which paints according to the cachedvalue. When clicking undo, the gui needs to be updated to reflect the undo’ed state. So I have attached a listener that repaints the grid sequencer on undo changes. What I’m noticing is that this callback (undomanager as source) gets triggered even when values are set as usual as well as when values are undo’ed. I’m looking to avoid extra and unnecessary repaints from this listener callback when values are set. So somehow, I need to distinguish between undomanager changes triggered by undo()/redo() calls only (within the changelistenercallback). Or use a different pattern altogether…


#6

Sounds like your whole approach is a bit wrong…

If you’re using ValueTrees then your GUI should listen only to the ValueTree, and a particular GUI component should update itself when the tree changes in a way that means it needs to do so. The thing that caused the tree to change doesn’t matter - regardless of whether it was the user or the undomanager the result is the same - when the tree changes, the GUI follows that.


#7

Right yeah it appears this makes the most sense now, I begun making it without undo in mind and am now trying to tack it on. Thanks heaps for your help !