LMMS
Loading...
Searching...
No Matches
juce_PopupMenu.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{
31 const int scrollZone = 24;
32 const int dismissCommandId = 0x6287345f;
33
35}
36
37//==============================================================================
39{
40
42struct MenuWindow;
43
44static bool canBeTriggered (const PopupMenu::Item& item) noexcept
45{
46 return item.isEnabled
47 && item.itemID != 0
48 && ! item.isSectionHeader
49 && (item.customComponent == nullptr || item.customComponent->isTriggeredAutomatically());
50}
51
52static bool hasActiveSubMenu (const PopupMenu::Item& item) noexcept
53{
54 return item.isEnabled
55 && item.subMenu != nullptr
56 && item.subMenu->items.size() > 0;
57}
58
59//==============================================================================
61{
62 HeaderItemComponent (const String& name, const Options& opts)
63 : CustomComponent (false), options (opts)
64 {
65 setName (name);
66 }
67
68 void paint (Graphics& g) override
69 {
70 getLookAndFeel().drawPopupMenuSectionHeaderWithOptions (g,
72 getName(),
73 options);
74 }
75
76 void getIdealSize (int& idealWidth, int& idealHeight) override
77 {
78 getLookAndFeel().getIdealPopupMenuItemSizeWithOptions (getName(),
79 false,
80 -1,
81 idealWidth,
82 idealHeight,
83 options);
84 idealHeight += idealHeight / 2;
85 idealWidth += idealWidth / 4;
86 }
87
88 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
89 {
91 }
92
94
96};
97
98//==============================================================================
99struct ItemComponent : public Component
100{
102 : item (i), parentWindow (parent), options (o), customComp (i.customComponent)
103 {
104 if (item.isSectionHeader)
106
107 if (customComp != nullptr)
108 {
111 }
112
113 parent.addAndMakeVisible (this);
114
116
117 int itemW = 80;
118 int itemH = 16;
119 getIdealSize (itemW, itemH, options.getStandardItemHeight());
120 setSize (itemW, jlimit (1, 600, itemH));
121
122 addMouseListener (&parent, false);
123 }
124
125 ~ItemComponent() override
126 {
127 if (customComp != nullptr)
128 setItem (*customComp, nullptr);
129
131 }
132
133 void getIdealSize (int& idealWidth, int& idealHeight, const int standardItemHeight)
134 {
135 if (customComp != nullptr)
136 customComp->getIdealSize (idealWidth, idealHeight);
137 else
138 getLookAndFeel().getIdealPopupMenuItemSizeWithOptions (getTextForMeasurement(),
139 item.isSeparator,
140 standardItemHeight,
141 idealWidth, idealHeight,
142 options);
143 }
144
145 void paint (Graphics& g) override
146 {
147 if (customComp == nullptr)
148 getLookAndFeel().drawPopupMenuItemWithOptions (g, getLocalBounds(),
150 item,
151 options);
152 }
153
154 void resized() override
155 {
156 if (auto* child = getChildComponent (0))
157 {
158 const auto border = getLookAndFeel().getPopupMenuBorderSizeWithOptions (options);
159 child->setBounds (getLocalBounds().reduced (border, 0));
160 }
161 }
162
163 void setHighlighted (bool shouldBeHighlighted)
164 {
165 shouldBeHighlighted = shouldBeHighlighted && item.isEnabled;
166
167 if (isHighlighted != shouldBeHighlighted)
168 {
169 isHighlighted = shouldBeHighlighted;
170
171 if (customComp != nullptr)
172 customComp->setHighlighted (shouldBeHighlighted);
173
174 if (isHighlighted)
175 if (auto* handler = getAccessibilityHandler())
176 handler->grabFocus();
177
178 repaint();
179 }
180 }
181
183 {
184 return item.isSectionHeader || hasActiveSubMenu (item) || canBeTriggered (item);
185 }
186
188
189private:
190 //==============================================================================
192 {
193 public:
194 explicit ItemAccessibilityHandler (ItemComponent& itemComponentToWrap)
195 : AccessibilityHandler (itemComponentToWrap,
198 getAccessibilityActions (*this, itemComponentToWrap)),
199 itemComponent (itemComponentToWrap)
200 {
201 }
202
203 String getTitle() const override
204 {
205 return itemComponent.item.text;
206 }
207
209 {
210 auto state = AccessibilityHandler::getCurrentState().withSelectable()
211 .withAccessibleOffscreen();
212
214 {
215 state = itemComponent.parentWindow.isSubMenuVisible() ? state.withExpandable().withExpanded()
216 : state.withExpandable().withCollapsed();
217 }
218
219 if (itemComponent.item.isTicked)
220 state = state.withCheckable().withChecked();
221
222 return state.isFocused() ? state.withSelected() : state;
223 }
224
225 private:
228 {
229 auto onFocus = [&item]
230 {
231 item.parentWindow.disableTimerUntilMouseMoves();
232 item.parentWindow.ensureItemComponentIsVisible (item, -1);
233 item.parentWindow.setCurrentlyHighlightedChild (&item);
234 };
235
236 auto onToggle = [&handler, &item, onFocus]
237 {
238 if (handler.getCurrentState().isSelected())
239 item.parentWindow.setCurrentlyHighlightedChild (nullptr);
240 else
241 onFocus();
242 };
243
245 .addAction (AccessibilityActionType::toggle, std::move (onToggle));
246
247 if (canBeTriggered (item.item))
248 {
250 {
251 item.parentWindow.setCurrentlyHighlightedChild (&item);
252 item.parentWindow.triggerCurrentlyHighlightedItem();
253 });
254 }
255
256 if (hasActiveSubMenu (item.item))
257 {
258 auto showSubMenu = [&item]
259 {
260 item.parentWindow.showSubMenuFor (&item);
261
262 if (auto* subMenu = item.parentWindow.activeSubMenu.get())
263 subMenu->setCurrentlyHighlightedChild (subMenu->items.getFirst());
264 };
265
266 actions.addAction (AccessibilityActionType::press, showSubMenu);
267 actions.addAction (AccessibilityActionType::showMenu, showSubMenu);
268 }
269
270 return actions;
271 }
272
274 };
275
276 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
277 {
278 return item.isSeparator ? createIgnoredAccessibilityHandler (*this)
279 : std::make_unique<ItemAccessibilityHandler> (*this);
280 }
281
282 //==============================================================================
285 // NB: we use a copy of the one from the item info in case we're using our own section comp
287 bool isHighlighted = false;
288
290 {
291 if (item.commandManager != nullptr
292 && item.itemID != 0
293 && item.shortcutKeyDescription.isEmpty())
294 {
295 String shortcutKey;
296
297 for (auto& keypress : item.commandManager->getKeyMappings()
298 ->getKeyPressesAssignedToCommand (item.itemID))
299 {
300 auto key = keypress.getTextDescriptionWithIcons();
301
302 if (shortcutKey.isNotEmpty())
303 shortcutKey << ", ";
304
305 if (key.length() == 1 && key[0] < 128)
306 shortcutKey << "shortcut: '" << key << '\'';
307 else
308 shortcutKey << key;
309 }
310
311 item.shortcutKeyDescription = shortcutKey.trim();
312 }
313 }
314
316 {
317 return item.shortcutKeyDescription.isNotEmpty() ? item.text + " " + item.shortcutKeyDescription
318 : item.text;
319 }
320
322};
323
324//==============================================================================
325struct MenuWindow : public Component
326{
327 MenuWindow (const PopupMenu& menu, MenuWindow* parentWindow,
328 Options opts, bool alignToRectangle, bool shouldDismissOnMouseUp,
329 ApplicationCommandManager** manager, float parentScaleFactor = 1.0f)
330 : Component ("menu"),
331 parent (parentWindow),
332 options (opts.withParentComponent (getLookAndFeel().getParentComponentForMenuOptions (opts))),
333 managerOfChosenCommand (manager),
334 componentAttachedTo (options.getTargetComponent()),
335 dismissOnMouseUp (shouldDismissOnMouseUp),
336 windowCreationTime (Time::getMillisecondCounter()),
339 scaleFactor (parentWindow != nullptr ? parentScaleFactor : 1.0f)
340 {
341 setWantsKeyboardFocus (false);
343 setAlwaysOnTop (true);
345
346 setLookAndFeel (parent != nullptr ? &(parent->getLookAndFeel())
347 : menu.lookAndFeel.get());
348
349 auto& lf = getLookAndFeel();
350
351 if (auto* pc = options.getParentComponent())
352 {
353 pc->addChildComponent (this);
354 }
355 else
356 {
357 const auto shouldDisableAccessibility = [this]
358 {
359 const auto* compToCheck = parent != nullptr ? parent
360 : options.getTargetComponent();
361
362 return compToCheck != nullptr && ! compToCheck->isAccessible();
363 }();
364
365 if (shouldDisableAccessibility)
366 setAccessible (false);
367
370 | lf.getMenuWindowFlags());
371
372 Desktop::getInstance().addGlobalMouseListener (this);
373 }
374
375 if (options.getParentComponent() == nullptr && parentWindow == nullptr && lf.shouldPopupMenuScaleWithTargetComponent (options))
376 if (auto* targetComponent = options.getTargetComponent())
378
379 setOpaque (lf.findColour (PopupMenu::backgroundColourId).isOpaque()
381
382 const auto initialSelectedId = options.getInitiallySelectedItemId();
383
384 for (int i = 0; i < menu.items.size(); ++i)
385 {
386 auto& item = menu.items.getReference (i);
387
388 if (i + 1 < menu.items.size() || ! item.isSeparator)
389 {
390 auto* child = items.add (new ItemComponent (item, options, *this));
391
392 if (initialSelectedId != 0 && item.itemID == initialSelectedId)
394 }
395 }
396
397 auto targetArea = options.getTargetScreenArea() / scaleFactor;
398
399 calculateWindowPos (targetArea, alignToRectangle);
400 setTopLeftPosition (windowPos.getPosition());
401
402 if (auto visibleID = options.getItemThatMustBeVisible())
403 {
404 for (auto* item : items)
405 {
406 if (item->item.itemID == visibleID)
407 {
408 const auto targetPosition = [&]
409 {
410 if (auto* pc = options.getParentComponent())
411 return pc->getLocalPoint (nullptr, targetArea.getTopLeft());
412
413 return targetArea.getTopLeft();
414 }();
415
416 auto y = targetPosition.getY() - windowPos.getY();
417 ensureItemComponentIsVisible (*item, isPositiveAndBelow (y, windowPos.getHeight()) ? y : -1);
418
419 break;
420 }
421 }
422 }
423
425
426 getActiveWindows().add (this);
427 lf.preparePopupMenuWindow (*this);
428
429 getMouseState (Desktop::getInstance().getMainMouseSource()); // forces creation of a mouse source watcher for the main mouse
430 }
431
432 ~MenuWindow() override
433 {
434 getActiveWindows().removeFirstMatchingValue (this);
435 Desktop::getInstance().removeGlobalMouseListener (this);
436 activeSubMenu.reset();
437 items.clear();
438 }
439
440 //==============================================================================
441 void paint (Graphics& g) override
442 {
443 if (isOpaque())
444 g.fillAll (Colours::white);
445
446 auto& theme = getLookAndFeel();
447 theme.drawPopupMenuBackgroundWithOptions (g, getWidth(), getHeight(), options);
448
449 if (columnWidths.isEmpty())
450 return;
451
452 const auto separatorWidth = theme.getPopupMenuColumnSeparatorWidthWithOptions (options);
453 const auto border = theme.getPopupMenuBorderSizeWithOptions (options);
454
455 auto currentX = 0;
456
457 std::for_each (columnWidths.begin(), std::prev (columnWidths.end()), [&] (int width)
458 {
459 const Rectangle<int> separator (currentX + width,
460 border,
461 separatorWidth,
462 getHeight() - border * 2);
463 theme.drawPopupMenuColumnSeparatorWithOptions (g, separator, options);
464 currentX += width + separatorWidth;
465 });
466 }
467
468 void paintOverChildren (Graphics& g) override
469 {
470 auto& lf = getLookAndFeel();
471
472 if (options.getParentComponent())
473 lf.drawResizableFrame (g, getWidth(), getHeight(),
474 BorderSize<int> (getLookAndFeel().getPopupMenuBorderSizeWithOptions (options)));
475
476 if (canScroll())
477 {
479 {
480 lf.drawPopupMenuUpDownArrowWithOptions (g,
481 getWidth(),
483 true,
484 options);
485 }
486
488 {
489 g.setOrigin (0, getHeight() - PopupMenuSettings::scrollZone);
490 lf.drawPopupMenuUpDownArrowWithOptions (g,
491 getWidth(),
493 false,
494 options);
495 }
496 }
497 }
498
499 //==============================================================================
500 // hide this and all sub-comps
501 void hide (const PopupMenu::Item* item, bool makeInvisible)
502 {
503 if (isVisible())
504 {
505 WeakReference<Component> deletionChecker (this);
506
507 activeSubMenu.reset();
508 currentChild = nullptr;
509
510 if (item != nullptr
511 && item->commandManager != nullptr
512 && item->itemID != 0)
513 {
515 }
516
517 auto resultID = options.hasWatchedComponentBeenDeleted() ? 0 : getResultItemID (item);
518
519 exitModalState (resultID);
520
521 if (deletionChecker != nullptr)
522 {
523 exitingModalState = true;
524
525 if (makeInvisible)
526 setVisible (false);
527 }
528
529 if (resultID != 0
530 && item != nullptr
531 && item->action != nullptr)
533 }
534 }
535
536 static int getResultItemID (const PopupMenu::Item* item)
537 {
538 if (item == nullptr)
539 return 0;
540
541 if (auto* cc = item->customCallback.get())
542 if (! cc->menuItemTriggered())
543 return 0;
544
545 return item->itemID;
546 }
547
548 void dismissMenu (const PopupMenu::Item* item)
549 {
550 if (parent != nullptr)
551 {
552 parent->dismissMenu (item);
553 }
554 else
555 {
556 if (item != nullptr)
557 {
558 // need a copy of this on the stack as the one passed in will get deleted during this call
559 auto mi (*item);
560 hide (&mi, false);
561 }
562 else
563 {
564 hide (nullptr, true);
565 }
566 }
567 }
568
569 float getDesktopScaleFactor() const override { return scaleFactor * Desktop::getInstance().getGlobalScaleFactor(); }
570
571 void visibilityChanged() override
572 {
573 if (! isShowing())
574 return;
575
576 auto* accessibleFocus = [this]
577 {
578 if (currentChild != nullptr)
579 if (auto* childHandler = currentChild->getAccessibilityHandler())
580 return childHandler;
581
583 }();
584
585 if (accessibleFocus != nullptr)
586 accessibleFocus->grabFocus();
587 }
588
589 //==============================================================================
590 bool keyPressed (const KeyPress& key) override
591 {
592 if (key.isKeyCode (KeyPress::downKey))
593 {
595 }
596 else if (key.isKeyCode (KeyPress::upKey))
597 {
599 }
600 else if (key.isKeyCode (KeyPress::leftKey))
601 {
602 if (parent != nullptr)
603 {
605 ItemComponent* currentChildOfParent = parentWindow->currentChild;
606
607 hide (nullptr, true);
608
609 if (parentWindow != nullptr)
610 parentWindow->setCurrentlyHighlightedChild (currentChildOfParent);
611
613 }
614 else if (componentAttachedTo != nullptr)
615 {
616 componentAttachedTo->keyPressed (key);
617 }
618 }
619 else if (key.isKeyCode (KeyPress::rightKey))
620 {
622
624 {
625 if (isSubMenuVisible())
627 }
628 else if (componentAttachedTo != nullptr)
629 {
630 componentAttachedTo->keyPressed (key);
631 }
632 }
633 else if (key.isKeyCode (KeyPress::returnKey) || key.isKeyCode (KeyPress::spaceKey))
634 {
636 }
637 else if (key.isKeyCode (KeyPress::escapeKey))
638 {
639 dismissMenu (nullptr);
640 }
641 else
642 {
643 return false;
644 }
645
646 return true;
647 }
648
649 void inputAttemptWhenModal() override
650 {
651 WeakReference<Component> deletionChecker (this);
652
653 for (auto* ms : mouseSourceStates)
654 {
655 ms->timerCallback();
656
657 if (deletionChecker == nullptr)
658 return;
659 }
660
661 if (! isOverAnyMenu())
662 {
663 if (componentAttachedTo != nullptr)
664 {
665 // we want to dismiss the menu, but if we do it synchronously, then
666 // the mouse-click will be allowed to pass through. That's good, except
667 // when the user clicks on the button that originally popped the menu up,
668 // as they'll expect the menu to go away, and in fact it'll just
669 // come back. So only dismiss synchronously if they're not on the original
670 // comp that we're attached to.
671 auto mousePos = componentAttachedTo->getMouseXYRelative();
672
673 if (componentAttachedTo->reallyContains (mousePos, true))
674 {
676 return;
677 }
678 }
679
680 dismissMenu (nullptr);
681 }
682 }
683
684 void handleCommandMessage (int commandId) override
685 {
687
689 dismissMenu (nullptr);
690 }
691
692 //==============================================================================
693 void mouseMove (const MouseEvent& e) override { handleMouseEvent (e); }
694 void mouseDown (const MouseEvent& e) override { handleMouseEvent (e); }
695 void mouseDrag (const MouseEvent& e) override { handleMouseEvent (e); }
696 void mouseUp (const MouseEvent& e) override { handleMouseEvent (e); }
697
698 void mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel) override
699 {
701 }
702
704 {
705 getMouseState (e.source).handleMouseEvent (e);
706 }
707
709 {
710 if (! isVisible())
711 return false;
712
713 if (componentAttachedTo != options.getTargetComponent())
714 {
715 dismissMenu (nullptr);
716 return false;
717 }
718
719 if (auto* currentlyModalWindow = dynamic_cast<MenuWindow*> (Component::getCurrentlyModalComponent()))
720 if (! treeContains (currentlyModalWindow))
721 return false;
722
724 return false;
725
726 return true;
727 }
728
730 {
731 static Array<MenuWindow*> activeMenuWindows;
732 return activeMenuWindows;
733 }
734
736 {
737 MouseSourceState* mouseState = nullptr;
738
739 for (auto* ms : mouseSourceStates)
740 {
741 if (ms->source == source) mouseState = ms;
742 else if (ms->source.getType() != source.getType()) ms->stopTimer();
743 }
744
745 if (mouseState == nullptr)
746 {
747 mouseState = new MouseSourceState (*this, source);
748 mouseSourceStates.add (mouseState);
749 }
750
751 return *mouseState;
752 }
753
754 //==============================================================================
755 bool isOverAnyMenu() const
756 {
757 return parent != nullptr ? parent->isOverAnyMenu()
758 : isOverChildren();
759 }
760
761 bool isOverChildren() const
762 {
763 return isVisible()
764 && (isAnyMouseOver() || (activeSubMenu != nullptr && activeSubMenu->isOverChildren()));
765 }
766
767 bool isAnyMouseOver() const
768 {
769 for (auto* ms : mouseSourceStates)
770 if (ms->isOver())
771 return true;
772
773 return false;
774 }
775
776 bool treeContains (const MenuWindow* const window) const noexcept
777 {
778 auto* mw = this;
779
780 while (mw->parent != nullptr)
781 mw = mw->parent;
782
783 while (mw != nullptr)
784 {
785 if (mw == window)
786 return true;
787
788 mw = mw->activeSubMenu.get();
789 }
790
791 return false;
792 }
793
795 {
797 return false;
798
800 return true;
801
802 for (int i = ComponentPeer::getNumPeers(); --i >= 0;)
803 {
804 if (ComponentPeer::getPeer (i)->isFocused())
805 {
807 return true;
808 }
809 }
810
811 return ! hasAnyJuceCompHadFocus;
812 }
813
814 //==============================================================================
815 Rectangle<int> getParentArea (Point<int> targetPoint, Component* relativeTo = nullptr)
816 {
817 if (relativeTo != nullptr)
818 targetPoint = relativeTo->localPointToGlobal (targetPoint);
819
820 auto* display = Desktop::getInstance().getDisplays().getDisplayForPoint (targetPoint * scaleFactor);
821 auto parentArea = display->safeAreaInsets.subtractedFrom (display->totalArea);
822
823 if (auto* pc = options.getParentComponent())
824 {
825 return pc->getLocalArea (nullptr,
826 pc->getScreenBounds()
827 .reduced (getLookAndFeel().getPopupMenuBorderSizeWithOptions (options))
828 .getIntersection (parentArea));
829 }
830
831 return parentArea;
832 }
833
834 void calculateWindowPos (Rectangle<int> target, const bool alignToRectangle)
835 {
836 auto parentArea = getParentArea (target.getCentre()) / scaleFactor;
837
838 if (auto* pc = options.getParentComponent())
839 target = pc->getLocalArea (nullptr, target).getIntersection (parentArea);
840
841 auto maxMenuHeight = parentArea.getHeight() - 24;
842
843 int x, y, widthToUse, heightToUse;
844 layoutMenuItems (parentArea.getWidth() - 24, maxMenuHeight, widthToUse, heightToUse);
845
846 if (alignToRectangle)
847 {
848 x = target.getX();
849
850 auto spaceUnder = parentArea.getBottom() - target.getBottom();
851 auto spaceOver = target.getY() - parentArea.getY();
852 auto bufferHeight = 30;
853
854 if (options.getPreferredPopupDirection() == Options::PopupDirection::upwards)
855 y = (heightToUse < spaceOver - bufferHeight || spaceOver >= spaceUnder) ? target.getY() - heightToUse
856 : target.getBottom();
857 else
858 y = (heightToUse < spaceUnder - bufferHeight || spaceUnder >= spaceOver) ? target.getBottom()
859 : target.getY() - heightToUse;
860 }
861 else
862 {
863 bool tendTowardsRight = target.getCentreX() < parentArea.getCentreX();
864
865 if (parent != nullptr)
866 {
867 if (parent->parent != nullptr)
868 {
869 const bool parentGoingRight = (parent->getX() + parent->getWidth() / 2
870 > parent->parent->getX() + parent->parent->getWidth() / 2);
871
872 if (parentGoingRight && target.getRight() + widthToUse < parentArea.getRight() - 4)
873 tendTowardsRight = true;
874 else if ((! parentGoingRight) && target.getX() > widthToUse + 4)
875 tendTowardsRight = false;
876 }
877 else if (target.getRight() + widthToUse < parentArea.getRight() - 32)
878 {
879 tendTowardsRight = true;
880 }
881 }
882
883 auto biggestSpace = jmax (parentArea.getRight() - target.getRight(),
884 target.getX() - parentArea.getX()) - 32;
885
886 if (biggestSpace < widthToUse)
887 {
888 layoutMenuItems (biggestSpace + target.getWidth() / 3, maxMenuHeight, widthToUse, heightToUse);
889
890 if (numColumns > 1)
891 layoutMenuItems (biggestSpace - 4, maxMenuHeight, widthToUse, heightToUse);
892
893 tendTowardsRight = (parentArea.getRight() - target.getRight()) >= (target.getX() - parentArea.getX());
894 }
895
896 x = tendTowardsRight ? jmin (parentArea.getRight() - widthToUse - 4, target.getRight())
897 : jmax (parentArea.getX() + 4, target.getX() - widthToUse);
898
899 if (getLookAndFeel().getPopupMenuBorderSizeWithOptions (options) == 0) // workaround for dismissing the window on mouse up when border size is 0
900 x += tendTowardsRight ? 1 : -1;
901
902 const auto border = getLookAndFeel().getPopupMenuBorderSizeWithOptions (options);
903 y = target.getCentreY() > parentArea.getCentreY() ? jmax (parentArea.getY(), target.getBottom() - heightToUse) + border
904 : target.getY() - border;
905 }
906
907 x = jmax (parentArea.getX() + 1, jmin (parentArea.getRight() - (widthToUse + 6), x));
908 y = jmax (parentArea.getY() + 1, jmin (parentArea.getBottom() - (heightToUse + 6), y));
909
910 windowPos.setBounds (x, y, widthToUse, heightToUse);
911
912 // sets this flag if it's big enough to obscure any of its parent menus
913 hideOnExit = parent != nullptr
914 && parent->windowPos.intersects (windowPos.expanded (-4, -4));
915 }
916
917 void layoutMenuItems (const int maxMenuW, const int maxMenuH, int& width, int& height)
918 {
919 // Ensure we don't try to add an empty column after the final item
920 if (auto* last = items.getLast())
921 last->item.shouldBreakAfter = false;
922
923 const auto isBreak = [] (const ItemComponent* item) { return item->item.shouldBreakAfter; };
924 const auto numBreaks = static_cast<int> (std::count_if (items.begin(), items.end(), isBreak));
925 numColumns = numBreaks + 1;
926
927 if (numBreaks == 0)
928 insertColumnBreaks (maxMenuW, maxMenuH);
929
930 workOutManualSize (maxMenuW);
931 height = jmin (contentHeight, maxMenuH);
932
934
936 }
937
938 void insertColumnBreaks (const int maxMenuW, const int maxMenuH)
939 {
940 numColumns = options.getMinimumNumColumns();
941 contentHeight = 0;
942
943 auto maximumNumColumns = options.getMaximumNumColumns() > 0 ? options.getMaximumNumColumns() : 7;
944
945 for (;;)
946 {
947 auto totalW = workOutBestSize (maxMenuW);
948
949 if (totalW > maxMenuW)
950 {
951 numColumns = jmax (1, numColumns - 1);
952 workOutBestSize (maxMenuW); // to update col widths
953 break;
954 }
955
956 if (totalW > maxMenuW / 2
957 || contentHeight < maxMenuH
958 || numColumns >= maximumNumColumns)
959 break;
960
961 ++numColumns;
962 }
963
964 const auto itemsPerColumn = (items.size() + numColumns - 1) / numColumns;
965
966 for (auto i = 0;; i += itemsPerColumn)
967 {
968 const auto breakIndex = i + itemsPerColumn - 1;
969
970 if (breakIndex >= items.size())
971 break;
972
973 items[breakIndex]->item.shouldBreakAfter = true;
974 }
975
976 if (! items.isEmpty())
977 (*std::prev (items.end()))->item.shouldBreakAfter = false;
978 }
979
980 int correctColumnWidths (const int maxMenuW)
981 {
982 auto totalW = std::accumulate (columnWidths.begin(), columnWidths.end(), 0);
983 const auto minWidth = jmin (maxMenuW, options.getMinimumWidth());
984
985 if (totalW < minWidth)
986 {
987 totalW = minWidth;
988
989 for (auto& column : columnWidths)
990 column = totalW / numColumns;
991 }
992
993 return totalW;
994 }
995
996 void workOutManualSize (const int maxMenuW)
997 {
998 contentHeight = 0;
999 columnWidths.clear();
1000
1001 for (auto it = items.begin(), end = items.end(); it != end;)
1002 {
1003 const auto isBreak = [] (const ItemComponent* item) { return item->item.shouldBreakAfter; };
1004 const auto nextBreak = std::find_if (it, end, isBreak);
1005 const auto columnEnd = nextBreak == end ? end : std::next (nextBreak);
1006
1007 const auto getMaxWidth = [] (int acc, const ItemComponent* item) { return jmax (acc, item->getWidth()); };
1008 const auto colW = std::accumulate (it, columnEnd, options.getStandardItemHeight(), getMaxWidth);
1009 const auto adjustedColW = jmin (maxMenuW / jmax (1, numColumns - 2),
1010 colW + getLookAndFeel().getPopupMenuBorderSizeWithOptions (options) * 2);
1011
1012 const auto sumHeight = [] (int acc, const ItemComponent* item) { return acc + item->getHeight(); };
1013 const auto colH = std::accumulate (it, columnEnd, 0, sumHeight);
1014
1016 columnWidths.add (adjustedColW);
1017 it = columnEnd;
1018 }
1019
1020 contentHeight += getLookAndFeel().getPopupMenuBorderSizeWithOptions (options) * 2;
1021
1022 correctColumnWidths (maxMenuW);
1023 }
1024
1025 int workOutBestSize (const int maxMenuW)
1026 {
1027 contentHeight = 0;
1028 int childNum = 0;
1029
1030 for (int col = 0; col < numColumns; ++col)
1031 {
1032 int colW = options.getStandardItemHeight(), colH = 0;
1033
1034 auto numChildren = jmin (items.size() - childNum,
1035 (items.size() + numColumns - 1) / numColumns);
1036
1037 for (int i = numChildren; --i >= 0;)
1038 {
1039 colW = jmax (colW, items.getUnchecked (childNum + i)->getWidth());
1040 colH += items.getUnchecked (childNum + i)->getHeight();
1041 }
1042
1043 colW = jmin (maxMenuW / jmax (1, numColumns - 2),
1044 colW + getLookAndFeel().getPopupMenuBorderSizeWithOptions (options) * 2);
1045
1046 columnWidths.set (col, colW);
1048
1049 childNum += numChildren;
1050 }
1051
1052 return correctColumnWidths (maxMenuW);
1053 }
1054
1055 void ensureItemComponentIsVisible (const ItemComponent& itemComp, int wantedY)
1056 {
1057 if (windowPos.getHeight() > PopupMenuSettings::scrollZone * 4)
1058 {
1059 auto currentY = itemComp.getY();
1060
1061 if (wantedY > 0 || currentY < 0 || itemComp.getBottom() > windowPos.getHeight())
1062 {
1063 if (wantedY < 0)
1066 windowPos.getHeight() - (PopupMenuSettings::scrollZone + itemComp.getHeight())),
1067 currentY);
1068
1069 auto parentArea = getParentArea (windowPos.getPosition(), options.getParentComponent()) / scaleFactor;
1070 auto deltaY = wantedY - currentY;
1071
1072 windowPos.setSize (jmin (windowPos.getWidth(), parentArea.getWidth()),
1073 jmin (windowPos.getHeight(), parentArea.getHeight()));
1074
1075 auto newY = jlimit (parentArea.getY(),
1076 parentArea.getBottom() - windowPos.getHeight(),
1077 windowPos.getY() + deltaY);
1078
1079 deltaY -= newY - windowPos.getY();
1080
1081 childYOffset -= deltaY;
1082 windowPos.setPosition (windowPos.getX(), newY);
1083
1085 }
1086 }
1087 }
1088
1090 {
1091 auto r = windowPos;
1092
1093 if (childYOffset < 0)
1094 {
1095 r = r.withTop (r.getY() - childYOffset);
1096 }
1097 else if (childYOffset > 0)
1098 {
1099 auto spaceAtBottom = r.getHeight() - (contentHeight - childYOffset);
1100
1101 if (spaceAtBottom > 0)
1102 r.setSize (r.getWidth(), r.getHeight() - spaceAtBottom);
1103 }
1104
1105 setBounds (r);
1107 }
1108
1109 void alterChildYPos (int delta)
1110 {
1111 if (canScroll())
1112 {
1113 childYOffset += delta;
1114
1115 childYOffset = [&]
1116 {
1117 if (delta < 0)
1118 return jmax (childYOffset, 0);
1119
1120 if (delta > 0)
1121 {
1122 const auto limit = contentHeight
1123 - windowPos.getHeight()
1124 + getLookAndFeel().getPopupMenuBorderSizeWithOptions (options);
1125 return jmin (childYOffset, limit);
1126 }
1127
1128 return childYOffset;
1129 }();
1130
1132 }
1133 else
1134 {
1135 childYOffset = 0;
1136 }
1137
1139 repaint();
1140 }
1141
1143 {
1144 const auto separatorWidth = getLookAndFeel().getPopupMenuColumnSeparatorWidthWithOptions (options);
1145 const auto initialY = getLookAndFeel().getPopupMenuBorderSizeWithOptions (options)
1146 - (childYOffset + (getY() - windowPos.getY()));
1147
1148 auto col = 0;
1149 auto x = 0;
1150 auto y = initialY;
1151
1152 for (const auto& item : items)
1153 {
1154 jassert (col < columnWidths.size());
1155 const auto columnWidth = columnWidths[col];
1156 item->setBounds (x, y, columnWidth, item->getHeight());
1157 y += item->getHeight();
1158
1159 if (item->item.shouldBreakAfter)
1160 {
1161 col += 1;
1162 x += columnWidth + separatorWidth;
1163 y = initialY;
1164 }
1165 }
1166
1167 return std::accumulate (columnWidths.begin(), columnWidths.end(), 0)
1168 + (separatorWidth * (columnWidths.size() - 1));
1169 }
1170
1172 {
1173 if (currentChild != nullptr)
1174 currentChild->setHighlighted (false);
1175
1176 currentChild = child;
1177
1178 if (currentChild != nullptr)
1179 {
1180 currentChild->setHighlighted (true);
1182 }
1183
1184 if (auto* handler = getAccessibilityHandler())
1185 handler->notifyAccessibilityEvent (AccessibilityEvent::rowSelectionChanged);
1186 }
1187
1188 bool isSubMenuVisible() const noexcept { return activeSubMenu != nullptr && activeSubMenu->isVisible(); }
1189
1191 {
1192 activeSubMenu.reset();
1193
1194 if (childComp != nullptr
1195 && hasActiveSubMenu (childComp->item))
1196 {
1197 activeSubMenu.reset (new HelperClasses::MenuWindow (*(childComp->item.subMenu), this,
1198 options.withTargetScreenArea (childComp->getScreenBounds())
1199 .withMinimumWidth (0)
1200 .withTargetComponent (nullptr),
1202
1203 activeSubMenu->setVisible (true); // (must be called before enterModalState on Windows to avoid DropShadower confusion)
1204 activeSubMenu->enterModalState (false);
1205 activeSubMenu->toFront (false);
1206 return true;
1207 }
1208
1209 return false;
1210 }
1211
1213 {
1214 if (currentChild != nullptr && canBeTriggered (currentChild->item))
1215 {
1216 dismissMenu (&currentChild->item);
1217 }
1218 }
1219
1221 {
1222 forwards,
1223 backwards,
1224 current
1225 };
1226
1228 {
1230
1231 auto start = [&]
1232 {
1233 auto index = items.indexOf (currentChild);
1234
1235 if (index >= 0)
1236 return index;
1237
1238 return direction == MenuSelectionDirection::backwards ? items.size() - 1
1239 : 0;
1240 }();
1241
1242 auto preIncrement = (direction != MenuSelectionDirection::current && currentChild != nullptr);
1243
1244 for (int i = items.size(); --i >= 0;)
1245 {
1246 if (preIncrement)
1247 start += (direction == MenuSelectionDirection::backwards ? -1 : 1);
1248
1249 if (auto* mic = items.getUnchecked ((start + items.size()) % items.size()))
1250 {
1251 if (canBeTriggered (mic->item) || hasActiveSubMenu (mic->item))
1252 {
1254 return;
1255 }
1256 }
1257
1258 if (! preIncrement)
1259 preIncrement = true;
1260 }
1261 }
1262
1264 {
1265 disableMouseMoves = true;
1266
1267 if (parent != nullptr)
1268 parent->disableTimerUntilMouseMoves();
1269 }
1270
1274
1275 //==============================================================================
1276 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
1277 {
1278 return std::make_unique<AccessibilityHandler> (*this,
1281 {
1282 if (currentChild != nullptr)
1283 {
1284 if (auto* handler = currentChild->getAccessibilityHandler())
1285 handler->grabFocus();
1286 }
1287 else
1288 {
1290 }
1291 }));
1292 }
1293
1294 //==============================================================================
1301 bool hasBeenOver = false, needsToScroll = false;
1305 std::unique_ptr<MenuWindow> activeSubMenu;
1310 bool exitingModalState = false;
1311
1313};
1314
1315//==============================================================================
1317{
1318public:
1320 : window (w), source (s), lastScrollTime (Time::getMillisecondCounter())
1321 {
1322 startTimerHz (20);
1323 }
1324
1326 {
1327 if (! window.windowIsStillValid())
1328 return;
1329
1330 startTimerHz (20);
1331 handleMousePosition (e.getScreenPosition());
1332 }
1333
1334 void timerCallback() override
1335 {
1336 #if JUCE_WINDOWS
1337 // touch and pen devices on Windows send an offscreen mouse move after mouse up events
1338 // but we don't want to forward these on as they will dismiss the menu
1339 if ((source.isTouch() || source.isPen()) && ! isValidMousePosition())
1340 return;
1341 #endif
1342
1343 if (window.windowIsStillValid())
1344 handleMousePosition (source.getScreenPosition().roundToInt());
1345 }
1346
1347 bool isOver() const
1348 {
1349 return window.reallyContains (window.getLocalPoint (nullptr, source.getScreenPosition()).roundToInt(), true);
1350 }
1351
1354
1355private:
1359 bool isDown = false;
1360
1361 void handleMousePosition (Point<int> globalMousePos)
1362 {
1363 auto localMousePos = window.getLocalPoint (nullptr, globalMousePos);
1364 auto timeNow = Time::getMillisecondCounter();
1365
1366 if (timeNow > window.timeEnteredCurrentChildComp + 100
1367 && window.reallyContains (localMousePos, true)
1368 && window.currentChild != nullptr
1369 && ! (window.disableMouseMoves || window.isSubMenuVisible()))
1370 {
1371 window.showSubMenuFor (window.currentChild);
1372 }
1373
1374 highlightItemUnderMouse (globalMousePos, localMousePos, timeNow);
1375
1376 const bool overScrollArea = scrollIfNecessary (localMousePos, timeNow);
1377 const bool isOverAny = window.isOverAnyMenu();
1378
1379 if (window.hideOnExit && window.hasBeenOver && ! isOverAny)
1380 window.hide (nullptr, true);
1381 else
1382 checkButtonState (localMousePos, timeNow, isDown, overScrollArea, isOverAny);
1383 }
1384
1385 void checkButtonState (Point<int> localMousePos, const uint32 timeNow,
1386 const bool wasDown, const bool overScrollArea, const bool isOverAny)
1387 {
1388 isDown = window.hasBeenOver
1389 && (ModifierKeys::currentModifiers.isAnyMouseButtonDown()
1390 || ComponentPeer::getCurrentModifiersRealtime().isAnyMouseButtonDown());
1391
1392 if (! window.doesAnyJuceCompHaveFocus())
1393 {
1394 if (timeNow > window.lastFocusedTime + 10)
1395 {
1397 window.dismissMenu (nullptr);
1398 // Note: This object may have been deleted by the previous call.
1399 }
1400 }
1401 else if (wasDown && timeNow > window.windowCreationTime + 250
1402 && ! (isDown || overScrollArea))
1403 {
1404 if (window.reallyContains (localMousePos, true))
1405 window.triggerCurrentlyHighlightedItem();
1406 else if ((window.hasBeenOver || ! window.dismissOnMouseUp) && ! isOverAny)
1407 window.dismissMenu (nullptr);
1408
1409 // Note: This object may have been deleted by the previous call.
1410 }
1411 else
1412 {
1413 window.lastFocusedTime = timeNow;
1414 }
1415 }
1416
1417 void highlightItemUnderMouse (Point<int> globalMousePos, Point<int> localMousePos, const uint32 timeNow)
1418 {
1419 if (globalMousePos != lastMousePos || timeNow > lastMouseMoveTime + 350)
1420 {
1421 const auto isMouseOver = window.reallyContains (localMousePos, true);
1422
1423 if (isMouseOver)
1424 window.hasBeenOver = true;
1425
1426 if (lastMousePos.getDistanceFrom (globalMousePos) > 2)
1427 {
1428 lastMouseMoveTime = timeNow;
1429
1430 if (window.disableMouseMoves && isMouseOver)
1431 window.disableMouseMoves = false;
1432 }
1433
1434 if (window.disableMouseMoves || (window.activeSubMenu != nullptr && window.activeSubMenu->isOverChildren()))
1435 return;
1436
1437 const bool isMovingTowardsMenu = isMouseOver && globalMousePos != lastMousePos
1438 && isMovingTowardsSubmenu (globalMousePos);
1439
1440 lastMousePos = globalMousePos;
1441
1442 if (! isMovingTowardsMenu)
1443 {
1444 auto* c = window.getComponentAt (localMousePos);
1445
1446 if (c == &window)
1447 c = nullptr;
1448
1449 auto* itemUnderMouse = dynamic_cast<ItemComponent*> (c);
1450
1451 if (itemUnderMouse == nullptr && c != nullptr)
1452 itemUnderMouse = c->findParentComponentOfClass<ItemComponent>();
1453
1454 if (itemUnderMouse != window.currentChild
1455 && (isMouseOver || (window.activeSubMenu == nullptr) || ! window.activeSubMenu->isVisible()))
1456 {
1457 if (isMouseOver && (c != nullptr) && (window.activeSubMenu != nullptr))
1458 window.activeSubMenu->hide (nullptr, true);
1459
1460 if (! isMouseOver)
1461 {
1462 if (! window.hasBeenOver)
1463 return;
1464
1465 itemUnderMouse = nullptr;
1466 }
1467
1468 window.setCurrentlyHighlightedChild (itemUnderMouse);
1469 }
1470 }
1471 }
1472 }
1473
1474 bool isMovingTowardsSubmenu (Point<int> newGlobalPos) const
1475 {
1476 if (window.activeSubMenu == nullptr)
1477 return false;
1478
1479 // try to intelligently guess whether the user is moving the mouse towards a currently-open
1480 // submenu. To do this, look at whether the mouse stays inside a triangular region that
1481 // extends from the last mouse pos to the submenu's rectangle..
1482
1483 auto itemScreenBounds = window.activeSubMenu->getScreenBounds();
1484 auto subX = (float) itemScreenBounds.getX();
1485
1486 auto oldGlobalPos = lastMousePos;
1487
1488 if (itemScreenBounds.getX() > window.getX())
1489 {
1490 oldGlobalPos -= Point<int> (2, 0); // to enlarge the triangle a bit, in case the mouse only moves a couple of pixels
1491 }
1492 else
1493 {
1494 oldGlobalPos += Point<int> (2, 0);
1495 subX += (float) itemScreenBounds.getWidth();
1496 }
1497
1498 Path areaTowardsSubMenu;
1499 areaTowardsSubMenu.addTriangle ((float) oldGlobalPos.x, (float) oldGlobalPos.y,
1500 subX, (float) itemScreenBounds.getY(),
1501 subX, (float) itemScreenBounds.getBottom());
1502
1503 return areaTowardsSubMenu.contains (newGlobalPos.toFloat());
1504 }
1505
1506 bool scrollIfNecessary (Point<int> localMousePos, const uint32 timeNow)
1507 {
1508 if (window.canScroll()
1509 && isPositiveAndBelow (localMousePos.x, window.getWidth())
1510 && (isPositiveAndBelow (localMousePos.y, window.getHeight()) || source.isDragging()))
1511 {
1512 if (window.isTopScrollZoneActive() && localMousePos.y < PopupMenuSettings::scrollZone)
1513 return scroll (timeNow, -1);
1514
1515 if (window.isBottomScrollZoneActive() && localMousePos.y > window.getHeight() - PopupMenuSettings::scrollZone)
1516 return scroll (timeNow, 1);
1517 }
1518
1519 scrollAcceleration = 1.0;
1520 return false;
1521 }
1522
1523 bool scroll (const uint32 timeNow, const int direction)
1524 {
1525 if (timeNow > lastScrollTime + 20)
1526 {
1528 int amount = 0;
1529
1530 for (int i = 0; i < window.items.size() && amount == 0; ++i)
1531 amount = ((int) scrollAcceleration) * window.items.getUnchecked (i)->getHeight();
1532
1533 window.alterChildYPos (amount * direction);
1534 lastScrollTime = timeNow;
1535 }
1536
1537 return true;
1538 }
1539
1540 #if JUCE_WINDOWS
1541 bool isValidMousePosition()
1542 {
1543 auto screenPos = source.getScreenPosition();
1544 auto localPos = (window.activeSubMenu == nullptr) ? window.getLocalPoint (nullptr, screenPos)
1545 : window.activeSubMenu->getLocalPoint (nullptr, screenPos);
1546
1547 if (localPos.x < 0 && localPos.y < 0)
1548 return false;
1549
1550 return true;
1551 }
1552 #endif
1553
1555};
1556
1557//==============================================================================
1559{
1560 NormalComponentWrapper (Component& comp, int w, int h, bool triggerMenuItemAutomaticallyWhenClicked)
1561 : PopupMenu::CustomComponent (triggerMenuItemAutomaticallyWhenClicked),
1562 width (w), height (h)
1563 {
1565 }
1566
1567 void getIdealSize (int& idealWidth, int& idealHeight) override
1568 {
1569 idealWidth = width;
1570 idealHeight = height;
1571 }
1572
1573 void resized() override
1574 {
1575 if (auto* child = getChildComponent (0))
1576 child->setBounds (getLocalBounds());
1577 }
1578
1579 const int width, height;
1580
1582};
1583
1584};
1585
1586//==============================================================================
1588 : items (other.items),
1589 lookAndFeel (other.lookAndFeel)
1590{
1591}
1592
1593PopupMenu& PopupMenu::operator= (const PopupMenu& other)
1594{
1595 if (this != &other)
1596 {
1597 items = other.items;
1598 lookAndFeel = other.lookAndFeel;
1599 }
1600
1601 return *this;
1602}
1603
1605 : items (std::move (other.items)),
1606 lookAndFeel (std::move (other.lookAndFeel))
1607{
1608}
1609
1610PopupMenu& PopupMenu::operator= (PopupMenu&& other) noexcept
1611{
1612 items = std::move (other.items);
1613 lookAndFeel = other.lookAndFeel;
1614 return *this;
1615}
1616
1617PopupMenu::~PopupMenu() = default;
1618
1620{
1621 items.clear();
1622}
1623
1624//==============================================================================
1625PopupMenu::Item::Item() = default;
1627
1628PopupMenu::Item::Item (Item&&) = default;
1629PopupMenu::Item& PopupMenu::Item::operator= (Item&&) = default;
1630
1632 : text (other.text),
1633 itemID (other.itemID),
1634 action (other.action),
1635 subMenu (createCopyIfNotNull (other.subMenu.get())),
1636 image (other.image != nullptr ? other.image->createCopy() : nullptr),
1641 colour (other.colour),
1642 isEnabled (other.isEnabled),
1643 isTicked (other.isTicked),
1644 isSeparator (other.isSeparator),
1647{}
1648
1649PopupMenu::Item& PopupMenu::Item::operator= (const Item& other)
1650{
1651 text = other.text;
1652 itemID = other.itemID;
1653 action = other.action;
1654 subMenu.reset (createCopyIfNotNull (other.subMenu.get()));
1655 image = other.image != nullptr ? other.image->createCopy() : std::unique_ptr<Drawable>();
1660 colour = other.colour;
1661 isEnabled = other.isEnabled;
1662 isTicked = other.isTicked;
1663 isSeparator = other.isSeparator;
1666 return *this;
1667}
1668
1669PopupMenu::Item& PopupMenu::Item::setTicked (bool shouldBeTicked) & noexcept
1670{
1671 isTicked = shouldBeTicked;
1672 return *this;
1673}
1674
1675PopupMenu::Item& PopupMenu::Item::setEnabled (bool shouldBeEnabled) & noexcept
1676{
1677 isEnabled = shouldBeEnabled;
1678 return *this;
1679}
1680
1681PopupMenu::Item& PopupMenu::Item::setAction (std::function<void()> newAction) & noexcept
1682{
1683 action = std::move (newAction);
1684 return *this;
1685}
1686
1688{
1689 itemID = newID;
1690 return *this;
1691}
1692
1694{
1695 colour = newColour;
1696 return *this;
1697}
1698
1704
1705PopupMenu::Item& PopupMenu::Item::setImage (std::unique_ptr<Drawable> newImage) & noexcept
1706{
1707 image = std::move (newImage);
1708 return *this;
1709}
1710
1711PopupMenu::Item&& PopupMenu::Item::setTicked (bool shouldBeTicked) && noexcept
1712{
1713 isTicked = shouldBeTicked;
1714 return std::move (*this);
1715}
1716
1717PopupMenu::Item&& PopupMenu::Item::setEnabled (bool shouldBeEnabled) && noexcept
1718{
1719 isEnabled = shouldBeEnabled;
1720 return std::move (*this);
1721}
1722
1723PopupMenu::Item&& PopupMenu::Item::setAction (std::function<void()> newAction) && noexcept
1724{
1725 action = std::move (newAction);
1726 return std::move (*this);
1727}
1728
1730{
1731 itemID = newID;
1732 return std::move (*this);
1733}
1734
1736{
1737 colour = newColour;
1738 return std::move (*this);
1739}
1740
1746
1747PopupMenu::Item&& PopupMenu::Item::setImage (std::unique_ptr<Drawable> newImage) && noexcept
1748{
1749 image = std::move (newImage);
1750 return std::move (*this);
1751}
1752
1754{
1755 // An ID of 0 is used as a return value to indicate that the user
1756 // didn't pick anything, so you shouldn't use it as the ID for an item.
1757 jassert (newItem.itemID != 0
1758 || newItem.isSeparator || newItem.isSectionHeader
1759 || newItem.subMenu != nullptr);
1760
1761 items.add (std::move (newItem));
1762}
1763
1764void PopupMenu::addItem (String itemText, std::function<void()> action)
1765{
1766 addItem (std::move (itemText), true, false, std::move (action));
1767}
1768
1769void PopupMenu::addItem (String itemText, bool isActive, bool isTicked, std::function<void()> action)
1770{
1771 Item i (std::move (itemText));
1772 i.action = std::move (action);
1773 i.isEnabled = isActive;
1774 i.isTicked = isTicked;
1775 addItem (std::move (i));
1776}
1777
1778void PopupMenu::addItem (int itemResultID, String itemText, bool isActive, bool isTicked)
1779{
1780 Item i (std::move (itemText));
1781 i.itemID = itemResultID;
1782 i.isEnabled = isActive;
1783 i.isTicked = isTicked;
1784 addItem (std::move (i));
1785}
1786
1787static std::unique_ptr<Drawable> createDrawableFromImage (const Image& im)
1788{
1789 if (im.isValid())
1790 {
1791 auto d = new DrawableImage();
1792 d->setImage (im);
1793 return std::unique_ptr<Drawable> (d);
1794 }
1795
1796 return {};
1797}
1798
1799void PopupMenu::addItem (int itemResultID, String itemText, bool isActive, bool isTicked, const Image& iconToUse)
1800{
1801 addItem (itemResultID, std::move (itemText), isActive, isTicked, createDrawableFromImage (iconToUse));
1802}
1803
1804void PopupMenu::addItem (int itemResultID, String itemText, bool isActive,
1805 bool isTicked, std::unique_ptr<Drawable> iconToUse)
1806{
1807 Item i (std::move (itemText));
1808 i.itemID = itemResultID;
1809 i.isEnabled = isActive;
1810 i.isTicked = isTicked;
1811 i.image = std::move (iconToUse);
1812 addItem (std::move (i));
1813}
1814
1816 const CommandID commandID,
1817 String displayName,
1818 std::unique_ptr<Drawable> iconToUse)
1819{
1820 jassert (commandManager != nullptr && commandID != 0);
1821
1822 if (auto* registeredInfo = commandManager->getCommandForID (commandID))
1823 {
1824 ApplicationCommandInfo info (*registeredInfo);
1825 auto* target = commandManager->getTargetForCommand (commandID, info);
1826
1827 Item i;
1828 i.text = displayName.isNotEmpty() ? std::move (displayName) : info.shortName;
1829 i.itemID = (int) commandID;
1830 i.commandManager = commandManager;
1831 i.isEnabled = target != nullptr && (info.flags & ApplicationCommandInfo::isDisabled) == 0;
1832 i.isTicked = (info.flags & ApplicationCommandInfo::isTicked) != 0;
1833 i.image = std::move (iconToUse);
1834 addItem (std::move (i));
1835 }
1836}
1837
1838void PopupMenu::addColouredItem (int itemResultID, String itemText, Colour itemTextColour,
1839 bool isActive, bool isTicked, std::unique_ptr<Drawable> iconToUse)
1840{
1841 Item i (std::move (itemText));
1842 i.itemID = itemResultID;
1843 i.colour = itemTextColour;
1844 i.isEnabled = isActive;
1845 i.isTicked = isTicked;
1846 i.image = std::move (iconToUse);
1847 addItem (std::move (i));
1848}
1849
1850void PopupMenu::addColouredItem (int itemResultID, String itemText, Colour itemTextColour,
1851 bool isActive, bool isTicked, const Image& iconToUse)
1852{
1853 Item i (std::move (itemText));
1854 i.itemID = itemResultID;
1855 i.colour = itemTextColour;
1856 i.isEnabled = isActive;
1857 i.isTicked = isTicked;
1858 i.image = createDrawableFromImage (iconToUse);
1859 addItem (std::move (i));
1860}
1861
1862void PopupMenu::addCustomItem (int itemResultID,
1863 std::unique_ptr<CustomComponent> cc,
1864 std::unique_ptr<const PopupMenu> subMenu,
1865 const String& itemTitle)
1866{
1867 Item i;
1868 i.text = itemTitle;
1869 i.itemID = itemResultID;
1870 i.customComponent = cc.release();
1871 i.subMenu.reset (createCopyIfNotNull (subMenu.get()));
1872
1873 // If this assertion is hit, this item will be visible to screen readers but with
1874 // no name, which may be confusing to users.
1875 // It's probably a good idea to add a title for this menu item that describes
1876 // the meaning of the item, or the contents of the submenu, as appropriate.
1877 // If you don't want this menu item to be press-able directly, pass "false" to the
1878 // constructor of the CustomComponent.
1880
1881 addItem (std::move (i));
1882}
1883
1884void PopupMenu::addCustomItem (int itemResultID,
1885 Component& customComponent,
1886 int idealWidth, int idealHeight,
1887 bool triggerMenuItemAutomaticallyWhenClicked,
1888 std::unique_ptr<const PopupMenu> subMenu,
1889 const String& itemTitle)
1890{
1891 auto comp = std::make_unique<HelperClasses::NormalComponentWrapper> (customComponent, idealWidth, idealHeight,
1892 triggerMenuItemAutomaticallyWhenClicked);
1893 addCustomItem (itemResultID, std::move (comp), std::move (subMenu), itemTitle);
1894}
1895
1896void PopupMenu::addSubMenu (String subMenuName, PopupMenu subMenu, bool isActive)
1897{
1898 addSubMenu (std::move (subMenuName), std::move (subMenu), isActive, nullptr, false, 0);
1899}
1900
1901void PopupMenu::addSubMenu (String subMenuName, PopupMenu subMenu, bool isActive,
1902 const Image& iconToUse, bool isTicked, int itemResultID)
1903{
1904 addSubMenu (std::move (subMenuName), std::move (subMenu), isActive,
1905 createDrawableFromImage (iconToUse), isTicked, itemResultID);
1906}
1907
1908void PopupMenu::addSubMenu (String subMenuName, PopupMenu subMenu, bool isActive,
1909 std::unique_ptr<Drawable> iconToUse, bool isTicked, int itemResultID)
1910{
1911 Item i (std::move (subMenuName));
1912 i.itemID = itemResultID;
1913 i.isEnabled = isActive && (itemResultID != 0 || subMenu.getNumItems() > 0);
1914 i.subMenu.reset (new PopupMenu (std::move (subMenu)));
1915 i.isTicked = isTicked;
1916 i.image = std::move (iconToUse);
1917 addItem (std::move (i));
1918}
1919
1921{
1922 if (items.size() > 0 && ! items.getLast().isSeparator)
1923 {
1924 Item i;
1925 i.isSeparator = true;
1926 addItem (std::move (i));
1927 }
1928}
1929
1931{
1932 Item i (std::move (title));
1933 i.itemID = 0;
1934 i.isSectionHeader = true;
1935 addItem (std::move (i));
1936}
1937
1939{
1940 if (! items.isEmpty())
1941 std::prev (items.end())->shouldBreakAfter = true;
1942}
1943
1944//==============================================================================
1949
1950template <typename Member, typename Item>
1951static PopupMenu::Options with (PopupMenu::Options options, Member&& member, Item&& item)
1952{
1953 options.*member = std::forward<Item> (item);
1954 return options;
1955}
1956
1958{
1959 auto o = with (*this, &Options::targetComponent, comp);
1960
1961 if (comp != nullptr)
1962 o.targetArea = comp->getScreenBounds();
1963
1964 return o;
1965}
1966
1971
1976
1981
1988
1993
1995{
1996 return with (*this, &Options::minColumns, cols);
1997}
1998
2000{
2001 return with (*this, &Options::maxColumns, cols);
2002}
2003
2008
2010{
2011 return with (*this, &Options::visibleItemID, idOfItemToBeVisible);
2012}
2013
2018
2023
2025{
2026 return with (*this, &Options::initiallySelectedItemId, idOfItemToBeSelected);
2027}
2028
2030 ApplicationCommandManager** managerOfChosenCommand) const
2031{
2032 #if JUCE_WINDOWS
2033 const auto scope = [&]() -> std::unique_ptr<ScopedThreadDPIAwarenessSetter>
2034 {
2035 if (auto* target = options.getTargetComponent())
2036 if (auto* handle = target->getWindowHandle())
2037 return std::make_unique<ScopedThreadDPIAwarenessSetter> (handle);
2038
2039 return nullptr;
2040 }();
2041 #endif
2042
2043 return items.isEmpty() ? nullptr
2044 : new HelperClasses::MenuWindow (*this, nullptr, options,
2045 ! options.getTargetScreenArea().isEmpty(),
2046 ModifierKeys::currentModifiers.isAnyMouseButtonDown(),
2047 managerOfChosenCommand);
2048}
2049
2050//==============================================================================
2051// This invokes any command manager commands and deletes the menu window when it is dismissed
2053{
2055
2056 void modalStateFinished (int result) override
2057 {
2058 if (managerOfChosenCommand != nullptr && result != 0)
2059 {
2062
2063 managerOfChosenCommand->invoke (info, true);
2064 }
2065
2066 // (this would be the place to fade out the component, if that's what's required)
2067 component.reset();
2068
2070 return;
2071
2072 if (auto* focusComponent = Component::getCurrentlyFocusedComponent())
2073 {
2074 const auto focusedIsNotMinimised = [focusComponent]
2075 {
2076 if (auto* peer = focusComponent->getPeer())
2077 return ! peer->isMinimised();
2078
2079 return false;
2080 }();
2081
2082 if (focusedIsNotMinimised)
2083 {
2084 if (auto* topLevel = focusComponent->getTopLevelComponent())
2085 topLevel->toFront (true);
2086
2087 if (focusComponent->isShowing() && ! focusComponent->hasKeyboardFocus (true))
2088 focusComponent->grabKeyboardFocus();
2089 }
2090 }
2091 }
2092
2094 std::unique_ptr<Component> component;
2095
2097};
2098
2100 ModalComponentManager::Callback* userCallback,
2101 bool canBeModal)
2102{
2103 std::unique_ptr<ModalComponentManager::Callback> userCallbackDeleter (userCallback);
2104 std::unique_ptr<PopupMenuCompletionCallback> callback (new PopupMenuCompletionCallback());
2105
2106 if (auto* window = createWindow (options, &(callback->managerOfChosenCommand)))
2107 {
2108 callback->component.reset (window);
2109
2111
2112 window->setVisible (true); // (must be called before enterModalState on Windows to avoid DropShadower confusion)
2113 window->enterModalState (false, userCallbackDeleter.release());
2114 ModalComponentManager::getInstance()->attachCallback (window, callback.release());
2115
2116 window->toFront (false); // need to do this after making it modal, or it could
2117 // be stuck behind other comps that are already modal..
2118
2119 #if JUCE_MODAL_LOOPS_PERMITTED
2120 if (userCallback == nullptr && canBeModal)
2121 return window->runModalLoop();
2122 #else
2123 ignoreUnused (canBeModal);
2124 jassert (! (userCallback == nullptr && canBeModal));
2125 #endif
2126 }
2127
2128 return 0;
2129}
2130
2131//==============================================================================
2132#if JUCE_MODAL_LOOPS_PERMITTED
2133int PopupMenu::showMenu (const Options& options)
2134{
2135 return showWithOptionalCallback (options, nullptr, true);
2136}
2137#endif
2138
2140{
2141 showWithOptionalCallback (options, nullptr, false);
2142}
2143
2145{
2146 #if ! JUCE_MODAL_LOOPS_PERMITTED
2147 jassert (userCallback != nullptr);
2148 #endif
2149
2150 showWithOptionalCallback (options, userCallback, false);
2151}
2152
2153void PopupMenu::showMenuAsync (const Options& options, std::function<void (int)> userCallback)
2154{
2155 showWithOptionalCallback (options, ModalCallbackFunction::create (userCallback), false);
2156}
2157
2158//==============================================================================
2159#if JUCE_MODAL_LOOPS_PERMITTED
2160int PopupMenu::show (int itemIDThatMustBeVisible, int minimumWidth,
2161 int maximumNumColumns, int standardItemHeight,
2163{
2164 return showWithOptionalCallback (Options().withItemThatMustBeVisible (itemIDThatMustBeVisible)
2165 .withMinimumWidth (minimumWidth)
2166 .withMaximumNumColumns (maximumNumColumns)
2167 .withStandardItemHeight (standardItemHeight),
2168 callback, true);
2169}
2170
2171int PopupMenu::showAt (Rectangle<int> screenAreaToAttachTo,
2172 int itemIDThatMustBeVisible, int minimumWidth,
2173 int maximumNumColumns, int standardItemHeight,
2174 ModalComponentManager::Callback* callback)
2175{
2176 return showWithOptionalCallback (Options().withTargetScreenArea (screenAreaToAttachTo)
2177 .withItemThatMustBeVisible (itemIDThatMustBeVisible)
2178 .withMinimumWidth (minimumWidth)
2179 .withMaximumNumColumns (maximumNumColumns)
2180 .withStandardItemHeight (standardItemHeight),
2181 callback, true);
2182}
2183
2184int PopupMenu::showAt (Component* componentToAttachTo,
2185 int itemIDThatMustBeVisible, int minimumWidth,
2186 int maximumNumColumns, int standardItemHeight,
2187 ModalComponentManager::Callback* callback)
2188{
2189 auto options = Options().withItemThatMustBeVisible (itemIDThatMustBeVisible)
2190 .withMinimumWidth (minimumWidth)
2191 .withMaximumNumColumns (maximumNumColumns)
2192 .withStandardItemHeight (standardItemHeight);
2193
2194 if (componentToAttachTo != nullptr)
2195 options = options.withTargetComponent (componentToAttachTo);
2196
2197 return showWithOptionalCallback (options, callback, true);
2198}
2199#endif
2200
2202{
2204 auto numWindows = windows.size();
2205
2206 for (int i = numWindows; --i >= 0;)
2207 {
2208 if (auto* pmw = windows[i])
2209 {
2210 pmw->setLookAndFeel (nullptr);
2211 pmw->dismissMenu (nullptr);
2212 }
2213 }
2214
2215 return numWindows > 0;
2216}
2217
2218//==============================================================================
2220{
2221 int num = 0;
2222
2223 for (auto& mi : items)
2224 if (! mi.isSeparator)
2225 ++num;
2226
2227 return num;
2228}
2229
2230bool PopupMenu::containsCommandItem (const int commandID) const
2231{
2232 for (auto& mi : items)
2233 if ((mi.itemID == commandID && mi.commandManager != nullptr)
2234 || (mi.subMenu != nullptr && mi.subMenu->containsCommandItem (commandID)))
2235 return true;
2236
2237 return false;
2238}
2239
2241{
2242 for (auto& mi : items)
2243 {
2244 if (mi.subMenu != nullptr)
2245 {
2246 if (mi.subMenu->containsAnyActiveItems())
2247 return true;
2248 }
2249 else if (mi.isEnabled)
2250 {
2251 return true;
2252 }
2253 }
2254
2255 return false;
2256}
2257
2258void PopupMenu::setLookAndFeel (LookAndFeel* const newLookAndFeel)
2259{
2260 lookAndFeel = newLookAndFeel;
2261}
2262
2263void PopupMenu::setItem (CustomComponent& c, const Item* itemToUse)
2264{
2265 c.item = itemToUse;
2266 c.repaint();
2267}
2268
2269//==============================================================================
2271
2273 : triggeredAutomatically (autoTrigger)
2274{
2275}
2276
2277void PopupMenu::CustomComponent::setHighlighted (bool shouldBeHighlighted)
2278{
2279 isHighlighted = shouldBeHighlighted;
2280 repaint();
2281}
2282
2284{
2286 {
2287 if (auto* pmw = mic->findParentComponentOfClass<HelperClasses::MenuWindow>())
2288 {
2289 pmw->dismissMenu (&mic->item);
2290 }
2291 else
2292 {
2293 // something must have gone wrong with the component hierarchy if this happens..
2295 }
2296 }
2297 else
2298 {
2299 // why isn't this component inside a menu? Not much point triggering the item if
2300 // there's no menu.
2302 }
2303}
2304
2305//==============================================================================
2308
2309//==============================================================================
2311{
2312 index.add (0);
2313 menus.add (&m);
2314}
2315
2317
2319{
2320 if (index.size() == 0 || menus.getLast()->items.size() == 0)
2321 return false;
2322
2323 currentItem = const_cast<PopupMenu::Item*> (&(menus.getLast()->items.getReference (index.getLast())));
2324
2325 if (searchRecursively && currentItem->subMenu != nullptr)
2326 {
2327 index.add (0);
2328 menus.add (currentItem->subMenu.get());
2329 }
2330 else
2331 {
2332 index.setUnchecked (index.size() - 1, index.getLast() + 1);
2333 }
2334
2335 while (index.size() > 0 && index.getLast() >= (int) menus.getLast()->items.size())
2336 {
2337 index.removeLast();
2338 menus.removeLast();
2339
2340 if (index.size() > 0)
2341 index.setUnchecked (index.size() - 1, index.getLast() + 1);
2342 }
2343
2344 return true;
2345}
2346
2348{
2349 jassert (currentItem != nullptr);
2350 return *(currentItem);
2351}
2352
2354
2356 bool, bool, bool,
2357 bool, bool,
2358 const String&,
2359 const String&,
2360 const Drawable*,
2361 const Colour*) {}
2362
2365
2367
2369
2371
2372} // namespace juce
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define noexcept
Definition DistrhoDefines.h:72
#define nullptr
Definition DistrhoDefines.h:75
static Audio_Scope * scope
Definition player.cpp:26
uint16_t pc
Definition Spc_Cpu.h:144
T limit(T val, T min, T max)
Definition Util.h:78
Definition juce_AccessibilityActions.h:73
AccessibilityActions & addAction(AccessibilityActionType type, std::function< void()> actionCallback)
Definition juce_AccessibilityActions.h:88
virtual AccessibleState getCurrentState() const
Definition juce_AccessibilityHandler.cpp:75
AccessibilityActions actions
Definition juce_AccessibilityHandler.h:311
AccessibilityHandler(Component &componentToWrap, AccessibilityRole accessibilityRole, AccessibilityActions actions={}, Interfaces interfaces={})
Definition juce_AccessibilityHandler.cpp:55
Definition juce_AccessibilityState.h:39
Definition juce_ApplicationCommandManager.h:88
ApplicationCommandTarget * getTargetForCommand(CommandID commandID, ApplicationCommandInfo &upToDateInfo)
Definition juce_ApplicationCommandManager.cpp:217
const ApplicationCommandInfo * getCommandForID(CommandID commandID) const noexcept
Definition juce_ApplicationCommandManager.cpp:131
Definition juce_Array.h:56
Definition juce_BorderSize.h:42
Definition juce_Colour.h:38
Definition juce_Component.h:2287
Definition juce_Component.h:36
void setLookAndFeel(LookAndFeel *newLookAndFeel)
Definition juce_Component.cpp:2182
static Component *JUCE_CALLTYPE getCurrentlyModalComponent(int index=0) noexcept
Definition juce_Component.cpp:1842
void setAccessible(bool shouldBeAccessible)
Definition juce_Component.cpp:3273
bool isVisible() const noexcept
Definition juce_Component.h:122
int getBottom() const noexcept
Definition juce_Component.h:295
bool isOpaque() const noexcept
Definition juce_Component.cpp:843
void setFocusContainerType(FocusContainerType containerType) noexcept
Definition juce_Component.cpp:2862
int getHeight() const noexcept
Definition juce_Component.h:274
static Component *JUCE_CALLTYPE getCurrentlyFocusedComponent() noexcept
Definition juce_Component.cpp:3092
bool isShowing() const
Definition juce_Component.cpp:634
static float JUCE_CALLTYPE getApproximateScaleFactorForComponent(const Component *targetComponent)
Definition juce_Component.cpp:1383
void addAndMakeVisible(Component *child, int zOrder=-1)
Definition juce_Component.cpp:1554
void setAlwaysOnTop(bool shouldStayOnTop)
Definition juce_Component.cpp:1074
void addMouseListener(MouseListener *newListener, bool wantsEventsForAllNestedChildComponents)
Definition juce_Component.cpp:2376
AccessibilityHandler * getAccessibilityHandler()
Definition juce_Component.cpp:3302
void setOpaque(bool shouldBeOpaque)
Definition juce_Component.cpp:829
void postCommandMessage(int commandId)
Definition juce_Component.cpp:2361
void repaint()
Definition juce_Component.cpp:1917
Component() noexcept
Definition juce_Component.cpp:517
@ focusContainer
Definition juce_Component.h:1295
Rectangle< int > getScreenBounds() const
Definition juce_Component.cpp:1134
void exitModalState(int returnValue)
Definition juce_Component.cpp:1795
int getY() const noexcept
Definition juce_Component.h:268
virtual void setName(const String &newName)
Definition juce_Component.cpp:551
void removeChildComponent(Component *childToRemove)
Definition juce_Component.cpp:1569
Component * getChildComponent(int index) const noexcept
Definition juce_Component.cpp:1648
virtual void addToDesktop(int windowStyleFlags, void *nativeWindowToAttachTo=nullptr)
Definition juce_Component.cpp:658
void setBounds(int x, int y, int width, int height)
Definition juce_Component.cpp:1147
void setSize(int newWidth, int newHeight)
Definition juce_Component.cpp:1262
TargetClass * findParentComponentOfClass() const
Definition juce_Component.h:813
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Definition juce_Component.cpp:2842
void setMouseClickGrabsKeyboardFocus(bool shouldGrabFocus)
Definition juce_Component.cpp:2847
static std::unique_ptr< AccessibilityHandler > createIgnoredAccessibilityHandler(Component &)
Definition juce_Component.cpp:3292
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
void setTopLeftPosition(int x, int y)
Definition juce_Component.cpp:1264
virtual void setVisible(bool shouldBeVisible)
Definition juce_Component.cpp:575
String getName() const noexcept
Definition juce_Component.h:76
virtual void handleCommandMessage(int commandId)
Definition juce_Component.cpp:2370
static ModifierKeys getCurrentModifiersRealtime() noexcept
Definition juce_ComponentPeer.cpp:596
static int getNumPeers() noexcept
Definition juce_ComponentPeer.cpp:51
@ windowIsTemporary
Definition juce_ComponentPeer.h:52
@ windowIgnoresKeyPresses
Definition juce_ComponentPeer.h:71
static ComponentPeer * getPeer(int index) noexcept
Definition juce_ComponentPeer.cpp:56
static Point< int > getMousePosition()
Definition juce_Desktop.cpp:153
static Desktop &JUCE_CALLTYPE getInstance()
Definition juce_Desktop.cpp:50
static bool canUseSemiTransparentWindows() noexcept
Definition juce_linux_Windowing.cpp:603
Definition juce_Drawable.h:38
Definition juce_DrawableImage.h:38
Definition juce_GraphicsContext.h:45
Definition juce_Image.h:58
bool isValid() const noexcept
Definition juce_Image.h:147
Definition juce_KeyPress.h:40
static const int upKey
Definition juce_KeyPress.h:198
static const int rightKey
Definition juce_KeyPress.h:201
static const int downKey
Definition juce_KeyPress.h:199
static const int spaceKey
Definition juce_KeyPress.h:189
static const int escapeKey
Definition juce_KeyPress.h:190
static const int returnKey
Definition juce_KeyPress.h:191
static const int leftKey
Definition juce_KeyPress.h:200
Definition juce_LookAndFeel.h:108
static bool callAsync(std::function< void()> functionToCall)
Definition juce_MessageManager.cpp:192
static ModalComponentManager::Callback * create(CallbackFn &&fn)
Definition juce_ModalComponentManager.h:174
Definition juce_ModalComponentManager.h:56
static ModifierKeys currentModifiers
Definition juce_ModifierKeys.h:189
Definition juce_MouseEvent.h:39
Definition juce_MouseInputSource.h:52
MouseInputSource::InputSourceType getType() const noexcept
Definition juce_MouseInputSource.cpp:569
Point< float > getScreenPosition() const noexcept
Definition juce_MouseInputSource.cpp:577
Definition juce_OwnedArray.h:51
Definition juce_Path.h:65
bool contains(float x, float y, float tolerance=defaultToleranceForTesting) const
Definition juce_Path.cpp:937
void addTriangle(float x1, float y1, float x2, float y2, float x3, float y3)
Definition juce_Path.cpp:417
Definition juce_Point.h:42
constexpr Point< float > toFloat() const noexcept
Definition juce_Point.h:234
ValueType y
Definition juce_Point.h:247
ValueType x
Definition juce_Point.h:246
CustomCallback()
Definition juce_PopupMenu.cpp:2306
~CustomCallback() override
Definition juce_PopupMenu.cpp:2307
Definition juce_PopupMenu.h:829
friend PopupMenu
Definition juce_PopupMenu.h:885
bool triggeredAutomatically
Definition juce_PopupMenu.h:882
void triggerMenuItem()
Definition juce_PopupMenu.cpp:2283
void setHighlighted(bool shouldBeHighlighted)
Definition juce_PopupMenu.cpp:2277
CustomComponent()
Definition juce_PopupMenu.cpp:2270
bool isHighlighted
Definition juce_PopupMenu.h:882
static AccessibilityActions getAccessibilityActions(ItemAccessibilityHandler &handler, ItemComponent &item)
Definition juce_PopupMenu.cpp:226
ItemComponent & itemComponent
Definition juce_PopupMenu.cpp:273
String getTitle() const override
Definition juce_PopupMenu.cpp:203
ItemAccessibilityHandler(ItemComponent &itemComponentToWrap)
Definition juce_PopupMenu.cpp:194
AccessibleState getCurrentState() const override
Definition juce_PopupMenu.cpp:208
Definition juce_PopupMenu.cpp:1317
bool isMovingTowardsSubmenu(Point< int > newGlobalPos) const
Definition juce_PopupMenu.cpp:1474
MouseInputSource source
Definition juce_PopupMenu.cpp:1353
void checkButtonState(Point< int > localMousePos, const uint32 timeNow, const bool wasDown, const bool overScrollArea, const bool isOverAny)
Definition juce_PopupMenu.cpp:1385
void highlightItemUnderMouse(Point< int > globalMousePos, Point< int > localMousePos, const uint32 timeNow)
Definition juce_PopupMenu.cpp:1417
void timerCallback() override
Definition juce_PopupMenu.cpp:1334
uint32 lastMouseMoveTime
Definition juce_PopupMenu.cpp:1358
void handleMousePosition(Point< int > globalMousePos)
Definition juce_PopupMenu.cpp:1361
Point< int > lastMousePos
Definition juce_PopupMenu.cpp:1356
bool scrollIfNecessary(Point< int > localMousePos, const uint32 timeNow)
Definition juce_PopupMenu.cpp:1506
MenuWindow & window
Definition juce_PopupMenu.cpp:1352
MouseSourceState(MenuWindow &w, MouseInputSource s)
Definition juce_PopupMenu.cpp:1319
void handleMouseEvent(const MouseEvent &e)
Definition juce_PopupMenu.cpp:1325
bool isOver() const
Definition juce_PopupMenu.cpp:1347
bool isDown
Definition juce_PopupMenu.cpp:1359
uint32 lastScrollTime
Definition juce_PopupMenu.cpp:1358
bool scroll(const uint32 timeNow, const int direction)
Definition juce_PopupMenu.cpp:1523
double scrollAcceleration
Definition juce_PopupMenu.cpp:1357
Array< const PopupMenu * > menus
Definition juce_PopupMenu.h:816
bool next()
Definition juce_PopupMenu.cpp:2318
Item & getItem() const
Definition juce_PopupMenu.cpp:2347
PopupMenu::Item * currentItem
Definition juce_PopupMenu.h:817
MenuItemIterator(const PopupMenu &menu, bool searchRecursively=false)
Definition juce_PopupMenu.cpp:2310
Array< int > index
Definition juce_PopupMenu.h:815
bool searchRecursively
Definition juce_PopupMenu.h:813
Definition juce_PopupMenu.h:457
int standardHeight
Definition juce_PopupMenu.h:636
WeakReference< Component > targetComponent
Definition juce_PopupMenu.h:635
JUCE_NODISCARD Options withMinimumNumColumns(int minNumColumns) const
Definition juce_PopupMenu.cpp:1994
JUCE_NODISCARD Options withMousePosition() const
Definition juce_PopupMenu.cpp:1977
Rectangle< int > getTargetScreenArea() const noexcept
Definition juce_PopupMenu.h:588
JUCE_NODISCARD Options withStandardItemHeight(int standardHeight) const
Definition juce_PopupMenu.cpp:2004
int initiallySelectedItemId
Definition juce_PopupMenu.h:636
JUCE_NODISCARD Options withPreferredPopupDirection(PopupDirection direction) const
Definition juce_PopupMenu.cpp:2019
JUCE_NODISCARD Options withMaximumNumColumns(int maxNumColumns) const
Definition juce_PopupMenu.cpp:1999
int minColumns
Definition juce_PopupMenu.h:636
bool isWatchingForDeletion
Definition juce_PopupMenu.h:637
JUCE_NODISCARD Options withTargetScreenArea(Rectangle< int > targetArea) const
Definition juce_PopupMenu.cpp:1972
WeakReference< Component > componentToWatchForDeletion
Definition juce_PopupMenu.h:635
JUCE_NODISCARD Options withMinimumWidth(int minWidth) const
Definition juce_PopupMenu.cpp:1989
Rectangle< int > targetArea
Definition juce_PopupMenu.h:634
int minWidth
Definition juce_PopupMenu.h:636
JUCE_NODISCARD Options withDeletionCheck(Component &componentToWatchForDeletion) const
Definition juce_PopupMenu.cpp:1982
JUCE_NODISCARD Options withTargetComponent(Component *targetComponent) const
Definition juce_PopupMenu.cpp:1957
Options()
Definition juce_PopupMenu.cpp:1945
WeakReference< Component > parentComponent
Definition juce_PopupMenu.h:635
PopupDirection preferredPopupDirection
Definition juce_PopupMenu.h:638
int maxColumns
Definition juce_PopupMenu.h:636
PopupDirection
Definition juce_PopupMenu.h:466
@ upwards
Definition juce_PopupMenu.h:467
int visibleItemID
Definition juce_PopupMenu.h:636
Component * getTargetComponent() const noexcept
Definition juce_PopupMenu.h:576
JUCE_NODISCARD Options withItemThatMustBeVisible(int idOfItemToBeVisible) const
Definition juce_PopupMenu.cpp:2009
JUCE_NODISCARD Options withParentComponent(Component *parentComponent) const
Definition juce_PopupMenu.cpp:2014
JUCE_NODISCARD Options withInitiallySelectedItem(int idOfItemToBeSelected) const
Definition juce_PopupMenu.cpp:2024
bool containsCommandItem(int commandID) const
Definition juce_PopupMenu.cpp:2230
Array< Item > items
Definition juce_PopupMenu.h:1035
void addSeparator()
Definition juce_PopupMenu.cpp:1920
void showMenuAsync(const Options &options)
Definition juce_PopupMenu.cpp:2139
void addCustomItem(int itemResultID, std::unique_ptr< CustomComponent > customComponent, std::unique_ptr< const PopupMenu > optionalSubMenu=nullptr, const String &itemTitle={})
Definition juce_PopupMenu.cpp:1862
void addColouredItem(int itemResultID, String itemText, Colour itemTextColour, bool isEnabled=true, bool isTicked=false, const Image &iconToUse={})
Definition juce_PopupMenu.cpp:1850
void addSectionHeader(String title)
Definition juce_PopupMenu.cpp:1930
int getNumItems() const noexcept
Definition juce_PopupMenu.cpp:2219
void setLookAndFeel(LookAndFeel *newLookAndFeel)
Definition juce_PopupMenu.cpp:2258
@ backgroundColourId
Definition juce_PopupMenu.h:760
PopupMenu()=default
void clear()
Definition juce_PopupMenu.cpp:1619
void addColumnBreak()
Definition juce_PopupMenu.cpp:1938
void addSubMenu(String subMenuName, PopupMenu subMenu, bool isEnabled=true)
Definition juce_PopupMenu.cpp:1896
static void setItem(CustomComponent &, const Item *)
Definition juce_PopupMenu.cpp:2263
bool containsAnyActiveItems() const noexcept
Definition juce_PopupMenu.cpp:2240
int showWithOptionalCallback(const Options &, ModalComponentManager::Callback *, bool)
Definition juce_PopupMenu.cpp:2099
void addCommandItem(ApplicationCommandManager *commandManager, CommandID commandID, String displayName={}, std::unique_ptr< Drawable > iconToUse={})
Definition juce_PopupMenu.cpp:1815
void addItem(Item newItem)
Definition juce_PopupMenu.cpp:1753
static bool JUCE_CALLTYPE dismissAllActiveMenus()
Definition juce_PopupMenu.cpp:2201
Component * createWindow(const Options &, ApplicationCommandManager **) const
Definition juce_PopupMenu.cpp:2029
WeakReference< LookAndFeel > lookAndFeel
Definition juce_PopupMenu.h:1036
Definition juce_Rectangle.h:67
ValueType getRight() const noexcept
Definition juce_Rectangle.h:139
Point< ValueType > getCentre() const noexcept
Definition juce_Rectangle.h:151
ValueType getCentreX() const noexcept
Definition juce_Rectangle.h:145
ValueType getCentreY() const noexcept
Definition juce_Rectangle.h:148
ValueType getBottom() const noexcept
Definition juce_Rectangle.h:142
ValueType getX() const noexcept
Definition juce_Rectangle.h:127
ValueType getWidth() const noexcept
Definition juce_Rectangle.h:133
bool isEmpty() const noexcept
Definition juce_Rectangle.h:121
JUCE_NODISCARD Rectangle withPosition(ValueType newX, ValueType newY) const noexcept
Definition juce_Rectangle.h:232
ValueType getY() const noexcept
Definition juce_Rectangle.h:130
Definition juce_ReferenceCountedObject.h:247
Definition juce_String.h:53
String trim() const
Definition juce_String.cpp:1656
bool isEmpty() const noexcept
Definition juce_String.h:310
bool isNotEmpty() const noexcept
Definition juce_String.h:316
Definition juce_Time.h:37
static uint32 getApproximateMillisecondCounter() noexcept
Definition juce_Time.cpp:261
static uint32 getMillisecondCounter() noexcept
Definition juce_Time.cpp:241
void stopTimer() noexcept
Definition juce_Timer.cpp:357
Timer() noexcept
Definition juce_Timer.cpp:316
void startTimerHz(int timerFrequencyHz) noexcept
Definition juce_Timer.cpp:349
Definition juce_WeakReference.h:78
* e
Definition inflate.c:1404
UINT_D64 w
Definition inflate.c:942
unsigned * m
Definition inflate.c:1559
struct huft * t
Definition inflate.c:943
int y
Definition inflate.c:1588
unsigned d
Definition inflate.c:940
int g
Definition inflate.c:1573
register unsigned i
Definition inflate.c:1575
static ZCONST unsigned border[]
Definition inflate.c:749
unsigned s
Definition inflate.c:1555
unsigned x[BMAX+1]
Definition inflate.c:1586
static const char * title
Definition pugl.h:1747
static const char * name
Definition pugl.h:1582
static int int height
Definition pugl.h:1594
static int width
Definition pugl.h:1593
static uintptr_t parent
Definition pugl.h:1644
virtual ASIOError start()=0
struct backing_store_struct * info
Definition jmemsys.h:183
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE(className)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define jassertfalse
#define JUCE_CALLTYPE
static int JUCE_CDECL comp(const void *a, const void *b)
Definition lsp.c:298
const Colour white
Definition juce_Colours.h:180
Definition juce_PopupMenu.cpp:30
const int scrollZone
Definition juce_PopupMenu.cpp:31
static bool menuWasHiddenBecauseOfAppChange
Definition juce_PopupMenu.cpp:34
const int dismissCommandId
Definition juce_PopupMenu.cpp:32
Definition carla_juce.cpp:31
Type * createCopyIfNotNull(const Type *objectToCopy)
Definition juce_Memory.h:60
constexpr Type jmin(Type a, Type b)
Definition juce_MathsFunctions.h:106
unsigned int uint32
Definition juce_MathsFunctions.h:45
int CommandID
Definition juce_ApplicationCommandID.h:37
constexpr Type jmax(Type a, Type b)
Definition juce_MathsFunctions.h:94
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Definition juce_RangedDirectoryIterator.h:184
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Definition juce_MathsFunctions.h:262
@ rowSelectionChanged
Definition juce_AccessibilityEvent.h:78
void ignoreUnused(Types &&...) noexcept
Definition juce_MathsFunctions.h:333
@ showMenu
Definition juce_AccessibilityActions.h:61
@ focus
Definition juce_AccessibilityActions.h:54
@ toggle
Definition juce_AccessibilityActions.h:47
@ press
Definition juce_AccessibilityActions.h:40
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Definition juce_MathsFunctions.h:279
static URL::InputStreamOptions with(URL::InputStreamOptions options, Member &&member, Item &&item)
Definition juce_URL.cpp:561
static std::unique_ptr< Drawable > createDrawableFromImage(const Image &im)
Definition juce_PopupMenu.cpp:1787
int roundToInt(const FloatType value) noexcept
Definition juce_MathsFunctions.h:465
AccessibilityRole
Definition juce_AccessibilityRole.h:37
@ window
Definition juce_AccessibilityRole.h:63
@ column
Definition juce_AccessibilityRole.h:52
@ menuItem
Definition juce_AccessibilityRole.h:47
@ popupMenu
Definition juce_AccessibilityRole.h:49
@ ignored
Definition juce_AccessibilityRole.h:67
static bool isForegroundOrEmbeddedProcess(Component *viewComponent)
Definition juce_gui_basics.cpp:120
Definition juce_Uuid.h:141
#define true
Definition ordinals.h:82
#define false
Definition ordinals.h:83
Definition juce_ApplicationCommandInfo.h:45
@ isTicked
Definition juce_ApplicationCommandInfo.h:156
@ isDisabled
Definition juce_ApplicationCommandInfo.h:146
Definition juce_ApplicationCommandTarget.h:61
@ fromMenu
Definition juce_ApplicationCommandTarget.h:80
Definition juce_MouseEvent.h:392
float deltaY
Definition juce_MouseEvent.h:410
void getIdealSize(int &idealWidth, int &idealHeight) override
Definition juce_PopupMenu.cpp:76
void paint(Graphics &g) override
Definition juce_PopupMenu.cpp:68
HeaderItemComponent(const String &name, const Options &opts)
Definition juce_PopupMenu.cpp:62
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_PopupMenu.cpp:88
const Options & options
Definition juce_PopupMenu.cpp:93
Definition juce_PopupMenu.cpp:100
ItemComponent(const PopupMenu::Item &i, const PopupMenu::Options &o, MenuWindow &parent)
Definition juce_PopupMenu.cpp:101
ReferenceCountedObjectPtr< CustomComponent > customComp
Definition juce_PopupMenu.cpp:286
String getTextForMeasurement() const
Definition juce_PopupMenu.cpp:315
void paint(Graphics &g) override
Definition juce_PopupMenu.cpp:145
bool isHighlighted
Definition juce_PopupMenu.cpp:287
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_PopupMenu.cpp:276
MenuWindow & parentWindow
Definition juce_PopupMenu.cpp:283
~ItemComponent() override
Definition juce_PopupMenu.cpp:125
PopupMenu::Item item
Definition juce_PopupMenu.cpp:187
void resized() override
Definition juce_PopupMenu.cpp:154
void setHighlighted(bool shouldBeHighlighted)
Definition juce_PopupMenu.cpp:163
void updateShortcutKeyDescription()
Definition juce_PopupMenu.cpp:289
const PopupMenu::Options & options
Definition juce_PopupMenu.cpp:284
static bool isAccessibilityHandlerRequired(const PopupMenu::Item &item)
Definition juce_PopupMenu.cpp:182
void getIdealSize(int &idealWidth, int &idealHeight, const int standardItemHeight)
Definition juce_PopupMenu.cpp:133
Definition juce_PopupMenu.cpp:326
const Options options
Definition juce_PopupMenu.cpp:1296
void disableTimerUntilMouseMoves()
Definition juce_PopupMenu.cpp:1263
bool hasBeenOver
Definition juce_PopupMenu.cpp:1301
void inputAttemptWhenModal() override
Definition juce_PopupMenu.cpp:649
bool needsToScroll
Definition juce_PopupMenu.cpp:1301
bool canScroll() const noexcept
Definition juce_PopupMenu.cpp:1271
bool keyPressed(const KeyPress &key) override
Definition juce_PopupMenu.cpp:590
float scaleFactor
Definition juce_PopupMenu.cpp:1309
bool dismissOnMouseUp
Definition juce_PopupMenu.cpp:1302
void handleCommandMessage(int commandId) override
Definition juce_PopupMenu.cpp:684
void triggerCurrentlyHighlightedItem()
Definition juce_PopupMenu.cpp:1212
void mouseDrag(const MouseEvent &e) override
Definition juce_PopupMenu.cpp:695
std::unique_ptr< MenuWindow > activeSubMenu
Definition juce_PopupMenu.cpp:1305
bool hasAnyJuceCompHadFocus
Definition juce_PopupMenu.cpp:1302
void paint(Graphics &g) override
Definition juce_PopupMenu.cpp:441
void calculateWindowPos(Rectangle< int > target, const bool alignToRectangle)
Definition juce_PopupMenu.cpp:834
void selectNextItem(MenuSelectionDirection direction)
Definition juce_PopupMenu.cpp:1227
static int getResultItemID(const PopupMenu::Item *item)
Definition juce_PopupMenu.cpp:536
ApplicationCommandManager ** managerOfChosenCommand
Definition juce_PopupMenu.cpp:1298
Rectangle< int > getParentArea(Point< int > targetPoint, Component *relativeTo=nullptr)
Definition juce_PopupMenu.cpp:815
bool disableMouseMoves
Definition juce_PopupMenu.cpp:1302
void visibilityChanged() override
Definition juce_PopupMenu.cpp:571
Array< int > columnWidths
Definition juce_PopupMenu.cpp:1306
void mouseWheelMove(const MouseEvent &, const MouseWheelDetails &wheel) override
Definition juce_PopupMenu.cpp:698
int correctColumnWidths(const int maxMenuW)
Definition juce_PopupMenu.cpp:980
MenuWindow(const PopupMenu &menu, MenuWindow *parentWindow, Options opts, bool alignToRectangle, bool shouldDismissOnMouseUp, ApplicationCommandManager **manager, float parentScaleFactor=1.0f)
Definition juce_PopupMenu.cpp:327
float getDesktopScaleFactor() const override
Definition juce_PopupMenu.cpp:569
uint32 windowCreationTime
Definition juce_PopupMenu.cpp:1307
bool isTopScrollZoneActive() const noexcept
Definition juce_PopupMenu.cpp:1272
WeakReference< Component > componentAttachedTo
Definition juce_PopupMenu.cpp:1299
MouseSourceState & getMouseState(MouseInputSource source)
Definition juce_PopupMenu.cpp:735
bool isOverChildren() const
Definition juce_PopupMenu.cpp:761
void mouseDown(const MouseEvent &e) override
Definition juce_PopupMenu.cpp:694
Component::SafePointer< ItemComponent > currentChild
Definition juce_PopupMenu.cpp:1304
~MenuWindow() override
Definition juce_PopupMenu.cpp:432
MenuSelectionDirection
Definition juce_PopupMenu.cpp:1221
void insertColumnBreaks(const int maxMenuW, const int maxMenuH)
Definition juce_PopupMenu.cpp:938
uint32 lastFocusedTime
Definition juce_PopupMenu.cpp:1307
void mouseUp(const MouseEvent &e) override
Definition juce_PopupMenu.cpp:696
bool exitingModalState
Definition juce_PopupMenu.cpp:1310
uint32 timeEnteredCurrentChildComp
Definition juce_PopupMenu.cpp:1307
void resizeToBestWindowPos()
Definition juce_PopupMenu.cpp:1089
bool treeContains(const MenuWindow *const window) const noexcept
Definition juce_PopupMenu.cpp:776
bool doesAnyJuceCompHaveFocus()
Definition juce_PopupMenu.cpp:794
void setCurrentlyHighlightedChild(ItemComponent *child)
Definition juce_PopupMenu.cpp:1171
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_PopupMenu.cpp:1276
void workOutManualSize(const int maxMenuW)
Definition juce_PopupMenu.cpp:996
static Array< MenuWindow * > & getActiveWindows()
Definition juce_PopupMenu.cpp:729
bool showSubMenuFor(ItemComponent *childComp)
Definition juce_PopupMenu.cpp:1190
int numColumns
Definition juce_PopupMenu.cpp:1303
OwnedArray< ItemComponent > items
Definition juce_PopupMenu.cpp:1297
void handleMouseEvent(const MouseEvent &e)
Definition juce_PopupMenu.cpp:703
void mouseMove(const MouseEvent &e) override
Definition juce_PopupMenu.cpp:693
bool isSubMenuVisible() const noexcept
Definition juce_PopupMenu.cpp:1188
int updateYPositions()
Definition juce_PopupMenu.cpp:1142
int contentHeight
Definition juce_PopupMenu.cpp:1303
void alterChildYPos(int delta)
Definition juce_PopupMenu.cpp:1109
Rectangle< int > windowPos
Definition juce_PopupMenu.cpp:1300
bool isOverAnyMenu() const
Definition juce_PopupMenu.cpp:755
void hide(const PopupMenu::Item *item, bool makeInvisible)
Definition juce_PopupMenu.cpp:501
MenuWindow * parent
Definition juce_PopupMenu.cpp:1295
bool hideOnExit
Definition juce_PopupMenu.cpp:1302
int childYOffset
Definition juce_PopupMenu.cpp:1303
void dismissMenu(const PopupMenu::Item *item)
Definition juce_PopupMenu.cpp:548
bool isBottomScrollZoneActive() const noexcept
Definition juce_PopupMenu.cpp:1273
void ensureItemComponentIsVisible(const ItemComponent &itemComp, int wantedY)
Definition juce_PopupMenu.cpp:1055
void paintOverChildren(Graphics &g) override
Definition juce_PopupMenu.cpp:468
void layoutMenuItems(const int maxMenuW, const int maxMenuH, int &width, int &height)
Definition juce_PopupMenu.cpp:917
OwnedArray< MouseSourceState > mouseSourceStates
Definition juce_PopupMenu.cpp:1308
bool isAnyMouseOver() const
Definition juce_PopupMenu.cpp:767
bool windowIsStillValid()
Definition juce_PopupMenu.cpp:708
int workOutBestSize(const int maxMenuW)
Definition juce_PopupMenu.cpp:1025
void resized() override
Definition juce_PopupMenu.cpp:1573
const int width
Definition juce_PopupMenu.cpp:1579
NormalComponentWrapper(Component &comp, int w, int h, bool triggerMenuItemAutomaticallyWhenClicked)
Definition juce_PopupMenu.cpp:1560
void getIdealSize(int &idealWidth, int &idealHeight) override
Definition juce_PopupMenu.cpp:1567
const int height
Definition juce_PopupMenu.cpp:1579
Definition juce_PopupMenu.cpp:39
static bool canBeTriggered(const PopupMenu::Item &item) noexcept
Definition juce_PopupMenu.cpp:44
static bool hasActiveSubMenu(const PopupMenu::Item &item) noexcept
Definition juce_PopupMenu.cpp:52
Definition juce_PopupMenu.h:111
ApplicationCommandManager * commandManager
Definition juce_PopupMenu.h:155
bool isTicked
Definition juce_PopupMenu.h:174
bool isSectionHeader
Definition juce_PopupMenu.h:180
bool shouldBreakAfter
Definition juce_PopupMenu.h:183
ReferenceCountedObjectPtr< CustomCallback > customCallback
Definition juce_PopupMenu.h:152
Item & setImage(std::unique_ptr< Drawable >) &noexcept
Definition juce_PopupMenu.cpp:1705
Item & setTicked(bool shouldBeTicked=true) &noexcept
Definition juce_PopupMenu.cpp:1669
std::unique_ptr< Drawable > image
Definition juce_PopupMenu.h:146
String text
Definition juce_PopupMenu.h:130
std::unique_ptr< PopupMenu > subMenu
Definition juce_PopupMenu.h:143
int itemID
Definition juce_PopupMenu.h:137
ReferenceCountedObjectPtr< CustomComponent > customComponent
Definition juce_PopupMenu.h:149
bool isEnabled
Definition juce_PopupMenu.h:171
std::function< void()> action
Definition juce_PopupMenu.h:140
Item & setCustomComponent(ReferenceCountedObjectPtr< CustomComponent > customComponent) &noexcept
Definition juce_PopupMenu.cpp:1699
Item & setEnabled(bool shouldBeEnabled) &noexcept
Definition juce_PopupMenu.cpp:1675
bool isSeparator
Definition juce_PopupMenu.h:177
String shortcutKeyDescription
Definition juce_PopupMenu.h:163
Item & setAction(std::function< void()> action) &noexcept
Definition juce_PopupMenu.cpp:1681
Colour colour
Definition juce_PopupMenu.h:168
Item & setID(int newID) &noexcept
Definition juce_PopupMenu.cpp:1687
Item & setColour(Colour) &noexcept
Definition juce_PopupMenu.cpp:1693
virtual void drawPopupMenuUpDownArrow(Graphics &, int width, int height, bool isScrollUpArrow)
Definition juce_PopupMenu.cpp:2366
virtual int getPopupMenuBorderSize()
Definition juce_PopupMenu.cpp:2370
virtual void drawPopupMenuSectionHeader(Graphics &, const Rectangle< int > &, const String &)
Definition juce_PopupMenu.cpp:2363
virtual void getIdealPopupMenuItemSize(const String &text, bool isSeparator, int standardMenuItemHeight, int &idealWidth, int &idealHeight)
Definition juce_PopupMenu.cpp:2368
virtual void drawPopupMenuBackground(Graphics &, int width, int height)
Definition juce_PopupMenu.cpp:2353
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)
Definition juce_PopupMenu.cpp:2355
Definition juce_PopupMenu.cpp:2053
void modalStateFinished(int result) override
Definition juce_PopupMenu.cpp:2056
ApplicationCommandManager * managerOfChosenCommand
Definition juce_PopupMenu.cpp:2093
std::unique_ptr< Component > component
Definition juce_PopupMenu.cpp:2094
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
void Rectangle(HDC ctx, int l, int t, int r, int b)
Definition swell-gdi-generic.cpp:279
return c
Definition crypt.c:175
ZCONST char * key
Definition crypt.c:587
int r
Definition crypt.c:458
if(GLOBAL(newzip))
Definition crypt.c:475
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
void handler(int signal)
Definition fileio.c:1632
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()
#define const
Definition zconf.h:137