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_CallOutBox.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 : content (c)
31{
32 addAndMakeVisible (content);
33
34 if (parent != nullptr)
35 {
36 parent->addChildComponent (this);
37 updatePosition (area, parent->getLocalBounds());
38 setVisible (true);
39 }
40 else
41 {
43 updatePosition (area, Desktop::getInstance().getDisplays().getDisplayForRect (area)->userArea);
45
46 startTimer (100);
47 }
48
49 creationTime = Time::getCurrentTime();
50}
51
52//==============================================================================
54 private Timer
55{
56public:
58 : content (std::move (c)),
59 callout (*content, area, parent)
60 {
61 callout.setVisible (true);
62 callout.enterModalState (true, this);
63 startTimer (200);
64 }
65
66 void modalStateFinished (int) override {}
67
68 void timerCallback() override
69 {
70 if (! detail::WindowingHelpers::isForegroundOrEmbeddedProcess (&callout))
71 callout.dismiss();
72 }
73
75 CallOutBox callout;
76
78};
79
81{
82 jassert (content != nullptr); // must be a valid content component!
83
84 return (new CallOutBoxCallback (std::move (content), area, parent))->callout;
85}
86
87//==============================================================================
89{
90 arrowSize = newSize;
91 refreshPath();
92}
93
94int CallOutBox::getBorderSize() const noexcept
95{
96 return jmax (getLookAndFeel().getCallOutBoxBorderSize (*this), (int) arrowSize);
97}
98
103
105{
106 getLookAndFeel().drawCallOutBoxBackground (*this, g, outline, background);
107}
108
110{
111 auto borderSpace = getBorderSize();
113 refreshPath();
114}
115
117{
118 refreshPath();
119}
120
122{
123 updatePosition (targetArea, availableArea);
124}
125
126bool CallOutBox::hitTest (int x, int y)
127{
128 return outline.contains ((float) x, (float) y);
129}
130
132{
133 if (dismissalMouseClicksAreAlwaysConsumed
134 || targetArea.contains (getMouseXYRelative() + getBounds().getPosition()))
135 {
136 // if you click on the area that originally popped-up the callout, you expect it
137 // to get rid of the box, but deleting the box here allows the click to pass through and
138 // probably re-trigger it, so we need to dismiss the box asynchronously to consume the click..
139
140 // For touchscreens, we make sure not to dismiss the CallOutBox immediately,
141 // as Windows still sends touch events before the CallOutBox had a chance
142 // to really open.
143
144 auto elapsed = Time::getCurrentTime() - creationTime;
145
146 if (elapsed.inMilliseconds() > 200)
147 dismiss();
148 }
149 else
150 {
151 exitModalState (0);
152 setVisible (false);
153 }
154}
155
157{
158 dismissalMouseClicksAreAlwaysConsumed = b;
159}
160
161static constexpr int callOutBoxDismissCommandId = 0x4f83a04b;
162
164{
166
167 if (commandId == callOutBoxDismissCommandId)
168 {
169 exitModalState (0);
170 setVisible (false);
171 }
172}
173
175{
176 postCommandMessage (callOutBoxDismissCommandId);
177}
178
180{
182 {
184 return true;
185 }
186
187 return false;
188}
189
191{
192 targetArea = newAreaToPointTo;
193 availableArea = newAreaToFitIn;
194
195 auto borderSpace = getBorderSize();
196 auto newBounds = getLocalArea (&content, Rectangle<int> (content.getWidth() + borderSpace * 2,
197 content.getHeight() + borderSpace * 2));
198
199 auto hw = newBounds.getWidth() / 2;
200 auto hh = newBounds.getHeight() / 2;
201 auto hwReduced = (float) (hw - borderSpace * 2);
202 auto hhReduced = (float) (hh - borderSpace * 2);
203 auto arrowIndent = (float) borderSpace - arrowSize;
204
205 Point<float> targets[4] = { { (float) targetArea.getCentreX(), (float) targetArea.getBottom() },
206 { (float) targetArea.getRight(), (float) targetArea.getCentreY() },
207 { (float) targetArea.getX(), (float) targetArea.getCentreY() },
208 { (float) targetArea.getCentreX(), (float) targetArea.getY() } };
209
210 Line<float> lines[4] = { { targets[0].translated (-hwReduced, hh - arrowIndent), targets[0].translated (hwReduced, hh - arrowIndent) },
211 { targets[1].translated (hw - arrowIndent, -hhReduced), targets[1].translated (hw - arrowIndent, hhReduced) },
212 { targets[2].translated (-(hw - arrowIndent), -hhReduced), targets[2].translated (-(hw - arrowIndent), hhReduced) },
213 { targets[3].translated (-hwReduced, -(hh - arrowIndent)), targets[3].translated (hwReduced, -(hh - arrowIndent)) } };
214
215 auto centrePointArea = newAreaToFitIn.reduced (hw, hh).toFloat();
216 auto targetCentre = targetArea.getCentre().toFloat();
217
218 float nearest = 1.0e9f;
219
220 for (int i = 0; i < 4; ++i)
221 {
222 Line<float> constrainedLine (centrePointArea.getConstrainedPoint (lines[i].getStart()),
223 centrePointArea.getConstrainedPoint (lines[i].getEnd()));
224
225 auto centre = constrainedLine.findNearestPointTo (targetCentre);
226 auto distanceFromCentre = centre.getDistanceFrom (targets[i]);
227
228 if (! centrePointArea.intersects (lines[i]))
229 distanceFromCentre += 1000.0f;
230
232 {
234 targetPoint = targets[i];
235
236 newBounds.setPosition ((int) (centre.x - (float) hw),
237 (int) (centre.y - (float) hh));
238 }
239 }
240
242}
243
244void CallOutBox::refreshPath()
245{
246 repaint();
247 background = {};
248 outline.clear();
249
250 const float gap = 4.5f;
251
252 outline.addBubble (getLocalArea (&content, content.getLocalBounds().toFloat()).expanded (gap, gap),
253 getLocalBounds().toFloat(),
254 targetPoint - getPosition().toFloat(),
255 getLookAndFeel().getCallOutBoxCornerSize (*this), arrowSize * 0.7f);
256}
257
258void CallOutBox::timerCallback()
259{
260 toFront (true);
261 stopTimer();
262}
263
264//==============================================================================
266{
267 return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::dialogWindow);
268}
269
270} // namespace juce
void timerCallback() override
The user-defined callback routine that actually gets called periodically.
void modalStateFinished(int) override
Called to indicate that a modal component has been dismissed.
A box with a small arrow that can be used as a temporary pop-up window to show extra controls when a ...
void inputAttemptWhenModal() override
Called when the user tries to click on a component that is blocked by another modal component.
bool keyPressed(const KeyPress &) override
Called when a key is pressed.
void handleCommandMessage(int) override
Called to handle a command that was sent by postCommandMessage().
void dismiss()
Posts a message which will dismiss the callout box asynchronously.
void updatePosition(const Rectangle< int > &newAreaToPointTo, const Rectangle< int > &newAreaToFitIn)
Updates the position and size of the box.
void childBoundsChanged(Component *) override
Called when one of this component's children is moved or resized.
void setDismissalMouseClicksAreAlwaysConsumed(bool shouldAlwaysBeConsumed) noexcept
Determines whether the mouse events for clicks outside the calloutbox are consumed,...
void setArrowSize(float newSize)
Changes the base width of the arrow.
static CallOutBox & launchAsynchronously(std::unique_ptr< Component > contentComponent, Rectangle< int > areaToPointTo, Component *parentComponent)
This will launch a callout box containing the given content, pointing to the specified target compone...
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Override this method to return a custom AccessibilityHandler for this component.
CallOutBox(Component &contentComponent, Rectangle< int > areaToPointTo, Component *parentComponent)
Creates a CallOutBox.
bool hitTest(int x, int y) override
Tests whether a given point is inside the component.
void paint(Graphics &) override
Components can override this method to draw their content.
void lookAndFeelChanged() override
Called to let the component react to a change in the look-and-feel setting.
void resized() override
Called when this component's size has been changed.
void moved() override
Called when this component's position has been changed.
@ windowIsTemporary
Indicates that the window is a temporary popup, like a menu, tooltip, etc.
The base class for all JUCE user-interface objects.
void exitModalState(int returnValue=0)
Ends a component's modal state.
Point< int > getPosition() const noexcept
Returns the component's top-left position as a Point.
int getHeight() const noexcept
Returns the component's height in pixels.
Rectangle< int > getLocalArea(const Component *sourceComponent, Rectangle< int > areaRelativeToSourceComponent) const
Converts a rectangle to be relative to this component's coordinate space.
void toFront(bool shouldAlsoGainKeyboardFocus)
Brings the component to the front of its siblings.
void addAndMakeVisible(Component *child, int zOrder=-1)
Adds a child component to this one, and also makes the child visible if it isn't already.
void setAlwaysOnTop(bool shouldStayOnTop)
Sets whether the component should always be kept at the front of its siblings.
void postCommandMessage(int commandId)
Dispatches a numbered message to this component.
Rectangle< int > getBounds() const noexcept
Returns this component's bounding box.
void repaint()
Marks the whole component as needing to be redrawn.
Point< int > getMouseXYRelative() const
Returns the mouse's current position, relative to this component.
virtual void addToDesktop(int windowStyleFlags, void *nativeWindowToAttachTo=nullptr)
Makes this component appear as a window on the desktop.
void setBounds(int x, int y, int width, int height)
Changes the component's position and size.
void enterModalState(bool takeKeyboardFocus=true, ModalComponentManager::Callback *callback=nullptr, bool deleteWhenDismissed=false)
Puts the component into a modal state.
int getWidth() const noexcept
Returns the component's width in pixels.
LookAndFeel & getLookAndFeel() const noexcept
Finds the appropriate look-and-feel to use for this component.
Rectangle< int > getLocalBounds() const noexcept
Returns the component's bounds, relative to its own origin.
void setTopLeftPosition(int x, int y)
Moves the component to a new position.
void addChildComponent(Component *child, int zOrder=-1)
Adds a child component to this one.
virtual void setVisible(bool shouldBeVisible)
Makes the component visible or invisible.
virtual void handleCommandMessage(int commandId)
Called to handle a command that was sent by postCommandMessage().
static Desktop &JUCE_CALLTYPE getInstance()
There's only one desktop object, and this method will return it.
A graphics context, used for drawing a component or image.
Represents a key press, including any modifier keys that are needed.
bool isKeyCode(int keyCodeToCompare) const noexcept
Checks whether the KeyPress's key is the same as the one provided, without checking the modifiers.
static const int escapeKey
key-code for the escape key
Represents a line.
Definition juce_Line.h:47
Point< ValueType > getEnd() const noexcept
Returns the line's end point.
Definition juce_Line.h:91
Point< ValueType > getStart() const noexcept
Returns the line's start point.
Definition juce_Line.h:88
Receives callbacks when a modal component is dismissed.
bool contains(float x, float y, float tolerance=defaultToleranceForTesting) const
Checks whether a point lies within the path.
void addBubble(Rectangle< float > bodyArea, Rectangle< float > maximumArea, Point< float > arrowTipPosition, float cornerSize, float arrowBaseWidth)
Adds a speech-bubble shape to the path.
void clear() noexcept
Removes all lines and curves, resetting the path completely.
A pair of (x, y) coordinates.
Definition juce_Point.h:42
constexpr Point translated(ValueType deltaX, ValueType deltaY) const noexcept
Returns a point with a given offset from this one.
Definition juce_Point.h:97
constexpr Point< float > toFloat() const noexcept
Casts this point to a Point<float> object.
Definition juce_Point.h:239
Manages a rectangle and allows geometric operations to be performed on it.
ValueType getRight() const noexcept
Returns the x coordinate of the rectangle's right-hand-side.
Point< ValueType > getCentre() const noexcept
Returns the centre point of the rectangle.
Rectangle< float > toFloat() const noexcept
Casts this rectangle to a Rectangle<float>.
bool contains(ValueType xCoord, ValueType yCoord) const noexcept
Returns true if this coordinate is inside the rectangle.
ValueType getX() const noexcept
Returns the x coordinate of the rectangle's left-hand-side.
ValueType getCentreX() const noexcept
Returns the x coordinate of the rectangle's centre.
ValueType getCentreY() const noexcept
Returns the y coordinate of the rectangle's centre.
ValueType getBottom() const noexcept
Returns the y coordinate of the rectangle's bottom edge.
ValueType getY() const noexcept
Returns the y coordinate of the rectangle's top edge.
Rectangle expanded(ValueType deltaX, ValueType deltaY) const noexcept
Returns a rectangle that is larger than this one by a given amount.
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
Makes repeated callbacks to a virtual method at a specified time interval.
Definition juce_Timer.h:52
void stopTimer() noexcept
Stops the timer.
void startTimer(int intervalInMilliseconds) noexcept
Starts the timer and sets the length of interval required.
#define jassert(expression)
Platform-independent assertion macro.
#define JUCE_DECLARE_NON_COPYABLE(className)
This is a shorthand macro for deleting a class's copy constructor and copy assignment operator.
typedef float
JUCE Namespace.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
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
static bool areThereAnyAlwaysOnTopWindows()
Returns true if any windows have a z order that is higher than normal.