git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
302
deps/juce/modules/juce_gui_basics/menus/juce_BurgerMenuComponent.cpp
vendored
Normal file
302
deps/juce/modules/juce_gui_basics/menus/juce_BurgerMenuComponent.cpp
vendored
Normal file
@ -0,0 +1,302 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - 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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
struct CustomMenuBarItemHolder : public Component
|
||||
{
|
||||
CustomMenuBarItemHolder (const ReferenceCountedObjectPtr<PopupMenu::CustomComponent>& customComponent)
|
||||
{
|
||||
setInterceptsMouseClicks (false, true);
|
||||
update (customComponent);
|
||||
}
|
||||
|
||||
void update (const ReferenceCountedObjectPtr<PopupMenu::CustomComponent>& newComponent)
|
||||
{
|
||||
jassert (newComponent != nullptr);
|
||||
|
||||
if (newComponent != custom)
|
||||
{
|
||||
if (custom != nullptr)
|
||||
removeChildComponent (custom.get());
|
||||
|
||||
custom = newComponent;
|
||||
addAndMakeVisible (*custom);
|
||||
resized();
|
||||
}
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
custom->setBounds (getLocalBounds());
|
||||
}
|
||||
|
||||
ReferenceCountedObjectPtr<PopupMenu::CustomComponent> custom;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomMenuBarItemHolder)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
BurgerMenuComponent::BurgerMenuComponent (MenuBarModel* modelToUse)
|
||||
{
|
||||
lookAndFeelChanged();
|
||||
listBox.addMouseListener (this, true);
|
||||
|
||||
setModel (modelToUse);
|
||||
addAndMakeVisible (listBox);
|
||||
}
|
||||
|
||||
BurgerMenuComponent::~BurgerMenuComponent()
|
||||
{
|
||||
if (model != nullptr)
|
||||
model->removeListener (this);
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::setModel (MenuBarModel* newModel)
|
||||
{
|
||||
if (newModel != model)
|
||||
{
|
||||
if (model != nullptr)
|
||||
model->removeListener (this);
|
||||
|
||||
model = newModel;
|
||||
|
||||
if (model != nullptr)
|
||||
model->addListener (this);
|
||||
|
||||
refresh();
|
||||
listBox.updateContent();
|
||||
}
|
||||
}
|
||||
|
||||
MenuBarModel* BurgerMenuComponent::getModel() const noexcept
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::refresh()
|
||||
{
|
||||
lastRowClicked = inputSourceIndexOfLastClick = -1;
|
||||
|
||||
rows.clear();
|
||||
|
||||
if (model != nullptr)
|
||||
{
|
||||
auto menuBarNames = model->getMenuBarNames();
|
||||
|
||||
for (auto menuIdx = 0; menuIdx < menuBarNames.size(); ++menuIdx)
|
||||
{
|
||||
PopupMenu::Item menuItem;
|
||||
menuItem.text = menuBarNames[menuIdx];
|
||||
|
||||
String ignore;
|
||||
auto menu = model->getMenuForIndex (menuIdx, ignore);
|
||||
|
||||
rows.add (Row { true, menuIdx, menuItem });
|
||||
addMenuBarItemsForMenu (menu, menuIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::addMenuBarItemsForMenu (PopupMenu& menu, int menuIdx)
|
||||
{
|
||||
for (PopupMenu::MenuItemIterator it (menu); it.next();)
|
||||
{
|
||||
auto& item = it.getItem();
|
||||
|
||||
if (item.isSeparator)
|
||||
continue;
|
||||
|
||||
if (hasSubMenu (item))
|
||||
addMenuBarItemsForMenu (*item.subMenu, menuIdx);
|
||||
else
|
||||
rows.add (Row {false, menuIdx, it.getItem()});
|
||||
}
|
||||
}
|
||||
|
||||
int BurgerMenuComponent::getNumRows()
|
||||
{
|
||||
return rows.size();
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::paint (Graphics& g)
|
||||
{
|
||||
getLookAndFeel().drawPopupMenuBackground (g, getWidth(), getHeight());
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::paintListBoxItem (int rowIndex, Graphics& g, int w, int h, bool highlight)
|
||||
{
|
||||
auto& lf = getLookAndFeel();
|
||||
Rectangle<int> r (w, h);
|
||||
|
||||
auto row = (rowIndex < rows.size() ? rows.getReference (rowIndex)
|
||||
: Row { true, 0, {} });
|
||||
|
||||
g.fillAll (findColour (PopupMenu::backgroundColourId));
|
||||
|
||||
if (row.isMenuHeader)
|
||||
{
|
||||
lf.drawPopupMenuSectionHeader (g, r.reduced (20, 0), row.item.text);
|
||||
g.setColour (Colours::grey);
|
||||
g.fillRect (r.withHeight (1));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& item = row.item;
|
||||
auto* colour = item.colour != Colour() ? &item.colour : nullptr;
|
||||
|
||||
if (item.customComponent == nullptr)
|
||||
lf.drawPopupMenuItem (g, r.reduced (20, 0),
|
||||
item.isSeparator,
|
||||
item.isEnabled,
|
||||
highlight,
|
||||
item.isTicked,
|
||||
hasSubMenu (item),
|
||||
item.text,
|
||||
item.shortcutKeyDescription,
|
||||
item.image.get(),
|
||||
colour);
|
||||
}
|
||||
}
|
||||
|
||||
bool BurgerMenuComponent::hasSubMenu (const PopupMenu::Item& item)
|
||||
{
|
||||
return item.subMenu != nullptr && (item.itemID == 0 || item.subMenu->getNumItems() > 0);
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::listBoxItemClicked (int rowIndex, const MouseEvent& e)
|
||||
{
|
||||
auto row = rowIndex < rows.size() ? rows.getReference (rowIndex)
|
||||
: Row { true, 0, {} };
|
||||
|
||||
if (! row.isMenuHeader)
|
||||
{
|
||||
lastRowClicked = rowIndex;
|
||||
inputSourceIndexOfLastClick = e.source.getIndex();
|
||||
}
|
||||
}
|
||||
|
||||
Component* BurgerMenuComponent::refreshComponentForRow (int rowIndex, bool isRowSelected, Component* existing)
|
||||
{
|
||||
auto row = rowIndex < rows.size() ? rows.getReference (rowIndex)
|
||||
: Row { true, 0, {} };
|
||||
|
||||
auto hasCustomComponent = (row.item.customComponent != nullptr);
|
||||
|
||||
if (existing == nullptr && hasCustomComponent)
|
||||
return new CustomMenuBarItemHolder (row.item.customComponent);
|
||||
|
||||
if (existing != nullptr)
|
||||
{
|
||||
auto* componentToUpdate = dynamic_cast<CustomMenuBarItemHolder*> (existing);
|
||||
jassert (componentToUpdate != nullptr);
|
||||
|
||||
if (hasCustomComponent && componentToUpdate != nullptr)
|
||||
{
|
||||
row.item.customComponent->setHighlighted (isRowSelected);
|
||||
componentToUpdate->update (row.item.customComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete existing;
|
||||
existing = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return existing;
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::resized()
|
||||
{
|
||||
listBox.setBounds (getLocalBounds());
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::menuBarItemsChanged (MenuBarModel* menuBarModel)
|
||||
{
|
||||
setModel (menuBarModel);
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::menuCommandInvoked (MenuBarModel*, const ApplicationCommandTarget::InvocationInfo&)
|
||||
{
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::mouseUp (const MouseEvent& event)
|
||||
{
|
||||
auto rowIndex = listBox.getSelectedRow();
|
||||
|
||||
if (rowIndex == lastRowClicked && rowIndex < rows.size()
|
||||
&& event.source.getIndex() == inputSourceIndexOfLastClick)
|
||||
{
|
||||
auto& row = rows.getReference (rowIndex);
|
||||
|
||||
if (! row.isMenuHeader)
|
||||
{
|
||||
listBox.selectRow (-1);
|
||||
|
||||
lastRowClicked = -1;
|
||||
inputSourceIndexOfLastClick = -1;
|
||||
|
||||
topLevelIndexClicked = row.topLevelMenuIndex;
|
||||
auto& item = row.item;
|
||||
|
||||
if (auto* managerOfChosenCommand = item.commandManager)
|
||||
{
|
||||
ApplicationCommandTarget::InvocationInfo info (item.itemID);
|
||||
info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu;
|
||||
|
||||
managerOfChosenCommand->invoke (info, true);
|
||||
}
|
||||
|
||||
postCommandMessage (item.itemID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::handleCommandMessage (int commandID)
|
||||
{
|
||||
if (model != nullptr)
|
||||
{
|
||||
model->menuItemSelected (commandID, topLevelIndexClicked);
|
||||
topLevelIndexClicked = -1;
|
||||
|
||||
refresh();
|
||||
listBox.updateContent();
|
||||
}
|
||||
}
|
||||
|
||||
void BurgerMenuComponent::lookAndFeelChanged()
|
||||
{
|
||||
listBox.setRowHeight (roundToInt (getLookAndFeel().getPopupMenuFont().getHeight() * 2.0f));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<AccessibilityHandler> BurgerMenuComponent::createAccessibilityHandler()
|
||||
{
|
||||
return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::menuBar);
|
||||
}
|
||||
|
||||
} // namespace juce
|
110
deps/juce/modules/juce_gui_basics/menus/juce_BurgerMenuComponent.h
vendored
Normal file
110
deps/juce/modules/juce_gui_basics/menus/juce_BurgerMenuComponent.h
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - 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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A component which lists all menu items and groups them into categories
|
||||
by their respective parent menus. This kind of component is often used
|
||||
for so-called "burger" menus in mobile apps.
|
||||
|
||||
@see MenuBarModel
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class BurgerMenuComponent : public Component,
|
||||
private ListBoxModel,
|
||||
private MenuBarModel::Listener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a burger menu component.
|
||||
|
||||
@param model the model object to use to control this burger menu. You can
|
||||
set the parameter or pass nullptr into this if you like,
|
||||
and set the model later using the setModel() method.
|
||||
|
||||
@see setModel
|
||||
*/
|
||||
BurgerMenuComponent (MenuBarModel* model = nullptr);
|
||||
|
||||
/** Destructor. */
|
||||
~BurgerMenuComponent() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the model object to use to control the burger menu.
|
||||
|
||||
This can be a nullptr, in which case the bar will be empty. This object will not be
|
||||
owned by the BurgerMenuComponent so it is up to you to manage its lifetime.
|
||||
Don't delete the object that is passed-in while it's still being used by this MenuBar.
|
||||
Any submenus in your MenuBarModel will be recursively flattened and added to the
|
||||
top-level burger menu section.
|
||||
*/
|
||||
void setModel (MenuBarModel* newModel);
|
||||
|
||||
/** Returns the current burger menu model being used. */
|
||||
MenuBarModel* getModel() const noexcept;
|
||||
|
||||
/** @internal */
|
||||
void lookAndFeelChanged() override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
struct Row
|
||||
{
|
||||
bool isMenuHeader;
|
||||
int topLevelMenuIndex;
|
||||
PopupMenu::Item item;
|
||||
};
|
||||
|
||||
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
|
||||
void refresh();
|
||||
void paint (Graphics&) override;
|
||||
int getNumRows() override;
|
||||
void paintListBoxItem (int, Graphics&, int, int, bool) override;
|
||||
void listBoxItemClicked (int, const MouseEvent&) override;
|
||||
Component* refreshComponentForRow (int, bool, Component*) override;
|
||||
void resized() override;
|
||||
void menuBarItemsChanged (MenuBarModel*) override;
|
||||
void menuCommandInvoked (MenuBarModel*, const ApplicationCommandTarget::InvocationInfo&) override;
|
||||
void mouseUp (const MouseEvent&) override;
|
||||
void handleCommandMessage (int) override;
|
||||
void addMenuBarItemsForMenu (PopupMenu&, int);
|
||||
static bool hasSubMenu (const PopupMenu::Item&);
|
||||
|
||||
//==============================================================================
|
||||
MenuBarModel* model = nullptr;
|
||||
ListBox listBox {"BurgerMenuListBox", this};
|
||||
Array<Row> rows;
|
||||
|
||||
int lastRowClicked = -1, inputSourceIndexOfLastClick = -1, topLevelIndexClicked = -1;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BurgerMenuComponent)
|
||||
};
|
||||
|
||||
} // namespace juce
|
451
deps/juce/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp
vendored
Normal file
451
deps/juce/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp
vendored
Normal file
@ -0,0 +1,451 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - 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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-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
|
||||
{
|
||||
|
||||
class MenuBarComponent::AccessibleItemComponent : public Component
|
||||
{
|
||||
public:
|
||||
AccessibleItemComponent (MenuBarComponent& comp, const String& menuItemName)
|
||||
: owner (comp),
|
||||
name (menuItemName)
|
||||
{
|
||||
setInterceptsMouseClicks (false, false);
|
||||
}
|
||||
|
||||
const String& getName() const noexcept { return name; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
|
||||
{
|
||||
class ComponentHandler : public AccessibilityHandler
|
||||
{
|
||||
public:
|
||||
explicit ComponentHandler (AccessibleItemComponent& item)
|
||||
: AccessibilityHandler (item,
|
||||
AccessibilityRole::menuItem,
|
||||
getAccessibilityActions (item)),
|
||||
itemComponent (item)
|
||||
{
|
||||
}
|
||||
|
||||
String getTitle() const override { return itemComponent.name; }
|
||||
|
||||
private:
|
||||
static AccessibilityActions getAccessibilityActions (AccessibleItemComponent& item)
|
||||
{
|
||||
auto showMenu = [&item] { item.owner.showMenu (item.owner.indexOfItemComponent (&item)); };
|
||||
|
||||
return AccessibilityActions().addAction (AccessibilityActionType::focus,
|
||||
[&item] { item.owner.setItemUnderMouse (item.owner.indexOfItemComponent (&item)); })
|
||||
.addAction (AccessibilityActionType::press, showMenu)
|
||||
.addAction (AccessibilityActionType::showMenu, showMenu);
|
||||
}
|
||||
|
||||
AccessibleItemComponent& itemComponent;
|
||||
};
|
||||
|
||||
return std::make_unique<ComponentHandler> (*this);
|
||||
}
|
||||
|
||||
MenuBarComponent& owner;
|
||||
const String name;
|
||||
};
|
||||
|
||||
MenuBarComponent::MenuBarComponent (MenuBarModel* m)
|
||||
{
|
||||
setRepaintsOnMouseActivity (true);
|
||||
setWantsKeyboardFocus (false);
|
||||
setMouseClickGrabsKeyboardFocus (false);
|
||||
|
||||
setModel (m);
|
||||
}
|
||||
|
||||
MenuBarComponent::~MenuBarComponent()
|
||||
{
|
||||
setModel (nullptr);
|
||||
Desktop::getInstance().removeGlobalMouseListener (this);
|
||||
}
|
||||
|
||||
MenuBarModel* MenuBarComponent::getModel() const noexcept
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
void MenuBarComponent::setModel (MenuBarModel* const newModel)
|
||||
{
|
||||
if (model != newModel)
|
||||
{
|
||||
if (model != nullptr)
|
||||
model->removeListener (this);
|
||||
|
||||
model = newModel;
|
||||
|
||||
if (model != nullptr)
|
||||
model->addListener (this);
|
||||
|
||||
repaint();
|
||||
menuBarItemsChanged (nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MenuBarComponent::paint (Graphics& g)
|
||||
{
|
||||
const auto isMouseOverBar = (currentPopupIndex >= 0 || itemUnderMouse >= 0 || isMouseOver());
|
||||
|
||||
getLookAndFeel().drawMenuBarBackground (g, getWidth(), getHeight(), isMouseOverBar, *this);
|
||||
|
||||
if (model == nullptr)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < itemComponents.size(); ++i)
|
||||
{
|
||||
const auto& itemComponent = itemComponents[i];
|
||||
const auto itemBounds = itemComponent->getBounds();
|
||||
|
||||
Graphics::ScopedSaveState ss (g);
|
||||
|
||||
g.setOrigin (itemBounds.getX(), 0);
|
||||
g.reduceClipRegion (0, 0, itemBounds.getWidth(), itemBounds.getHeight());
|
||||
|
||||
getLookAndFeel().drawMenuBarItem (g,
|
||||
itemBounds.getWidth(),
|
||||
itemBounds.getHeight(),
|
||||
(int) i,
|
||||
itemComponent->getName(),
|
||||
(int) i == itemUnderMouse,
|
||||
(int) i == currentPopupIndex,
|
||||
isMouseOverBar,
|
||||
*this);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::resized()
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
for (size_t i = 0; i < itemComponents.size(); ++i)
|
||||
{
|
||||
auto& itemComponent = itemComponents[i];
|
||||
|
||||
auto w = getLookAndFeel().getMenuBarItemWidth (*this, (int) i, itemComponent->getName());
|
||||
itemComponent->setBounds (x, 0, w, getHeight());
|
||||
x += w;
|
||||
}
|
||||
}
|
||||
|
||||
int MenuBarComponent::getItemAt (Point<int> p)
|
||||
{
|
||||
for (size_t i = 0; i < itemComponents.size(); ++i)
|
||||
if (itemComponents[i]->getBounds().contains (p) && reallyContains (p, true))
|
||||
return (int) i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MenuBarComponent::repaintMenuItem (int index)
|
||||
{
|
||||
if (isPositiveAndBelow (index, (int) itemComponents.size()))
|
||||
{
|
||||
auto itemBounds = itemComponents[(size_t) index]->getBounds();
|
||||
|
||||
repaint (itemBounds.getX() - 2,
|
||||
0,
|
||||
itemBounds.getWidth() + 4,
|
||||
itemBounds.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::setItemUnderMouse (int index)
|
||||
{
|
||||
if (itemUnderMouse == index)
|
||||
return;
|
||||
|
||||
repaintMenuItem (itemUnderMouse);
|
||||
itemUnderMouse = index;
|
||||
repaintMenuItem (itemUnderMouse);
|
||||
|
||||
if (isPositiveAndBelow (itemUnderMouse, (int) itemComponents.size()))
|
||||
if (auto* handler = itemComponents[(size_t) itemUnderMouse]->getAccessibilityHandler())
|
||||
handler->grabFocus();
|
||||
}
|
||||
|
||||
void MenuBarComponent::setOpenItem (int index)
|
||||
{
|
||||
if (currentPopupIndex != index)
|
||||
{
|
||||
if (currentPopupIndex < 0 && index >= 0)
|
||||
model->handleMenuBarActivate (true);
|
||||
else if (currentPopupIndex >= 0 && index < 0)
|
||||
model->handleMenuBarActivate (false);
|
||||
|
||||
repaintMenuItem (currentPopupIndex);
|
||||
currentPopupIndex = index;
|
||||
repaintMenuItem (currentPopupIndex);
|
||||
|
||||
auto& desktop = Desktop::getInstance();
|
||||
|
||||
if (index >= 0)
|
||||
desktop.addGlobalMouseListener (this);
|
||||
else
|
||||
desktop.removeGlobalMouseListener (this);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::updateItemUnderMouse (Point<int> p)
|
||||
{
|
||||
setItemUnderMouse (getItemAt (p));
|
||||
}
|
||||
|
||||
void MenuBarComponent::showMenu (int index)
|
||||
{
|
||||
if (index != currentPopupIndex)
|
||||
{
|
||||
PopupMenu::dismissAllActiveMenus();
|
||||
menuBarItemsChanged (nullptr);
|
||||
|
||||
setOpenItem (index);
|
||||
setItemUnderMouse (index);
|
||||
|
||||
if (isPositiveAndBelow (index, (int) itemComponents.size()))
|
||||
{
|
||||
const auto& itemComponent = itemComponents[(size_t) index];
|
||||
auto m = model->getMenuForIndex (itemUnderMouse, itemComponent->getName());
|
||||
|
||||
if (m.lookAndFeel == nullptr)
|
||||
m.setLookAndFeel (&getLookAndFeel());
|
||||
|
||||
auto itemBounds = itemComponent->getBounds();
|
||||
|
||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (this)
|
||||
.withTargetScreenArea (localAreaToGlobal (itemBounds))
|
||||
.withMinimumWidth (itemBounds.getWidth()),
|
||||
[this, index] (int result) { menuDismissed (index, result); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::menuDismissed (int topLevelIndex, int itemId)
|
||||
{
|
||||
topLevelIndexClicked = topLevelIndex;
|
||||
postCommandMessage (itemId);
|
||||
}
|
||||
|
||||
void MenuBarComponent::handleCommandMessage (int commandId)
|
||||
{
|
||||
updateItemUnderMouse (getMouseXYRelative());
|
||||
|
||||
if (currentPopupIndex == topLevelIndexClicked)
|
||||
setOpenItem (-1);
|
||||
|
||||
if (commandId != 0 && model != nullptr)
|
||||
model->menuItemSelected (commandId, topLevelIndexClicked);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MenuBarComponent::mouseEnter (const MouseEvent& e)
|
||||
{
|
||||
if (e.eventComponent == this)
|
||||
updateItemUnderMouse (e.getPosition());
|
||||
}
|
||||
|
||||
void MenuBarComponent::mouseExit (const MouseEvent& e)
|
||||
{
|
||||
if (e.eventComponent == this)
|
||||
updateItemUnderMouse (e.getPosition());
|
||||
}
|
||||
|
||||
void MenuBarComponent::mouseDown (const MouseEvent& e)
|
||||
{
|
||||
if (currentPopupIndex < 0)
|
||||
{
|
||||
updateItemUnderMouse (e.getEventRelativeTo (this).getPosition());
|
||||
|
||||
currentPopupIndex = -2;
|
||||
showMenu (itemUnderMouse);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
const auto item = getItemAt (e.getEventRelativeTo (this).getPosition());
|
||||
|
||||
if (item >= 0)
|
||||
showMenu (item);
|
||||
}
|
||||
|
||||
void MenuBarComponent::mouseUp (const MouseEvent& e)
|
||||
{
|
||||
const auto e2 = e.getEventRelativeTo (this);
|
||||
|
||||
updateItemUnderMouse (e2.getPosition());
|
||||
|
||||
if (itemUnderMouse < 0 && getLocalBounds().contains (e2.x, e2.y))
|
||||
{
|
||||
setOpenItem (-1);
|
||||
PopupMenu::dismissAllActiveMenus();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::mouseMove (const MouseEvent& e)
|
||||
{
|
||||
const auto e2 = e.getEventRelativeTo (this);
|
||||
|
||||
if (lastMousePos != e2.getPosition())
|
||||
{
|
||||
if (currentPopupIndex >= 0)
|
||||
{
|
||||
const auto item = getItemAt (e2.getPosition());
|
||||
|
||||
if (item >= 0)
|
||||
showMenu (item);
|
||||
}
|
||||
else
|
||||
{
|
||||
updateItemUnderMouse (e2.getPosition());
|
||||
}
|
||||
|
||||
lastMousePos = e2.getPosition();
|
||||
}
|
||||
}
|
||||
|
||||
bool MenuBarComponent::keyPressed (const KeyPress& key)
|
||||
{
|
||||
const auto numMenus = (int) itemComponents.size();
|
||||
|
||||
if (numMenus > 0)
|
||||
{
|
||||
const auto currentIndex = jlimit (0, numMenus - 1, currentPopupIndex);
|
||||
|
||||
if (key.isKeyCode (KeyPress::leftKey))
|
||||
{
|
||||
showMenu ((currentIndex + numMenus - 1) % numMenus);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.isKeyCode (KeyPress::rightKey))
|
||||
{
|
||||
showMenu ((currentIndex + 1) % numMenus);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MenuBarComponent::menuBarItemsChanged (MenuBarModel*)
|
||||
{
|
||||
StringArray newNames;
|
||||
|
||||
if (model != nullptr)
|
||||
newNames = model->getMenuBarNames();
|
||||
|
||||
auto itemsHaveChanged = [this, &newNames]
|
||||
{
|
||||
if ((int) itemComponents.size() != newNames.size())
|
||||
return true;
|
||||
|
||||
for (size_t i = 0; i < itemComponents.size(); ++i)
|
||||
if (itemComponents[i]->getName() != newNames[(int) i])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}();
|
||||
|
||||
if (itemsHaveChanged)
|
||||
{
|
||||
updateItemComponents (newNames);
|
||||
|
||||
repaint();
|
||||
resized();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::updateItemComponents (const StringArray& menuNames)
|
||||
{
|
||||
itemComponents.clear();
|
||||
|
||||
for (const auto& name : menuNames)
|
||||
{
|
||||
itemComponents.push_back (std::make_unique<AccessibleItemComponent> (*this, name));
|
||||
addAndMakeVisible (*itemComponents.back());
|
||||
}
|
||||
}
|
||||
|
||||
int MenuBarComponent::indexOfItemComponent (AccessibleItemComponent* itemComponent) const
|
||||
{
|
||||
const auto iter = std::find_if (itemComponents.cbegin(), itemComponents.cend(),
|
||||
[itemComponent] (const std::unique_ptr<AccessibleItemComponent>& c) { return c.get() == itemComponent; });
|
||||
|
||||
if (iter != itemComponents.cend())
|
||||
return (int) std::distance (itemComponents.cbegin(), iter);
|
||||
|
||||
jassertfalse;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MenuBarComponent::menuCommandInvoked (MenuBarModel*, const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
if (model == nullptr || (info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) != 0)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < itemComponents.size(); ++i)
|
||||
{
|
||||
const auto menu = model->getMenuForIndex ((int) i, itemComponents[i]->getName());
|
||||
|
||||
if (menu.containsCommandItem (info.commandID))
|
||||
{
|
||||
setItemUnderMouse ((int) i);
|
||||
startTimer (200);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::timerCallback()
|
||||
{
|
||||
stopTimer();
|
||||
updateItemUnderMouse (getMouseXYRelative());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<AccessibilityHandler> MenuBarComponent::createAccessibilityHandler()
|
||||
{
|
||||
struct MenuBarComponentAccessibilityHandler : public AccessibilityHandler
|
||||
{
|
||||
explicit MenuBarComponentAccessibilityHandler (MenuBarComponent& menuBarComponent)
|
||||
: AccessibilityHandler (menuBarComponent, AccessibilityRole::menuBar)
|
||||
{
|
||||
}
|
||||
|
||||
AccessibleState getCurrentState() const override { return AccessibleState().withIgnored(); }
|
||||
};
|
||||
|
||||
return std::make_unique<MenuBarComponentAccessibilityHandler> (*this);
|
||||
}
|
||||
|
||||
} // namespace juce
|
127
deps/juce/modules/juce_gui_basics/menus/juce_MenuBarComponent.h
vendored
Normal file
127
deps/juce/modules/juce_gui_basics/menus/juce_MenuBarComponent.h
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - 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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A menu bar component.
|
||||
|
||||
@see MenuBarModel
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API MenuBarComponent : public Component,
|
||||
private MenuBarModel::Listener,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a menu bar.
|
||||
|
||||
@param model the model object to use to control this bar. You can
|
||||
pass omit the parameter or pass nullptr into this if you like,
|
||||
and set the model later using the setModel() method.
|
||||
*/
|
||||
MenuBarComponent (MenuBarModel* model = nullptr);
|
||||
|
||||
/** Destructor. */
|
||||
~MenuBarComponent() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the model object to use to control the bar.
|
||||
|
||||
This can be a null pointer, in which case the bar will be empty. Don't delete the object
|
||||
that is passed-in while it's still being used by this MenuBar.
|
||||
*/
|
||||
void setModel (MenuBarModel* newModel);
|
||||
|
||||
/** Returns the current menu bar model being used. */
|
||||
MenuBarModel* getModel() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Pops up one of the menu items.
|
||||
|
||||
This lets you manually open one of the menus - it could be triggered by a
|
||||
key shortcut, for example.
|
||||
*/
|
||||
void showMenu (int menuIndex);
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void paint (Graphics&) override;
|
||||
/** @internal */
|
||||
void resized() override;
|
||||
/** @internal */
|
||||
void mouseEnter (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void mouseExit (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void mouseDown (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void mouseDrag (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void mouseUp (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void mouseMove (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void handleCommandMessage (int commandId) override;
|
||||
/** @internal */
|
||||
bool keyPressed (const KeyPress&) override;
|
||||
/** @internal */
|
||||
void menuBarItemsChanged (MenuBarModel*) override;
|
||||
/** @internal */
|
||||
void menuCommandInvoked (MenuBarModel*, const ApplicationCommandTarget::InvocationInfo&) override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class AccessibleItemComponent;
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
|
||||
void timerCallback() override;
|
||||
|
||||
int getItemAt (Point<int>);
|
||||
void setItemUnderMouse (int);
|
||||
void setOpenItem (int);
|
||||
void updateItemUnderMouse (Point<int>);
|
||||
void repaintMenuItem (int);
|
||||
void menuDismissed (int, int);
|
||||
|
||||
void updateItemComponents (const StringArray&);
|
||||
int indexOfItemComponent (AccessibleItemComponent*) const;
|
||||
|
||||
//==============================================================================
|
||||
MenuBarModel* model = nullptr;
|
||||
std::vector<std::unique_ptr<AccessibleItemComponent>> itemComponents;
|
||||
|
||||
Point<int> lastMousePos;
|
||||
int itemUnderMouse = -1, currentPopupIndex = -1, topLevelIndexClicked = 0;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MenuBarComponent)
|
||||
};
|
||||
|
||||
} // namespace juce
|
99
deps/juce/modules/juce_gui_basics/menus/juce_MenuBarModel.cpp
vendored
Normal file
99
deps/juce/modules/juce_gui_basics/menus/juce_MenuBarModel.cpp
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - 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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-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
|
||||
{
|
||||
|
||||
MenuBarModel::MenuBarModel() noexcept
|
||||
: manager (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
MenuBarModel::~MenuBarModel()
|
||||
{
|
||||
setApplicationCommandManagerToWatch (nullptr);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MenuBarModel::menuItemsChanged()
|
||||
{
|
||||
triggerAsyncUpdate();
|
||||
}
|
||||
|
||||
void MenuBarModel::setApplicationCommandManagerToWatch (ApplicationCommandManager* newManager)
|
||||
{
|
||||
if (manager != newManager)
|
||||
{
|
||||
if (manager != nullptr)
|
||||
manager->removeListener (this);
|
||||
|
||||
manager = newManager;
|
||||
|
||||
if (manager != nullptr)
|
||||
manager->addListener (this);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarModel::addListener (Listener* newListener)
|
||||
{
|
||||
listeners.add (newListener);
|
||||
}
|
||||
|
||||
void MenuBarModel::removeListener (Listener* listenerToRemove)
|
||||
{
|
||||
// Trying to remove a listener that isn't on the list!
|
||||
// If this assertion happens because this object is a dangling pointer, make sure you've not
|
||||
// deleted this menu model while it's still being used by something (e.g. by a MenuBarComponent)
|
||||
jassert (listeners.contains (listenerToRemove));
|
||||
|
||||
listeners.remove (listenerToRemove);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MenuBarModel::handleAsyncUpdate()
|
||||
{
|
||||
listeners.call ([this] (Listener& l) { l.menuBarItemsChanged (this); });
|
||||
}
|
||||
|
||||
void MenuBarModel::applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
listeners.call ([this, &info] (Listener& l) { l.menuCommandInvoked (this, info); });
|
||||
}
|
||||
|
||||
void MenuBarModel::applicationCommandListChanged()
|
||||
{
|
||||
menuItemsChanged();
|
||||
}
|
||||
|
||||
void MenuBarModel::handleMenuBarActivate (bool isActive)
|
||||
{
|
||||
menuBarActivated (isActive);
|
||||
listeners.call ([this, isActive] (Listener& l) { l.menuBarActivated (this, isActive); });
|
||||
}
|
||||
|
||||
void MenuBarModel::menuBarActivated (bool) {}
|
||||
void MenuBarModel::Listener::menuBarActivated (MenuBarModel*, bool) {}
|
||||
|
||||
} // namespace juce
|
192
deps/juce/modules/juce_gui_basics/menus/juce_MenuBarModel.h
vendored
Normal file
192
deps/juce/modules/juce_gui_basics/menus/juce_MenuBarModel.h
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - 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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A class for controlling MenuBar components.
|
||||
|
||||
This class is used to tell a MenuBar what menus to show, and to respond
|
||||
to a menu being selected.
|
||||
|
||||
@see MenuBarModel::Listener, MenuBarComponent, PopupMenu
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API MenuBarModel : private AsyncUpdater,
|
||||
private ApplicationCommandManagerListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
MenuBarModel() noexcept;
|
||||
|
||||
/** Destructor. */
|
||||
~MenuBarModel() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Call this when some of your menu items have changed.
|
||||
|
||||
This method will cause a callback to any MenuBarListener objects that
|
||||
are registered with this model.
|
||||
|
||||
If this model is displaying items from an ApplicationCommandManager, you
|
||||
can use the setApplicationCommandManagerToWatch() method to cause
|
||||
change messages to be sent automatically when the ApplicationCommandManager
|
||||
is changed.
|
||||
|
||||
@see addListener, removeListener, MenuBarListener
|
||||
*/
|
||||
void menuItemsChanged();
|
||||
|
||||
/** Tells the menu bar to listen to the specified command manager, and to update
|
||||
itself when the commands change.
|
||||
|
||||
This will also allow it to flash a menu name when a command from that menu
|
||||
is invoked using a keystroke.
|
||||
*/
|
||||
void setApplicationCommandManagerToWatch (ApplicationCommandManager* manager);
|
||||
|
||||
//==============================================================================
|
||||
/** A class to receive callbacks when a MenuBarModel changes.
|
||||
|
||||
@see MenuBarModel::addListener, MenuBarModel::removeListener, MenuBarModel::menuItemsChanged
|
||||
*/
|
||||
class JUCE_API Listener
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~Listener() = default;
|
||||
|
||||
//==============================================================================
|
||||
/** This callback is made when items are changed in the menu bar model. */
|
||||
virtual void menuBarItemsChanged (MenuBarModel* menuBarModel) = 0;
|
||||
|
||||
/** This callback is made when an application command is invoked that
|
||||
is represented by one of the items in the menu bar model.
|
||||
*/
|
||||
virtual void menuCommandInvoked (MenuBarModel* menuBarModel,
|
||||
const ApplicationCommandTarget::InvocationInfo& info) = 0;
|
||||
|
||||
/** Called when the menu bar is first activated or when the user finished interacting
|
||||
with the menu bar. */
|
||||
virtual void menuBarActivated (MenuBarModel* menuBarModel, bool isActive);
|
||||
};
|
||||
|
||||
/** Registers a listener for callbacks when the menu items in this model change.
|
||||
|
||||
The listener object will get callbacks when this object's menuItemsChanged()
|
||||
method is called.
|
||||
|
||||
@see removeListener
|
||||
*/
|
||||
void addListener (Listener* listenerToAdd);
|
||||
|
||||
/** Removes a listener.
|
||||
@see addListener
|
||||
*/
|
||||
void removeListener (Listener* listenerToRemove);
|
||||
|
||||
//==============================================================================
|
||||
/** This method must return a list of the names of the menus. */
|
||||
virtual StringArray getMenuBarNames() = 0;
|
||||
|
||||
/** This should return the popup menu to display for a given top-level menu.
|
||||
|
||||
@param topLevelMenuIndex the index of the top-level menu to show
|
||||
@param menuName the name of the top-level menu item to show
|
||||
*/
|
||||
virtual PopupMenu getMenuForIndex (int topLevelMenuIndex,
|
||||
const String& menuName) = 0;
|
||||
|
||||
/** This is called when a menu item has been clicked on.
|
||||
|
||||
@param menuItemID the item ID of the PopupMenu item that was selected
|
||||
@param topLevelMenuIndex the index of the top-level menu from which the item was
|
||||
chosen (just in case you've used duplicate ID numbers
|
||||
on more than one of the popup menus)
|
||||
*/
|
||||
virtual void menuItemSelected (int menuItemID,
|
||||
int topLevelMenuIndex) = 0;
|
||||
|
||||
/** This is called when the user starts/stops navigating the menu bar.
|
||||
|
||||
@param isActive true when the user starts navigating the menu bar
|
||||
*/
|
||||
virtual void menuBarActivated (bool isActive);
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_MAC || DOXYGEN
|
||||
/** OSX ONLY - Sets the model that is currently being shown as the main
|
||||
menu bar at the top of the screen on the Mac.
|
||||
|
||||
You can pass nullptr to stop the current model being displayed. Be careful
|
||||
not to delete a model while it is being used.
|
||||
|
||||
An optional extra menu can be specified, containing items to add to the top of
|
||||
the apple menu. (Confusingly, the 'apple' menu isn't the one with a picture of
|
||||
an apple, it's the one next to it, with your application's name at the top
|
||||
and the services menu etc on it). When one of these items is selected, the
|
||||
menu bar model will be used to invoke it, and in the menuItemSelected() callback
|
||||
the topLevelMenuIndex parameter will be -1. If you pass in an extraAppleMenuItems
|
||||
object then newMenuBarModel must be non-null.
|
||||
|
||||
If the recentItemsMenuName parameter is non-empty, then any sub-menus with this
|
||||
name will be replaced by OSX's special recent-files menu.
|
||||
*/
|
||||
static void setMacMainMenu (MenuBarModel* newMenuBarModel,
|
||||
const PopupMenu* extraAppleMenuItems = nullptr,
|
||||
const String& recentItemsMenuName = String());
|
||||
|
||||
/** OSX ONLY - Returns the menu model that is currently being shown as
|
||||
the main menu bar.
|
||||
*/
|
||||
static MenuBarModel* getMacMainMenu();
|
||||
|
||||
/** OSX ONLY - Returns the menu that was last passed as the extraAppleMenuItems
|
||||
argument to setMacMainMenu(), or nullptr if none was specified.
|
||||
*/
|
||||
static const PopupMenu* getMacExtraAppleItemsMenu();
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo&) override;
|
||||
/** @internal */
|
||||
void applicationCommandListChanged() override;
|
||||
/** @internal */
|
||||
void handleAsyncUpdate() override;
|
||||
/** @internal */
|
||||
void handleMenuBarActivate (bool isActive);
|
||||
private:
|
||||
ApplicationCommandManager* manager;
|
||||
ListenerList<Listener> listeners;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MenuBarModel)
|
||||
};
|
||||
|
||||
|
||||
} // namespace juce
|
2327
deps/juce/modules/juce_gui_basics/menus/juce_PopupMenu.cpp
vendored
Normal file
2327
deps/juce/modules/juce_gui_basics/menus/juce_PopupMenu.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1033
deps/juce/modules/juce_gui_basics/menus/juce_PopupMenu.h
vendored
Normal file
1033
deps/juce/modules/juce_gui_basics/menus/juce_PopupMenu.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user