LMMS
Loading...
Searching...
No Matches
juce_MenuBarComponent.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
30{
31public:
33 : owner (comp),
34 name (menuItemName)
35 {
36 setInterceptsMouseClicks (false, false);
37 }
38
39 const String& getName() const noexcept { return name; }
40
41private:
42 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
43 {
44 class ComponentHandler : public AccessibilityHandler
45 {
46 public:
47 explicit ComponentHandler (AccessibleItemComponent& item)
50 getAccessibilityActions (item)),
51 itemComponent (item)
52 {
53 }
54
55 String getTitle() const override { return itemComponent.name; }
56
57 private:
58 static AccessibilityActions getAccessibilityActions (AccessibleItemComponent& item)
59 {
60 auto showMenu = [&item] { item.owner.showMenu (item.owner.indexOfItemComponent (&item)); };
61
63 [&item] { item.owner.setItemUnderMouse (item.owner.indexOfItemComponent (&item)); })
66 }
67
68 AccessibleItemComponent& itemComponent;
69 };
70
71 return std::make_unique<ComponentHandler> (*this);
72 }
73
75 const String name;
76};
77
86
88{
89 setModel (nullptr);
90 Desktop::getInstance().removeGlobalMouseListener (this);
91}
92
97
99{
100 if (model != newModel)
101 {
102 if (model != nullptr)
103 model->removeListener (this);
104
105 model = newModel;
106
107 if (model != nullptr)
108 model->addListener (this);
109
110 repaint();
111 menuBarItemsChanged (nullptr);
112 }
113}
114
115//==============================================================================
117{
118 const auto isMouseOverBar = (currentPopupIndex >= 0 || itemUnderMouse >= 0 || isMouseOver());
119
120 getLookAndFeel().drawMenuBarBackground (g, getWidth(), getHeight(), isMouseOverBar, *this);
121
122 if (model == nullptr)
123 return;
124
125 for (size_t i = 0; i < itemComponents.size(); ++i)
126 {
127 const auto& itemComponent = itemComponents[i];
128 const auto itemBounds = itemComponent->getBounds();
129
131
132 g.setOrigin (itemBounds.getX(), 0);
133 g.reduceClipRegion (0, 0, itemBounds.getWidth(), itemBounds.getHeight());
134
135 getLookAndFeel().drawMenuBarItem (g,
136 itemBounds.getWidth(),
137 itemBounds.getHeight(),
138 (int) i,
139 itemComponent->getName(),
140 (int) i == itemUnderMouse,
141 (int) i == currentPopupIndex,
142 isMouseOverBar,
143 *this);
144 }
145}
146
148{
149 int x = 0;
150
151 for (size_t i = 0; i < itemComponents.size(); ++i)
152 {
153 auto& itemComponent = itemComponents[i];
154
155 auto w = getLookAndFeel().getMenuBarItemWidth (*this, (int) i, itemComponent->getName());
156 itemComponent->setBounds (x, 0, w, getHeight());
157 x += w;
158 }
159}
160
162{
163 for (size_t i = 0; i < itemComponents.size(); ++i)
164 if (itemComponents[i]->getBounds().contains (p) && reallyContains (p, true))
165 return (int) i;
166
167 return -1;
168}
169
171{
172 if (isPositiveAndBelow (index, (int) itemComponents.size()))
173 {
174 auto itemBounds = itemComponents[(size_t) index]->getBounds();
175
176 repaint (itemBounds.getX() - 2,
177 0,
178 itemBounds.getWidth() + 4,
179 itemBounds.getHeight());
180 }
181}
182
184{
185 if (itemUnderMouse == index)
186 return;
187
189 itemUnderMouse = index;
191
194 handler->grabFocus();
195}
196
198{
199 if (currentPopupIndex != index)
200 {
201 if (currentPopupIndex < 0 && index >= 0)
202 model->handleMenuBarActivate (true);
203 else if (currentPopupIndex >= 0 && index < 0)
204 model->handleMenuBarActivate (false);
205
207 currentPopupIndex = index;
209
210 auto& desktop = Desktop::getInstance();
211
212 if (index >= 0)
213 desktop.addGlobalMouseListener (this);
214 else
215 desktop.removeGlobalMouseListener (this);
216 }
217}
218
223
225{
226 if (index != currentPopupIndex)
227 {
229 menuBarItemsChanged (nullptr);
230
231 setOpenItem (index);
232 setItemUnderMouse (index);
233
234 if (isPositiveAndBelow (index, (int) itemComponents.size()))
235 {
236 const auto& itemComponent = itemComponents[(size_t) index];
237 auto m = model->getMenuForIndex (itemUnderMouse, itemComponent->getName());
238
239 if (m.lookAndFeel == nullptr)
240 m.setLookAndFeel (&getLookAndFeel());
241
242 auto itemBounds = itemComponent->getBounds();
243
244 const auto callback = [ref = SafePointer<MenuBarComponent> (this), index] (int result)
245 {
246 if (ref != nullptr)
247 ref->menuDismissed (index, result);
248 };
249
250 m.showMenuAsync (PopupMenu::Options().withTargetComponent (this)
251 .withTargetScreenArea (localAreaToGlobal (itemBounds))
252 .withMinimumWidth (itemBounds.getWidth()),
253 callback);
254 }
255 }
256}
257
258void MenuBarComponent::menuDismissed (int topLevelIndex, int itemId)
259{
260 topLevelIndexClicked = topLevelIndex;
261 postCommandMessage (itemId);
262}
263
265{
267
269 setOpenItem (-1);
270
271 if (commandId != 0 && model != nullptr)
272 model->menuItemSelected (commandId, topLevelIndexClicked);
273}
274
275//==============================================================================
277{
278 if (e.eventComponent == this)
279 updateItemUnderMouse (e.getPosition());
280}
281
283{
284 if (e.eventComponent == this)
285 updateItemUnderMouse (e.getPosition());
286}
287
289{
290 if (currentPopupIndex < 0)
291 {
292 updateItemUnderMouse (e.getEventRelativeTo (this).getPosition());
293
296 }
297}
298
300{
301 const auto item = getItemAt (e.getEventRelativeTo (this).getPosition());
302
303 if (item >= 0)
304 showMenu (item);
305}
306
308{
309 const auto e2 = e.getEventRelativeTo (this);
310
311 updateItemUnderMouse (e2.getPosition());
312
313 if (itemUnderMouse < 0 && getLocalBounds().contains (e2.x, e2.y))
314 {
315 setOpenItem (-1);
317 }
318}
319
321{
322 const auto e2 = e.getEventRelativeTo (this);
323
324 if (lastMousePos != e2.getPosition())
325 {
326 if (currentPopupIndex >= 0)
327 {
328 const auto item = getItemAt (e2.getPosition());
329
330 if (item >= 0)
331 showMenu (item);
332 }
333 else
334 {
335 updateItemUnderMouse (e2.getPosition());
336 }
337
338 lastMousePos = e2.getPosition();
339 }
340}
341
343{
344 const auto numMenus = (int) itemComponents.size();
345
346 if (numMenus > 0)
347 {
348 const auto currentIndex = jlimit (0, numMenus - 1, currentPopupIndex);
349
350 if (key.isKeyCode (KeyPress::leftKey))
351 {
352 showMenu ((currentIndex + numMenus - 1) % numMenus);
353 return true;
354 }
355
356 if (key.isKeyCode (KeyPress::rightKey))
357 {
358 showMenu ((currentIndex + 1) % numMenus);
359 return true;
360 }
361 }
362
363 return false;
364}
365
367{
368 StringArray newNames;
369
370 if (model != nullptr)
371 newNames = model->getMenuBarNames();
372
373 auto itemsHaveChanged = [this, &newNames]
374 {
375 if ((int) itemComponents.size() != newNames.size())
376 return true;
377
378 for (size_t i = 0; i < itemComponents.size(); ++i)
379 if (itemComponents[i]->getName() != newNames[(int) i])
380 return true;
381
382 return false;
383 }();
384
385 if (itemsHaveChanged)
386 {
387 updateItemComponents (newNames);
388
389 repaint();
390 resized();
391 }
392}
393
395{
396 itemComponents.clear();
397
398 for (const auto& name : menuNames)
399 {
400 itemComponents.push_back (std::make_unique<AccessibleItemComponent> (*this, name));
402 }
403}
404
406{
407 const auto iter = std::find_if (itemComponents.cbegin(), itemComponents.cend(),
408 [itemComponent] (const std::unique_ptr<AccessibleItemComponent>& c) { return c.get() == itemComponent; });
409
410 if (iter != itemComponents.cend())
411 return (int) std::distance (itemComponents.cbegin(), iter);
412
414 return -1;
415}
416
418{
419 if (model == nullptr || (info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) != 0)
420 return;
421
422 for (size_t i = 0; i < itemComponents.size(); ++i)
423 {
424 const auto menu = model->getMenuForIndex ((int) i, itemComponents[i]->getName());
425
426 if (menu.containsCommandItem (info.commandID))
427 {
428 setItemUnderMouse ((int) i);
429 startTimer (200);
430 break;
431 }
432 }
433}
434
440
441//==============================================================================
442std::unique_ptr<AccessibilityHandler> MenuBarComponent::createAccessibilityHandler()
443{
444 struct MenuBarComponentAccessibilityHandler : public AccessibilityHandler
445 {
446 explicit MenuBarComponentAccessibilityHandler (MenuBarComponent& menuBarComponent)
448 {
449 }
450
451 AccessibleState getCurrentState() const override { return AccessibleState().withIgnored(); }
452 };
453
454 return std::make_unique<MenuBarComponentAccessibilityHandler> (*this);
455}
456
457} // namespace juce
#define noexcept
Definition DistrhoDefines.h:72
Definition juce_AccessibilityActions.h:73
AccessibilityActions & addAction(AccessibilityActionType type, std::function< void()> actionCallback)
Definition juce_AccessibilityActions.h:88
Definition juce_AccessibilityHandler.h:41
Definition juce_AccessibilityState.h:39
JUCE_NODISCARD AccessibleState withIgnored() const noexcept
Definition juce_AccessibilityState.h:95
Definition juce_Component.h:2287
bool contains(Point< int > localPoint)
Definition juce_Component.cpp:1434
void setRepaintsOnMouseActivity(bool shouldRepaint) noexcept
Definition juce_Component.cpp:1881
void setInterceptsMouseClicks(bool allowClicksOnThisComponent, bool allowClicksOnChildComponents) noexcept
Definition juce_Component.cpp:1420
String getTitle() const noexcept
Definition juce_Component.h:2418
bool reallyContains(Point< int > localPoint, bool returnTrueIfWithinAChild)
Definition juce_Component.cpp:1454
int getHeight() const noexcept
Definition juce_Component.h:274
void addAndMakeVisible(Component *child, int zOrder=-1)
Definition juce_Component.cpp:1554
AccessibilityHandler * getAccessibilityHandler()
Definition juce_Component.cpp:3302
void postCommandMessage(int commandId)
Definition juce_Component.cpp:2361
Rectangle< int > getBounds() const noexcept
Definition juce_Component.h:304
void repaint()
Definition juce_Component.cpp:1917
Component() noexcept
Definition juce_Component.cpp:517
Point< int > getMouseXYRelative() const
Definition juce_Component.cpp:3210
Rectangle< int > localAreaToGlobal(Rectangle< int > localArea) const
Definition juce_Component.cpp:1143
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Definition juce_Component.cpp:2842
bool isMouseOver(bool includeChildren=false) const
Definition juce_Component.cpp:3159
void setMouseClickGrabsKeyboardFocus(bool shouldGrabFocus)
Definition juce_Component.cpp:2847
int getWidth() const noexcept
Definition juce_Component.h:271
LookAndFeel & getLookAndFeel() const noexcept
Definition juce_Component.cpp:2173
Rectangle< int > getLocalBounds() const noexcept
Definition juce_Component.cpp:2283
String getName() const noexcept
Definition juce_Component.h:76
static Desktop &JUCE_CALLTYPE getInstance()
Definition juce_Desktop.cpp:50
Definition juce_GraphicsContext.h:660
Definition juce_GraphicsContext.h:45
Definition juce_KeyPress.h:40
static const int rightKey
Definition juce_KeyPress.h:201
static const int leftKey
Definition juce_KeyPress.h:200
Definition juce_MenuBarComponent.cpp:30
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_MenuBarComponent.cpp:42
const String name
Definition juce_MenuBarComponent.cpp:75
MenuBarComponent & owner
Definition juce_MenuBarComponent.cpp:74
AccessibleItemComponent(MenuBarComponent &comp, const String &menuItemName)
Definition juce_MenuBarComponent.cpp:32
const String & getName() const noexcept
Definition juce_MenuBarComponent.cpp:39
void updateItemUnderMouse(Point< int >)
Definition juce_MenuBarComponent.cpp:219
void setOpenItem(int)
Definition juce_MenuBarComponent.cpp:197
Point< int > lastMousePos
Definition juce_MenuBarComponent.h:121
void setModel(MenuBarModel *newModel)
Definition juce_MenuBarComponent.cpp:98
~MenuBarComponent() override
Definition juce_MenuBarComponent.cpp:87
void menuBarItemsChanged(MenuBarModel *) override
Definition juce_MenuBarComponent.cpp:366
void repaintMenuItem(int)
Definition juce_MenuBarComponent.cpp:170
void mouseExit(const MouseEvent &) override
Definition juce_MenuBarComponent.cpp:282
void setItemUnderMouse(int)
Definition juce_MenuBarComponent.cpp:183
bool keyPressed(const KeyPress &) override
Definition juce_MenuBarComponent.cpp:342
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_MenuBarComponent.cpp:442
void paint(Graphics &) override
Definition juce_MenuBarComponent.cpp:116
void timerCallback() override
Definition juce_MenuBarComponent.cpp:435
void menuDismissed(int, int)
Definition juce_MenuBarComponent.cpp:258
void handleCommandMessage(int commandId) override
Definition juce_MenuBarComponent.cpp:264
std::vector< std::unique_ptr< AccessibleItemComponent > > itemComponents
Definition juce_MenuBarComponent.h:119
void updateItemComponents(const StringArray &)
Definition juce_MenuBarComponent.cpp:394
void mouseMove(const MouseEvent &) override
Definition juce_MenuBarComponent.cpp:320
int indexOfItemComponent(AccessibleItemComponent *) const
Definition juce_MenuBarComponent.cpp:405
void mouseDrag(const MouseEvent &) override
Definition juce_MenuBarComponent.cpp:299
void resized() override
Definition juce_MenuBarComponent.cpp:147
void mouseUp(const MouseEvent &) override
Definition juce_MenuBarComponent.cpp:307
MenuBarModel * getModel() const noexcept
Definition juce_MenuBarComponent.cpp:93
int itemUnderMouse
Definition juce_MenuBarComponent.h:122
int topLevelIndexClicked
Definition juce_MenuBarComponent.h:122
void mouseEnter(const MouseEvent &) override
Definition juce_MenuBarComponent.cpp:276
int currentPopupIndex
Definition juce_MenuBarComponent.h:122
void menuCommandInvoked(MenuBarModel *, const ApplicationCommandTarget::InvocationInfo &) override
Definition juce_MenuBarComponent.cpp:417
void showMenu(int menuIndex)
Definition juce_MenuBarComponent.cpp:224
MenuBarModel * model
Definition juce_MenuBarComponent.h:118
MenuBarComponent(MenuBarModel *model=nullptr)
Definition juce_MenuBarComponent.cpp:78
int getItemAt(Point< int >)
Definition juce_MenuBarComponent.cpp:161
void mouseDown(const MouseEvent &) override
Definition juce_MenuBarComponent.cpp:288
Definition juce_MenuBarModel.h:42
Definition juce_MouseEvent.h:39
Definition juce_Point.h:42
Definition juce_PopupMenu.h:457
static bool JUCE_CALLTYPE dismissAllActiveMenus()
Definition juce_PopupMenu.cpp:2201
Definition juce_StringArray.h:35
int size() const noexcept
Definition juce_StringArray.h:136
Definition juce_String.h:53
void stopTimer() noexcept
Definition juce_Timer.cpp:357
void startTimer(int intervalInMilliseconds) noexcept
Definition juce_Timer.cpp:332
* e
Definition inflate.c:1404
UINT_D64 w
Definition inflate.c:942
unsigned * m
Definition inflate.c:1559
int g
Definition inflate.c:1573
register unsigned i
Definition inflate.c:1575
unsigned x[BMAX+1]
Definition inflate.c:1586
static const char * name
Definition pugl.h:1582
struct backing_store_struct * info
Definition jmemsys.h:183
#define jassertfalse
static int JUCE_CDECL comp(const void *a, const void *b)
Definition lsp.c:298
Definition carla_juce.cpp:31
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Definition juce_MathsFunctions.h:262
@ showMenu
Definition juce_AccessibilityActions.h:61
@ focus
Definition juce_AccessibilityActions.h:54
@ press
Definition juce_AccessibilityActions.h:40
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Definition juce_MathsFunctions.h:279
@ menuItem
Definition juce_AccessibilityRole.h:47
@ menuBar
Definition juce_AccessibilityRole.h:48
@ dontTriggerVisualFeedback
Definition juce_ApplicationCommandInfo.h:179
Definition juce_ApplicationCommandTarget.h:61
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
uch * p
Definition crypt.c:594
return c
Definition crypt.c:175
ZCONST char * key
Definition crypt.c:587
void handler(int signal)
Definition fileio.c:1632
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()
ss
Definition zipinfo.c:2292
#define const
Definition zconf.h:137