mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Added some PopupMenu::addItem overloads which let you attach a lambda callback to be invoked for a menu item.
This commit is contained in:
parent
acbdec3f71
commit
0367d5c3a9
7 changed files with 215 additions and 139 deletions
|
|
@ -195,7 +195,7 @@ public:
|
|||
}
|
||||
|
||||
/** Takes a non-normalised value and snaps it based on either the interval property of
|
||||
this NormalisedRange or the lambda function supplied to the constructor.
|
||||
this NormalisableRange or the lambda function supplied to the constructor.
|
||||
*/
|
||||
ValueType snapToLegalValue (ValueType v) const noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE (AsyncFunctionCallback)
|
||||
};
|
||||
|
||||
void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* const func, void* const parameter)
|
||||
void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* func, void* parameter)
|
||||
{
|
||||
if (isThisTheMessageThread())
|
||||
return func (parameter);
|
||||
|
|
@ -184,6 +184,18 @@ void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* cons
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void MessageManager::callAsync (std::function<void()> fn)
|
||||
{
|
||||
struct AsyncCallInvoker : public MessageBase
|
||||
{
|
||||
AsyncCallInvoker (std::function<void()> f) : callback (std::move (f)) { post(); }
|
||||
void messageCallback() override { callback(); }
|
||||
std::function<void()> callback;
|
||||
};
|
||||
|
||||
new AsyncCallInvoker (std::move (fn));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MessageManager::deliverBroadcastMessage (const String& value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -95,11 +95,7 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
/** Asynchronously invokes a function or C++11 lambda on the message thread. */
|
||||
template <typename FunctionType>
|
||||
static void callAsync (FunctionType&& functionToCall)
|
||||
{
|
||||
new AsyncCallInvoker<FunctionType> (std::forward<FunctionType> (functionToCall));
|
||||
}
|
||||
static void callAsync (std::function<void()> functionToCall);
|
||||
|
||||
/** Calls a function using the message-thread.
|
||||
|
||||
|
|
@ -340,16 +336,6 @@ private:
|
|||
static void doPlatformSpecificShutdown();
|
||||
static bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages);
|
||||
|
||||
template <typename FunctionType>
|
||||
struct AsyncCallInvoker : public MessageBase
|
||||
{
|
||||
AsyncCallInvoker (FunctionType&& f) : callback (std::forward<FunctionType> (f)) { post(); }
|
||||
void messageCallback() override { callback(); }
|
||||
FunctionType callback;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AsyncCallInvoker)
|
||||
};
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MessageManager)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -223,12 +223,12 @@ struct MenuWindow : public Component
|
|||
setOpaque (lf.findColour (PopupMenu::backgroundColourId).isOpaque()
|
||||
|| ! Desktop::canUseSemiTransparentWindows());
|
||||
|
||||
for (int i = 0; i < menu.items.size(); ++i)
|
||||
for (size_t i = 0; i < menu.items.size(); ++i)
|
||||
{
|
||||
auto item = menu.items.getUnchecked (i);
|
||||
auto& item = menu.items[i];
|
||||
|
||||
if (i < menu.items.size() - 1 || ! item->isSeparator)
|
||||
items.add (new ItemComponent (*item, options.getStandardItemHeight(), *this));
|
||||
if (i + 1 < menu.items.size() || ! item.isSeparator)
|
||||
items.add (new ItemComponent (item, options.getStandardItemHeight(), *this));
|
||||
}
|
||||
|
||||
auto targetArea = options.getTargetScreenArea() / scaleFactor;
|
||||
|
|
@ -323,10 +323,15 @@ struct MenuWindow : public Component
|
|||
*managerOfChosenCommand = item->commandManager;
|
||||
}
|
||||
|
||||
exitModalState (getResultItemID (item));
|
||||
auto resultID = getResultItemID (item);
|
||||
|
||||
if (makeInvisible && (deletionChecker != nullptr))
|
||||
exitModalState (resultID);
|
||||
|
||||
if (makeInvisible && deletionChecker != nullptr)
|
||||
setVisible (false);
|
||||
|
||||
if (resultID != 0 && item != nullptr && item->action != nullptr)
|
||||
MessageManager::callAsync (item->action);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1262,42 +1267,36 @@ PopupMenu::PopupMenu()
|
|||
}
|
||||
|
||||
PopupMenu::PopupMenu (const PopupMenu& other)
|
||||
: lookAndFeel (other.lookAndFeel)
|
||||
: items (other.items),
|
||||
lookAndFeel (other.lookAndFeel)
|
||||
{
|
||||
items.addCopiesOf (other.items);
|
||||
}
|
||||
|
||||
PopupMenu& PopupMenu::operator= (const PopupMenu& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
items = other.items;
|
||||
lookAndFeel = other.lookAndFeel;
|
||||
|
||||
clear();
|
||||
items.addCopiesOf (other.items);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PopupMenu::PopupMenu (PopupMenu&& other) noexcept
|
||||
: lookAndFeel (other.lookAndFeel)
|
||||
: items (std::move (other.items)),
|
||||
lookAndFeel (std::move (other.lookAndFeel))
|
||||
{
|
||||
items.swapWith (other.items);
|
||||
}
|
||||
|
||||
PopupMenu& PopupMenu::operator= (PopupMenu&& other) noexcept
|
||||
{
|
||||
jassert (this != &other); // hopefully the compiler should make this situation impossible!
|
||||
|
||||
items.swapWith (other.items);
|
||||
items = std::move (other.items);
|
||||
lookAndFeel = other.lookAndFeel;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PopupMenu::~PopupMenu()
|
||||
{
|
||||
}
|
||||
PopupMenu::~PopupMenu() = default;
|
||||
|
||||
void PopupMenu::clear()
|
||||
{
|
||||
|
|
@ -1305,13 +1304,54 @@ void PopupMenu::clear()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
PopupMenu::Item::Item() noexcept
|
||||
PopupMenu::Item::Item() = default;
|
||||
|
||||
#if JUCE_MSVC && _MSC_VER < 1900 // tedious VC2013 workaround
|
||||
PopupMenu::Item::Item (Item&& other)
|
||||
: text (std::move (other.text)),
|
||||
itemID (other.itemID),
|
||||
action (std::move (other.action)),
|
||||
subMenu (std::move (other.subMenu)),
|
||||
image (std::move (other.image)),
|
||||
customComponent (std::move (other.customComponent)),
|
||||
customCallback (std::move (other.customCallback)),
|
||||
commandManager (other.commandManager),
|
||||
shortcutKeyDescription (std::move (other.shortcutKeyDescription)),
|
||||
colour (other.colour),
|
||||
isEnabled (other.isEnabled),
|
||||
isTicked (other.isTicked),
|
||||
isSeparator (other.isSeparator),
|
||||
isSectionHeader (other.isSectionHeader)
|
||||
{
|
||||
}
|
||||
|
||||
PopupMenu::Item& PopupMenu::Item::operator= (Item&& other)
|
||||
{
|
||||
text = std::move (other.text);
|
||||
itemID = other.itemID;
|
||||
action = std::move (other.action);
|
||||
subMenu = std::move (other.subMenu);
|
||||
image = std::move (other.image);
|
||||
customComponent = std::move (other.customComponent);
|
||||
customCallback = std::move (other.customCallback);
|
||||
commandManager = other.commandManager;
|
||||
shortcutKeyDescription = std::move (other.shortcutKeyDescription);
|
||||
colour = other.colour;
|
||||
isEnabled = other.isEnabled;
|
||||
isTicked = other.isTicked;
|
||||
isSeparator = other.isSeparator;
|
||||
isSectionHeader = other.isSectionHeader;
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
PopupMenu::Item::Item (Item&&) = default;
|
||||
PopupMenu::Item& PopupMenu::Item::operator= (Item&&) = default;
|
||||
#endif
|
||||
|
||||
PopupMenu::Item::Item (const Item& other)
|
||||
: text (other.text),
|
||||
itemID (other.itemID),
|
||||
action (other.action),
|
||||
subMenu (createCopyIfNotNull (other.subMenu.get())),
|
||||
image (other.image != nullptr ? other.image->createCopy() : nullptr),
|
||||
customComponent (other.customComponent),
|
||||
|
|
@ -1330,6 +1370,7 @@ PopupMenu::Item& PopupMenu::Item::operator= (const Item& other)
|
|||
{
|
||||
text = other.text;
|
||||
itemID = other.itemID;
|
||||
action = other.action;
|
||||
subMenu.reset (createCopyIfNotNull (other.subMenu.get()));
|
||||
image = other.image != nullptr ? other.image->createCopy() : std::unique_ptr<Drawable>();
|
||||
customComponent = other.customComponent;
|
||||
|
|
@ -1344,7 +1385,7 @@ PopupMenu::Item& PopupMenu::Item::operator= (const Item& other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
void PopupMenu::addItem (const Item& newItem)
|
||||
void PopupMenu::addItem (Item newItem)
|
||||
{
|
||||
// An ID of 0 is used as a return value to indicate that the user
|
||||
// didn't pick anything, so you shouldn't use it as the ID for an item..
|
||||
|
|
@ -1352,17 +1393,33 @@ void PopupMenu::addItem (const Item& newItem)
|
|||
|| newItem.isSeparator || newItem.isSectionHeader
|
||||
|| newItem.subMenu != nullptr);
|
||||
|
||||
items.add (new Item (newItem));
|
||||
items.push_back (std::move (newItem));
|
||||
}
|
||||
|
||||
void PopupMenu::addItem (int itemResultID, const String& itemText, bool isActive, bool isTicked)
|
||||
void PopupMenu::addItem (String itemText, std::function<void()> action)
|
||||
{
|
||||
addItem (std::move (itemText), true, false, std::move (action));
|
||||
}
|
||||
|
||||
void PopupMenu::addItem (String itemText, bool isActive, bool isTicked, std::function<void()> action)
|
||||
{
|
||||
Item i;
|
||||
i.text = itemText;
|
||||
i.text = std::move (itemText);
|
||||
i.action = std::move (action);
|
||||
i.itemID = -1;
|
||||
i.isEnabled = isActive;
|
||||
i.isTicked = isTicked;
|
||||
addItem (std::move (i));
|
||||
}
|
||||
|
||||
void PopupMenu::addItem (int itemResultID, String itemText, bool isActive, bool isTicked)
|
||||
{
|
||||
Item i;
|
||||
i.text = std::move (itemText);
|
||||
i.itemID = itemResultID;
|
||||
i.isEnabled = isActive;
|
||||
i.isTicked = isTicked;
|
||||
addItem (i);
|
||||
addItem (std::move (i));
|
||||
}
|
||||
|
||||
static std::unique_ptr<Drawable> createDrawableFromImage (const Image& im)
|
||||
|
|
@ -1377,26 +1434,26 @@ static std::unique_ptr<Drawable> createDrawableFromImage (const Image& im)
|
|||
return {};
|
||||
}
|
||||
|
||||
void PopupMenu::addItem (int itemResultID, const String& itemText, bool isActive, bool isTicked, const Image& iconToUse)
|
||||
void PopupMenu::addItem (int itemResultID, String itemText, bool isActive, bool isTicked, const Image& iconToUse)
|
||||
{
|
||||
addItem (itemResultID, itemText, isActive, isTicked, createDrawableFromImage (iconToUse));
|
||||
addItem (itemResultID, std::move (itemText), isActive, isTicked, createDrawableFromImage (iconToUse));
|
||||
}
|
||||
|
||||
void PopupMenu::addItem (int itemResultID, const String& itemText, bool isActive,
|
||||
void PopupMenu::addItem (int itemResultID, String itemText, bool isActive,
|
||||
bool isTicked, std::unique_ptr<Drawable> iconToUse)
|
||||
{
|
||||
Item i;
|
||||
i.text = itemText;
|
||||
i.text = std::move (itemText);
|
||||
i.itemID = itemResultID;
|
||||
i.isEnabled = isActive;
|
||||
i.isTicked = isTicked;
|
||||
i.image = std::move (iconToUse);
|
||||
addItem (i);
|
||||
addItem (std::move (i));
|
||||
}
|
||||
|
||||
void PopupMenu::addCommandItem (ApplicationCommandManager* commandManager,
|
||||
const CommandID commandID,
|
||||
const String& displayName,
|
||||
String displayName,
|
||||
std::unique_ptr<Drawable> iconToUse)
|
||||
{
|
||||
jassert (commandManager != nullptr && commandID != 0);
|
||||
|
|
@ -1407,40 +1464,40 @@ void PopupMenu::addCommandItem (ApplicationCommandManager* commandManager,
|
|||
auto* target = commandManager->getTargetForCommand (commandID, info);
|
||||
|
||||
Item i;
|
||||
i.text = displayName.isNotEmpty() ? displayName : info.shortName;
|
||||
i.text = displayName.isNotEmpty() ? std::move (displayName) : info.shortName;
|
||||
i.itemID = (int) commandID;
|
||||
i.commandManager = commandManager;
|
||||
i.isEnabled = target != nullptr && (info.flags & ApplicationCommandInfo::isDisabled) == 0;
|
||||
i.isTicked = (info.flags & ApplicationCommandInfo::isTicked) != 0;
|
||||
i.image = std::move (iconToUse);
|
||||
addItem (i);
|
||||
addItem (std::move (i));
|
||||
}
|
||||
}
|
||||
|
||||
void PopupMenu::addColouredItem (int itemResultID, const String& itemText, Colour itemTextColour,
|
||||
void PopupMenu::addColouredItem (int itemResultID, String itemText, Colour itemTextColour,
|
||||
bool isActive, bool isTicked, std::unique_ptr<Drawable> iconToUse)
|
||||
{
|
||||
Item i;
|
||||
i.text = itemText;
|
||||
i.text = std::move (itemText);
|
||||
i.itemID = itemResultID;
|
||||
i.colour = itemTextColour;
|
||||
i.isEnabled = isActive;
|
||||
i.isTicked = isTicked;
|
||||
i.image = std::move (iconToUse);
|
||||
addItem (i);
|
||||
addItem (std::move (i));
|
||||
}
|
||||
|
||||
void PopupMenu::addColouredItem (int itemResultID, const String& itemText, Colour itemTextColour,
|
||||
void PopupMenu::addColouredItem (int itemResultID, String itemText, Colour itemTextColour,
|
||||
bool isActive, bool isTicked, const Image& iconToUse)
|
||||
{
|
||||
Item i;
|
||||
i.text = itemText;
|
||||
i.text = std::move (itemText);
|
||||
i.itemID = itemResultID;
|
||||
i.colour = itemTextColour;
|
||||
i.isEnabled = isActive;
|
||||
i.isTicked = isTicked;
|
||||
i.image = createDrawableFromImage (iconToUse);
|
||||
addItem (i);
|
||||
addItem (std::move (i));
|
||||
}
|
||||
|
||||
void PopupMenu::addCustomItem (int itemResultID, CustomComponent* cc, const PopupMenu* subMenu)
|
||||
|
|
@ -1449,7 +1506,7 @@ void PopupMenu::addCustomItem (int itemResultID, CustomComponent* cc, const Popu
|
|||
i.itemID = itemResultID;
|
||||
i.customComponent = cc;
|
||||
i.subMenu.reset (createCopyIfNotNull (subMenu));
|
||||
addItem (i);
|
||||
addItem (std::move (i));
|
||||
}
|
||||
|
||||
void PopupMenu::addCustomItem (int itemResultID, Component* customComponent, int idealWidth, int idealHeight,
|
||||
|
|
@ -1461,46 +1518,47 @@ void PopupMenu::addCustomItem (int itemResultID, Component* customComponent, int
|
|||
subMenu);
|
||||
}
|
||||
|
||||
void PopupMenu::addSubMenu (const String& subMenuName, const PopupMenu& subMenu, bool isActive)
|
||||
void PopupMenu::addSubMenu (String subMenuName, PopupMenu subMenu, bool isActive)
|
||||
{
|
||||
addSubMenu (subMenuName, subMenu, isActive, nullptr, false, 0);
|
||||
addSubMenu (std::move (subMenuName), std::move (subMenu), isActive, nullptr, false, 0);
|
||||
}
|
||||
|
||||
void PopupMenu::addSubMenu (const String& subMenuName, const PopupMenu& subMenu, bool isActive,
|
||||
void PopupMenu::addSubMenu (String subMenuName, PopupMenu subMenu, bool isActive,
|
||||
const Image& iconToUse, bool isTicked, int itemResultID)
|
||||
{
|
||||
addSubMenu (subMenuName, subMenu, isActive, createDrawableFromImage (iconToUse), isTicked, itemResultID);
|
||||
addSubMenu (std::move (subMenuName), std::move (subMenu), isActive,
|
||||
createDrawableFromImage (iconToUse), isTicked, itemResultID);
|
||||
}
|
||||
|
||||
void PopupMenu::addSubMenu (const String& subMenuName, const PopupMenu& subMenu, bool isActive,
|
||||
void PopupMenu::addSubMenu (String subMenuName, PopupMenu subMenu, bool isActive,
|
||||
std::unique_ptr<Drawable> iconToUse, bool isTicked, int itemResultID)
|
||||
{
|
||||
Item i;
|
||||
i.text = subMenuName;
|
||||
i.text = std::move (subMenuName);
|
||||
i.itemID = itemResultID;
|
||||
i.subMenu.reset (new PopupMenu (subMenu));
|
||||
i.isEnabled = isActive && (itemResultID != 0 || subMenu.getNumItems() > 0);
|
||||
i.subMenu.reset (new PopupMenu (std::move (subMenu)));
|
||||
i.isTicked = isTicked;
|
||||
i.image = std::move (iconToUse);
|
||||
addItem (i);
|
||||
addItem (std::move (i));
|
||||
}
|
||||
|
||||
void PopupMenu::addSeparator()
|
||||
{
|
||||
if (items.size() > 0 && ! items.getLast()->isSeparator)
|
||||
if (items.size() > 0 && ! items.back().isSeparator)
|
||||
{
|
||||
Item i;
|
||||
i.isSeparator = true;
|
||||
addItem (i);
|
||||
addItem (std::move (i));
|
||||
}
|
||||
}
|
||||
|
||||
void PopupMenu::addSectionHeader (const String& title)
|
||||
void PopupMenu::addSectionHeader (String title)
|
||||
{
|
||||
Item i;
|
||||
i.text = title;
|
||||
i.text = std::move (title);
|
||||
i.isSectionHeader = true;
|
||||
addItem (i);
|
||||
addItem (std::move (i));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1579,11 +1637,11 @@ PopupMenu::Options PopupMenu::Options::withPreferredPopupDirection (PopupDirecti
|
|||
Component* PopupMenu::createWindow (const Options& options,
|
||||
ApplicationCommandManager** managerOfChosenCommand) const
|
||||
{
|
||||
return items.isEmpty() ? nullptr
|
||||
: new HelperClasses::MenuWindow (*this, nullptr, options,
|
||||
! options.getTargetScreenArea().isEmpty(),
|
||||
ModifierKeys::currentModifiers.isAnyMouseButtonDown(),
|
||||
managerOfChosenCommand);
|
||||
return items.empty() ? nullptr
|
||||
: new HelperClasses::MenuWindow (*this, nullptr, options,
|
||||
! options.getTargetScreenArea().isEmpty(),
|
||||
ModifierKeys::currentModifiers.isAnyMouseButtonDown(),
|
||||
managerOfChosenCommand);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1627,8 +1685,9 @@ struct PopupMenuCompletionCallback : public ModalComponentManager::Callback
|
|||
JUCE_DECLARE_NON_COPYABLE (PopupMenuCompletionCallback)
|
||||
};
|
||||
|
||||
int PopupMenu::showWithOptionalCallback (const Options& options, ModalComponentManager::Callback* const userCallback,
|
||||
const bool canBeModal)
|
||||
int PopupMenu::showWithOptionalCallback (const Options& options,
|
||||
ModalComponentManager::Callback* userCallback,
|
||||
bool canBeModal)
|
||||
{
|
||||
std::unique_ptr<ModalComponentManager::Callback> userCallbackDeleter (userCallback);
|
||||
std::unique_ptr<PopupMenuCompletionCallback> callback (new PopupMenuCompletionCallback());
|
||||
|
|
@ -1664,6 +1723,11 @@ int PopupMenu::showMenu (const Options& options)
|
|||
}
|
||||
#endif
|
||||
|
||||
void PopupMenu::showMenuAsync (const Options& options)
|
||||
{
|
||||
showWithOptionalCallback (options, nullptr, false);
|
||||
}
|
||||
|
||||
void PopupMenu::showMenuAsync (const Options& options, ModalComponentManager::Callback* userCallback)
|
||||
{
|
||||
#if ! JUCE_MODAL_LOOPS_PERMITTED
|
||||
|
|
@ -1743,8 +1807,8 @@ int PopupMenu::getNumItems() const noexcept
|
|||
{
|
||||
int num = 0;
|
||||
|
||||
for (auto* mi : items)
|
||||
if (! mi->isSeparator)
|
||||
for (auto& mi : items)
|
||||
if (! mi.isSeparator)
|
||||
++num;
|
||||
|
||||
return num;
|
||||
|
|
@ -1752,9 +1816,9 @@ int PopupMenu::getNumItems() const noexcept
|
|||
|
||||
bool PopupMenu::containsCommandItem (const int commandID) const
|
||||
{
|
||||
for (auto* mi : items)
|
||||
if ((mi->itemID == commandID && mi->commandManager != nullptr)
|
||||
|| (mi->subMenu != nullptr && mi->subMenu->containsCommandItem (commandID)))
|
||||
for (auto& mi : items)
|
||||
if ((mi.itemID == commandID && mi.commandManager != nullptr)
|
||||
|| (mi.subMenu != nullptr && mi.subMenu->containsCommandItem (commandID)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
@ -1762,14 +1826,14 @@ bool PopupMenu::containsCommandItem (const int commandID) const
|
|||
|
||||
bool PopupMenu::containsAnyActiveItems() const noexcept
|
||||
{
|
||||
for (auto* mi : items)
|
||||
for (auto& mi : items)
|
||||
{
|
||||
if (mi->subMenu != nullptr)
|
||||
if (mi.subMenu != nullptr)
|
||||
{
|
||||
if (mi->subMenu->containsAnyActiveItems())
|
||||
if (mi.subMenu->containsAnyActiveItems())
|
||||
return true;
|
||||
}
|
||||
else if (mi->isEnabled)
|
||||
else if (mi.isEnabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1832,14 +1896,14 @@ PopupMenu::MenuItemIterator::MenuItemIterator (const PopupMenu& m, bool recurse)
|
|||
menus.add (&m);
|
||||
}
|
||||
|
||||
PopupMenu::MenuItemIterator::~MenuItemIterator() {}
|
||||
PopupMenu::MenuItemIterator::~MenuItemIterator() = default;
|
||||
|
||||
bool PopupMenu::MenuItemIterator::next()
|
||||
{
|
||||
if (index.size() == 0 || menus.getLast()->items.size() == 0)
|
||||
return false;
|
||||
|
||||
currentItem = menus.getLast()->items.getUnchecked (index.getLast());
|
||||
currentItem = const_cast<PopupMenu::Item*> (&(menus.getLast()->items[(size_t) index.getLast()]));
|
||||
|
||||
if (searchRecursively && currentItem->subMenu != nullptr)
|
||||
{
|
||||
|
|
@ -1851,7 +1915,7 @@ bool PopupMenu::MenuItemIterator::next()
|
|||
index.setUnchecked (index.size() - 1, index.getLast() + 1);
|
||||
}
|
||||
|
||||
while (index.size() > 0 && index.getLast() >= menus.getLast()->items.size())
|
||||
while (index.size() > 0 && index.getLast() >= (int) menus.getLast()->items.size())
|
||||
{
|
||||
index.removeLast();
|
||||
menus.removeLast();
|
||||
|
|
@ -1863,7 +1927,7 @@ bool PopupMenu::MenuItemIterator::next()
|
|||
return true;
|
||||
}
|
||||
|
||||
PopupMenu::Item& PopupMenu::MenuItemIterator::getItem() const noexcept
|
||||
PopupMenu::Item& PopupMenu::MenuItemIterator::getItem() const
|
||||
{
|
||||
jassert (currentItem != nullptr);
|
||||
return *(currentItem);
|
||||
|
|
|
|||
|
|
@ -79,13 +79,7 @@ namespace juce
|
|||
*/
|
||||
class JUCE_API PopupMenu
|
||||
{
|
||||
private:
|
||||
class Window;
|
||||
|
||||
public:
|
||||
class CustomComponent;
|
||||
class CustomCallback;
|
||||
|
||||
//==============================================================================
|
||||
/** Creates an empty popup menu. */
|
||||
PopupMenu();
|
||||
|
|
@ -105,6 +99,10 @@ public:
|
|||
/** Move assignment operator */
|
||||
PopupMenu& operator= (PopupMenu&&) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
class CustomComponent;
|
||||
class CustomCallback;
|
||||
|
||||
//==============================================================================
|
||||
/** Resets the menu, removing all its items. */
|
||||
void clear();
|
||||
|
|
@ -116,13 +114,12 @@ public:
|
|||
You'll need to set some fields after creating an Item before you
|
||||
can add it to a PopupMenu
|
||||
*/
|
||||
Item() noexcept;
|
||||
Item();
|
||||
|
||||
/** Creates a copy of an item. */
|
||||
Item (const Item&);
|
||||
|
||||
/** Creates a copy of an item. */
|
||||
Item& operator= (const Item&);
|
||||
Item (Item&&);
|
||||
Item& operator= (Item&&);
|
||||
|
||||
/** The menu item's name. */
|
||||
String text;
|
||||
|
|
@ -130,6 +127,9 @@ public:
|
|||
/** The menu item's ID. This must not be 0 if you want the item to be triggerable! */
|
||||
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;
|
||||
|
||||
|
|
@ -175,7 +175,17 @@ public:
|
|||
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 (const Item& newItem);
|
||||
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.
|
||||
|
||||
|
|
@ -190,7 +200,7 @@ public:
|
|||
@see addSeparator, addColouredItem, addCustomItem, addSubMenu
|
||||
*/
|
||||
void addItem (int itemResultID,
|
||||
const String& itemText,
|
||||
String itemText,
|
||||
bool isEnabled = true,
|
||||
bool isTicked = false);
|
||||
|
||||
|
|
@ -208,7 +218,7 @@ public:
|
|||
@see addSeparator, addColouredItem, addCustomItem, addSubMenu
|
||||
*/
|
||||
void addItem (int itemResultID,
|
||||
const String& itemText,
|
||||
String itemText,
|
||||
bool isEnabled,
|
||||
bool isTicked,
|
||||
const Image& iconToUse);
|
||||
|
|
@ -228,7 +238,7 @@ public:
|
|||
@see addSeparator, addColouredItem, addCustomItem, addSubMenu
|
||||
*/
|
||||
void addItem (int itemResultID,
|
||||
const String& itemText,
|
||||
String itemText,
|
||||
bool isEnabled,
|
||||
bool isTicked,
|
||||
std::unique_ptr<Drawable> iconToUse);
|
||||
|
|
@ -246,7 +256,7 @@ public:
|
|||
*/
|
||||
void addCommandItem (ApplicationCommandManager* commandManager,
|
||||
CommandID commandID,
|
||||
const String& displayName = String(),
|
||||
String displayName = {},
|
||||
std::unique_ptr<Drawable> iconToUse = {});
|
||||
|
||||
/** Appends a text item with a special colour.
|
||||
|
|
@ -256,11 +266,11 @@ public:
|
|||
current look-and-feel. See addItem() for a description of the parameters.
|
||||
*/
|
||||
void addColouredItem (int itemResultID,
|
||||
const String& itemText,
|
||||
String itemText,
|
||||
Colour itemTextColour,
|
||||
bool isEnabled = true,
|
||||
bool isTicked = false,
|
||||
const Image& iconToUse = Image());
|
||||
const Image& iconToUse = {});
|
||||
|
||||
/** Appends a text item with a special colour.
|
||||
|
||||
|
|
@ -269,7 +279,7 @@ public:
|
|||
current look-and-feel. See addItem() for a description of the parameters.
|
||||
*/
|
||||
void addColouredItem (int itemResultID,
|
||||
const String& itemText,
|
||||
String itemText,
|
||||
Colour itemTextColour,
|
||||
bool isEnabled,
|
||||
bool isTicked,
|
||||
|
|
@ -314,8 +324,8 @@ public:
|
|||
If the itemResultID argument is non-zero, then the sub-menu item itself can be
|
||||
clicked to trigger it as a command.
|
||||
*/
|
||||
void addSubMenu (const String& subMenuName,
|
||||
const PopupMenu& subMenu,
|
||||
void addSubMenu (String subMenuName,
|
||||
PopupMenu subMenu,
|
||||
bool isEnabled = true);
|
||||
|
||||
/** Appends a sub-menu with an icon.
|
||||
|
|
@ -324,8 +334,8 @@ public:
|
|||
If the itemResultID argument is non-zero, then the sub-menu item itself can be
|
||||
clicked to trigger it as a command.
|
||||
*/
|
||||
void addSubMenu (const String& subMenuName,
|
||||
const PopupMenu& subMenu,
|
||||
void addSubMenu (String subMenuName,
|
||||
PopupMenu subMenu,
|
||||
bool isEnabled,
|
||||
const Image& iconToUse,
|
||||
bool isTicked = false,
|
||||
|
|
@ -341,8 +351,8 @@ public:
|
|||
the item. The menu will take ownership of this drawable object and will delete it
|
||||
later when no longer needed
|
||||
*/
|
||||
void addSubMenu (const String& subMenuName,
|
||||
const PopupMenu& subMenu,
|
||||
void addSubMenu (String subMenuName,
|
||||
PopupMenu subMenu,
|
||||
bool isEnabled,
|
||||
std::unique_ptr<Drawable> iconToUse,
|
||||
bool isTicked = false,
|
||||
|
|
@ -360,7 +370,7 @@ public:
|
|||
This is a bold-font items which can be used as a header to separate the items
|
||||
into named groups.
|
||||
*/
|
||||
void addSectionHeader (const String& title);
|
||||
void addSectionHeader (String title);
|
||||
|
||||
/** Returns the number of items that the menu currently contains.
|
||||
(This doesn't count separators).
|
||||
|
|
@ -509,6 +519,9 @@ public:
|
|||
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);
|
||||
|
|
@ -594,7 +607,7 @@ public:
|
|||
/** 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 noexcept;
|
||||
Item& getItem() const;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
|
|
@ -749,10 +762,11 @@ public:
|
|||
private:
|
||||
//==============================================================================
|
||||
JUCE_PUBLIC_IN_DLL_BUILD (struct HelperClasses)
|
||||
class Window;
|
||||
friend struct HelperClasses;
|
||||
friend class MenuBarComponent;
|
||||
|
||||
OwnedArray<Item> items;
|
||||
std::vector<Item> items;
|
||||
WeakReference<LookAndFeel> lookAndFeel;
|
||||
|
||||
Component* createWindow (const Options&, ApplicationCommandManager**) const;
|
||||
|
|
|
|||
|
|
@ -543,7 +543,7 @@ void Toolbar::showMissingItems()
|
|||
{
|
||||
PopupMenu m;
|
||||
m.addCustomItem (1, new MissingItemsComponent (*this, getThickness()));
|
||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (missingItemsButton.get()), [] (int) {});
|
||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (missingItemsButton.get()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ namespace juce
|
|||
class KeyMappingEditorComponent::ChangeKeyButton : public Button
|
||||
{
|
||||
public:
|
||||
ChangeKeyButton (KeyMappingEditorComponent& kec, const CommandID command,
|
||||
const String& keyName, const int keyIndex)
|
||||
ChangeKeyButton (KeyMappingEditorComponent& kec, CommandID command,
|
||||
const String& keyName, int keyIndex)
|
||||
: Button (keyName),
|
||||
owner (kec),
|
||||
commandID (command),
|
||||
|
|
@ -50,31 +50,31 @@ public:
|
|||
keyNum >= 0 ? getName() : String());
|
||||
}
|
||||
|
||||
static void menuCallback (int result, ChangeKeyButton* button)
|
||||
{
|
||||
if (button != nullptr)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case 1: button->assignNewKey(); break;
|
||||
case 2: button->owner.getMappings().removeKeyPress (button->commandID, button->keyNum); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clicked() override
|
||||
{
|
||||
if (keyNum >= 0)
|
||||
{
|
||||
// existing key clicked..
|
||||
Component::SafePointer<ChangeKeyButton> button (this);
|
||||
PopupMenu m;
|
||||
m.addItem (1, TRANS("Change this key-mapping"));
|
||||
m.addSeparator();
|
||||
m.addItem (2, TRANS("Remove this key-mapping"));
|
||||
|
||||
m.showMenuAsync (PopupMenu::Options(),
|
||||
ModalCallbackFunction::forComponent (menuCallback, this));
|
||||
m.addItem (TRANS("Change this key-mapping"),
|
||||
[button]
|
||||
{
|
||||
if (button != nullptr)
|
||||
button.getComponent()->assignNewKey();
|
||||
});
|
||||
|
||||
m.addSeparator();
|
||||
|
||||
m.addItem (TRANS("Remove this key-mapping"),
|
||||
[button]
|
||||
{
|
||||
if (button != nullptr)
|
||||
button->owner.getMappings().removeKeyPress (button->commandID,
|
||||
button->keyNum);
|
||||
});
|
||||
|
||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (this));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue