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.

334 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. }
  37. DrawableText::~DrawableText()
  38. {
  39. }
  40. //==============================================================================
  41. void DrawableText::setText (const String& newText)
  42. {
  43. if (text != newText)
  44. {
  45. text = newText;
  46. refreshBounds();
  47. }
  48. }
  49. void DrawableText::setColour (Colour newColour)
  50. {
  51. if (colour != newColour)
  52. {
  53. colour = newColour;
  54. repaint();
  55. }
  56. }
  57. void DrawableText::setFont (const Font& newFont, bool applySizeAndScale)
  58. {
  59. if (font != newFont)
  60. {
  61. font = newFont;
  62. if (applySizeAndScale)
  63. {
  64. fontHeight = font.getHeight();
  65. fontHScale = font.getHorizontalScale();
  66. }
  67. refreshBounds();
  68. }
  69. }
  70. void DrawableText::setJustification (Justification newJustification)
  71. {
  72. justification = newJustification;
  73. repaint();
  74. }
  75. void DrawableText::setBoundingBox (const RelativeParallelogram& newBounds)
  76. {
  77. if (bounds != newBounds)
  78. {
  79. bounds = newBounds;
  80. refreshBounds();
  81. }
  82. }
  83. void DrawableText::setFontHeight (const RelativeCoordinate& newHeight)
  84. {
  85. if (fontHeight != newHeight)
  86. {
  87. fontHeight = newHeight;
  88. refreshBounds();
  89. }
  90. }
  91. void DrawableText::setFontHorizontalScale (const RelativeCoordinate& newScale)
  92. {
  93. if (fontHScale != newScale)
  94. {
  95. fontHScale = newScale;
  96. refreshBounds();
  97. }
  98. }
  99. void DrawableText::refreshBounds()
  100. {
  101. if (bounds.isDynamic() || fontHeight.isDynamic() || fontHScale.isDynamic())
  102. {
  103. Drawable::Positioner<DrawableText>* const p = new Drawable::Positioner<DrawableText> (*this);
  104. setPositioner (p);
  105. p->apply();
  106. }
  107. else
  108. {
  109. setPositioner (0);
  110. recalculateCoordinates (0);
  111. }
  112. }
  113. bool DrawableText::registerCoordinates (RelativeCoordinatePositionerBase& pos)
  114. {
  115. bool ok = pos.addPoint (bounds.topLeft);
  116. ok = pos.addPoint (bounds.topRight) && ok;
  117. ok = pos.addPoint (bounds.bottomLeft) && ok;
  118. ok = pos.addCoordinate (fontHeight) && ok;
  119. return pos.addCoordinate (fontHScale) && ok;
  120. }
  121. void DrawableText::recalculateCoordinates (Expression::Scope* scope)
  122. {
  123. bounds.resolveThreePoints (resolvedPoints, scope);
  124. const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
  125. const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
  126. const float height = jlimit (0.01f, jmax (0.01f, h), (float) fontHeight.resolve (scope));
  127. const float hscale = jlimit (0.01f, jmax (0.01f, w), (float) fontHScale.resolve (scope));
  128. scaledFont = font;
  129. scaledFont.setHeight (height);
  130. scaledFont.setHorizontalScale (hscale);
  131. setBoundsToEnclose (getDrawableBounds());
  132. repaint();
  133. }
  134. //==============================================================================
  135. void DrawableText::paint (Graphics& g)
  136. {
  137. transformContextToCorrectOrigin (g);
  138. const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
  139. const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
  140. g.addTransform (AffineTransform::fromTargetPoints (0, 0, resolvedPoints[0].x, resolvedPoints[0].y,
  141. w, 0, resolvedPoints[1].x, resolvedPoints[1].y,
  142. 0, h, resolvedPoints[2].x, resolvedPoints[2].y));
  143. g.setFont (scaledFont);
  144. g.setColour (colour);
  145. g.drawFittedText (text, Rectangle<float> (w, h).getSmallestIntegerContainer(), justification, 0x100000);
  146. }
  147. Rectangle<float> DrawableText::getDrawableBounds() const
  148. {
  149. return RelativeParallelogram::getBoundingBox (resolvedPoints);
  150. }
  151. Drawable* DrawableText::createCopy() const
  152. {
  153. return new DrawableText (*this);
  154. }
  155. //==============================================================================
  156. const Identifier DrawableText::valueTreeType ("Text");
  157. const Identifier DrawableText::ValueTreeWrapper::text ("text");
  158. const Identifier DrawableText::ValueTreeWrapper::colour ("colour");
  159. const Identifier DrawableText::ValueTreeWrapper::font ("font");
  160. const Identifier DrawableText::ValueTreeWrapper::justification ("justification");
  161. const Identifier DrawableText::ValueTreeWrapper::topLeft ("topLeft");
  162. const Identifier DrawableText::ValueTreeWrapper::topRight ("topRight");
  163. const Identifier DrawableText::ValueTreeWrapper::bottomLeft ("bottomLeft");
  164. const Identifier DrawableText::ValueTreeWrapper::fontHeight ("fontHeight");
  165. const Identifier DrawableText::ValueTreeWrapper::fontHScale ("fontHScale");
  166. //==============================================================================
  167. DrawableText::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
  168. : ValueTreeWrapperBase (state_)
  169. {
  170. jassert (state.hasType (valueTreeType));
  171. }
  172. String DrawableText::ValueTreeWrapper::getText() const
  173. {
  174. return state [text].toString();
  175. }
  176. void DrawableText::ValueTreeWrapper::setText (const String& newText, UndoManager* undoManager)
  177. {
  178. state.setProperty (text, newText, undoManager);
  179. }
  180. Value DrawableText::ValueTreeWrapper::getTextValue (UndoManager* undoManager)
  181. {
  182. return state.getPropertyAsValue (text, undoManager);
  183. }
  184. Colour DrawableText::ValueTreeWrapper::getColour() const
  185. {
  186. return Colour::fromString (state [colour].toString());
  187. }
  188. void DrawableText::ValueTreeWrapper::setColour (Colour newColour, UndoManager* undoManager)
  189. {
  190. state.setProperty (colour, newColour.toString(), undoManager);
  191. }
  192. Justification DrawableText::ValueTreeWrapper::getJustification() const
  193. {
  194. return Justification ((int) state [justification]);
  195. }
  196. void DrawableText::ValueTreeWrapper::setJustification (Justification newJustification, UndoManager* undoManager)
  197. {
  198. state.setProperty (justification, newJustification.getFlags(), undoManager);
  199. }
  200. Font DrawableText::ValueTreeWrapper::getFont() const
  201. {
  202. return Font::fromString (state [font]);
  203. }
  204. void DrawableText::ValueTreeWrapper::setFont (const Font& newFont, UndoManager* undoManager)
  205. {
  206. state.setProperty (font, newFont.toString(), undoManager);
  207. }
  208. Value DrawableText::ValueTreeWrapper::getFontValue (UndoManager* undoManager)
  209. {
  210. return state.getPropertyAsValue (font, undoManager);
  211. }
  212. RelativeParallelogram DrawableText::ValueTreeWrapper::getBoundingBox() const
  213. {
  214. return RelativeParallelogram (state [topLeft].toString(), state [topRight].toString(), state [bottomLeft].toString());
  215. }
  216. void DrawableText::ValueTreeWrapper::setBoundingBox (const RelativeParallelogram& newBounds, UndoManager* undoManager)
  217. {
  218. state.setProperty (topLeft, newBounds.topLeft.toString(), undoManager);
  219. state.setProperty (topRight, newBounds.topRight.toString(), undoManager);
  220. state.setProperty (bottomLeft, newBounds.bottomLeft.toString(), undoManager);
  221. }
  222. RelativeCoordinate DrawableText::ValueTreeWrapper::getFontHeight() const
  223. {
  224. return state [fontHeight].toString();
  225. }
  226. void DrawableText::ValueTreeWrapper::setFontHeight (const RelativeCoordinate& coord, UndoManager* undoManager)
  227. {
  228. state.setProperty (fontHeight, coord.toString(), undoManager);
  229. }
  230. RelativeCoordinate DrawableText::ValueTreeWrapper::getFontHorizontalScale() const
  231. {
  232. return state [fontHScale].toString();
  233. }
  234. void DrawableText::ValueTreeWrapper::setFontHorizontalScale (const RelativeCoordinate& coord, UndoManager* undoManager)
  235. {
  236. state.setProperty (fontHScale, coord.toString(), undoManager);
  237. }
  238. //==============================================================================
  239. void DrawableText::refreshFromValueTree (const ValueTree& tree, ComponentBuilder&)
  240. {
  241. ValueTreeWrapper v (tree);
  242. setComponentID (v.getID());
  243. const RelativeParallelogram newBounds (v.getBoundingBox());
  244. const RelativeCoordinate newFontHeight (v.getFontHeight());
  245. const RelativeCoordinate newFontHScale (v.getFontHorizontalScale());
  246. const Colour newColour (v.getColour());
  247. const Justification newJustification (v.getJustification());
  248. const String newText (v.getText());
  249. const Font newFont (v.getFont());
  250. if (text != newText || font != newFont || justification != newJustification
  251. || colour != newColour || bounds != newBounds
  252. || newFontHeight != fontHeight || newFontHScale != fontHScale)
  253. {
  254. setBoundingBox (newBounds);
  255. setFontHeight (newFontHeight);
  256. setFontHorizontalScale (newFontHScale);
  257. setColour (newColour);
  258. setFont (newFont, false);
  259. setJustification (newJustification);
  260. setText (newText);
  261. }
  262. }
  263. ValueTree DrawableText::createValueTree (ComponentBuilder::ImageProvider*) const
  264. {
  265. ValueTree tree (valueTreeType);
  266. ValueTreeWrapper v (tree);
  267. v.setID (getComponentID());
  268. v.setText (text, nullptr);
  269. v.setFont (font, nullptr);
  270. v.setJustification (justification, nullptr);
  271. v.setColour (colour, nullptr);
  272. v.setBoundingBox (bounds, nullptr);
  273. v.setFontHeight (fontHeight, nullptr);
  274. v.setFontHorizontalScale (fontHScale, nullptr);
  275. return tree;
  276. }