Showing progress notice on message thread


#1

I’m struggling with a seemingly trivial task for hours:

What is the best way for batch-like code run on the message thread to show a (temporary) notification window to provide updates on progress (labels, progress bar)?

I created a window with a label component, which seems to work, but it either it doesn’t show up on screen, or does so only randomly. Updating the label’s text has no effect.

Label*  label = new Label();
label->setText("Please wait ...", dontSendNotification);
label->setJustificationType(Justification::centred);
label->setBounds(0,0, 400, 90);

DocumentWindow win (JucePlugin_Name, GlobalWindowBackground, 0);
win.setUsingNativeTitleBar (true);
win.setContentOwned (label, true);
win.setTitleBarHeight (0);
win.setTitleBarButtonsRequired (DocumentWindow::closeButton, false);
win.centreAroundComponent(nullptr, 400, 100);
win.setVisible (true);
win.toFront(false);
win.setAlwaysOnTop(true);

// doing task stuff here
label->setText("Doing this now", dontSendNotification);
// do even more stuff ...
label->setText("Doing more stuff now", dontSendNotification);
// window gets deleted and closed when method is exited

I understand that a display refresh can be forced with MessageManager::getInstance()-> runDispatchLoopUntil(100) after opening the window and updating the label. This however seems to be incompatible with MessageManager::getInstance()->callFunctionOnMessageThread() , which is used to run this batch and happens to hang after closing the window.

What’s the recommended way of pushing some task to the message thread and showing a progress notice? What am I missing?


#2

We have the ThreadWithProgressWindow class, but the whole approach of running a modal loop on the message thread is dodgy in desktop apps, very dangerous in plugins, and completely impossible on Android, so I don’t recommend it.

The correct thing to do is to just launch a thread to do it, and if you need to block your GUI, use a modal component but don’t run a modal loop.


#3

Wow! I am amazed there’s still great stuff to discover. This slipped my attention. Perfect solution. Thanks.


#4

Well no… I tried to make it really clear that it’s a very bad solution! We may even deprecate it one day.

It works and is easy to use, but like I said, modal loops are evil and will bite you on the ass one day. Using stuff like this is technical debt that you’ll one day regret and will have to refactor - best not to do it in the first place.


#5

Yeah. Just saw it’s using the same technique and it hangs again.

Not that I like progress dialogs. But leaving the user unclear about what’s going on when there’s no response for 10 seconds or more is just bad UX design. EastWest show progress with their PLAY plugin when loading samples, which can take minutes in the worst case. Does seem to work fine.


#6

Try not using Labels, but paint your text – and update the text using AsyncUpdater to trigger a repaint.

Rail


#7

Maybe I’m not making myself very clear today!

Obviously I’m not suggesting you don’t provide a great UX with feedback about what’s going on. I’m not even suggesting that you don’t use modal components to show progress. I’m just saying you should do it without running a modal loop!

If you’re unclear, try setting JUCE_MODAL_LOOPS_PERMITTED=0 and you’ll be unable to use any of the stuff I’m warning you against.


#8

Oh, I didn’t mean you suggested this. I just thought out loud why I wouldn’t give up on looking for a solution.

I’ll try that JUCE_MODAL_LOOPS_PERMITTED=0 setting. Also, painting text is an interesting idea. Thanks for your help.