|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2022 - Raw Material Software Limited
-
- JUCE is an open source library subject to commercial or open-source
- licensing.
-
- By using JUCE, you agree to the terms of both the JUCE 7 End-User License
- Agreement and JUCE Privacy Policy.
-
- End User License Agreement: www.juce.com/juce-7-licence
- Privacy Policy: www.juce.com/juce-privacy-policy
-
- Or: You may also use this code under the terms of the GPL v3 (see
- www.gnu.org/licenses).
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- namespace juce
- {
-
- //==============================================================================
- /** Creates and displays a popup-menu.
-
- To show a popup-menu, you create one of these, add some items to it, then
- call its show() method, which returns the id of the item the user selects.
-
- E.g. @code
- void MyWidget::mouseDown (const MouseEvent& e)
- {
- PopupMenu m;
- m.addItem (1, "item 1");
- m.addItem (2, "item 2");
-
- m.showMenuAsync (PopupMenu::Options(),
- [] (int result)
- {
- if (result == 0)
- {
- // user dismissed the menu without picking anything
- }
- else if (result == 1)
- {
- // user picked item 1
- }
- else if (result == 2)
- {
- // user picked item 2
- }
- });
- }
- @endcode
-
- Submenus are easy too: @code
-
- void MyWidget::mouseDown (const MouseEvent& e)
- {
- PopupMenu subMenu;
- subMenu.addItem (1, "item 1");
- subMenu.addItem (2, "item 2");
-
- PopupMenu mainMenu;
- mainMenu.addItem (3, "item 3");
- mainMenu.addSubMenu ("other choices", subMenu);
-
- m.showMenuAsync (...);
- }
- @endcode
-
- @tags{GUI}
- */
- class JUCE_API PopupMenu
- {
- public:
- //==============================================================================
- /** Creates an empty popup menu. */
- PopupMenu() = default;
-
- /** Creates a copy of another menu. */
- PopupMenu (const PopupMenu&);
-
- /** Destructor. */
- ~PopupMenu();
-
- /** Copies this menu from another one. */
- PopupMenu& operator= (const PopupMenu&);
-
- /** Move constructor */
- PopupMenu (PopupMenu&&) noexcept;
-
- /** Move assignment operator */
- PopupMenu& operator= (PopupMenu&&) noexcept;
-
- //==============================================================================
- class CustomComponent;
- class CustomCallback;
-
- //==============================================================================
- /** Resets the menu, removing all its items. */
- void clear();
-
- /** Describes a popup menu item. */
- struct JUCE_API Item
- {
- /** Creates a null item.
- You'll need to set some fields after creating an Item before you
- can add it to a PopupMenu
- */
- Item();
-
- /** Creates an item with the given text.
- This constructor also initialises the itemID to -1, which makes it suitable for
- creating lambda-based item actions.
- */
- Item (String text);
-
- Item (const Item&);
- Item& operator= (const Item&);
- Item (Item&&);
- Item& operator= (Item&&);
-
- /** The menu item's name. */
- String text;
-
- /** The menu item's ID.
- This must not be 0 if you want the item to be triggerable, but if you're attaching
- an action callback to the item, you can set the itemID to -1 to indicate that it
- isn't actively needed.
- */
- int itemID = 0;
-
- /** An optional function which should be invoked when this menu item is triggered. */
- std::function<void()> action;
-
- /** A sub-menu, or nullptr if there isn't one. */
- std::unique_ptr<PopupMenu> subMenu;
-
- /** A drawable to use as an icon, or nullptr if there isn't one. */
- std::unique_ptr<Drawable> image;
-
- /** A custom component for the item to display, or nullptr if there isn't one. */
- ReferenceCountedObjectPtr<CustomComponent> customComponent;
-
- /** A custom callback for the item to use, or nullptr if there isn't one. */
- ReferenceCountedObjectPtr<CustomCallback> customCallback;
-
- /** A command manager to use to automatically invoke the command, or nullptr if none is specified. */
- ApplicationCommandManager* commandManager = nullptr;
-
- /** An optional string describing the shortcut key for this item.
- This is only used for displaying at the right-hand edge of a menu item - the
- menu won't attempt to actually catch or process the key. If you supply a
- commandManager parameter then the menu will attempt to fill-in this field
- automatically.
- */
- String shortcutKeyDescription;
-
- /** A colour to use to draw the menu text.
- By default this is transparent black, which means that the LookAndFeel should choose the colour.
- */
- Colour colour;
-
- /** True if this menu item is enabled. */
- bool isEnabled = true;
-
- /** True if this menu item should have a tick mark next to it. */
- bool isTicked = false;
-
- /** True if this menu item is a separator line. */
- bool isSeparator = false;
-
- /** True if this menu item is a section header. */
- bool isSectionHeader = false;
-
- /** True if this is the final item in the current column. */
- bool shouldBreakAfter = false;
-
- /** Sets the isTicked flag (and returns a reference to this item to allow chaining). */
- Item& setTicked (bool shouldBeTicked = true) & noexcept;
- /** Sets the isEnabled flag (and returns a reference to this item to allow chaining). */
- Item& setEnabled (bool shouldBeEnabled) & noexcept;
- /** Sets the action property (and returns a reference to this item to allow chaining). */
- Item& setAction (std::function<void()> action) & noexcept;
- /** Sets the itemID property (and returns a reference to this item to allow chaining). */
- Item& setID (int newID) & noexcept;
- /** Sets the colour property (and returns a reference to this item to allow chaining). */
- Item& setColour (Colour) & noexcept;
- /** Sets the customComponent property (and returns a reference to this item to allow chaining). */
- Item& setCustomComponent (ReferenceCountedObjectPtr<CustomComponent> customComponent) & noexcept;
- /** Sets the image property (and returns a reference to this item to allow chaining). */
- Item& setImage (std::unique_ptr<Drawable>) & noexcept;
-
- /** Sets the isTicked flag (and returns a reference to this item to allow chaining). */
- Item&& setTicked (bool shouldBeTicked = true) && noexcept;
- /** Sets the isEnabled flag (and returns a reference to this item to allow chaining). */
- Item&& setEnabled (bool shouldBeEnabled) && noexcept;
- /** Sets the action property (and returns a reference to this item to allow chaining). */
- Item&& setAction (std::function<void()> action) && noexcept;
- /** Sets the itemID property (and returns a reference to this item to allow chaining). */
- Item&& setID (int newID) && noexcept;
- /** Sets the colour property (and returns a reference to this item to allow chaining). */
- Item&& setColour (Colour) && noexcept;
- /** Sets the customComponent property (and returns a reference to this item to allow chaining). */
- Item&& setCustomComponent (ReferenceCountedObjectPtr<CustomComponent> customComponent) && noexcept;
- /** Sets the image property (and returns a reference to this item to allow chaining). */
- Item&& setImage (std::unique_ptr<Drawable>) && noexcept;
- };
-
- /** Adds an item to the menu.
- You can call this method for full control over the item that is added, or use the other
- addItem helper methods if you want to pass arguments rather than creating an Item object.
- */
- void addItem (Item newItem);
-
- /** Adds an item to the menu with an action callback. */
- void addItem (String itemText,
- std::function<void()> action);
-
- /** Adds an item to the menu with an action callback. */
- void addItem (String itemText,
- bool isEnabled,
- bool isTicked,
- std::function<void()> action);
-
- /** Appends a new text item for this menu to show.
-
- @param itemResultID the number that will be returned from the show() method
- if the user picks this item. The value should never be
- zero, because that's used to indicate that the user didn't
- select anything.
- @param itemText the text to show.
- @param isEnabled if false, the item will be shown 'greyed-out' and can't be picked
- @param isTicked if true, the item will be shown with a tick next to it
-
- @see addSeparator, addColouredItem, addCustomItem, addSubMenu
- */
- void addItem (int itemResultID,
- String itemText,
- bool isEnabled = true,
- bool isTicked = false);
-
- /** Appends a new item with an icon.
-
- @param itemResultID the number that will be returned from the show() method
- if the user picks this item. The value should never be
- zero, because that's used to indicate that the user didn't
- select anything.
- @param itemText the text to show.
- @param isEnabled if false, the item will be shown 'greyed-out' and can't be picked
- @param isTicked if true, the item will be shown with a tick next to it
- @param iconToUse if this is a valid image, it will be displayed to the left of the item.
-
- @see addSeparator, addColouredItem, addCustomItem, addSubMenu
- */
- void addItem (int itemResultID,
- String itemText,
- bool isEnabled,
- bool isTicked,
- const Image& iconToUse);
-
- /** Appends a new item with an icon.
-
- @param itemResultID the number that will be returned from the show() method
- if the user picks this item. The value should never be
- zero, because that's used to indicate that the user didn't
- select anything.
- @param itemText the text to show.
- @param isEnabled if false, the item will be shown 'greyed-out' and can't be picked
- @param isTicked if true, the item will be shown with a tick next to it
- @param iconToUse a Drawable object to use as the icon to the left of the item.
- The menu will take ownership of this drawable object and will
- delete it later when no longer needed
- @see addSeparator, addColouredItem, addCustomItem, addSubMenu
- */
- void addItem (int itemResultID,
- String itemText,
- bool isEnabled,
- bool isTicked,
- std::unique_ptr<Drawable> iconToUse);
-
- /** Adds an item that represents one of the commands in a command manager object.
-
- @param commandManager the manager to use to trigger the command and get information
- about it
- @param commandID the ID of the command
- @param displayName if this is non-empty, then this string will be used instead of
- the command's registered name
- @param iconToUse an optional Drawable object to use as the icon to the left of the item.
- The menu will take ownership of this drawable object and will
- delete it later when no longer needed
- */
- void addCommandItem (ApplicationCommandManager* commandManager,
- CommandID commandID,
- String displayName = {},
- std::unique_ptr<Drawable> iconToUse = {});
-
- /** Appends a text item with a special colour.
-
- This is the same as addItem(), but specifies a colour to use for the
- text, which will override the default colours that are used by the
- current look-and-feel. See addItem() for a description of the parameters.
- */
- void addColouredItem (int itemResultID,
- String itemText,
- Colour itemTextColour,
- bool isEnabled = true,
- bool isTicked = false,
- const Image& iconToUse = {});
-
- /** Appends a text item with a special colour.
-
- This is the same as addItem(), but specifies a colour to use for the
- text, which will override the default colours that are used by the
- current look-and-feel. See addItem() for a description of the parameters.
- */
- void addColouredItem (int itemResultID,
- String itemText,
- Colour itemTextColour,
- bool isEnabled,
- bool isTicked,
- std::unique_ptr<Drawable> iconToUse);
-
- /** Appends a custom menu item.
-
- This will add a user-defined component to use as a menu item.
-
- Note that native macOS menus do not support custom components.
-
- itemTitle will be used as the fallback text for this item, and will
- be exposed to screen reader clients.
-
- @see CustomComponent
- */
- void addCustomItem (int itemResultID,
- std::unique_ptr<CustomComponent> customComponent,
- std::unique_ptr<const PopupMenu> optionalSubMenu = nullptr,
- const String& itemTitle = {});
-
- /** Appends a custom menu item that can't be used to trigger a result.
-
- This will add a user-defined component to use as a menu item.
- The caller must ensure that the passed-in component stays alive
- until after the menu has been hidden.
-
- If triggerMenuItemAutomaticallyWhenClicked is true, the menu itself will handle
- detection of a mouse-click on your component, and use that to trigger the
- menu ID specified in itemResultID. If this is false, the menu item can't
- be triggered, so itemResultID is not used.
-
- itemTitle will be used as the fallback text for this item, and will
- be exposed to screen reader clients.
-
- Note that native macOS menus do not support custom components.
- */
- void addCustomItem (int itemResultID,
- Component& customComponent,
- int idealWidth,
- int idealHeight,
- bool triggerMenuItemAutomaticallyWhenClicked,
- std::unique_ptr<const PopupMenu> optionalSubMenu = nullptr,
- const String& itemTitle = {});
-
- /** Appends a sub-menu.
-
- If the menu that's passed in is empty, it will appear as an inactive item.
- If the itemResultID argument is non-zero, then the sub-menu item itself can be
- clicked to trigger it as a command.
- */
- void addSubMenu (String subMenuName,
- PopupMenu subMenu,
- bool isEnabled = true);
-
- /** Appends a sub-menu with an icon.
-
- If the menu that's passed in is empty, it will appear as an inactive item.
- If the itemResultID argument is non-zero, then the sub-menu item itself can be
- clicked to trigger it as a command.
- */
- void addSubMenu (String subMenuName,
- PopupMenu subMenu,
- bool isEnabled,
- const Image& iconToUse,
- bool isTicked = false,
- int itemResultID = 0);
-
- /** Appends a sub-menu with an icon.
-
- If the menu that's passed in is empty, it will appear as an inactive item.
- If the itemResultID argument is non-zero, then the sub-menu item itself can be
- clicked to trigger it as a command.
-
- The iconToUse parameter is a Drawable object to use as the icon to the left of
- the item. The menu will take ownership of this drawable object and will delete it
- later when no longer needed
- */
- void addSubMenu (String subMenuName,
- PopupMenu subMenu,
- bool isEnabled,
- std::unique_ptr<Drawable> iconToUse,
- bool isTicked = false,
- int itemResultID = 0);
-
- /** Appends a separator to the menu, to help break it up into sections.
- The menu class is smart enough not to display separators at the top or bottom
- of the menu, and it will replace multiple adjacent separators with a single
- one, so your code can be quite free and easy about adding these, and it'll
- always look ok.
- */
- void addSeparator();
-
- /** Adds a non-clickable text item to the menu.
- This is a bold-font items which can be used as a header to separate the items
- into named groups.
- */
- void addSectionHeader (String title);
-
- /** Adds a column break to the menu, to help break it up into sections.
- Subsequent items will be placed in a new column, rather than being appended
- to the current column.
-
- If a menu contains explicit column breaks, the menu will never add additional
- breaks.
- */
- void addColumnBreak();
-
- /** Returns the number of items that the menu currently contains.
- (This doesn't count separators).
- */
- int getNumItems() const noexcept;
-
- /** Returns true if the menu contains a command item that triggers the given command. */
- bool containsCommandItem (int commandID) const;
-
- /** Returns true if the menu contains any items that can be used. */
- bool containsAnyActiveItems() const noexcept;
-
- //==============================================================================
- /** Class used to create a set of options to pass to the show() method.
- You can chain together a series of calls to this class's methods to create
- a set of whatever options you want to specify.
- E.g. @code
- PopupMenu menu;
- ...
- menu.showMenu (PopupMenu::Options().withMinimumWidth (100)
- .withMaximumNumColumns (3)
- .withTargetComponent (myComp));
- @endcode
- */
- class JUCE_API Options
- {
- public:
- /** By default, the target screen area will be the current mouse position. */
- Options();
-
- Options (const Options&) = default;
- Options& operator= (const Options&) = default;
-
- enum class PopupDirection
- {
- upwards,
- downwards
- };
-
- //==============================================================================
- /** Sets the target component to use when displaying the menu.
-
- This is normally the button or other control that triggered the menu.
-
- The target component is primarily used to control the scale of the menu, so
- it's important to supply a target component if you'll be using your program
- on hi-DPI displays.
-
- This function will also set the target screen area, so that the menu displays
- next to the target component. If you need to display the menu at a specific
- location, you should call withTargetScreenArea() after withTargetComponent.
-
- @see withTargetComponent, withTargetScreenArea
- */
- JUCE_NODISCARD Options withTargetComponent (Component* targetComponent) const;
- JUCE_NODISCARD Options withTargetComponent (Component& targetComponent) const;
-
- /** Sets the region of the screen next to which the menu should be displayed.
-
- To display the menu next to the mouse cursor use withMousePosition(),
- which is equivalent to passing the following to this function:
- @code
- Rectangle<int>{}.withPosition (Desktop::getMousePosition())
- @endcode
-
- withTargetComponent() will also set the target screen area. If you need
- a target component and a target screen area, make sure to call
- withTargetScreenArea() after withTargetComponent().
-
- @see withMousePosition
- */
- JUCE_NODISCARD Options withTargetScreenArea (Rectangle<int> targetArea) const;
-
- /** Sets the target screen area to match the current mouse position.
-
- Make sure to call this after withTargetComponent().
-
- @see withTargetScreenArea
- */
- JUCE_NODISCARD Options withMousePosition() const;
-
- /** If the passed component has been deleted when the popup menu exits,
- the selected item's action will not be called.
-
- This is useful for avoiding dangling references inside the action
- callback, in the case that the callback needs to access a component that
- may be deleted.
- */
- JUCE_NODISCARD Options withDeletionCheck (Component& componentToWatchForDeletion) const;
-
- /** Sets the minimum width of the popup window. */
- JUCE_NODISCARD Options withMinimumWidth (int minWidth) const;
-
- /** Sets the minimum number of columns in the popup window. */
- JUCE_NODISCARD Options withMinimumNumColumns (int minNumColumns) const;
-
- /** Sets the maximum number of columns in the popup window. */
- JUCE_NODISCARD Options withMaximumNumColumns (int maxNumColumns) const;
-
- /** Sets the default height of each item in the popup menu. */
- JUCE_NODISCARD Options withStandardItemHeight (int standardHeight) const;
-
- /** Sets an item which must be visible when the menu is initially drawn.
-
- This is useful to ensure that a particular item is shown when the menu
- contains too many items to display on a single screen.
- */
- JUCE_NODISCARD Options withItemThatMustBeVisible (int idOfItemToBeVisible) const;
-
- /** Sets a component that the popup menu will be drawn into.
-
- Some plugin formats, such as AUv3, dislike it when the plugin editor
- spawns additional windows. Some AUv3 hosts display pink backgrounds
- underneath transparent popup windows, which is confusing and can appear
- as though the plugin is malfunctioning. Setting a parent component will
- avoid this unwanted behaviour, but with the downside that the menu size
- will be constrained by the size of the parent component.
- */
- JUCE_NODISCARD Options withParentComponent (Component* parentComponent) const;
-
- /** Sets the direction of the popup menu relative to the target screen area. */
- JUCE_NODISCARD Options withPreferredPopupDirection (PopupDirection direction) const;
-
- /** Sets an item to select in the menu.
-
- This is useful for controls such as combo boxes, where opening the combo box
- with the keyboard should ideally highlight the currently-selected item, allowing
- the next/previous item to be selected by pressing up/down on the keyboard, rather
- than needing to move the highlighted row down from the top of the menu each time
- it is opened.
- */
- JUCE_NODISCARD Options withInitiallySelectedItem (int idOfItemToBeSelected) const;
-
- //==============================================================================
- /** Gets the parent component. This may be nullptr if the Component has been deleted.
-
- @see withParentComponent
- */
- Component* getParentComponent() const noexcept { return parentComponent; }
-
- /** Gets the target component. This may be nullptr if the Component has been deleted.
-
- @see withTargetComponent
- */
- Component* getTargetComponent() const noexcept { return targetComponent; }
-
- /** Returns true if the menu was watching a component, and that component has been deleted, and false otherwise.
-
- @see withDeletionCheck
- */
- bool hasWatchedComponentBeenDeleted() const noexcept { return isWatchingForDeletion && componentToWatchForDeletion == nullptr; }
-
- /** Gets the target screen area.
-
- @see withTargetScreenArea
- */
- Rectangle<int> getTargetScreenArea() const noexcept { return targetArea; }
-
- /** Gets the minimum width.
-
- @see withMinimumWidth
- */
- int getMinimumWidth() const noexcept { return minWidth; }
-
- /** Gets the maximum number of columns.
-
- @see withMaximumNumColumns
- */
- int getMaximumNumColumns() const noexcept { return maxColumns; }
-
- /** Gets the minimum number of columns.
-
- @see withMinimumNumColumns
- */
- int getMinimumNumColumns() const noexcept { return minColumns; }
-
- /** Gets the default height of items in the menu.
-
- @see withStandardItemHeight
- */
- int getStandardItemHeight() const noexcept { return standardHeight; }
-
- /** Gets the ID of the item that must be visible when the menu is initially shown.
-
- @see withItemThatMustBeVisible
- */
- int getItemThatMustBeVisible() const noexcept { return visibleItemID; }
-
- /** Gets the preferred popup menu direction.
-
- @see withPreferredPopupDirection
- */
- PopupDirection getPreferredPopupDirection() const noexcept { return preferredPopupDirection; }
-
- /** Gets the ID of the item that must be selected when the menu is initially shown.
-
- @see withItemThatMustBeVisible
- */
- int getInitiallySelectedItemId() const noexcept { return initiallySelectedItemId; }
-
- private:
- //==============================================================================
- Rectangle<int> targetArea;
- WeakReference<Component> targetComponent, parentComponent, componentToWatchForDeletion;
- int visibleItemID = 0, minWidth = 0, minColumns = 1, maxColumns = 0, standardHeight = 0, initiallySelectedItemId = 0;
- bool isWatchingForDeletion = false;
- PopupDirection preferredPopupDirection = PopupDirection::downwards;
- };
-
- //==============================================================================
- #if JUCE_MODAL_LOOPS_PERMITTED
- /** Displays the menu and waits for the user to pick something.
-
- This will display the menu modally, and return the ID of the item that the
- user picks. If they click somewhere off the menu to get rid of it without
- choosing anything, this will return 0.
-
- The current location of the mouse will be used as the position to show the
- menu - to explicitly set the menu's position, use showAt() instead. Depending
- on where this point is on the screen, the menu will appear above, below or
- to the side of the point.
-
- @param itemIDThatMustBeVisible if you set this to the ID of one of the menu items,
- then when the menu first appears, it will make sure
- that this item is visible. So if the menu has too many
- items to fit on the screen, it will be scrolled to a
- position where this item is visible.
- @param minimumWidth a minimum width for the menu, in pixels. It may be wider
- than this if some items are too long to fit.
- @param maximumNumColumns if there are too many items to fit on-screen in a single
- vertical column, the menu may be laid out as a series of
- columns - this is the maximum number allowed. To use the
- default value for this (probably about 7), you can pass
- in zero.
- @param standardItemHeight if this is non-zero, it will be used as the standard
- height for menu items (apart from custom items)
- @param callback if this is not a nullptr, the menu will be launched
- asynchronously, returning immediately, and the callback
- will receive a call when the menu is either dismissed or
- has an item selected. This object will be owned and
- deleted by the system, so make sure that it works safely
- and that any pointers that it uses are safely within scope.
- @see showAt
- */
- int show (int itemIDThatMustBeVisible = 0,
- int minimumWidth = 0,
- int maximumNumColumns = 0,
- int standardItemHeight = 0,
- ModalComponentManager::Callback* callback = nullptr);
-
-
- /** Displays the menu at a specific location.
-
- This is the same as show(), but uses a specific location (in global screen
- coordinates) rather than the current mouse position.
-
- The screenAreaToAttachTo parameter indicates a screen area to which the menu
- will be adjacent. Depending on where this is, the menu will decide which edge to
- attach itself to, in order to fit itself fully on-screen. If you just want to
- trigger a menu at a specific point, you can pass in a rectangle of size (0, 0)
- with the position that you want.
-
- @see show()
- */
- int showAt (Rectangle<int> screenAreaToAttachTo,
- int itemIDThatMustBeVisible = 0,
- int minimumWidth = 0,
- int maximumNumColumns = 0,
- int standardItemHeight = 0,
- ModalComponentManager::Callback* callback = nullptr);
-
- /** Displays the menu as if it's attached to a component such as a button.
-
- This is similar to showAt(), but will position it next to the given component, e.g.
- so that the menu's edge is aligned with that of the component. This is intended for
- things like buttons that trigger a pop-up menu.
- */
- int showAt (Component* componentToAttachTo,
- int itemIDThatMustBeVisible = 0,
- int minimumWidth = 0,
- int maximumNumColumns = 0,
- int standardItemHeight = 0,
- ModalComponentManager::Callback* callback = nullptr);
-
- /** Displays and runs the menu modally, with a set of options.
- */
- int showMenu (const Options& options);
- #endif
-
- /** Runs the menu asynchronously. */
- void showMenuAsync (const Options& options);
-
- /** Runs the menu asynchronously, with a user-provided callback that will receive the result. */
- void showMenuAsync (const Options& options,
- ModalComponentManager::Callback* callback);
-
- /** Runs the menu asynchronously, with a user-provided callback that will receive the result. */
- void showMenuAsync (const Options& options,
- std::function<void (int)> callback);
-
- //==============================================================================
- /** Closes any menus that are currently open.
-
- This might be useful if you have a situation where your window is being closed
- by some means other than a user action, and you'd like to make sure that menus
- aren't left hanging around.
- */
- static bool JUCE_CALLTYPE dismissAllActiveMenus();
-
-
- //==============================================================================
- /** Specifies a look-and-feel for the menu and any sub-menus that it has.
-
- This can be called before show() if you need a customised menu. Be careful
- not to delete the LookAndFeel object before the menu has been deleted.
- */
- void setLookAndFeel (LookAndFeel* newLookAndFeel);
-
- //==============================================================================
- /** A set of colour IDs to use to change the colour of various aspects of the menu.
-
- These constants can be used either via the LookAndFeel::setColour()
- method for the look and feel that is set for this menu with setLookAndFeel()
-
- @see setLookAndFeel, LookAndFeel::setColour, LookAndFeel::findColour
- */
- enum ColourIds
- {
- backgroundColourId = 0x1000700, /**< The colour to fill the menu's background with. */
- textColourId = 0x1000600, /**< The colour for normal menu item text, (unless the
- colour is specified when the item is added). */
- headerTextColourId = 0x1000601, /**< The colour for section header item text (see the
- addSectionHeader() method). */
- highlightedBackgroundColourId = 0x1000900, /**< The colour to fill the background of the currently
- highlighted menu item. */
- highlightedTextColourId = 0x1000800, /**< The colour to use for the text of the currently
- highlighted item. */
- };
-
- //==============================================================================
- /**
- Allows you to iterate through the items in a pop-up menu, and examine
- their properties.
-
- To use this, just create one and repeatedly call its next() method. When this
- returns true, all the member variables of the iterator are filled-out with
- information describing the menu item. When it returns false, the end of the
- list has been reached.
- */
- class JUCE_API MenuItemIterator
- {
- public:
- //==============================================================================
- /** Creates an iterator that will scan through the items in the specified
- menu.
-
- Be careful not to add any items to a menu while it is being iterated,
- or things could get out of step.
-
- @param menu the menu that needs to be scanned
-
- @param searchRecursively if true, all submenus will be recursed into to
- do an exhaustive search
- */
- MenuItemIterator (const PopupMenu& menu, bool searchRecursively = false);
-
- /** Destructor. */
- ~MenuItemIterator();
-
- /** Returns true if there is another item, and sets up all this object's
- member variables to reflect that item's properties.
- */
- bool next();
-
- /** Returns a reference to the description of the current item.
- It is only valid to call this after next() has returned true!
- */
- Item& getItem() const;
-
- private:
- //==============================================================================
- bool searchRecursively;
-
- Array<int> index;
- Array<const PopupMenu*> menus;
- PopupMenu::Item* currentItem = nullptr;
-
- MenuItemIterator& operator= (const MenuItemIterator&);
- JUCE_LEAK_DETECTOR (MenuItemIterator)
- };
-
- //==============================================================================
- /** A user-defined component that can be used as an item in a popup menu.
- @see PopupMenu::addCustomItem
- */
- class JUCE_API CustomComponent : public Component,
- public SingleThreadedReferenceCountedObject
- {
- public:
- /** Creates a custom item that is triggered automatically. */
- CustomComponent();
-
- /** Creates a custom item.
-
- If isTriggeredAutomatically is true, then the menu will automatically detect
- a mouse-click on this component and use that to invoke the menu item. If it's
- false, then it's up to your class to manually trigger the item when it wants to.
-
- If isTriggeredAutomatically is true, then an accessibility handler 'wrapper'
- will be created for the item that allows pressing, focusing, and toggling.
- If isTriggeredAutomatically is false, and the item has no submenu, then
- no accessibility wrapper will be created and your component must be
- independently accessible.
- */
- explicit CustomComponent (bool isTriggeredAutomatically);
-
- /** Returns a rectangle with the size that this component would like to have.
-
- Note that the size which this method returns isn't necessarily the one that
- the menu will give it, as the items will be stretched to have a uniform width.
- */
- virtual void getIdealSize (int& idealWidth, int& idealHeight) = 0;
-
- /** Dismisses the menu, indicating that this item has been chosen.
-
- This will cause the menu to exit from its modal state, returning
- this item's id as the result.
- */
- void triggerMenuItem();
-
- /** Returns true if this item should be highlighted because the mouse is over it.
- You can call this method in your paint() method to find out whether
- to draw a highlight.
- */
- bool isItemHighlighted() const noexcept { return isHighlighted; }
-
- /** Returns a pointer to the Item that holds this custom component, if this
- component is currently held by an Item.
- You can query the Item for information that you might want to use
- in your paint() method, such as the item's enabled and ticked states.
- */
- const PopupMenu::Item* getItem() const noexcept { return item; }
-
- /** @internal */
- bool isTriggeredAutomatically() const noexcept { return triggeredAutomatically; }
- /** @internal */
- void setHighlighted (bool shouldBeHighlighted);
-
- private:
- //==============================================================================
- bool isHighlighted = false, triggeredAutomatically;
- const PopupMenu::Item* item = nullptr;
-
- friend PopupMenu;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomComponent)
- };
-
- //==============================================================================
- /** A user-defined callback that can be used for specific items in a popup menu.
- @see PopupMenu::Item::customCallback
- */
- class JUCE_API CustomCallback : public SingleThreadedReferenceCountedObject
- {
- public:
- CustomCallback();
- ~CustomCallback() override;
-
- /** Callback to indicate this item has been triggered.
- @returns true if the itemID should be sent to the exitModalState method, or
- false if it should send 0, indicating no further action should be taken
- */
- virtual bool menuItemTriggered() = 0;
-
- private:
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomCallback)
- };
-
- //==============================================================================
- /** This abstract base class is implemented by LookAndFeel classes to provide
- menu drawing functionality.
- */
- struct JUCE_API LookAndFeelMethods
- {
- virtual ~LookAndFeelMethods() = default;
-
- /** Fills the background of a popup menu component. */
- virtual void drawPopupMenuBackground (Graphics&, int width, int height);
-
- /** Fills the background of a popup menu component. */
- virtual void drawPopupMenuBackgroundWithOptions (Graphics&,
- int width,
- int height,
- const Options&) = 0;
-
- /** Draws one of the items in a popup menu. */
- virtual void drawPopupMenuItem (Graphics&, const Rectangle<int>& area,
- bool isSeparator, bool isActive, bool isHighlighted,
- bool isTicked, bool hasSubMenu,
- const String& text,
- const String& shortcutKeyText,
- const Drawable* icon,
- const Colour* textColour);
-
- /** Draws one of the items in a popup menu. */
- virtual void drawPopupMenuItemWithOptions (Graphics&, const Rectangle<int>& area,
- bool isHighlighted,
- const Item& item,
- const Options&) = 0;
-
- virtual void drawPopupMenuSectionHeader (Graphics&, const Rectangle<int>&,
- const String&);
-
- virtual void drawPopupMenuSectionHeaderWithOptions (Graphics&, const Rectangle<int>& area,
- const String& sectionName,
- const Options&) = 0;
-
- /** Returns the size and style of font to use in popup menus. */
- virtual Font getPopupMenuFont() = 0;
-
- virtual void drawPopupMenuUpDownArrow (Graphics&,
- int width, int height,
- bool isScrollUpArrow);
-
- virtual void drawPopupMenuUpDownArrowWithOptions (Graphics&,
- int width, int height,
- bool isScrollUpArrow,
- const Options&) = 0;
-
- /** Finds the best size for an item in a popup menu. */
- virtual void getIdealPopupMenuItemSize (const String& text,
- bool isSeparator,
- int standardMenuItemHeight,
- int& idealWidth,
- int& idealHeight);
-
- /** Finds the best size for an item in a popup menu. */
- virtual void getIdealPopupMenuItemSizeWithOptions (const String& text,
- bool isSeparator,
- int standardMenuItemHeight,
- int& idealWidth,
- int& idealHeight,
- const Options&) = 0;
-
- virtual int getMenuWindowFlags() = 0;
-
- virtual void drawMenuBarBackground (Graphics&, int width, int height,
- bool isMouseOverBar,
- MenuBarComponent&) = 0;
-
- virtual int getDefaultMenuBarHeight() = 0;
-
- virtual int getMenuBarItemWidth (MenuBarComponent&, int itemIndex, const String& itemText) = 0;
-
- virtual Font getMenuBarFont (MenuBarComponent&, int itemIndex, const String& itemText) = 0;
-
- virtual void drawMenuBarItem (Graphics&, int width, int height,
- int itemIndex,
- const String& itemText,
- bool isMouseOverItem,
- bool isMenuOpen,
- bool isMouseOverBar,
- MenuBarComponent&) = 0;
-
- virtual Component* getParentComponentForMenuOptions (const Options& options) = 0;
-
- 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
- */
- 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<int>& bounds,
- const Options&) = 0;
-
- /** Return the amount of space that should be left between popup menu columns. */
- virtual int getPopupMenuColumnSeparatorWidthWithOptions (const Options&) = 0;
- };
-
- //==============================================================================
- #ifndef DOXYGEN
- [[deprecated ("Use the new method.")]]
- int drawPopupMenuItem (Graphics&, int, int, bool, bool, bool, bool, bool, const String&, const String&, Image*, const Colour*) { return 0; }
- #endif
-
- private:
- //==============================================================================
- JUCE_PUBLIC_IN_DLL_BUILD (struct HelperClasses)
- class Window;
- friend struct HelperClasses;
- friend class MenuBarComponent;
-
- Array<Item> items;
- WeakReference<LookAndFeel> lookAndFeel;
-
- Component* createWindow (const Options&, ApplicationCommandManager**) const;
- int showWithOptionalCallback (const Options&, ModalComponentManager::Callback*, bool);
-
- static void setItem (CustomComponent&, const Item*);
-
- JUCE_LEAK_DETECTOR (PopupMenu)
- };
-
- } // namespace juce
|