When is it safe to call getTopLevelComponent()?

Hi all,

I realized that calling getTopLevelComponent() in the constructor of the MainComponent returns null although it should return the DocumentWindow that is owning the MainComponent. I want to call getTopLevelComponent()->isAlwaysOnTop() for a ToggleButton’s state in the constructor but that doesn’t work. I can, however, call that function from resized() without any problems. Any hints how to do that in a correct way?

I used an AsyncUpdater in the meantime but that doesn’t seem to be an elegant way and also I would like to understand why I cannot call getTopLevelComponent() from within the constructor.

thanks,
Stefan

Every Component keeps a pointer to its parent, which gets set when you call methods like addChildComponent() and addAndMakeVisible(). When your Component is being constructed, it hasn’t been added to any parent component yet, so its parent pointer is null. The getTopLevelComponent() implementation uses these parent pointers to traverse the component hierarchy, so calling it before your component has actually been added to its parent will always return nullptr. You can override parentHierarchyChanged() to get a callback whenever your Component has been added to or removed from its parent.

I don’t think getTopLevelComponent() will ever return the DocumentWindow object, though, since it’s not actually a parent of the MainComponent (hence why ResizableWindow methods like setContentOwned() are used instead of Component methods like addAndMakeVisible() when displaying the MainComponent inside the DocumentWindow).

If you need the top level window, ResizableWindow::getTopLevelWindow() or ResizableWindow::getActiveTopLevelWindow() should work.

1 Like

Hi Connor,

thanks for your reply.

Every Component keeps a pointer to its parent, which gets set when you call methods like addChildComponent() and addAndMakeVisible() . When your Component is being constructed, it hasn’t been added to any parent component yet, so its parent pointer is null.

That makes perfectly sense. I thought maybe setContentOwned() would do some addAndMakeVisible() in the background.

parentHierarchyChanged()was a good hint. Haven’t known about that until now. That’s working.

ResizableWindow::getTopLevelWindow() didn’t do the trick. It’s the same problem. As the MainComponent is the content of the ResizableWindow it is not yet connected while constructing.

Kind regards,
Stefan

You could try querying the top level component when the visibility of your Component changes (i.e. override Component::visibilityChanged()) as the hierarchy will almost certainly be setup by the time the Component is actually made visible. However that may be too late depending on what you plan to do with the TLC once you’ve found it.

When speaking of “safe” be aware that sendVisibilityChangeMessage() is triggered from setVisible(), which can also be a result from addAndMakeVisible().

If your panel was constructed and added later, the call getTopLevelComponent() returns something different from what’s expected.

Thanks guys! visibilityChanged() should also work, thanks.
In my case it’s fairly simple. I have a fairly flat hierarchy of components and I need to know in one child component if the TLC is set to be always on top or not. It’s working with parentHierachyChanged() and then looking for the TLC but in the end I may change that and work with a ValueTree to track the state.