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.

342 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. DrawableText::DrawableText()
  19. : colour (Colours::black),
  20. justification (Justification::centredLeft)
  21. {
  22. setBoundingBox (RelativeParallelogram (RelativePoint (0.0f, 0.0f),
  23. RelativePoint (50.0f, 0.0f),
  24. RelativePoint (0.0f, 20.0f)));
  25. setFont (Font (15.0f), true);
  26. }
  27. DrawableText::DrawableText (const DrawableText& 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 (const 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 (const 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. const AffineTransform DrawableText::getArrangementAndTransform (GlyphArrangement& glyphs) const
  135. {
  136. const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
  137. const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
  138. glyphs.addFittedText (scaledFont, text, 0, 0, w, h, justification, 0x100000);
  139. return AffineTransform::fromTargetPoints (0, 0, resolvedPoints[0].x, resolvedPoints[0].y,
  140. w, 0, resolvedPoints[1].x, resolvedPoints[1].y,
  141. 0, h, resolvedPoints[2].x, resolvedPoints[2].y);
  142. }
  143. //==============================================================================
  144. void DrawableText::paint (Graphics& g)
  145. {
  146. transformContextToCorrectOrigin (g);
  147. g.setColour (colour);
  148. GlyphArrangement ga;
  149. const AffineTransform transform (getArrangementAndTransform (ga));
  150. ga.draw (g, transform);
  151. }
  152. Rectangle<float> DrawableText::getDrawableBounds() const
  153. {
  154. return RelativeParallelogram::getBoundingBox (resolvedPoints);
  155. }
  156. Drawable* DrawableText::createCopy() const
  157. {
  158. return new DrawableText (*this);
  159. }
  160. //==============================================================================
  161. const Identifier DrawableText::valueTreeType ("Text");
  162. const Identifier DrawableText::ValueTreeWrapper::text ("text");
  163. const Identifier DrawableText::ValueTreeWrapper::colour ("colour");
  164. const Identifier DrawableText::ValueTreeWrapper::font ("font");
  165. const Identifier DrawableText::ValueTreeWrapper::justification ("justification");
  166. const Identifier DrawableText::ValueTreeWrapper::topLeft ("topLeft");
  167. const Identifier DrawableText::ValueTreeWrapper::topRight ("topRight");
  168. const Identifier DrawableText::ValueTreeWrapper::bottomLeft ("bottomLeft");
  169. const Identifier DrawableText::ValueTreeWrapper::fontHeight ("fontHeight");
  170. const Identifier DrawableText::ValueTreeWrapper::fontHScale ("fontHScale");
  171. //==============================================================================
  172. DrawableText::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
  173. : ValueTreeWrapperBase (state_)
  174. {
  175. jassert (state.hasType (valueTreeType));
  176. }
  177. String DrawableText::ValueTreeWrapper::getText() const
  178. {
  179. return state [text].toString();
  180. }
  181. void DrawableText::ValueTreeWrapper::setText (const String& newText, UndoManager* undoManager)
  182. {
  183. state.setProperty (text, newText, undoManager);
  184. }
  185. Value DrawableText::ValueTreeWrapper::getTextValue (UndoManager* undoManager)
  186. {
  187. return state.getPropertyAsValue (text, undoManager);
  188. }
  189. Colour DrawableText::ValueTreeWrapper::getColour() const
  190. {
  191. return Colour::fromString (state [colour].toString());
  192. }
  193. void DrawableText::ValueTreeWrapper::setColour (const Colour& newColour, UndoManager* undoManager)
  194. {
  195. state.setProperty (colour, newColour.toString(), undoManager);
  196. }
  197. Justification DrawableText::ValueTreeWrapper::getJustification() const
  198. {
  199. return Justification ((int) state [justification]);
  200. }
  201. void DrawableText::ValueTreeWrapper::setJustification (const Justification& newJustification, UndoManager* undoManager)
  202. {
  203. state.setProperty (justification, newJustification.getFlags(), undoManager);
  204. }
  205. Font DrawableText::ValueTreeWrapper::getFont() const
  206. {
  207. return Font::fromString (state [font]);
  208. }
  209. void DrawableText::ValueTreeWrapper::setFont (const Font& newFont, UndoManager* undoManager)
  210. {
  211. state.setProperty (font, newFont.toString(), undoManager);
  212. }
  213. Value DrawableText::ValueTreeWrapper::getFontValue (UndoManager* undoManager)
  214. {
  215. return state.getPropertyAsValue (font, undoManager);
  216. }
  217. RelativeParallelogram DrawableText::ValueTreeWrapper::getBoundingBox() const
  218. {
  219. return RelativeParallelogram (state [topLeft].toString(), state [topRight].toString(), state [bottomLeft].toString());
  220. }
  221. void DrawableText::ValueTreeWrapper::setBoundingBox (const RelativeParallelogram& newBounds, UndoManager* undoManager)
  222. {
  223. state.setProperty (topLeft, newBounds.topLeft.toString(), undoManager);
  224. state.setProperty (topRight, newBounds.topRight.toString(), undoManager);
  225. state.setProperty (bottomLeft, newBounds.bottomLeft.toString(), undoManager);
  226. }
  227. RelativeCoordinate DrawableText::ValueTreeWrapper::getFontHeight() const
  228. {
  229. return state [fontHeight].toString();
  230. }
  231. void DrawableText::ValueTreeWrapper::setFontHeight (const RelativeCoordinate& coord, UndoManager* undoManager)
  232. {
  233. state.setProperty (fontHeight, coord.toString(), undoManager);
  234. }
  235. RelativeCoordinate DrawableText::ValueTreeWrapper::getFontHorizontalScale() const
  236. {
  237. return state [fontHScale].toString();
  238. }
  239. void DrawableText::ValueTreeWrapper::setFontHorizontalScale (const RelativeCoordinate& coord, UndoManager* undoManager)
  240. {
  241. state.setProperty (fontHScale, coord.toString(), undoManager);
  242. }
  243. //==============================================================================
  244. void DrawableText::refreshFromValueTree (const ValueTree& tree, ComponentBuilder&)
  245. {
  246. ValueTreeWrapper v (tree);
  247. setComponentID (v.getID());
  248. const RelativeParallelogram newBounds (v.getBoundingBox());
  249. const RelativeCoordinate newFontHeight (v.getFontHeight());
  250. const RelativeCoordinate newFontHScale (v.getFontHorizontalScale());
  251. const Colour newColour (v.getColour());
  252. const Justification newJustification (v.getJustification());
  253. const String newText (v.getText());
  254. const Font newFont (v.getFont());
  255. if (text != newText || font != newFont || justification != newJustification
  256. || colour != newColour || bounds != newBounds
  257. || newFontHeight != fontHeight || newFontHScale != fontHScale)
  258. {
  259. setBoundingBox (newBounds);
  260. setFontHeight (newFontHeight);
  261. setFontHorizontalScale (newFontHScale);
  262. setColour (newColour);
  263. setFont (newFont, false);
  264. setJustification (newJustification);
  265. setText (newText);
  266. }
  267. }
  268. ValueTree DrawableText::createValueTree (ComponentBuilder::ImageProvider*) const
  269. {
  270. ValueTree tree (valueTreeType);
  271. ValueTreeWrapper v (tree);
  272. v.setID (getComponentID());
  273. v.setText (text, nullptr);
  274. v.setFont (font, nullptr);
  275. v.setJustification (justification, nullptr);
  276. v.setColour (colour, nullptr);
  277. v.setBoundingBox (bounds, nullptr);
  278. v.setFontHeight (fontHeight, nullptr);
  279. v.setFontHorizontalScale (fontHScale, nullptr);
  280. return tree;
  281. }