mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-14 00:14:18 +00:00
Added Animated App template and examples
This commit is contained in:
parent
fefcf7aca6
commit
ff6520a89a
1141 changed files with 438491 additions and 94 deletions
|
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
MenuBarComponent::MenuBarComponent (MenuBarModel* m)
|
||||
: model (nullptr),
|
||||
itemUnderMouse (-1),
|
||||
currentPopupIndex (-1),
|
||||
topLevelIndexClicked (0)
|
||||
{
|
||||
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 bool isMouseOverBar = currentPopupIndex >= 0 || itemUnderMouse >= 0 || isMouseOver();
|
||||
|
||||
getLookAndFeel().drawMenuBarBackground (g,
|
||||
getWidth(),
|
||||
getHeight(),
|
||||
isMouseOverBar,
|
||||
*this);
|
||||
|
||||
if (model != nullptr)
|
||||
{
|
||||
for (int i = 0; i < menuNames.size(); ++i)
|
||||
{
|
||||
Graphics::ScopedSaveState ss (g);
|
||||
|
||||
g.setOrigin (xPositions [i], 0);
|
||||
g.reduceClipRegion (0, 0, xPositions[i + 1] - xPositions[i], getHeight());
|
||||
|
||||
getLookAndFeel().drawMenuBarItem (g,
|
||||
xPositions[i + 1] - xPositions[i],
|
||||
getHeight(),
|
||||
i,
|
||||
menuNames[i],
|
||||
i == itemUnderMouse,
|
||||
i == currentPopupIndex,
|
||||
isMouseOverBar,
|
||||
*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::resized()
|
||||
{
|
||||
xPositions.clear();
|
||||
int x = 0;
|
||||
xPositions.add (x);
|
||||
|
||||
for (int i = 0; i < menuNames.size(); ++i)
|
||||
{
|
||||
x += getLookAndFeel().getMenuBarItemWidth (*this, i, menuNames[i]);
|
||||
xPositions.add (x);
|
||||
}
|
||||
}
|
||||
|
||||
int MenuBarComponent::getItemAt (Point<int> p)
|
||||
{
|
||||
for (int i = 0; i < xPositions.size(); ++i)
|
||||
if (p.x >= xPositions[i] && p.x < xPositions[i + 1])
|
||||
return reallyContains (p, true) ? i : -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MenuBarComponent::repaintMenuItem (int index)
|
||||
{
|
||||
if (isPositiveAndBelow (index, xPositions.size()))
|
||||
{
|
||||
const int x1 = xPositions [index];
|
||||
const int x2 = xPositions [index + 1];
|
||||
|
||||
repaint (x1 - 2, 0, x2 - x1 + 4, getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::setItemUnderMouse (const int index)
|
||||
{
|
||||
if (itemUnderMouse != index)
|
||||
{
|
||||
repaintMenuItem (itemUnderMouse);
|
||||
itemUnderMouse = index;
|
||||
repaintMenuItem (itemUnderMouse);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::setOpenItem (int index)
|
||||
{
|
||||
if (currentPopupIndex != index)
|
||||
{
|
||||
repaintMenuItem (currentPopupIndex);
|
||||
currentPopupIndex = index;
|
||||
repaintMenuItem (currentPopupIndex);
|
||||
|
||||
Desktop& 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 (index >= 0)
|
||||
{
|
||||
PopupMenu m (model->getMenuForIndex (itemUnderMouse,
|
||||
menuNames [itemUnderMouse]));
|
||||
|
||||
if (m.lookAndFeel == nullptr)
|
||||
m.setLookAndFeel (&getLookAndFeel());
|
||||
|
||||
const Rectangle<int> itemPos (xPositions [index], 0, xPositions [index + 1] - xPositions [index], getHeight());
|
||||
|
||||
m.showMenuAsync (PopupMenu::Options().withTargetComponent (this)
|
||||
.withTargetScreenArea (localAreaToGlobal (itemPos))
|
||||
.withMinimumWidth (itemPos.getWidth()),
|
||||
ModalCallbackFunction::forComponent (menuBarMenuDismissedCallback, this, index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::menuBarMenuDismissedCallback (int result, MenuBarComponent* bar, int topLevelIndex)
|
||||
{
|
||||
if (bar != nullptr)
|
||||
bar->menuDismissed (topLevelIndex, result);
|
||||
}
|
||||
|
||||
void MenuBarComponent::menuDismissed (int topLevelIndex, int itemId)
|
||||
{
|
||||
topLevelIndexClicked = topLevelIndex;
|
||||
postCommandMessage (itemId);
|
||||
}
|
||||
|
||||
void MenuBarComponent::handleCommandMessage (int commandId)
|
||||
{
|
||||
const Point<int> mousePos (getMouseXYRelative());
|
||||
updateItemUnderMouse (mousePos);
|
||||
|
||||
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)
|
||||
{
|
||||
const MouseEvent e2 (e.getEventRelativeTo (this));
|
||||
updateItemUnderMouse (e2.getPosition());
|
||||
|
||||
currentPopupIndex = -2;
|
||||
showMenu (itemUnderMouse);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
const MouseEvent e2 (e.getEventRelativeTo (this));
|
||||
const int item = getItemAt (e2.getPosition());
|
||||
|
||||
if (item >= 0)
|
||||
showMenu (item);
|
||||
}
|
||||
|
||||
void MenuBarComponent::mouseUp (const MouseEvent& e)
|
||||
{
|
||||
const MouseEvent 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 MouseEvent e2 (e.getEventRelativeTo (this));
|
||||
|
||||
if (lastMousePos != e2.getPosition())
|
||||
{
|
||||
if (currentPopupIndex >= 0)
|
||||
{
|
||||
const int item = getItemAt (e2.getPosition());
|
||||
|
||||
if (item >= 0)
|
||||
showMenu (item);
|
||||
}
|
||||
else
|
||||
{
|
||||
updateItemUnderMouse (e2.getPosition());
|
||||
}
|
||||
|
||||
lastMousePos = e2.getPosition();
|
||||
}
|
||||
}
|
||||
|
||||
bool MenuBarComponent::keyPressed (const KeyPress& key)
|
||||
{
|
||||
const int numMenus = menuNames.size();
|
||||
|
||||
if (numMenus > 0)
|
||||
{
|
||||
const int 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* /*menuBarModel*/)
|
||||
{
|
||||
StringArray newNames;
|
||||
|
||||
if (model != nullptr)
|
||||
newNames = model->getMenuBarNames();
|
||||
|
||||
if (newNames != menuNames)
|
||||
{
|
||||
menuNames = newNames;
|
||||
repaint();
|
||||
resized();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::menuCommandInvoked (MenuBarModel* /*menuBarModel*/,
|
||||
const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
if (model == nullptr || (info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) != 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < menuNames.size(); ++i)
|
||||
{
|
||||
const PopupMenu menu (model->getMenuForIndex (i, menuNames [i]));
|
||||
|
||||
if (menu.containsCommandItem (info.commandID))
|
||||
{
|
||||
setItemUnderMouse (i);
|
||||
startTimer (200);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::timerCallback()
|
||||
{
|
||||
stopTimer();
|
||||
updateItemUnderMouse (getMouseXYRelative());
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_MENUBARCOMPONENT_H_INCLUDED
|
||||
#define JUCE_MENUBARCOMPONENT_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A menu bar component.
|
||||
|
||||
@see MenuBarModel
|
||||
*/
|
||||
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 nullptr into this if you like, and set the model
|
||||
later using the setModel() method
|
||||
*/
|
||||
MenuBarComponent (MenuBarModel* model);
|
||||
|
||||
/** Destructor. */
|
||||
~MenuBarComponent();
|
||||
|
||||
//==============================================================================
|
||||
/** 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:
|
||||
//==============================================================================
|
||||
MenuBarModel* model;
|
||||
|
||||
StringArray menuNames;
|
||||
Array<int> xPositions;
|
||||
Point<int> lastMousePos;
|
||||
int itemUnderMouse, currentPopupIndex, topLevelIndexClicked;
|
||||
|
||||
int getItemAt (Point<int>);
|
||||
void setItemUnderMouse (int index);
|
||||
void setOpenItem (int index);
|
||||
void updateItemUnderMouse (Point<int>);
|
||||
void timerCallback() override;
|
||||
void repaintMenuItem (int index);
|
||||
void menuDismissed (int topLevelIndex, int itemId);
|
||||
static void menuBarMenuDismissedCallback (int, MenuBarComponent*, int);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MenuBarComponent)
|
||||
};
|
||||
|
||||
#endif // JUCE_MENUBARCOMPONENT_H_INCLUDED
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
MenuBarModel::MenuBarModel() noexcept
|
||||
: manager (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
MenuBarModel::~MenuBarModel()
|
||||
{
|
||||
setApplicationCommandManagerToWatch (nullptr);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MenuBarModel::menuItemsChanged()
|
||||
{
|
||||
triggerAsyncUpdate();
|
||||
}
|
||||
|
||||
void MenuBarModel::setApplicationCommandManagerToWatch (ApplicationCommandManager* const newManager) noexcept
|
||||
{
|
||||
if (manager != newManager)
|
||||
{
|
||||
if (manager != nullptr)
|
||||
manager->removeListener (this);
|
||||
|
||||
manager = newManager;
|
||||
|
||||
if (manager != nullptr)
|
||||
manager->addListener (this);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarModel::addListener (Listener* const newListener) noexcept
|
||||
{
|
||||
listeners.add (newListener);
|
||||
}
|
||||
|
||||
void MenuBarModel::removeListener (Listener* const listenerToRemove) noexcept
|
||||
{
|
||||
// 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 (&MenuBarModel::Listener::menuBarItemsChanged, this);
|
||||
}
|
||||
|
||||
void MenuBarModel::applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
listeners.call (&MenuBarModel::Listener::menuCommandInvoked, this, info);
|
||||
}
|
||||
|
||||
void MenuBarModel::applicationCommandListChanged()
|
||||
{
|
||||
menuItemsChanged();
|
||||
}
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_MENUBARMODEL_H_INCLUDED
|
||||
#define JUCE_MENUBARMODEL_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
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
|
||||
*/
|
||||
class JUCE_API MenuBarModel : private AsyncUpdater,
|
||||
private ApplicationCommandManagerListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
MenuBarModel() noexcept;
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~MenuBarModel();
|
||||
|
||||
//==============================================================================
|
||||
/** 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) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** A class to receive callbacks when a MenuBarModel changes.
|
||||
|
||||
@see MenuBarModel::addListener, MenuBarModel::removeListener, MenuBarModel::menuItemsChanged
|
||||
*/
|
||||
class JUCE_API Listener
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~Listener() {}
|
||||
|
||||
//==============================================================================
|
||||
/** 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;
|
||||
};
|
||||
|
||||
/** 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) noexcept;
|
||||
|
||||
/** Removes a listener.
|
||||
@see addListener
|
||||
*/
|
||||
void removeListener (Listener* listenerToRemove) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** 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;
|
||||
|
||||
//==============================================================================
|
||||
#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 0 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::empty);
|
||||
|
||||
/** 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;
|
||||
|
||||
private:
|
||||
ApplicationCommandManager* manager;
|
||||
ListenerList<Listener> listeners;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MenuBarModel)
|
||||
};
|
||||
|
||||
/** This typedef is just for compatibility with old code - newer code should use the MenuBarModel::Listener class directly. */
|
||||
typedef MenuBarModel::Listener MenuBarModelListener;
|
||||
|
||||
|
||||
#endif // JUCE_MENUBARMODEL_H_INCLUDED
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,624 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_POPUPMENU_H_INCLUDED
|
||||
#define JUCE_POPUPMENU_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** 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");
|
||||
|
||||
const int result = m.show();
|
||||
|
||||
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);
|
||||
|
||||
const int result = m.show();
|
||||
|
||||
...etc
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
class JUCE_API PopupMenu
|
||||
{
|
||||
private:
|
||||
class Window;
|
||||
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty popup menu. */
|
||||
PopupMenu();
|
||||
|
||||
/** Creates a copy of another menu. */
|
||||
PopupMenu (const PopupMenu& other);
|
||||
|
||||
/** Destructor. */
|
||||
~PopupMenu();
|
||||
|
||||
/** Copies this menu from another one. */
|
||||
PopupMenu& operator= (const PopupMenu& other);
|
||||
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
PopupMenu (PopupMenu&& other) noexcept;
|
||||
PopupMenu& operator= (PopupMenu&& other) noexcept;
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/** Resets the menu, removing all its items. */
|
||||
void clear();
|
||||
|
||||
/** 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,
|
||||
const 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,
|
||||
const 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,
|
||||
const String& itemText,
|
||||
bool isEnabled,
|
||||
bool isTicked,
|
||||
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
|
||||
*/
|
||||
void addCommandItem (ApplicationCommandManager* commandManager,
|
||||
CommandID commandID,
|
||||
const String& displayName = String::empty);
|
||||
|
||||
|
||||
/** 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,
|
||||
const String& itemText,
|
||||
Colour itemTextColour,
|
||||
bool isEnabled = true,
|
||||
bool isTicked = false,
|
||||
const Image& iconToUse = Image::null);
|
||||
|
||||
/** 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.
|
||||
It's the caller's responsibility to delete the component that is passed-in
|
||||
when it's no longer needed 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.
|
||||
|
||||
@see CustomComponent
|
||||
*/
|
||||
void addCustomItem (int itemResultID,
|
||||
Component* customComponent,
|
||||
int idealWidth, int idealHeight,
|
||||
bool triggerMenuItemAutomaticallyWhenClicked,
|
||||
const PopupMenu* optionalSubMenu = nullptr);
|
||||
|
||||
/** 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 (const String& subMenuName,
|
||||
const 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 (const String& subMenuName,
|
||||
const 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 (const String& subMenuName,
|
||||
const PopupMenu& subMenu,
|
||||
bool isEnabled,
|
||||
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 mutliple 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 (const String& title);
|
||||
|
||||
/** 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:
|
||||
Options();
|
||||
|
||||
Options withTargetComponent (Component* targetComponent) const noexcept;
|
||||
Options withTargetScreenArea (const Rectangle<int>& targetArea) const noexcept;
|
||||
Options withMinimumWidth (int minWidth) const noexcept;
|
||||
Options withMaximumNumColumns (int maxNumColumns) const noexcept;
|
||||
Options withStandardItemHeight (int standardHeight) const noexcept;
|
||||
Options withItemThatMustBeVisible (int idOfItemToBeVisible) const noexcept;
|
||||
|
||||
private:
|
||||
friend class PopupMenu;
|
||||
friend class PopupMenu::Window;
|
||||
Rectangle<int> targetArea;
|
||||
Component* targetComponent;
|
||||
int visibleItemID, minWidth, maxColumns, standardHeight;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
#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 non-zero, 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 (const 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, with a user-provided callback that will receive the result. */
|
||||
void showMenuAsync (const Options& options,
|
||||
ModalComponentManager::Callback* 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.
|
||||
*/
|
||||
MenuItemIterator (const PopupMenu& menu);
|
||||
|
||||
/** 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();
|
||||
|
||||
/** Adds an item to the target menu which has all the properties of this item. */
|
||||
void addItemTo (PopupMenu& targetMenu);
|
||||
|
||||
//==============================================================================
|
||||
String itemName;
|
||||
const PopupMenu* subMenu;
|
||||
int itemId;
|
||||
bool isSeparator;
|
||||
bool isTicked;
|
||||
bool isEnabled;
|
||||
bool isCustomComponent;
|
||||
bool isSectionHeader;
|
||||
const Colour* customColour;
|
||||
const Drawable* icon;
|
||||
ApplicationCommandManager* commandManager;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const PopupMenu& menu;
|
||||
int index;
|
||||
|
||||
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.
|
||||
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.
|
||||
*/
|
||||
CustomComponent (bool isTriggeredAutomatically = true);
|
||||
|
||||
/** Destructor. */
|
||||
~CustomComponent();
|
||||
|
||||
/** 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; }
|
||||
|
||||
/** @internal */
|
||||
bool isTriggeredAutomatically() const noexcept { return triggeredAutomatically; }
|
||||
/** @internal */
|
||||
void setHighlighted (bool shouldBeHighlighted);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
bool isHighlighted, triggeredAutomatically;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomComponent)
|
||||
};
|
||||
|
||||
/** Appends a custom menu item.
|
||||
|
||||
This will add a user-defined component to use as a menu item. The component
|
||||
passed in will be deleted by this menu when it's no longer needed.
|
||||
|
||||
@see CustomComponent
|
||||
*/
|
||||
void addCustomItem (int itemResultID, CustomComponent* customComponent,
|
||||
const PopupMenu* optionalSubMenu = nullptr);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** This abstract base class is implemented by LookAndFeel classes to provide
|
||||
menu drawing functionality.
|
||||
*/
|
||||
struct JUCE_API LookAndFeelMethods
|
||||
{
|
||||
virtual ~LookAndFeelMethods() {}
|
||||
|
||||
/** Fills the background of a popup menu component. */
|
||||
virtual void drawPopupMenuBackground (Graphics&, int width, int height) = 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) = 0;
|
||||
|
||||
virtual void drawPopupMenuSectionHeader (Graphics&, const Rectangle<int>& area,
|
||||
const String& sectionName) = 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) = 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) = 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;
|
||||
};
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
JUCE_PUBLIC_IN_DLL_BUILD (class Item)
|
||||
JUCE_PUBLIC_IN_DLL_BUILD (struct HelperClasses)
|
||||
friend struct HelperClasses;
|
||||
friend class MenuBarComponent;
|
||||
|
||||
OwnedArray<Item> items;
|
||||
LookAndFeel* lookAndFeel;
|
||||
|
||||
Component* createWindow (const Options&, ApplicationCommandManager**) const;
|
||||
int showWithOptionalCallback (const Options&, ModalComponentManager::Callback*, bool);
|
||||
|
||||
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
|
||||
// These methods have new implementations now - see its new definition
|
||||
int drawPopupMenuItem (Graphics&, int, int, bool, bool, bool, bool, bool, const String&, const String&, Image*, const Colour*) { return 0; }
|
||||
#endif
|
||||
|
||||
JUCE_LEAK_DETECTOR (PopupMenu)
|
||||
};
|
||||
|
||||
#endif // JUCE_POPUPMENU_H_INCLUDED
|
||||
Loading…
Add table
Add a link
Reference in a new issue