diff --git a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp index d9bbb27f91..7e7af1da47 100644 --- a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp +++ b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp @@ -1164,6 +1164,15 @@ int LookAndFeel_V2::getPopupMenuBorderSizeWithOptions (const PopupMenu::Options& return getPopupMenuBorderSize(); } +void LookAndFeel_V2::drawPopupMenuColumnSeparatorWithOptions (Graphics&, + const Rectangle&, + const PopupMenu::Options&) {} + +int LookAndFeel_V2::getPopupMenuColumnSeparatorWidthWithOptions (const PopupMenu::Options&) +{ + return 0; +} + //============================================================================== void LookAndFeel_V2::fillTextEditorBackground (Graphics& g, int /*width*/, int /*height*/, TextEditor& textEditor) { diff --git a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h index 7d11c4c545..8d07e8cec9 100644 --- a/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h +++ b/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h @@ -217,6 +217,12 @@ public: int getPopupMenuBorderSizeWithOptions (const PopupMenu::Options&) override; + void drawPopupMenuColumnSeparatorWithOptions (Graphics& g, + const Rectangle& bounds, + const PopupMenu::Options&) override; + + int getPopupMenuColumnSeparatorWidthWithOptions (const PopupMenu::Options&) override; + //============================================================================== void drawComboBox (Graphics&, int width, int height, bool isMouseButtonDown, int buttonX, int buttonY, int buttonW, int buttonH, diff --git a/modules/juce_gui_basics/menus/juce_PopupMenu.cpp b/modules/juce_gui_basics/menus/juce_PopupMenu.cpp index 145f40fc23..44b392c021 100644 --- a/modules/juce_gui_basics/menus/juce_PopupMenu.cpp +++ b/modules/juce_gui_basics/menus/juce_PopupMenu.cpp @@ -226,11 +226,25 @@ struct MenuWindow : public Component setLookAndFeel (parent != nullptr ? &(parent->getLookAndFeel()) : menu.lookAndFeel.get()); + auto& lf = getLookAndFeel(); parentComponent = lf.getParentComponentForMenuOptions (options); const_cast(options) = options.withParentComponent (parentComponent); + if (parentComponent != nullptr) + { + parentComponent->addChildComponent (this); + } + else + { + addToDesktop (ComponentPeer::windowIsTemporary + | ComponentPeer::windowIgnoresKeyPresses + | lf.getMenuWindowFlags()); + + Desktop::getInstance().addGlobalMouseListener (this); + } + if (parentComponent == nullptr && parentWindow == nullptr && lf.shouldPopupMenuScaleWithTargetComponent (options)) if (auto* targetComponent = options.getTargetComponent()) scaleFactor = Component::getApproximateScaleFactorForComponent (targetComponent); @@ -263,19 +277,6 @@ struct MenuWindow : public Component resizeToBestWindowPos(); - if (parentComponent != nullptr) - { - parentComponent->addChildComponent (this); - } - else - { - addToDesktop (ComponentPeer::windowIsTemporary - | ComponentPeer::windowIgnoresKeyPresses - | lf.getMenuWindowFlags()); - - Desktop::getInstance().addGlobalMouseListener (this); - } - getActiveWindows().add (this); lf.preparePopupMenuWindow (*this); @@ -296,7 +297,26 @@ struct MenuWindow : public Component if (isOpaque()) g.fillAll (Colours::white); - getLookAndFeel().drawPopupMenuBackgroundWithOptions (g, getWidth(), getHeight(), options); + auto& theme = getLookAndFeel(); + theme.drawPopupMenuBackgroundWithOptions (g, getWidth(), getHeight(), options); + + if (columnWidths.isEmpty()) + return; + + const auto separatorWidth = theme.getPopupMenuColumnSeparatorWidthWithOptions (options); + const auto border = theme.getPopupMenuBorderSizeWithOptions (options); + + auto currentX = 0; + + std::for_each (columnWidths.begin(), std::prev (columnWidths.end()), [&] (int width) + { + const Rectangle separator (currentX + width, + border, + separatorWidth, + getHeight() - border * 2); + theme.drawPopupMenuColumnSeparatorWithOptions (g, separator, options); + currentX += width + separatorWidth; + }); } void paintOverChildren (Graphics& g) override @@ -907,6 +927,8 @@ struct MenuWindow : public Component int x = 0; int childNum = 0; + const auto separatorWidth = getLookAndFeel().getPopupMenuColumnSeparatorWidthWithOptions (options); + for (int col = 0; col < numColumns; ++col) { auto numChildren = jmin (items.size() - childNum, @@ -923,10 +945,12 @@ struct MenuWindow : public Component y += c->getHeight(); } - x += colW; + x += colW + separatorWidth; childNum += numChildren; } + x -= separatorWidth; + return x; } diff --git a/modules/juce_gui_basics/menus/juce_PopupMenu.h b/modules/juce_gui_basics/menus/juce_PopupMenu.h index c92cd2c26d..7fb699f03e 100644 --- a/modules/juce_gui_basics/menus/juce_PopupMenu.h +++ b/modules/juce_gui_basics/menus/juce_PopupMenu.h @@ -835,12 +835,25 @@ public: virtual void preparePopupMenuWindow (Component& newWindow) = 0; /** Return true if you want your popup menus to scale with the target component's AffineTransform - or scale factor */ + or scale factor + */ virtual bool shouldPopupMenuScaleWithTargetComponent (const Options& options) = 0; virtual int getPopupMenuBorderSize(); virtual int getPopupMenuBorderSizeWithOptions (const Options&) = 0; + + /** Implement this to draw some custom decoration between the columns of the popup menu. + + `getPopupMenuColumnSeparatorWidthWithOptions` must return a positive value in order + to display the separator. + */ + virtual void drawPopupMenuColumnSeparatorWithOptions (Graphics& g, + const Rectangle& bounds, + const Options&) = 0; + + /** Return the amount of space that should be left between popup menu columns. */ + virtual int getPopupMenuColumnSeparatorWidthWithOptions (const Options&) = 0; }; private: