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_Label.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
29Label::Label (const String& name, const String& labelText)
30 : Component (name),
31 textValue (labelText),
32 lastTextValue (labelText)
33{
34 setColour (TextEditor::textColourId, Colours::black);
35 setColour (TextEditor::backgroundColourId, Colours::transparentBlack);
36 setColour (TextEditor::outlineColourId, Colours::transparentBlack);
37
38 textValue.addListener (this);
39}
40
42{
43 textValue.removeListener (this);
44
45 if (ownerComponent != nullptr)
46 ownerComponent->removeComponentListener (this);
47
48 editor.reset();
49}
50
51//==============================================================================
53{
54 hideEditor (true);
55
56 if (lastTextValue != newText)
57 {
58 lastTextValue = newText;
59 textValue = newText;
60 repaint();
61
63
64 if (ownerComponent != nullptr)
65 componentMovedOrResized (*ownerComponent, true, true);
66
68 callChangeListeners();
69 }
70}
71
73{
75 ? editor->getText()
76 : textValue.toString();
77}
78
80{
81 if (lastTextValue != textValue.toString())
82 setText (textValue.toString(), sendNotification);
83}
84
85//==============================================================================
87{
88 if (font != newFont)
89 {
90 font = newFont;
91 repaint();
92 }
93}
94
96{
97 return font;
98}
99
116
118{
119 if (justification != newJustification)
120 {
121 justification = newJustification;
122 repaint();
123 }
124}
125
127{
128 if (border != newBorder)
129 {
130 border = newBorder;
131 repaint();
132 }
133}
134
135//==============================================================================
137{
138 return ownerComponent.get();
139}
140
142{
143 jassert (owner != this); // Not a great idea to try to attach it to itself!
144
145 if (ownerComponent != nullptr)
146 ownerComponent->removeComponentListener (this);
147
148 ownerComponent = owner;
149 leftOfOwnerComp = onLeft;
150
151 if (ownerComponent != nullptr)
152 {
153 setVisible (ownerComponent->isVisible());
154 ownerComponent->addComponentListener (this);
155 componentParentHierarchyChanged (*ownerComponent);
156 componentMovedOrResized (*ownerComponent, true, true);
157 }
158}
159
160void Label::componentMovedOrResized (Component& component, bool /*wasMoved*/, bool /*wasResized*/)
161{
162 auto& lf = getLookAndFeel();
163 auto f = lf.getLabelFont (*this);
164 auto borderSize = lf.getLabelBorderSize (*this);
165
166 if (leftOfOwnerComp)
167 {
168 auto width = jmin (roundToInt (f.getStringWidthFloat (textValue.toString()) + 0.5f)
169 + borderSize.getLeftAndRight(),
170 component.getX());
171
172 setBounds (component.getX() - width, component.getY(), width, component.getHeight());
173 }
174 else
175 {
176 auto height = borderSize.getTopAndBottom() + 6 + roundToInt (f.getHeight() + 0.5f);
177
178 setBounds (component.getX(), component.getY() - height, component.getWidth(), height);
179 }
180}
181
183{
184 if (auto* parent = component.getParentComponent())
185 parent->addChildComponent (this);
186}
187
189{
190 setVisible (component.isVisible());
191}
192
193//==============================================================================
196
198{
200 listeners.callChecked (checker, [this, textEditor] (Label::Listener& l) { l.editorShown (this, *textEditor); });
201
202 if (checker.shouldBailOut())
203 return;
204
205 NullCheckedInvocation::invoke (onEditorShow);
206}
207
209{
211 listeners.callChecked (checker, [this, textEditor] (Label::Listener& l) { l.editorHidden (this, *textEditor); });
212
213 if (checker.shouldBailOut())
214 return;
215
216 NullCheckedInvocation::invoke (onEditorHide);
217}
218
220{
221 if (editor == nullptr)
222 {
223 editor.reset (createEditorComponent());
224 editor->setSize (10, 10);
225 addAndMakeVisible (editor.get());
226 editor->setText (getText(), false);
227 editor->setKeyboardType (keyboardType);
228 editor->addListener (this);
229 editor->grabKeyboardFocus();
230
231 if (editor == nullptr) // may be deleted by a callback
232 return;
233
234 editor->setHighlightedRegion (Range<int> (0, textValue.toString().length()));
235
236 resized();
237 repaint();
238
239 editorShown (editor.get());
240
241 enterModalState (false);
242 editor->grabKeyboardFocus();
243 }
244}
245
246bool Label::updateFromTextEditorContents (TextEditor& ed)
247{
248 auto newText = ed.getText();
249
250 if (textValue.toString() != newText)
251 {
252 lastTextValue = newText;
253 textValue = newText;
254 repaint();
255
257
258 if (ownerComponent != nullptr)
259 componentMovedOrResized (*ownerComponent, true, true);
260
261 return true;
262 }
263
264 return false;
265}
266
268{
269 if (editor != nullptr)
270 {
273 std::swap (outgoingEditor, editor);
274
276
277 const bool changed = (! discardCurrentEditorContents)
278 && updateFromTextEditorContents (*outgoingEditor);
279 outgoingEditor.reset();
280
281 if (deletionChecker != nullptr)
282 repaint();
283
284 if (changed)
286
287 if (deletionChecker != nullptr)
288 exitModalState (0);
289
290 if (changed && deletionChecker != nullptr)
291 callChangeListeners();
292 }
293}
294
296{
297 if (editor != nullptr)
298 {
299 if (lossOfFocusDiscardsChanges)
301 else
303 }
304}
305
307{
308 return editor != nullptr;
309}
310
311static void copyColourIfSpecified (Label& l, TextEditor& ed, int colourID, int targetColourID)
312{
313 if (l.isColourSpecified (colourID) || l.getLookAndFeel().isColourSpecified (colourID))
314 ed.setColour (targetColourID, l.findColour (colourID));
315}
316
318{
319 auto* ed = new TextEditor (getName());
320 ed->applyFontToAllText (getLookAndFeel().getLabelFont (*this));
322
323 copyColourIfSpecified (*this, *ed, textWhenEditingColourId, TextEditor::textColourId);
324 copyColourIfSpecified (*this, *ed, backgroundWhenEditingColourId, TextEditor::backgroundColourId);
325 copyColourIfSpecified (*this, *ed, outlineWhenEditingColourId, TextEditor::focusedOutlineColourId);
326
327 return ed;
328}
329
331{
332 return editor.get();
333}
334
335//==============================================================================
337{
338 getLookAndFeel().drawLabel (g, *this);
339}
340
342{
343 if (editSingleClick
344 && isEnabled()
345 && contains (e.getPosition())
347 {
348 showEditor();
349 }
350}
351
353{
354 if (editDoubleClick
355 && isEnabled()
356 && ! e.mods.isPopupMenu())
357 {
358 showEditor();
359 }
360}
361
363{
364 if (editor != nullptr)
365 editor->setBounds (getLocalBounds());
366}
367
369{
370 if (editSingleClick
371 && isEnabled()
373 {
374 showEditor();
375 }
376}
377
379{
380 repaint();
381}
382
384{
385 repaint();
386}
387
389{
390 if (! approximatelyEqual (minimumHorizontalScale, newScale))
391 {
392 minimumHorizontalScale = newScale;
393 repaint();
394 }
395}
396
397//==============================================================================
398// We'll use a custom focus traverser here to make sure focus goes from the
399// text editor to another component rather than back to the label itself.
401{
402public:
403 explicit LabelKeyboardFocusTraverser (Label& l) : owner (l) {}
404
406 {
407 if (auto* container = getKeyboardFocusContainer (parent))
409
410 return nullptr;
411 }
412
415
417 {
418 if (auto* container = getKeyboardFocusContainer (parent))
420
421 return {};
422 }
423
424private:
425 Component* getComp (Component* current) const
426 {
427 if (auto* ed = owner.getCurrentTextEditor())
428 if (current == ed)
429 return current->getParentComponent();
430
431 return current;
432 }
433
434 Component* getKeyboardFocusContainer (Component* parent) const
435 {
436 if (owner.getCurrentTextEditor() != nullptr && parent == &owner)
437 return owner.findKeyboardFocusContainer();
438
439 return parent;
440 }
441
442 Label& owner;
443
444 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LabelKeyboardFocusTraverser)
445};
446
448{
449 return std::make_unique<LabelKeyboardFocusTraverser> (*this);
450}
451
452//==============================================================================
453void Label::addListener (Label::Listener* l) { listeners.add (l); }
454void Label::removeListener (Label::Listener* l) { listeners.remove (l); }
455
456void Label::callChangeListeners()
457{
459 listeners.callChecked (checker, [this] (Listener& l) { l.labelTextChanged (this); });
460
461 if (checker.shouldBailOut())
462 return;
463
464 NullCheckedInvocation::invoke (onTextChange);
465}
466
467//==============================================================================
469{
470 if (editor != nullptr)
471 {
472 jassert (&ed == editor.get());
473
475 {
476 if (lossOfFocusDiscardsChanges)
478 else
480 }
481 }
482}
483
485{
486 if (editor != nullptr)
487 {
488 jassert (&ed == editor.get());
489
491 bool changed = updateFromTextEditorContents (ed);
492 hideEditor (true);
493
494 if (changed && deletionChecker != nullptr)
495 {
497
498 if (deletionChecker != nullptr)
499 callChangeListeners();
500 }
501 }
502}
503
505{
506 if (editor != nullptr)
507 {
508 jassert (&ed == editor.get());
509
510 editor->setText (textValue.toString(), false);
511 hideEditor (true);
512 }
513}
514
519
520//==============================================================================
522{
523public:
526 labelToWrap.isEditable() ? AccessibilityRole::editableText : AccessibilityRole::label,
527 getAccessibilityActions (labelToWrap),
528 { std::make_unique<LabelValueInterface> (labelToWrap) }),
529 label (labelToWrap)
530 {
531 }
532
533 String getTitle() const override { return label.getText(); }
534 String getHelp() const override { return label.getTooltip(); }
535
537 {
538 if (label.isBeingEdited())
539 return {}; // allow focus to pass through to the TextEditor
540
542 }
543
544private:
545 class LabelValueInterface final : public AccessibilityTextValueInterface
546 {
547 public:
548 explicit LabelValueInterface (Label& labelToWrap)
549 : label (labelToWrap)
550 {
551 }
552
553 bool isReadOnly() const override { return true; }
554 String getCurrentValueAsString() const override { return label.getText(); }
555 void setValueAsString (const String&) override {}
556
557 private:
558 Label& label;
559
560 //==============================================================================
562 };
563
564 static AccessibilityActions getAccessibilityActions (Label& label)
565 {
566 if (label.isEditable())
567 return AccessibilityActions().addAction (AccessibilityActionType::press, [&label] { label.showEditor(); });
568
569 return {};
570 }
571
572 Label& label;
573
574 //==============================================================================
575 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LabelAccessibilityHandler)
576};
577
579{
580 return std::make_unique<LabelAccessibilityHandler> (*this);
581}
582
583} // namespace juce
Base class for accessible Components.
virtual AccessibleState getCurrentState() const
Returns the current state of the UI element.
A value interface that represents a text value.
Represents the state of an accessible UI element.
Specifies a set of gaps to be left around the sides of a rectangle.
A class to keep an eye on a component and check for it being deleted.
The base class for all JUCE user-interface objects.
bool contains(Point< int > localPoint)
Returns true if a given point lies within this component or one of its children.
void copyAllExplicitColoursTo(Component &target) const
This looks for any colours that have been specified for this component, and copies them to the specif...
bool isVisible() const noexcept
Tests whether the component is visible or not.
Component * getParentComponent() const noexcept
Returns the component which this component is inside.
void exitModalState(int returnValue=0)
Ends a component's modal state.
void setFocusContainerType(FocusContainerType containerType) noexcept
Sets whether this component is a container for components that can have their focus traversed,...
int getHeight() const noexcept
Returns the component's height in pixels.
int getX() const noexcept
Returns the x coordinate of the component's left edge.
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.
FocusChangeType
Enumeration used by the focusGained() and focusLost() methods.
@ focusChangedByTabKey
Means that the user pressed the tab key to move the focus.
bool hasKeyboardFocus(bool trueIfChildIsFocused) const
Returns true if this component currently has the keyboard focus.
bool isCurrentlyBlockedByAnotherModalComponent() const
Checks whether there's a modal component somewhere that's stopping this one from receiving messages.
void repaint()
Marks the whole component as needing to be redrawn.
@ none
The component will not act as a focus container.
@ keyboardFocusContainer
The component will act as a top-level component within which keyboard focus is passed around.
int getY() const noexcept
Returns the y coordinate of the top of this component.
void setBounds(int x, int y, int width, int height)
Changes the component's position and size.
void setColour(int colourID, Colour newColour)
Registers a colour to be used for a particular purpose.
void enterModalState(bool takeKeyboardFocus=true, ModalComponentManager::Callback *callback=nullptr, bool deleteWhenDismissed=false)
Puts the component into a modal state.
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Sets a flag to indicate whether this component wants keyboard focus or not.
int getWidth() const noexcept
Returns the component's width in pixels.
bool isEnabled() const noexcept
Returns true if the component (and all its parents) are enabled.
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.
Component * findKeyboardFocusContainer() const
Returns the keyboard focus container for this component.
virtual void setVisible(bool shouldBeVisible)
Makes the component visible or invisible.
void invalidateAccessibilityHandler()
Invalidates the AccessibilityHandler that is currently being used for this component.
String getName() const noexcept
Returns the name of this component.
Represents a particular font, including its size, style, etc.
Definition juce_Font.h:42
A graphics context, used for drawing a component or image.
Represents a type of justification to be used when positioning graphical items.
Controls the order in which keyboard focus moves between components.
Component * getPreviousComponent(Component *current) override
Returns the component that should be given keyboard focus after the specified one when moving "backwa...
std::vector< Component * > getAllComponents(Component *parentComponent) override
Returns all of the components that can receive keyboard focus within the given parent component in tr...
Component * getNextComponent(Component *current) override
Returns the component that should be given keyboard focus after the specified one when moving "forwar...
Component * getDefaultComponent(Component *parentComponent) override
Returns the component that should receive keyboard focus by default within the given parent component...
AccessibleState getCurrentState() const override
Returns the current state of the UI element.
String getTitle() const override
The title of the UI element.
String getHelp() const override
Some help text for the UI element (if required).
Component * getNextComponent(Component *c) override
Returns the component that should be given keyboard focus after the specified one when moving "forwar...
Component * getPreviousComponent(Component *c) override
Returns the component that should be given keyboard focus after the specified one when moving "backwa...
Component * getDefaultComponent(Component *parent) override
Returns the component that should receive keyboard focus by default within the given parent component...
std::vector< Component * > getAllComponents(Component *parent) override
Returns all of the components that can receive keyboard focus within the given parent component in tr...
A class for receiving events from a Label.
Definition juce_Label.h:183
A component that displays a text string, and can optionally become a text editor when clicked.
Definition juce_Label.h:41
~Label() override
Destructor.
virtual void editorShown(TextEditor *)
Called when the text editor has just appeared, due to a user click or other focus change.
virtual TextEditor * createEditorComponent()
Creates the TextEditor component that will be used when the user has clicked on the label.
virtual void textWasEdited()
Called after the user changes the text.
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Override this method to return a custom AccessibilityHandler for this component.
void setEditable(bool editOnSingleClick, bool editOnDoubleClick=false, bool lossOfFocusDiscardsChanges=false)
Makes the label turn into a TextEditor when clicked.
void attachToComponent(Component *owner, bool onLeft)
Makes this label "stick to" another component.
Component * getAttachedComponent() const
If this label has been attached to another component using attachToComponent, this returns the other ...
std::function< void()> onTextChange
You can assign a lambda to this callback object to have it called when the label text is changed.
Definition juce_Label.h:206
void componentMovedOrResized(Component &, bool wasMoved, bool wasResized) override
Called when the component's position or size changes.
@ outlineWhenEditingColourId
An optional border colour when the label is being edited.
Definition juce_Label.h:112
@ textWhenEditingColourId
The colour for the text when the label is being edited.
Definition juce_Label.h:111
@ backgroundWhenEditingColourId
The background colour when the label is being edited.
Definition juce_Label.h:110
virtual void editorAboutToBeHidden(TextEditor *)
Called when the text editor is going to be deleted, after editing has finished.
void resized() override
Called when this component's size has been changed.
void setFont(const Font &newFont)
Changes the font to use to draw the text.
void hideEditor(bool discardCurrentEditorContents)
Hides the editor if it was being shown.
void valueChanged(Value &) override
Called when a Value object is changed.
void textEditorEscapeKeyPressed(TextEditor &) override
Called when the user presses the escape key.
bool isBeingEdited() const noexcept
Returns true if the editor is currently focused and active.
void showEditor()
Makes the editor appear as if the label had been clicked by the user.
void componentParentHierarchyChanged(Component &) override
Called to indicate that the component's parents have changed.
std::function< void()> onEditorShow
You can assign a lambda to this callback object to have it called when the label's editor is shown.
Definition juce_Label.h:209
Label(const String &componentName=String(), const String &labelText=String())
Creates a Label.
void mouseUp(const MouseEvent &) override
Called when a mouse button is released.
void textEditorReturnKeyPressed(TextEditor &) override
Called when the user presses the return key.
std::function< void()> onEditorHide
You can assign a lambda to this callback object to have it called when the label's editor is hidden.
Definition juce_Label.h:212
String getText(bool returnActiveEditorContents=false) const
Returns the label's current text.
std::unique_ptr< ComponentTraverser > createKeyboardFocusTraverser() override
Creates a ComponentTraverser object to use to determine the logic by which keyboard focus should be p...
void addListener(Listener *listener)
Registers a listener that will be called when the label's text changes.
void textEditorTextChanged(TextEditor &) override
Called when the user changes the text in some way.
void textEditorFocusLost(TextEditor &) override
Called when the text editor loses focus.
void setMinimumHorizontalScale(float newScale)
Specifies the minimum amount that the font can be squashed horizontally before it starts using ellips...
void removeListener(Listener *listener)
Deregisters a previously-registered listener.
Font getFont() const noexcept
Returns the font currently being used.
void mouseDoubleClick(const MouseEvent &) override
Called when a mouse button has been double-clicked on a component.
void componentVisibilityChanged(Component &) override
Called when the component is made visible or invisible.
void setJustificationType(Justification justification)
Sets the style of justification to be used for positioning the text.
virtual void textWasChanged()
Called when the text has been altered.
TextEditor * getCurrentTextEditor() const noexcept
Returns the currently-visible text editor, or nullptr if none is open.
void setBorderSize(BorderSize< int > newBorderSize)
Changes the border that is left between the edge of the component and the text.
void enablementChanged() override
Callback to indicate that this component has been enabled or disabled.
void colourChanged() override
This method is called when a colour is changed by the setColour() method, or when the look-and-feel i...
void focusGained(FocusChangeType) override
Called to indicate that this component has just acquired the keyboard focus.
void setText(const String &newText, NotificationType notification)
Changes the label text.
void inputAttemptWhenModal() override
Called when the user tries to click on a component that is blocked by another modal component.
void paint(Graphics &) override
Components can override this method to draw their content.
bool isPopupMenu() const noexcept
Checks whether the user is trying to launch a pop-up menu.
Contains position and status information about a mouse event.
const ModifierKeys mods
The key modifiers associated with the event.
Point< int > getPosition() const noexcept
The position of the mouse when the event occurred.
bool mouseWasDraggedSinceMouseDown() const noexcept
Returns true if the user seems to be performing a drag gesture.
A general-purpose range object, that simply represents any linear range with a start and end point.
Definition juce_Range.h:40
String getTooltip() override
Returns the tooltip assigned to this object.
The JUCE String class!
Definition juce_String.h:53
int length() const noexcept
Returns the number of characters in the string.
An editable text box.
@ backgroundColourId
The colour to use for the text component's background - this can be transparent if necessary.
@ textColourId
The colour that will be used when text is added to the editor.
@ outlineColourId
If this is non-transparent, it will be used to draw a box around the edge of the component.
@ focusedOutlineColourId
If this is non-transparent, it will be used to draw a box around the edge of the component when it ha...
String getText() const
Returns the entire contents of the editor.
void applyFontToAllText(const Font &newFont, bool changeCurrentFont=true)
Applies a font to all the text in the editor.
Represents a shared variant value.
Definition juce_Value.h:51
void addListener(Listener *listener)
Adds a listener to receive callbacks when the value changes.
void removeListener(Listener *listener)
Removes a listener that was previously added with addListener().
String toString() const
Returns the value as a string.
This class acts as a pointer which will automatically become null if the object to which it points is...
#define jassert(expression)
Platform-independent assertion macro.
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
This is a shorthand way of writing both a JUCE_DECLARE_NON_COPYABLE and JUCE_LEAK_DETECTOR macro for ...
JUCE Namespace.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
NotificationType
These enums are used in various classes to indicate whether a notification event should be sent out.
@ sendNotification
Requests a notification message, either synchronous or not.
@ dontSendNotification
No notification message should be sent.
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
@ press
Represents a "press" action.
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.
T swap(T... args)