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.

337 lines
11KB

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