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_TextPropertyComponent.cpp 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. class TextPropertyComponent::LabelComp : public Label,
  22. public FileDragAndDropTarget
  23. {
  24. public:
  25. LabelComp (TextPropertyComponent& tpc, int charLimit, bool multiline, bool editable)
  26. : Label ({}, {}),
  27. owner (tpc),
  28. maxChars (charLimit),
  29. isMultiline (multiline)
  30. {
  31. setEditable (editable, editable);
  32. updateColours();
  33. }
  34. bool isInterestedInFileDrag (const StringArray&) override
  35. {
  36. return interestedInFileDrag;
  37. }
  38. void filesDropped (const StringArray& files, int, int) override
  39. {
  40. setText (getText() + files.joinIntoString (isMultiline ? "\n" : ", "), sendNotificationSync);
  41. showEditor();
  42. }
  43. TextEditor* createEditorComponent() override
  44. {
  45. auto* ed = Label::createEditorComponent();
  46. ed->setInputRestrictions (maxChars);
  47. if (isMultiline)
  48. {
  49. ed->setMultiLine (true, true);
  50. ed->setReturnKeyStartsNewLine (true);
  51. }
  52. return ed;
  53. }
  54. void textWasEdited() override
  55. {
  56. owner.textWasEdited();
  57. }
  58. void updateColours()
  59. {
  60. setColour (backgroundColourId, owner.findColour (TextPropertyComponent::backgroundColourId));
  61. setColour (outlineColourId, owner.findColour (TextPropertyComponent::outlineColourId));
  62. setColour (textColourId, owner.findColour (TextPropertyComponent::textColourId));
  63. repaint();
  64. }
  65. void setInterestedInFileDrag (bool isInterested)
  66. {
  67. interestedInFileDrag = isInterested;
  68. }
  69. void setTextToDisplayWhenEmpty (const String& text, float alpha)
  70. {
  71. textToDisplayWhenEmpty = text;
  72. alphaToUseForEmptyText = alpha;
  73. }
  74. void paintOverChildren (Graphics& g) override
  75. {
  76. if (getText().isEmpty() && ! isBeingEdited())
  77. {
  78. auto& lf = owner.getLookAndFeel();
  79. auto textArea = lf.getLabelBorderSize (*this).subtractedFrom (getLocalBounds());
  80. auto labelFont = lf.getLabelFont (*this);
  81. g.setColour (owner.findColour (TextPropertyComponent::textColourId).withAlpha (alphaToUseForEmptyText));
  82. g.setFont (labelFont);
  83. g.drawFittedText (textToDisplayWhenEmpty, textArea, getJustificationType(),
  84. jmax (1, (int) ((float) textArea.getHeight() / labelFont.getHeight())),
  85. getMinimumHorizontalScale());
  86. }
  87. }
  88. private:
  89. TextPropertyComponent& owner;
  90. int maxChars;
  91. bool isMultiline;
  92. bool interestedInFileDrag = true;
  93. String textToDisplayWhenEmpty;
  94. float alphaToUseForEmptyText = 0.0f;
  95. };
  96. //==============================================================================
  97. class TextPropertyComponent::RemapperValueSourceWithDefault : public Value::ValueSource
  98. {
  99. public:
  100. RemapperValueSourceWithDefault (ValueWithDefault* vwd)
  101. : valueWithDefault (vwd)
  102. {
  103. }
  104. var getValue() const override
  105. {
  106. if (valueWithDefault == nullptr || valueWithDefault->isUsingDefault())
  107. return {};
  108. return valueWithDefault->get();
  109. }
  110. void setValue (const var& newValue) override
  111. {
  112. if (valueWithDefault == nullptr)
  113. return;
  114. if (newValue.toString().isEmpty())
  115. valueWithDefault->resetToDefault();
  116. else
  117. *valueWithDefault = newValue;
  118. }
  119. private:
  120. WeakReference<ValueWithDefault> valueWithDefault;
  121. //==============================================================================
  122. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSourceWithDefault)
  123. };
  124. //==============================================================================
  125. TextPropertyComponent::TextPropertyComponent (const String& name,
  126. int maxNumChars,
  127. bool multiLine,
  128. bool isEditable)
  129. : PropertyComponent (name),
  130. isMultiLine (multiLine)
  131. {
  132. createEditor (maxNumChars, isEditable);
  133. }
  134. TextPropertyComponent::TextPropertyComponent (const Value& valueToControl, const String& name,
  135. int maxNumChars, bool multiLine, bool isEditable)
  136. : TextPropertyComponent (name, maxNumChars, multiLine, isEditable)
  137. {
  138. textEditor->getTextValue().referTo (valueToControl);
  139. }
  140. TextPropertyComponent::TextPropertyComponent (ValueWithDefault& valueToControl, const String& name,
  141. int maxNumChars, bool multiLine, bool isEditable)
  142. : TextPropertyComponent (name, maxNumChars, multiLine, isEditable)
  143. {
  144. valueWithDefault = &valueToControl;
  145. textEditor->getTextValue().referTo (Value (new RemapperValueSourceWithDefault (valueWithDefault)));
  146. textEditor->setTextToDisplayWhenEmpty (valueWithDefault->getDefault(), 0.5f);
  147. valueWithDefault->onDefaultChange = [this]
  148. {
  149. textEditor->setTextToDisplayWhenEmpty (valueWithDefault->getDefault(), 0.5f);
  150. repaint();
  151. };
  152. }
  153. TextPropertyComponent::~TextPropertyComponent()
  154. {
  155. if (valueWithDefault != nullptr)
  156. valueWithDefault->onDefaultChange = nullptr;
  157. }
  158. void TextPropertyComponent::setText (const String& newText)
  159. {
  160. textEditor->setText (newText, sendNotificationSync);
  161. }
  162. String TextPropertyComponent::getText() const
  163. {
  164. return textEditor->getText();
  165. }
  166. Value& TextPropertyComponent::getValue() const
  167. {
  168. return textEditor->getTextValue();
  169. }
  170. void TextPropertyComponent::createEditor (int maxNumChars, bool isEditable)
  171. {
  172. textEditor.reset (new LabelComp (*this, maxNumChars, isMultiLine, isEditable));
  173. addAndMakeVisible (textEditor.get());
  174. if (isMultiLine)
  175. {
  176. textEditor->setJustificationType (Justification::topLeft);
  177. preferredHeight = 100;
  178. }
  179. }
  180. void TextPropertyComponent::refresh()
  181. {
  182. textEditor->setText (getText(), dontSendNotification);
  183. }
  184. void TextPropertyComponent::textWasEdited()
  185. {
  186. auto newText = textEditor->getText();
  187. if (getText() != newText)
  188. setText (newText);
  189. callListeners();
  190. }
  191. void TextPropertyComponent::addListener (TextPropertyComponent::Listener* l) { listenerList.add (l); }
  192. void TextPropertyComponent::removeListener (TextPropertyComponent::Listener* l) { listenerList.remove (l); }
  193. void TextPropertyComponent::callListeners()
  194. {
  195. Component::BailOutChecker checker (this);
  196. listenerList.callChecked (checker, [this] (Listener& l) { l.textPropertyComponentChanged (this); });
  197. }
  198. void TextPropertyComponent::colourChanged()
  199. {
  200. PropertyComponent::colourChanged();
  201. textEditor->updateColours();
  202. }
  203. void TextPropertyComponent::setInterestedInFileDrag (bool isInterested)
  204. {
  205. if (textEditor != nullptr)
  206. textEditor->setInterestedInFileDrag (isInterested);
  207. }
  208. void TextPropertyComponent::setEditable (bool isEditable)
  209. {
  210. if (textEditor != nullptr)
  211. textEditor->setEditable (isEditable, isEditable);
  212. }
  213. } // namespace juce