The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

255 lines
7.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  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 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace juce
  20. {
  21. //==============================================================================
  22. class TextPropertyComponent::LabelComp : public Label,
  23. public FileDragAndDropTarget
  24. {
  25. public:
  26. LabelComp (TextPropertyComponent& tpc, int charLimit, bool multiline, bool editable)
  27. : Label ({}, {}),
  28. owner (tpc),
  29. maxChars (charLimit),
  30. isMultiline (multiline)
  31. {
  32. setEditable (editable, editable);
  33. updateColours();
  34. }
  35. bool isInterestedInFileDrag (const StringArray&) override
  36. {
  37. return interestedInFileDrag;
  38. }
  39. void filesDropped (const StringArray& files, int, int) override
  40. {
  41. setText (getText() + files.joinIntoString (isMultiline ? "\n" : ", "), sendNotificationSync);
  42. showEditor();
  43. }
  44. TextEditor* createEditorComponent() override
  45. {
  46. auto* ed = Label::createEditorComponent();
  47. ed->setInputRestrictions (maxChars);
  48. if (isMultiline)
  49. {
  50. ed->setMultiLine (true, true);
  51. ed->setReturnKeyStartsNewLine (true);
  52. }
  53. return ed;
  54. }
  55. void textWasEdited() override
  56. {
  57. owner.textWasEdited();
  58. }
  59. void updateColours()
  60. {
  61. setColour (backgroundColourId, owner.findColour (TextPropertyComponent::backgroundColourId));
  62. setColour (outlineColourId, owner.findColour (TextPropertyComponent::outlineColourId));
  63. setColour (textColourId, owner.findColour (TextPropertyComponent::textColourId));
  64. repaint();
  65. }
  66. void setInterestedInFileDrag (bool isInterested)
  67. {
  68. interestedInFileDrag = isInterested;
  69. }
  70. void setTextToDisplayWhenEmpty (const String& text, float alpha)
  71. {
  72. textToDisplayWhenEmpty = text;
  73. alphaToUseForEmptyText = alpha;
  74. }
  75. void paintOverChildren (Graphics& g) override
  76. {
  77. if (getText().isEmpty() && ! isBeingEdited())
  78. {
  79. auto textArea = getBorderSize().subtractedFrom (getLocalBounds());
  80. auto labelFont = owner.getLookAndFeel().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) (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 (const ValueWithDefault& vwd)
  101. : valueWithDefault (vwd)
  102. {
  103. }
  104. var getValue() const override
  105. {
  106. return valueWithDefault.isUsingDefault() ? var() : valueWithDefault.get();
  107. }
  108. void setValue (const var& newValue) override
  109. {
  110. if (newValue.toString().isEmpty())
  111. valueWithDefault.resetToDefault();
  112. else
  113. valueWithDefault = newValue;
  114. }
  115. private:
  116. ValueWithDefault valueWithDefault;
  117. //==============================================================================
  118. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSourceWithDefault)
  119. };
  120. //==============================================================================
  121. TextPropertyComponent::TextPropertyComponent (const String& name,
  122. int maxNumChars,
  123. bool isMultiLine,
  124. bool isEditable)
  125. : PropertyComponent (name)
  126. {
  127. createEditor (maxNumChars, isMultiLine, isEditable);
  128. }
  129. TextPropertyComponent::TextPropertyComponent (const Value& valueToControl,
  130. const String& name,
  131. int maxNumChars,
  132. bool isMultiLine,
  133. bool isEditable)
  134. : TextPropertyComponent (name, maxNumChars, isMultiLine, isEditable)
  135. {
  136. textEditor->getTextValue().referTo (valueToControl);
  137. }
  138. TextPropertyComponent::TextPropertyComponent (const ValueWithDefault& valueToControl,
  139. const String& name,
  140. int maxNumChars,
  141. bool isMultiLine,
  142. bool isEditable)
  143. : TextPropertyComponent (name, maxNumChars, isMultiLine, isEditable)
  144. {
  145. textEditor->getTextValue().referTo (Value (new RemapperValueSourceWithDefault (valueToControl)));
  146. textEditor->setTextToDisplayWhenEmpty (valueToControl.getDefault(), 0.5f);
  147. }
  148. TextPropertyComponent::~TextPropertyComponent()
  149. {
  150. }
  151. void TextPropertyComponent::setText (const String& newText)
  152. {
  153. textEditor->setText (newText, sendNotificationSync);
  154. }
  155. String TextPropertyComponent::getText() const
  156. {
  157. return textEditor->getText();
  158. }
  159. Value& TextPropertyComponent::getValue() const
  160. {
  161. return textEditor->getTextValue();
  162. }
  163. void TextPropertyComponent::createEditor (int maxNumChars, bool isMultiLine, bool isEditable)
  164. {
  165. addAndMakeVisible (textEditor = new LabelComp (*this, maxNumChars, isMultiLine, isEditable));
  166. if (isMultiLine)
  167. {
  168. textEditor->setJustificationType (Justification::topLeft);
  169. preferredHeight = 100;
  170. }
  171. }
  172. void TextPropertyComponent::refresh()
  173. {
  174. textEditor->setText (getText(), dontSendNotification);
  175. }
  176. void TextPropertyComponent::textWasEdited()
  177. {
  178. auto newText = textEditor->getText();
  179. if (getText() != newText)
  180. setText (newText);
  181. callListeners();
  182. }
  183. void TextPropertyComponent::addListener (TextPropertyComponent::Listener* l) { listenerList.add (l); }
  184. void TextPropertyComponent::removeListener (TextPropertyComponent::Listener* l) { listenerList.remove (l); }
  185. void TextPropertyComponent::callListeners()
  186. {
  187. Component::BailOutChecker checker (this);
  188. listenerList.callChecked (checker, [this] (Listener& l) { l.textPropertyComponentChanged (this); });
  189. }
  190. void TextPropertyComponent::colourChanged()
  191. {
  192. PropertyComponent::colourChanged();
  193. textEditor->updateColours();
  194. }
  195. void TextPropertyComponent::setInterestedInFileDrag (bool isInterested)
  196. {
  197. if (textEditor != nullptr)
  198. textEditor->setInterestedInFileDrag (isInterested);
  199. }
  200. void TextPropertyComponent::setEditable (bool isEditable)
  201. {
  202. if (textEditor != nullptr)
  203. textEditor->setEditable (isEditable, isEditable);
  204. }
  205. } // namespace juce