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.

335 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. DrawableText::DrawableText()
  18. : colour (Colours::black),
  19. justification (Justification::centredLeft)
  20. {
  21. setBoundingBox (RelativeParallelogram (RelativePoint (0.0f, 0.0f),
  22. RelativePoint (50.0f, 0.0f),
  23. RelativePoint (0.0f, 20.0f)));
  24. setFont (Font (15.0f), true);
  25. }
  26. DrawableText::DrawableText (const DrawableText& other)
  27. : Drawable (other),
  28. bounds (other.bounds),
  29. fontHeight (other.fontHeight),
  30. fontHScale (other.fontHScale),
  31. font (other.font),
  32. text (other.text),
  33. colour (other.colour),
  34. justification (other.justification)
  35. {
  36. refreshBounds();
  37. }
  38. DrawableText::~DrawableText()
  39. {
  40. }
  41. //==============================================================================
  42. void DrawableText::setText (const String& newText)
  43. {
  44. if (text != newText)
  45. {
  46. text = newText;
  47. refreshBounds();
  48. }
  49. }
  50. void DrawableText::setColour (Colour newColour)
  51. {
  52. if (colour != newColour)
  53. {
  54. colour = newColour;
  55. repaint();
  56. }
  57. }
  58. void DrawableText::setFont (const Font& newFont, bool applySizeAndScale)
  59. {
  60. if (font != newFont)
  61. {
  62. font = newFont;
  63. if (applySizeAndScale)
  64. {
  65. fontHeight = font.getHeight();
  66. fontHScale = font.getHorizontalScale();
  67. }
  68. refreshBounds();
  69. }
  70. }
  71. void DrawableText::setJustification (Justification newJustification)
  72. {
  73. justification = newJustification;
  74. repaint();
  75. }
  76. void DrawableText::setBoundingBox (const RelativeParallelogram& newBounds)
  77. {
  78. if (bounds != newBounds)
  79. {
  80. bounds = newBounds;
  81. refreshBounds();
  82. }
  83. }
  84. void DrawableText::setFontHeight (const RelativeCoordinate& newHeight)
  85. {
  86. if (fontHeight != newHeight)
  87. {
  88. fontHeight = newHeight;
  89. refreshBounds();
  90. }
  91. }
  92. void DrawableText::setFontHorizontalScale (const RelativeCoordinate& newScale)
  93. {
  94. if (fontHScale != newScale)
  95. {
  96. fontHScale = newScale;
  97. refreshBounds();
  98. }
  99. }
  100. void DrawableText::refreshBounds()
  101. {
  102. if (bounds.isDynamic() || fontHeight.isDynamic() || fontHScale.isDynamic())
  103. {
  104. Drawable::Positioner<DrawableText>* const p = new Drawable::Positioner<DrawableText> (*this);
  105. setPositioner (p);
  106. p->apply();
  107. }
  108. else
  109. {
  110. setPositioner (0);
  111. recalculateCoordinates (0);
  112. }
  113. }
  114. bool DrawableText::registerCoordinates (RelativeCoordinatePositionerBase& pos)
  115. {
  116. bool ok = pos.addPoint (bounds.topLeft);
  117. ok = pos.addPoint (bounds.topRight) && ok;
  118. ok = pos.addPoint (bounds.bottomLeft) && ok;
  119. ok = pos.addCoordinate (fontHeight) && ok;
  120. return pos.addCoordinate (fontHScale) && ok;
  121. }
  122. void DrawableText::recalculateCoordinates (Expression::Scope* scope)
  123. {
  124. bounds.resolveThreePoints (resolvedPoints, scope);
  125. const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
  126. const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
  127. const float height = jlimit (0.01f, jmax (0.01f, h), (float) fontHeight.resolve (scope));
  128. const float hscale = jlimit (0.01f, jmax (0.01f, w), (float) fontHScale.resolve (scope));
  129. scaledFont = font;
  130. scaledFont.setHeight (height);
  131. scaledFont.setHorizontalScale (hscale);
  132. setBoundsToEnclose (getDrawableBounds());
  133. repaint();
  134. }
  135. //==============================================================================
  136. void DrawableText::paint (Graphics& g)
  137. {
  138. transformContextToCorrectOrigin (g);
  139. const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
  140. const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
  141. g.addTransform (AffineTransform::fromTargetPoints (0, 0, resolvedPoints[0].x, resolvedPoints[0].y,
  142. w, 0, resolvedPoints[1].x, resolvedPoints[1].y,
  143. 0, h, resolvedPoints[2].x, resolvedPoints[2].y));
  144. g.setFont (scaledFont);
  145. g.setColour (colour);
  146. g.drawFittedText (text, Rectangle<float> (w, h).getSmallestIntegerContainer(), justification, 0x100000);
  147. }
  148. Rectangle<float> DrawableText::getDrawableBounds() const
  149. {
  150. return RelativeParallelogram::getBoundingBox (resolvedPoints);
  151. }
  152. Drawable* DrawableText::createCopy() const
  153. {
  154. return new DrawableText (*this);
  155. }
  156. //==============================================================================
  157. const Identifier DrawableText::valueTreeType ("Text");
  158. const Identifier DrawableText::ValueTreeWrapper::text ("text");
  159. const Identifier DrawableText::ValueTreeWrapper::colour ("colour");
  160. const Identifier DrawableText::ValueTreeWrapper::font ("font");
  161. const Identifier DrawableText::ValueTreeWrapper::justification ("justification");
  162. const Identifier DrawableText::ValueTreeWrapper::topLeft ("topLeft");
  163. const Identifier DrawableText::ValueTreeWrapper::topRight ("topRight");
  164. const Identifier DrawableText::ValueTreeWrapper::bottomLeft ("bottomLeft");
  165. const Identifier DrawableText::ValueTreeWrapper::fontHeight ("fontHeight");
  166. const Identifier DrawableText::ValueTreeWrapper::fontHScale ("fontHScale");
  167. //==============================================================================
  168. DrawableText::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
  169. : ValueTreeWrapperBase (state_)
  170. {
  171. jassert (state.hasType (valueTreeType));
  172. }
  173. String DrawableText::ValueTreeWrapper::getText() const
  174. {
  175. return state [text].toString();
  176. }
  177. void DrawableText::ValueTreeWrapper::setText (const String& newText, UndoManager* undoManager)
  178. {
  179. state.setProperty (text, newText, undoManager);
  180. }
  181. Value DrawableText::ValueTreeWrapper::getTextValue (UndoManager* undoManager)
  182. {
  183. return state.getPropertyAsValue (text, undoManager);
  184. }
  185. Colour DrawableText::ValueTreeWrapper::getColour() const
  186. {
  187. return Colour::fromString (state [colour].toString());
  188. }
  189. void DrawableText::ValueTreeWrapper::setColour (Colour newColour, UndoManager* undoManager)
  190. {
  191. state.setProperty (colour, newColour.toString(), undoManager);
  192. }
  193. Justification DrawableText::ValueTreeWrapper::getJustification() const
  194. {
  195. return Justification ((int) state [justification]);
  196. }
  197. void DrawableText::ValueTreeWrapper::setJustification (Justification newJustification, UndoManager* undoManager)
  198. {
  199. state.setProperty (justification, newJustification.getFlags(), undoManager);
  200. }
  201. Font DrawableText::ValueTreeWrapper::getFont() const
  202. {
  203. return Font::fromString (state [font]);
  204. }
  205. void DrawableText::ValueTreeWrapper::setFont (const Font& newFont, UndoManager* undoManager)
  206. {
  207. state.setProperty (font, newFont.toString(), undoManager);
  208. }
  209. Value DrawableText::ValueTreeWrapper::getFontValue (UndoManager* undoManager)
  210. {
  211. return state.getPropertyAsValue (font, undoManager);
  212. }
  213. RelativeParallelogram DrawableText::ValueTreeWrapper::getBoundingBox() const
  214. {
  215. return RelativeParallelogram (state [topLeft].toString(), state [topRight].toString(), state [bottomLeft].toString());
  216. }
  217. void DrawableText::ValueTreeWrapper::setBoundingBox (const RelativeParallelogram& newBounds, UndoManager* undoManager)
  218. {
  219. state.setProperty (topLeft, newBounds.topLeft.toString(), undoManager);
  220. state.setProperty (topRight, newBounds.topRight.toString(), undoManager);
  221. state.setProperty (bottomLeft, newBounds.bottomLeft.toString(), undoManager);
  222. }
  223. RelativeCoordinate DrawableText::ValueTreeWrapper::getFontHeight() const
  224. {
  225. return state [fontHeight].toString();
  226. }
  227. void DrawableText::ValueTreeWrapper::setFontHeight (const RelativeCoordinate& coord, UndoManager* undoManager)
  228. {
  229. state.setProperty (fontHeight, coord.toString(), undoManager);
  230. }
  231. RelativeCoordinate DrawableText::ValueTreeWrapper::getFontHorizontalScale() const
  232. {
  233. return state [fontHScale].toString();
  234. }
  235. void DrawableText::ValueTreeWrapper::setFontHorizontalScale (const RelativeCoordinate& coord, UndoManager* undoManager)
  236. {
  237. state.setProperty (fontHScale, coord.toString(), undoManager);
  238. }
  239. //==============================================================================
  240. void DrawableText::refreshFromValueTree (const ValueTree& tree, ComponentBuilder&)
  241. {
  242. ValueTreeWrapper v (tree);
  243. setComponentID (v.getID());
  244. const RelativeParallelogram newBounds (v.getBoundingBox());
  245. const RelativeCoordinate newFontHeight (v.getFontHeight());
  246. const RelativeCoordinate newFontHScale (v.getFontHorizontalScale());
  247. const Colour newColour (v.getColour());
  248. const Justification newJustification (v.getJustification());
  249. const String newText (v.getText());
  250. const Font newFont (v.getFont());
  251. if (text != newText || font != newFont || justification != newJustification
  252. || colour != newColour || bounds != newBounds
  253. || newFontHeight != fontHeight || newFontHScale != fontHScale)
  254. {
  255. setBoundingBox (newBounds);
  256. setFontHeight (newFontHeight);
  257. setFontHorizontalScale (newFontHScale);
  258. setColour (newColour);
  259. setFont (newFont, false);
  260. setJustification (newJustification);
  261. setText (newText);
  262. }
  263. }
  264. ValueTree DrawableText::createValueTree (ComponentBuilder::ImageProvider*) const
  265. {
  266. ValueTree tree (valueTreeType);
  267. ValueTreeWrapper v (tree);
  268. v.setID (getComponentID());
  269. v.setText (text, nullptr);
  270. v.setFont (font, nullptr);
  271. v.setJustification (justification, nullptr);
  272. v.setColour (colour, nullptr);
  273. v.setBoundingBox (bounds, nullptr);
  274. v.setFontHeight (fontHeight, nullptr);
  275. v.setFontHorizontalScale (fontHScale, nullptr);
  276. return tree;
  277. }