Interacting with DocumentWindow from ContentComponent

What's the best way to talk to the DocumentWindow that's holding a MainContentComponent from within the main content?    

I have a document window object "mainWindow" with a content component that has 3 child components in it.  I'm trying to figure out the best way to convert the 3 child components into separate windows (they're subclassing DocumentWindow) and resize/rename the mainWindow.  I'm using a MenuBar to hold the commands, as done in the JuceDemo.  The MenuBar is inside the content component.  When I select the command to switch to separate windows, I need to rename the mainWindow's title as well as resize the window.   

right now I'm doing something like this, but I get errors when I exit the app:

 

class MainWindow: public DocumentWindow
{
public:  
MainWindow(String name) : DocumentWindow (name, Colours::lightgrey, DocumentWindow::allButtons) {
  centreWithSize( getWidth(), getHeight() );
  setUsingNativeTitleBar (true);
  mcc = new MainContentComponent( this );
  mcc->setVisible(true);
  setVisible(true);
} 

void closeButtonPressed() override { 
  JUCEApplication::getInstance()->systemRequestedQuit(); 
}

private: 
 MainContentComponent* mcc; 
};  

class MainContentComponent : public Component, private MenuBarModel, private MenuBarModel::Listener 
{
public:
MainContentComponent( DocumentWindow* dw ) {
  mainWindow = dw;
  addAndMakeVisible( menuBar = new MenuBarComponent( this ) );
  menuBar->setBounds( 0, 0, getWidth(), 20 );
}

~MainContentComponent() {
  mainWindow = 0; 
}

StringArray getMenuBarNames() {
  const char* const names[] = { "Options", nullptr };
  return StringArray( names );
} 

PopupMenu getMenuForIndex (int topLevelMenuIndex, const String &menuName) {
  PopupMenu menu;
  if( topLevelMenuIndex == 0 ) {
     //Options
     PopupMenu subMenu;
     subMenu.addItem(1, "Use Single Window", true, singleViewMode );
     subMenu.addItem(2, "Use Separate Windows", true, !singleViewMode );
     menu.addSubMenu("View", subMenu );
  }
  return menu; 
}

void menuItemSelected (int menuItemID, int topLevelMenuIndex) { 
  if( menuItemID == 1 ) {  //use Single Window
    mainWindow->setSize(1310, 654);
    //can't resize in single view mode
    mainWindow->setResizable(false, false); 
    singleViewMode = true; 
  } else if( menuItemID == 2 ) {            
    mainWindow->setResizable(true, true);
    mainWindow->setResizeLimits(300,
                                300,
                                Desktop::getInstance().getDisplays().getMainDisplay().userArea.getWidth(),
                                Desktop::getInstance().getDisplays().getMainDisplay().userArea.getHeight() );
    mainWindow->setSize( 300, 300 ); 
    singleViewMode = false; 
  }   
  menuItemsChanged(); //update tick marks 
} 
private: 
  DocumentWindow* mainWindow; 
  ScopedPointer<MenuBarComponent> menuBar; 
  bool singleViewMode = true;
}; //end

Hey Matkat, did you ever figure out the best way to migrate child components into new DocumentWindows? I am attempting to, but having a lot of problem with setContentOwned causing an error starting from line 239 of juce_ResizableWindow.cpp:

void ResizableWindow::childBoundsChanged (Component* child)
{
    if ((child == contentComponent) && (child != nullptr) && resizeToFitContent)
    {
        // not going to look very good if this component has a zero size..
        jassert (child->getWidth() > 0);         // (Asserted here -KK)
        jassert (child->getHeight() > 0);

        auto borders = getContentComponentBorder();

        setSize (child->getWidth() + borders.getLeftAndRight(),
                 child->getHeight() + borders.getTopAndBottom());
    }
}

I have been struggling with the order to size and resize the parent/child components, but I think what I need to be doing is adding a main content component to the document window, and then the assets to the content component, right?

Sorry if this is a rookie question, I am new to Juce. I will be following this tutorial from top to bottom as my next avenue - hopefully that helps. Cheers!

edit: the above tutorial did help a lot, as well as learning about unique pointers. It seems Juce is halfway between using unique pointers and references, which is preferred/best practice in Juce?

These are different tools for different jobs.

Unique_ptr’s are used when you need to control the lifetime of an object beyond the usual curly brace scope.

{
    int a = 2;
} // 'a' does not exist in memory/CPU registers after this closing curly brace

References are meant to allow you modify an object inside of a function and have those modifications exist AFTER the function ends.
References also require that the referenced object exists while it is being used inside of the function.

Const References are similar in that they must exist before and after the function they’re being used inside of, but they cannot be modified inside of that function.

You can think of References as Pointers that are guaranteed to not be null.
Just be aware that it is possible for references to stop existing, which results in a dangling reference bug.

I highly recommend watching this talk in its entirety to understand scope and lifetime better:

1 Like

Thank you for sharing this video, I am trying to absorb some ideas from it. I don’t have a lot of C++ experience, mostly C# (when I was much younger) and C (more recently). Definitely very new to me - I have been using new in the project thus far - but will start using and learning unique and shared pointers more. Thanks again!