Passing instance of object to modaldialog result

Hi,

I’ve got a relatively simple issue, but I can’t find a solution to it,
I’ve looked throughout all the JUCE class documentation,
and in the demos of the juce demorunner, and can’t find a solution.

I’m implementing a simple “do you want to save, yes, no, cancel” dialog window if the user wishes to exit my app.

I have a class called RootManager which contains EVERYTHING in my app.
The class has a “SaveProjectToFile” method that when called, will write the contents to file.
So when exiting the app, I just need to show a dialogbox, and if the user selected the result “1”, eg “yes”,
it should call the “SaveProjectToFile” method of the instance of my RootManager class.

Here’s my code:

bool RootManager::SaveProjectToFile() {
// Here is the code to select filename and
// save the contents of RootManager into an XML file

}

struct RootManager::ExitAlertBoxResultChosen
{
void operator() (int result) const noexcept
{
if (result == 1) {
// Yes → Save project
SaveProjectToFile();
JUCEApplication::getInstance()->systemRequestedQuit();
}
else if (result == 2) {
// No → Exit without saving
JUCEApplication::getInstance()->systemRequestedQuit();
}
else {
// Cancel → Don’t exit
return;
}
}
};

void RootManager::ExitApplication() {
if (saveRequired) {
// Ask user what to do about unsaved project
AlertWindow::showYesNoCancelBox(MessageBoxIconType::QuestionIcon, “HummingBird”,
“Save changes to Project "Untitled" before exiting ?”,
“Yes”, “No”, “Cancel”, {},
ModalCallbackFunction::create(ExitAlertBoxResultChosen{}));
}
else {
JUCEApplication::getInstance()->systemRequestedQuit();
}
}

Offcourse this doesn’t compile, and gives the following error on the line where I call “SaveProjectToFile();” in the callback function:

“A nonstatic member reference must be relative to a specific object”

The problem is that in the “struct RootManager::ExitAlertBoxResultChosen” I don’t have access to the instance of my RootManager class. Which is normal as it’s an operator on a struct.
How can I pass along or somehow gain access to a pointer or equiv to my RootManager (which is available in the “void RootManager::ExitApplication()” for example, to the modalcallback function “struct RootManager::ExitAlertBoxResultChosen”, so I can call my “SaveProjectToFile()” method properly ?
It’s been more than a decade since I’ve developed JUCE and C++, so I’m stuck here…

Thanks for your help, It’s much appreciated,
Terrence

Not sure if this will help, but I tend to use lambdas for my modal callback functions… and the capture can be used for scoping things into the lambda :slight_smile:

    newAlertWindow->enterModalState (true, juce::ModalCallbackFunction::create ([this] (int option)
    {
        newAlertWindow->exitModalState (option);
        newAlertWindow->setVisible (false);
        if (option == 1) // ok
        {
        }
        newAlertWindow.reset ();
    }));

Hi,

Can you maybe add a bit more code to show me how I integrate it into my code (the code I posted in my first post), as I’ve no idea how to get started with your proposed code…

Thanks again,
Terrence

I did not test this, just put it together in an editor…

    AlertWindow::showYesNoCancelBox (MessageBoxIconType::QuestionIcon, “HummingBird”,
        “Save changes to Project "Untitled" before exiting ? ”,
        “Yes”, “No”, “Cancel”, {},
        ModalCallbackFunction::create ([this] (int result)
        {
            if (result == 1) {
                // Yes → Save project
                SaveProjectToFile ();
                JUCEApplication::getInstance ()->systemRequestedQuit ();
            }
            else if (result == 2) {
                // No → Exit without saving
                JUCEApplication::getInstance ()->systemRequestedQuit ();
            }
            else {
                // Cancel → Don’t exit
                return;
            }
        }));

Thanks a lot :slight_smile:
I will try it out later today and report my results :slight_smile:

Cheers!,
Terrence

Hi,

I’m still having problems… :frowning:
I implemented your code,
and it turns out I can’t “save as” which is performed in the SaveProjectToFile() method,
as this code opens a modal dialog too, and it’s called in the modalcallbackfunction of this modal window.
If I simply call SaveProjectToFile() when the result == 1 inside the lambda function,
the app does’nt open my “save as…” modal window to choose a file, and then exits.

So I tried to modify the code a bit to just make the result == 1 change the value of a bool value called “saveFile”. It’s set to false before opening the window, and when result == 1 it’s set to true.
This did’nt compile and gave an error that local variables need to be “captured” for the lambda function to work, so I did some googling (never used a lambda function before) and I found that I should put a & in between the like so: [&] (with this it compiles fine) as you can see in the code listing:

	bool saveFile = false;

	AlertWindow::showYesNoCancelBox(MessageBoxIconType::QuestionIcon, "HummingBird",
		dialogText, "Yes", "No", "Cancel", {},
		ModalCallbackFunction::create([&](int result)    // !!! -> Changed [this] to [&] for use of saveFile
			{
				if (result == 1) {
					// Yes → Save project
					saveFile = true;
					//SaveProjectToFile();  // !!! -> This creates a "save as" filechooser async modal dialog!
					//JUCEApplication::getInstance()->systemRequestedQuit();
				}
				else if (result == 2) {
					// No → Exit without saving
					JUCEApplication::getInstance()->systemRequestedQuit();
				}
				else {
					// Cancel → Don’t exit
					return;
				}
			}));

	if (saveFile) {
		SaveProjectToFile();   // !!! -> This creates a "save as" filechooser async modal dialog
		JUCEApplication::getInstance()->systemRequestedQuit();
	}

Afterwards, outside of the function, I then check saveFile and if it’s true, launch my file chooser etc…
This should work, but it does’nt. The saveFile is still false after the function, and after putting a breakpoint in the code, it does set the saveFile to true when result == 1.
Very strange…

Does anyone have any knowledge that could help me solve this issue ?
Or, can anyone provide a working solution to my problem?

Thanks,
Terrence