VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / modules / juce_gui_extra / native / juce_mac_NSViewComponent.mm
blob7c85aef6dae3f158a02074d743377e5c5bdd3806
1 /*\r
2   ==============================================================================\r
3 \r
4    This file is part of the JUCE library.\r
5    Copyright (c) 2022 - Raw Material Software Limited\r
6 \r
7    JUCE is an open source library subject to commercial or open-source\r
8    licensing.\r
9 \r
10    By using JUCE, you agree to the terms of both the JUCE 7 End-User License\r
11    Agreement and JUCE Privacy Policy.\r
13    End User License Agreement: www.juce.com/juce-7-licence\r
14    Privacy Policy: www.juce.com/juce-privacy-policy\r
16    Or: You may also use this code under the terms of the GPL v3 (see\r
17    www.gnu.org/licenses).\r
19    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
20    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
21    DISCLAIMED.\r
23   ==============================================================================\r
24 */\r
26 namespace juce\r
27 {\r
29 class NSViewAttachment  : public ReferenceCountedObject,\r
30                           public ComponentMovementWatcher\r
31 {\r
32 public:\r
33     NSViewAttachment (NSView* v, Component& comp)\r
34         : ComponentMovementWatcher (&comp),\r
35           view (v), owner (comp),\r
36           currentPeer (nullptr)\r
37     {\r
38         [view retain];\r
39         [view setPostsFrameChangedNotifications: YES];\r
40         updateAlpha();\r
42         if (owner.isShowing())\r
43             componentPeerChanged();\r
44     }\r
46     ~NSViewAttachment() override\r
47     {\r
48         removeFromParent();\r
49         [view release];\r
50     }\r
52     void componentMovedOrResized (Component& comp, bool wasMoved, bool wasResized) override\r
53     {\r
54         ComponentMovementWatcher::componentMovedOrResized (comp, wasMoved, wasResized);\r
56         // The ComponentMovementWatcher version of this method avoids calling\r
57         // us when the top-level comp is resized, but if we're listening to the\r
58         // top-level comp we still want the NSView to track its size.\r
59         if (comp.isOnDesktop() && wasResized)\r
60             componentMovedOrResized (wasMoved, wasResized);\r
61     }\r
63     void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) override\r
64     {\r
65         if (auto* peer = owner.getTopLevelComponent()->getPeer())\r
66         {\r
67             const auto newArea = peer->getAreaCoveredBy (owner);\r
69             if (convertToRectInt ([view frame]) != newArea)\r
70                 [view setFrame: makeNSRect (newArea)];\r
71         }\r
72     }\r
74     void componentPeerChanged() override\r
75     {\r
76         auto* peer = owner.getPeer();\r
78         if (currentPeer != peer)\r
79         {\r
80             currentPeer = peer;\r
82             if (peer != nullptr)\r
83             {\r
84                 auto peerView = (NSView*) peer->getNativeHandle();\r
85                 [peerView addSubview: view];\r
86                 componentMovedOrResized (false, false);\r
87             }\r
88             else\r
89             {\r
90                 removeFromParent();\r
91             }\r
92         }\r
94         [view setHidden: ! owner.isShowing()];\r
95     }\r
97     void componentVisibilityChanged() override\r
98     {\r
99         componentPeerChanged();\r
100     }\r
102     void updateAlpha()\r
103     {\r
104         [view setAlphaValue: (CGFloat) owner.getAlpha()];\r
105     }\r
107     NSView* const view;\r
109     using Ptr = ReferenceCountedObjectPtr<NSViewAttachment>;\r
111 private:\r
112     Component& owner;\r
113     ComponentPeer* currentPeer;\r
114     NSViewFrameWatcher frameWatcher { view, [this] { owner.childBoundsChanged (nullptr); } };\r
116     void removeFromParent()\r
117     {\r
118         if ([view superview] != nil)\r
119             [view removeFromSuperview]; // Must be careful not to call this unless it's required - e.g. some Apple AU views\r
120                                         // override the call and use it as a sign that they're being deleted, which breaks everything..\r
121     }\r
123     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NSViewAttachment)\r
124 };\r
126 //==============================================================================\r
127 NSViewComponent::NSViewComponent() = default;\r
128 NSViewComponent::~NSViewComponent() = default;\r
130 void NSViewComponent::setView (void* view)\r
132     if (view != getView())\r
133     {\r
134         auto old = attachment;\r
136         attachment = nullptr;\r
138         if (view != nullptr)\r
139             attachment = attachViewToComponent (*this, view);\r
141         old = nullptr;\r
142     }\r
145 void* NSViewComponent::getView() const\r
147     return attachment != nullptr ? static_cast<NSViewAttachment*> (attachment.get())->view\r
148                                  : nullptr;\r
151 void NSViewComponent::resizeToFitView()\r
153     if (attachment != nullptr)\r
154     {\r
155         auto* view = static_cast<NSViewAttachment*> (attachment.get())->view;\r
156         auto r = [view frame];\r
157         setBounds (Rectangle<int> ((int) r.size.width, (int) r.size.height));\r
159         if (auto* peer = getTopLevelComponent()->getPeer())\r
160         {\r
161             const auto position = peer->getAreaCoveredBy (*this).getPosition();\r
162             [view setFrameOrigin: convertToCGPoint (position)];\r
163         }\r
164     }\r
167 void NSViewComponent::paint (Graphics&) {}\r
169 void NSViewComponent::alphaChanged()\r
171     if (attachment != nullptr)\r
172         (static_cast<NSViewAttachment*> (attachment.get()))->updateAlpha();\r
175 ReferenceCountedObject* NSViewComponent::attachViewToComponent (Component& comp, void* view)\r
177     return new NSViewAttachment ((NSView*) view, comp);\r
180 } // namespace juce\r