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.

juce_Label.h 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. //==============================================================================
  21. /**
  22. A component that displays a text string, and can optionally become a text
  23. editor when clicked.
  24. @tags{GUI}
  25. */
  26. class JUCE_API Label : public Component,
  27. public SettableTooltipClient,
  28. protected TextEditor::Listener,
  29. private ComponentListener,
  30. private Value::Listener
  31. {
  32. public:
  33. //==============================================================================
  34. /** Creates a Label.
  35. @param componentName the name to give the component
  36. @param labelText the text to show in the label
  37. */
  38. Label (const String& componentName = String(),
  39. const String& labelText = String());
  40. /** Destructor. */
  41. ~Label() override;
  42. //==============================================================================
  43. /** Changes the label text.
  44. The NotificationType parameter indicates whether to send a change message to
  45. any Label::Listener objects if the new text is different.
  46. */
  47. void setText (const String& newText,
  48. NotificationType notification);
  49. /** Returns the label's current text.
  50. @param returnActiveEditorContents if this is true and the label is currently
  51. being edited, then this method will return the
  52. text as it's being shown in the editor. If false,
  53. then the value returned here won't be updated until
  54. the user has finished typing and pressed the return
  55. key.
  56. */
  57. String getText (bool returnActiveEditorContents = false) const;
  58. /** Returns the text content as a Value object.
  59. You can call Value::referTo() on this object to make the label read and control
  60. a Value object that you supply.
  61. */
  62. Value& getTextValue() noexcept { return textValue; }
  63. //==============================================================================
  64. /** Changes the font to use to draw the text.
  65. @see getFont
  66. */
  67. void setFont (const Font& newFont);
  68. /** Returns the font currently being used.
  69. This may be the one set by setFont(), unless it has been overridden by the current LookAndFeel
  70. @see setFont
  71. */
  72. Font getFont() const noexcept;
  73. //==============================================================================
  74. /** A set of colour IDs to use to change the colour of various aspects of the label.
  75. These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
  76. methods.
  77. Note that you can also use the constants from TextEditor::ColourIds to change the
  78. colour of the text editor that is opened when a label is editable.
  79. @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
  80. */
  81. enum ColourIds
  82. {
  83. backgroundColourId = 0x1000280, /**< The background colour to fill the label with. */
  84. textColourId = 0x1000281, /**< The colour for the text. */
  85. outlineColourId = 0x1000282, /**< An optional colour to use to draw a border around the label.
  86. Leave this transparent to not have an outline. */
  87. backgroundWhenEditingColourId = 0x1000283, /**< The background colour when the label is being edited. */
  88. textWhenEditingColourId = 0x1000284, /**< The colour for the text when the label is being edited. */
  89. outlineWhenEditingColourId = 0x1000285 /**< An optional border colour when the label is being edited. */
  90. };
  91. //==============================================================================
  92. /** Sets the style of justification to be used for positioning the text.
  93. (The default is Justification::centredLeft)
  94. */
  95. void setJustificationType (Justification justification);
  96. /** Returns the type of justification, as set in setJustificationType(). */
  97. Justification getJustificationType() const noexcept { return justification; }
  98. /** Changes the border that is left between the edge of the component and the text.
  99. By default there's a small gap left at the sides of the component to allow for
  100. the drawing of the border, but you can change this if necessary.
  101. */
  102. void setBorderSize (BorderSize<int> newBorderSize);
  103. /** Returns the size of the border to be left around the text. */
  104. BorderSize<int> getBorderSize() const noexcept { return border; }
  105. /** Makes this label "stick to" another component.
  106. This will cause the label to follow another component around, staying
  107. either to its left or above it.
  108. @param owner the component to follow
  109. @param onLeft if true, the label will stay on the left of its component; if
  110. false, it will stay above it.
  111. */
  112. void attachToComponent (Component* owner, bool onLeft);
  113. /** If this label has been attached to another component using attachToComponent, this
  114. returns the other component.
  115. Returns nullptr if the label is not attached.
  116. */
  117. Component* getAttachedComponent() const;
  118. /** If the label is attached to the left of another component, this returns true.
  119. Returns false if the label is above the other component. This is only relevant if
  120. attachToComponent() has been called.
  121. */
  122. bool isAttachedOnLeft() const noexcept { return leftOfOwnerComp; }
  123. /** Specifies the minimum amount that the font can be squashed horizontally before it starts
  124. using ellipsis. Use a value of 0 for a default value.
  125. @see Graphics::drawFittedText
  126. */
  127. void setMinimumHorizontalScale (float newScale);
  128. /** Specifies the amount that the font can be squashed horizontally. */
  129. float getMinimumHorizontalScale() const noexcept { return minimumHorizontalScale; }
  130. /** Set a keyboard type for use when the text editor is shown. */
  131. void setKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept { keyboardType = type; }
  132. //==============================================================================
  133. /**
  134. A class for receiving events from a Label.
  135. You can register a Label::Listener with a Label using the Label::addListener()
  136. method, and it will be called when the text of the label changes, either because
  137. of a call to Label::setText() or by the user editing the text (if the label is
  138. editable).
  139. @see Label::addListener, Label::removeListener
  140. */
  141. class JUCE_API Listener
  142. {
  143. public:
  144. /** Destructor. */
  145. virtual ~Listener() = default;
  146. /** Called when a Label's text has changed. */
  147. virtual void labelTextChanged (Label* labelThatHasChanged) = 0;
  148. /** Called when a Label goes into editing mode and displays a TextEditor. */
  149. virtual void editorShown (Label*, TextEditor&) {}
  150. /** Called when a Label is about to delete its TextEditor and exit editing mode. */
  151. virtual void editorHidden (Label*, TextEditor&) {}
  152. };
  153. /** Registers a listener that will be called when the label's text changes. */
  154. void addListener (Listener* listener);
  155. /** Deregisters a previously-registered listener. */
  156. void removeListener (Listener* listener);
  157. //==============================================================================
  158. /** You can assign a lambda to this callback object to have it called when the label text is changed. */
  159. std::function<void()> onTextChange;
  160. /** You can assign a lambda to this callback object to have it called when the label's editor is shown. */
  161. std::function<void()> onEditorShow;
  162. /** You can assign a lambda to this callback object to have it called when the label's editor is hidden. */
  163. std::function<void()> onEditorHide;
  164. //==============================================================================
  165. /** Makes the label turn into a TextEditor when clicked.
  166. By default this is turned off.
  167. If turned on, then single- or double-clicking will turn the label into
  168. an editor. If the user then changes the text, then the ChangeBroadcaster
  169. base class will be used to send change messages to any listeners that
  170. have registered.
  171. If the user changes the text, the textWasEdited() method will be called
  172. afterwards, and subclasses can override this if they need to do anything
  173. special.
  174. @param editOnSingleClick if true, just clicking once on the label will start editing the text
  175. @param editOnDoubleClick if true, a double-click is needed to start editing
  176. @param lossOfFocusDiscardsChanges if true, clicking somewhere else while the text is being
  177. edited will discard any changes; if false, then this will
  178. commit the changes.
  179. @see showEditor, setEditorColours, TextEditor
  180. */
  181. void setEditable (bool editOnSingleClick,
  182. bool editOnDoubleClick = false,
  183. bool lossOfFocusDiscardsChanges = false);
  184. /** Returns true if this option was set using setEditable(). */
  185. bool isEditableOnSingleClick() const noexcept { return editSingleClick; }
  186. /** Returns true if this option was set using setEditable(). */
  187. bool isEditableOnDoubleClick() const noexcept { return editDoubleClick; }
  188. /** Returns true if this option has been set in a call to setEditable(). */
  189. bool doesLossOfFocusDiscardChanges() const noexcept { return lossOfFocusDiscardsChanges; }
  190. /** Returns true if the user can edit this label's text. */
  191. bool isEditable() const noexcept { return editSingleClick || editDoubleClick; }
  192. /** Makes the editor appear as if the label had been clicked by the user.
  193. @see textWasEdited, setEditable
  194. */
  195. void showEditor();
  196. /** Hides the editor if it was being shown.
  197. @param discardCurrentEditorContents if true, the label's text will be
  198. reset to whatever it was before the editor
  199. was shown; if false, the current contents of the
  200. editor will be used to set the label's text
  201. before it is hidden.
  202. */
  203. void hideEditor (bool discardCurrentEditorContents);
  204. /** Returns true if the editor is currently focused and active. */
  205. bool isBeingEdited() const noexcept;
  206. /** Returns the currently-visible text editor, or nullptr if none is open. */
  207. TextEditor* getCurrentTextEditor() const noexcept;
  208. //==============================================================================
  209. /** This abstract base class is implemented by LookAndFeel classes to provide
  210. label drawing functionality.
  211. */
  212. struct JUCE_API LookAndFeelMethods
  213. {
  214. virtual ~LookAndFeelMethods() = default;
  215. virtual void drawLabel (Graphics&, Label&) = 0;
  216. virtual Font getLabelFont (Label&) = 0;
  217. virtual BorderSize<int> getLabelBorderSize (Label&) = 0;
  218. };
  219. protected:
  220. //==============================================================================
  221. /** Creates the TextEditor component that will be used when the user has clicked on the label.
  222. Subclasses can override this if they need to customise this component in some way.
  223. */
  224. virtual TextEditor* createEditorComponent();
  225. /** Called after the user changes the text. */
  226. virtual void textWasEdited();
  227. /** Called when the text has been altered. */
  228. virtual void textWasChanged();
  229. /** Called when the text editor has just appeared, due to a user click or other focus change. */
  230. virtual void editorShown (TextEditor*);
  231. /** Called when the text editor is going to be deleted, after editing has finished. */
  232. virtual void editorAboutToBeHidden (TextEditor*);
  233. //==============================================================================
  234. /** @internal */
  235. void paint (Graphics&) override;
  236. /** @internal */
  237. void resized() override;
  238. /** @internal */
  239. void mouseUp (const MouseEvent&) override;
  240. /** @internal */
  241. void mouseDoubleClick (const MouseEvent&) override;
  242. /** @internal */
  243. void componentMovedOrResized (Component&, bool wasMoved, bool wasResized) override;
  244. /** @internal */
  245. void componentParentHierarchyChanged (Component&) override;
  246. /** @internal */
  247. void componentVisibilityChanged (Component&) override;
  248. /** @internal */
  249. void inputAttemptWhenModal() override;
  250. /** @internal */
  251. void focusGained (FocusChangeType) override;
  252. /** @internal */
  253. void enablementChanged() override;
  254. /** @internal */
  255. KeyboardFocusTraverser* createFocusTraverser() override;
  256. /** @internal */
  257. void textEditorTextChanged (TextEditor&) override;
  258. /** @internal */
  259. void textEditorReturnKeyPressed (TextEditor&) override;
  260. /** @internal */
  261. void textEditorEscapeKeyPressed (TextEditor&) override;
  262. /** @internal */
  263. void textEditorFocusLost (TextEditor&) override;
  264. /** @internal */
  265. void colourChanged() override;
  266. /** @internal */
  267. void valueChanged (Value&) override;
  268. /** @internal */
  269. void callChangeListeners();
  270. private:
  271. //==============================================================================
  272. Value textValue;
  273. String lastTextValue;
  274. Font font { 15.0f };
  275. Justification justification = Justification::centredLeft;
  276. std::unique_ptr<TextEditor> editor;
  277. ListenerList<Listener> listeners;
  278. WeakReference<Component> ownerComponent;
  279. BorderSize<int> border { 1, 5, 1, 5 };
  280. float minimumHorizontalScale = 0;
  281. TextInputTarget::VirtualKeyboardType keyboardType = TextInputTarget::textKeyboard;
  282. bool editSingleClick = false;
  283. bool editDoubleClick = false;
  284. bool lossOfFocusDiscardsChanges = false;
  285. bool leftOfOwnerComp = false;
  286. bool updateFromTextEditorContents (TextEditor&);
  287. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Label)
  288. };
  289. } // namespace juce