SafePointer Question

Okay, in that case, go ahead. I don’t know the example code too well :slight_smile:

Here’s the link.

It’s the BasicWindow class code example:

And yes, I’ll switch over to deleteAndZero()

1 Like

Ah, now I understand why you use a SafePointer in first place - to be able to check if the window has deleted itself (when it was closed). That makes sense.

1 Like

Yep, I don’t really know how else to manage any other pointer if it were used to point at a window that can self-delete. I wouldn’t have access to the window pointer to set it to NULL, so I use SafePointer.

SafePointers are very slick!

1 Like

I was given this suggestion for a popupwindow:

struct PopupWindow : public DocumentWindow
{
    std::function<void()> onClose;
    PopupWindow( /*args*/ ) : DocumentWindow( /*typical args*/ ) {}
    void closeButtonPressed() override
    {
        if( onClose ) { onClose(); }
    }
};

struct MainComponent : public Component
{
    std::unique_ptr<PopupWindow> popupWindow;
    //snip...
    void showPopup()
    {
        popupWindow = std::make_unique<PopupWindow>( /* args */ );
        popupWindow.get()->onClose = [this]()
        {
            this->popupWindow.reset( nullptr );
        };
        popupWindow.get()->centreWithSize( /*args */ );
        popupWindow.get()->setVisible(true);
    }
};

No safe pointers, no tight coupling, super easy to show/delete, and NO self deletion.

2 Likes

Thanks for this suggestion. I received similar advice but was unable to get the lambda to properly capture variables from the application for the pop-up window to interact with. For some reason, I was able to close the popup from the lambda, but not change text in my main application GUI.

I took this approach which worked:

Popup

class AudioSettingsWindow : public DocumentWindow, 
                                   ChangeListener 
{
    // (constructor, other code...)

    // override close button 
    void closeButtonPressed() override
    {
        if (closeSettings) 
        { 
            closeSettings(); 
        }
    }

    // callback method to be set in main application
    std::function<void()> closeSettings;
}

Main application

class BHRecDemo  : public Component
{

    BHRecDemo()
    {
        // other initialization code...

        // Creates settings window -KGK
        settingsButton.onClick = [this]
        {
            if (settingsWindow != nullptr) {
                settingsWindow.reset();
                settingsButton.setButtonText(openSettings);
            }
            else
            {
                // Create settings window 
                settingsWindow = std::make_unique<AudioSettingsWindow>(
                    "Audio Settings", audioDeviceManager.get());
                settingsWindow->centreWithSize(500, 600);
                settingsWindow->setVisible(true);
                // Assign callback to handle the deletion of the settings window
                settingsWindow.get()->closeSettings = std::bind(&BHRecDemo::closeSettingsWindow, this);

                // Cleanup main app 
                this->toFront(true);
                settingsButton.setButtonText(closeSettings);
            }
        };
    }

    void closeSettingsWindow()
    {
        settingsWindow.reset();
        settingsButton.setButtonText(openSettings);
    }

    const juce::String openSettings = "Open Settings";
    const juce::String closeSettings = "Close Settings";
    TextButton recordButton { "Record" };
    TextButton settingsButton{ openSettings };

    std::unique_ptr <AudioSettingsWindow> settingsWindow;
}

I like not having the callback function inline, but more importantly I had to do it this way to avoid null pointer errors when trying to update the button text. It was some kind of scoping issue, but it persisted even when I made the button a public member… really I don’t have a clue what the problem was.