JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_ComponentHelpers.h
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::detail
27{
28
29constexpr char colourPropertyPrefix[] = "jcclr_";
30
31//==============================================================================
33{
34 using SH = ScalingHelpers;
35
36 #if JUCE_MODAL_LOOPS_PERMITTED
37 static void* runModalLoopCallback (void* userData)
38 {
39 return (void*) (pointer_sized_int) static_cast<Component*> (userData)->runModalLoop();
40 }
41 #endif
42
43 static Identifier getColourPropertyID (int colourID)
44 {
45 char buffer[32];
46 auto* end = buffer + numElementsInArray (buffer) - 1;
47 auto* t = end;
48 *t = 0;
49
50 for (auto v = (uint32) colourID;;)
51 {
52 *--t = "0123456789abcdef" [v & 15];
53 v >>= 4;
54
55 if (v == 0)
56 break;
57 }
58
59 for (int i = (int) sizeof (colourPropertyPrefix) - 1; --i >= 0;)
60 *--t = colourPropertyPrefix[i];
61
62 return t;
63 }
64
65 //==============================================================================
66 static bool hitTest (Component& comp, Point<float> localPoint)
67 {
68 const auto intPoint = localPoint.roundToInt();
69 return Rectangle<int> { comp.getWidth(), comp.getHeight() }.contains (intPoint)
70 && comp.hitTest (intPoint.x, intPoint.y);
71 }
72
73 // converts an unscaled position within a peer to the local position within that peer's component
74 template <typename PointOrRect>
75 static PointOrRect rawPeerPositionToLocal (const Component& comp, PointOrRect pos) noexcept
76 {
77 if (comp.isTransformed())
78 pos = pos.transformedBy (comp.getTransform().inverted());
79
80 return SH::unscaledScreenPosToScaled (comp, pos);
81 }
82
83 // converts a position within a peer's component to the unscaled position within the peer
84 template <typename PointOrRect>
85 static PointOrRect localPositionToRawPeerPos (const Component& comp, PointOrRect pos) noexcept
86 {
87 if (comp.isTransformed())
88 pos = pos.transformedBy (comp.getTransform());
89
90 return SH::scaledScreenPosToUnscaled (comp, pos);
91 }
92
93 template <typename PointOrRect>
94 static PointOrRect convertFromParentSpace (const Component& comp, const PointOrRect pointInParentSpace)
95 {
96 const auto transformed = comp.affineTransform != nullptr ? pointInParentSpace.transformedBy (comp.affineTransform->inverted())
98
99 if (comp.isOnDesktop())
100 {
101 if (auto* peer = comp.getPeer())
102 return SH::unscaledScreenPosToScaled (comp, peer->globalToLocal (SH::scaledScreenPosToUnscaled (transformed)));
103
105 return transformed;
106 }
107
108 if (comp.getParentComponent() == nullptr)
109 return SH::subtractPosition (SH::unscaledScreenPosToScaled (comp, SH::scaledScreenPosToUnscaled (transformed)), comp);
110
111 return SH::subtractPosition (transformed, comp);
112 }
113
114 template <typename PointOrRect>
115 static PointOrRect convertToParentSpace (const Component& comp, const PointOrRect pointInLocalSpace)
116 {
117 const auto preTransform = [&]
118 {
119 if (comp.isOnDesktop())
120 {
121 if (auto* peer = comp.getPeer())
122 return SH::unscaledScreenPosToScaled (peer->localToGlobal (SH::scaledScreenPosToUnscaled (comp, pointInLocalSpace)));
123
125 return pointInLocalSpace;
126 }
127
128 if (comp.getParentComponent() == nullptr)
129 return SH::unscaledScreenPosToScaled (SH::scaledScreenPosToUnscaled (comp, SH::addPosition (pointInLocalSpace, comp)));
130
131 return SH::addPosition (pointInLocalSpace, comp);
132 }();
133
134 return comp.affineTransform != nullptr ? preTransform.transformedBy (*comp.affineTransform)
135 : preTransform;
136 }
137
138 template <typename PointOrRect>
139 static PointOrRect convertFromDistantParentSpace (const Component* parent, const Component& target, PointOrRect coordInParent)
140 {
141 auto* directParent = target.getParentComponent();
142 jassert (directParent != nullptr);
143
144 if (directParent == parent)
145 return convertFromParentSpace (target, coordInParent);
146
147 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6011)
148 return convertFromParentSpace (target, convertFromDistantParentSpace (parent, *directParent, coordInParent));
149 JUCE_END_IGNORE_WARNINGS_MSVC
150 }
151
152 template <typename PointOrRect>
153 static PointOrRect convertCoordinate (const Component* target, const Component* source, PointOrRect p)
154 {
155 while (source != nullptr)
156 {
157 if (source == target)
158 return p;
159
160 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6011)
161
162 if (source->isParentOf (target))
163 return convertFromDistantParentSpace (source, *target, p);
164
165 JUCE_END_IGNORE_WARNINGS_MSVC
166
167 p = convertToParentSpace (*source, p);
168 source = source->getParentComponent();
169 }
170
171 jassert (source == nullptr);
172 if (target == nullptr)
173 return p;
174
175 auto* topLevelComp = target->getTopLevelComponent();
176
177 p = convertFromParentSpace (*topLevelComp, p);
178
179 if (topLevelComp == target)
180 return p;
181
182 return convertFromDistantParentSpace (topLevelComp, *target, p);
183 }
184
185 static bool clipObscuredRegions (const Component& comp, Graphics& g,
187 {
188 bool wasClipped = false;
189
190 for (int i = comp.childComponentList.size(); --i >= 0;)
191 {
192 auto& child = *comp.childComponentList.getUnchecked (i);
193
194 if (child.isVisible() && ! child.isTransformed())
195 {
196 auto newClip = clipRect.getIntersection (child.boundsRelativeToParent);
197
198 if (! newClip.isEmpty())
199 {
200 if (child.isOpaque() && child.componentTransparency == 0)
201 {
202 g.excludeClipRegion (newClip + delta);
203 wasClipped = true;
204 }
205 else
206 {
207 auto childPos = child.getPosition();
208
209 if (clipObscuredRegions (child, g, newClip - childPos, childPos + delta))
210 wasClipped = true;
211 }
212 }
213 }
214 }
215
216 return wasClipped;
217 }
218
219 static Rectangle<int> getParentOrMainMonitorBounds (const Component& comp)
220 {
221 if (auto* p = comp.getParentComponent())
222 return p->getLocalBounds();
223
225 }
226
227 static void releaseAllCachedImageResources (Component& c)
228 {
229 if (auto* cached = c.getCachedComponentImage())
230 cached->releaseResources();
231
232 for (auto* child : c.childComponentList)
233 releaseAllCachedImageResources (*child);
234 }
235
236 //==============================================================================
237 static bool modalWouldBlockComponent (const Component& maybeBlocked, Component* modal)
238 {
239 return modal != nullptr
240 && modal != &maybeBlocked
241 && ! modal->isParentOf (&maybeBlocked)
242 && ! modal->canModalEventBeSentToComponent (&maybeBlocked);
243 }
244
245 template <typename Function>
246 static void sendMouseEventToComponentsThatAreBlockedByModal (Component& modal, Function&& function)
247 {
248 for (auto& ms : Desktop::getInstance().getMouseSources())
249 if (auto* c = ms.getComponentUnderMouse())
250 if (modalWouldBlockComponent (*c, &modal))
251 (c->*function) (ms, SH::screenPosToLocalPos (*c, ms.getScreenPosition()), Time::getCurrentTime());
252 }
253
255 {
256 public:
257 static auto& getInstance()
258 {
260 return instance;
261 }
262
263 ErasedScopeGuard addListener (std::function<void()> l)
264 {
265 return listeners.addListener (std::move (l));
266 }
267
268 void modalComponentManagerChanged()
269 {
270 listeners.call();
271 }
272
273 private:
275
277 };
278};
279
280} // namespace juce::detail
AffineTransform inverted() const noexcept
Returns a matrix which is the inverse operation of this one.
The base class for all JUCE user-interface objects.
AffineTransform getTransform() const
Returns the transform that is currently being applied to this component.
Component * getTopLevelComponent() const noexcept
Returns the highest-level component which contains this one or its parents.
Component * getParentComponent() const noexcept
Returns the component which this component is inside.
int getHeight() const noexcept
Returns the component's height in pixels.
bool isTransformed() const noexcept
Returns true if a non-identity transform is being applied to this component.
bool isOnDesktop() const noexcept
Returns true if this component is currently showing on the desktop.
virtual bool hitTest(int x, int y)
Tests whether a given point is inside the component.
bool isParentOf(const Component *possibleChild) const noexcept
Checks whether a component is anywhere inside this component or its children.
int getWidth() const noexcept
Returns the component's width in pixels.
CachedComponentImage * getCachedComponentImage() const noexcept
Returns the object that was set by setCachedComponentImage().
ComponentPeer * getPeer() const
Returns the heavyweight window that contains this component.
Point< int > getScreenPosition() const
Returns the position of this component's top-left corner relative to the screen's top-left.
const Displays & getDisplays() const noexcept
Returns the Displays object representing the connected displays.
static Desktop &JUCE_CALLTYPE getInstance()
There's only one desktop object, and this method will return it.
const Array< MouseInputSource > & getMouseSources() const noexcept
Provides access to the array of mouse sources, for iteration.
Rectangle< int > userArea
The total area of this display in logical pixels which isn't covered by OS-dependent objects like the...
const Display * getPrimaryDisplay() const noexcept
Returns the Display object representing the display acting as the user's main screen,...
A ScopeGuard that uses a std::function internally to allow type erasure.
A graphics context, used for drawing a component or image.
void excludeClipRegion(Rectangle< int > rectangleToExclude)
Excludes a rectangle to stop it being drawn into.
Represents a string identifier, designed for accessing properties by name.
A pair of (x, y) coordinates.
Definition juce_Point.h:42
Manages a rectangle and allows geometric operations to be performed on it.
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
#define jassert(expression)
Platform-independent assertion macro.
#define jassertfalse
This will always cause an assertion failure.
int pointer_sized_int
A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it.
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Returns a default-constructed sentinel value.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
unsigned int uint32
A platform-independent 32-bit unsigned integer type.
constexpr int numElementsInArray(Type(&)[N]) noexcept
Handy function for getting the number of elements in a simple const C array.