diff --git a/modules/juce_gui_basics/menus/juce_PopupMenu.cpp b/modules/juce_gui_basics/menus/juce_PopupMenu.cpp index 3c47a09482..d15f93a7c1 100644 --- a/modules/juce_gui_basics/menus/juce_PopupMenu.cpp +++ b/modules/juce_gui_basics/menus/juce_PopupMenu.cpp @@ -1195,22 +1195,19 @@ struct MenuWindow final : public Component { activeSubMenu.reset(); - if (childComp != nullptr - && hasActiveSubMenu (childComp->item)) - { - activeSubMenu.reset (new HelperClasses::MenuWindow (*(childComp->item.subMenu), this, - options.withTargetScreenArea (childComp->getScreenBounds()) - .withMinimumWidth (0) - .withTargetComponent (nullptr), - false, dismissOnMouseUp, managerOfChosenCommand, scaleFactor)); + if (childComp == nullptr || ! hasActiveSubMenu (childComp->item)) + return false; - activeSubMenu->setVisible (true); // (must be called before enterModalState on Windows to avoid DropShadower confusion) - activeSubMenu->enterModalState (false); - activeSubMenu->toFront (false); - return true; - } + activeSubMenu.reset (new HelperClasses::MenuWindow (*(childComp->item.subMenu), this, + options.forSubmenu() + .withTargetScreenArea (childComp->getScreenBounds()) + .withMinimumWidth (0), + false, dismissOnMouseUp, managerOfChosenCommand, scaleFactor)); - return false; + activeSubMenu->setVisible (true); // (must be called before enterModalState on Windows to avoid DropShadower confusion) + activeSubMenu->enterModalState (false); + activeSubMenu->toFront (false); + return true; } void triggerCurrentlyHighlightedItem() @@ -1975,7 +1972,7 @@ static PopupMenu::Options with (PopupMenu::Options options, Member&& member, Ite PopupMenu::Options PopupMenu::Options::withTargetComponent (Component* comp) const { - auto o = with (*this, &Options::targetComponent, comp); + auto o = with (with (*this, &Options::targetComponent, comp), &Options::topLevelTarget, comp); if (comp != nullptr) o.targetArea = comp->getScreenBounds(); @@ -2045,6 +2042,11 @@ PopupMenu::Options PopupMenu::Options::withInitiallySelectedItem (int idOfItemTo return with (*this, &Options::initiallySelectedItemId, idOfItemToBeSelected); } +PopupMenu::Options PopupMenu::Options::forSubmenu() const +{ + return with (*this, &Options::targetComponent, nullptr); +} + Component* PopupMenu::createWindow (const Options& options, ApplicationCommandManager** managerOfChosenCommand) const { diff --git a/modules/juce_gui_basics/menus/juce_PopupMenu.h b/modules/juce_gui_basics/menus/juce_PopupMenu.h index 6ca8c721d7..697ff1784b 100644 --- a/modules/juce_gui_basics/menus/juce_PopupMenu.h +++ b/modules/juce_gui_basics/menus/juce_PopupMenu.h @@ -562,6 +562,13 @@ public: */ [[nodiscard]] Options withInitiallySelectedItem (int idOfItemToBeSelected) const; + /** Returns a copy of these options with the target component set to null. The value of the + top-level target component will not be changed. + + @see getTargetComponent(), getTopLevelTargetComponent() + */ + [[nodiscard]] Options forSubmenu() const; + //============================================================================== /** Gets the parent component. This may be nullptr if the Component has been deleted. @@ -575,6 +582,14 @@ public: */ Component* getTargetComponent() const noexcept { return targetComponent; } + /** Gets the target component that was set for the top-level menu. + + When querying the options of a submenu, getTargetComponent() will always return + nullptr, while getTopLevelTargetComponent() will return the target passed to + withTargetComponent() when creating the top-level menu. + */ + Component* getTopLevelTargetComponent() const noexcept { return topLevelTarget; } + /** Returns true if the menu was watching a component, and that component has been deleted, and false otherwise. @see withDeletionCheck @@ -632,7 +647,7 @@ public: private: //============================================================================== Rectangle targetArea; - WeakReference targetComponent, parentComponent, componentToWatchForDeletion; + WeakReference targetComponent, parentComponent, componentToWatchForDeletion, topLevelTarget; int visibleItemID = 0, minWidth = 0, minColumns = 1, maxColumns = 0, standardHeight = 0, initiallySelectedItemId = 0; bool isWatchingForDeletion = false; PopupDirection preferredPopupDirection = PopupDirection::downwards;