Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
6.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. class NSViewAttachment : public ReferenceCountedObject,
  18. public ComponentMovementWatcher
  19. {
  20. public:
  21. NSViewAttachment (NSView* const v, Component& comp)
  22. : ComponentMovementWatcher (&comp),
  23. view (v), owner (comp),
  24. currentPeer (nullptr), frameChangeCallback (nullptr)
  25. {
  26. [view retain];
  27. [view setPostsFrameChangedNotifications: YES];
  28. if (owner.isShowing())
  29. componentPeerChanged();
  30. static ViewFrameChangeCallbackClass cls;
  31. frameChangeCallback = [cls.createInstance() init];
  32. ViewFrameChangeCallbackClass::setTarget (frameChangeCallback, &owner);
  33. [[NSNotificationCenter defaultCenter] addObserver: frameChangeCallback
  34. selector: @selector (frameChanged:)
  35. name: NSViewFrameDidChangeNotification
  36. object: view];
  37. }
  38. ~NSViewAttachment()
  39. {
  40. [[NSNotificationCenter defaultCenter] removeObserver: frameChangeCallback];
  41. [frameChangeCallback release];
  42. removeFromParent();
  43. [view release];
  44. }
  45. void componentMovedOrResized (Component& comp, bool wasMoved, bool wasResized) override
  46. {
  47. ComponentMovementWatcher::componentMovedOrResized (comp, wasMoved, wasResized);
  48. // The ComponentMovementWatcher version of this method avoids calling
  49. // us when the top-level comp is resized, but for an NSView we need to know this
  50. // because with inverted coordinates, we need to update the position even if the
  51. // top-left pos hasn't changed
  52. if (comp.isOnDesktop() && wasResized)
  53. componentMovedOrResized (wasMoved, wasResized);
  54. }
  55. void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) override
  56. {
  57. if (ComponentPeer* const peer = owner.getTopLevelComponent()->getPeer())
  58. {
  59. NSRect r = makeNSRect (peer->getAreaCoveredBy (owner));
  60. r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height);
  61. [view setFrame: r];
  62. }
  63. }
  64. void componentPeerChanged() override
  65. {
  66. ComponentPeer* const peer = owner.getPeer();
  67. if (currentPeer != peer)
  68. {
  69. removeFromParent();
  70. currentPeer = peer;
  71. if (peer != nullptr)
  72. {
  73. NSView* const peerView = (NSView*) peer->getNativeHandle();
  74. [peerView addSubview: view];
  75. componentMovedOrResized (false, false);
  76. }
  77. }
  78. [view setHidden: ! owner.isShowing()];
  79. }
  80. void componentVisibilityChanged() override
  81. {
  82. componentPeerChanged();
  83. }
  84. NSView* const view;
  85. private:
  86. Component& owner;
  87. ComponentPeer* currentPeer;
  88. id frameChangeCallback;
  89. void removeFromParent()
  90. {
  91. if ([view superview] != nil)
  92. [view removeFromSuperview]; // Must be careful not to call this unless it's required - e.g. some Apple AU views
  93. // override the call and use it as a sign that they're being deleted, which breaks everything..
  94. }
  95. //==============================================================================
  96. struct ViewFrameChangeCallbackClass : public ObjCClass<NSObject>
  97. {
  98. ViewFrameChangeCallbackClass() : ObjCClass<NSObject> ("JUCE_NSViewCallback_")
  99. {
  100. addIvar<Component*> ("target");
  101. addMethod (@selector (frameChanged:), frameChanged, "v@:@");
  102. registerClass();
  103. }
  104. static void setTarget (id self, Component* c)
  105. {
  106. object_setInstanceVariable (self, "target", c);
  107. }
  108. private:
  109. static void frameChanged (id self, SEL, NSNotification*)
  110. {
  111. if (Component* const target = getIvar<Component*> (self, "target"))
  112. target->childBoundsChanged (nullptr);
  113. }
  114. JUCE_DECLARE_NON_COPYABLE (ViewFrameChangeCallbackClass);
  115. };
  116. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NSViewAttachment)
  117. };
  118. //==============================================================================
  119. NSViewComponent::NSViewComponent() {}
  120. NSViewComponent::~NSViewComponent() {}
  121. void NSViewComponent::setView (void* const view)
  122. {
  123. if (view != getView())
  124. {
  125. attachment = nullptr;
  126. if (view != nullptr)
  127. attachment = attachViewToComponent (*this, view);
  128. }
  129. }
  130. void* NSViewComponent::getView() const
  131. {
  132. return attachment != nullptr ? static_cast<NSViewAttachment*> (attachment.get())->view
  133. : nullptr;
  134. }
  135. void NSViewComponent::resizeToFitView()
  136. {
  137. if (attachment != nullptr)
  138. {
  139. NSRect r = [static_cast<NSViewAttachment*> (attachment.get())->view frame];
  140. setBounds (Rectangle<int> ((int) r.size.width, (int) r.size.height));
  141. }
  142. }
  143. void NSViewComponent::paint (Graphics&) {}
  144. ReferenceCountedObject* NSViewComponent::attachViewToComponent (Component& comp, void* const view)
  145. {
  146. return new NSViewAttachment ((NSView*) view, comp);
  147. }