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. : Drawable (other),
  29. bounds (other.bounds),
  30. fontHeight (other.fontHeight),
  31. fontHScale (other.fontHScale),
  32. font (other.font),
  33. text (other.text),
  34. colour (other.colour),
  35. justification (other.justification)
  36. {
  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 (const 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 (const 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. const AffineTransform DrawableText::getArrangementAndTransform (GlyphArrangement& glyphs) const
  136. {
  137. const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
  138. const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
  139. glyphs.addFittedText (scaledFont, text, 0, 0, w, h, justification, 0x100000);
  140. return 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. }
  144. //==============================================================================
  145. void DrawableText::paint (Graphics& g)
  146. {
  147. transformContextToCorrectOrigin (g);
  148. g.setColour (colour);
  149. GlyphArrangement ga;
  150. const AffineTransform transform (getArrangementAndTransform (ga));
  151. ga.draw (g, transform);
  152. }
  153. Rectangle<float> DrawableText::getDrawableBounds() const
  154. {
  155. return RelativeParallelogram::getBoundingBox (resolvedPoints);
  156. }
  157. Drawable* DrawableText::createCopy() const
  158. {
  159. return new DrawableText (*this);
  160. }
  161. //==============================================================================
  162. const Identifier DrawableText::valueTreeType ("Text");
  163. const Identifier DrawableText::ValueTreeWrapper::text ("text");
  164. const Identifier DrawableText::ValueTreeWrapper::colour ("colour");
  165. const Identifier DrawableText::ValueTreeWrapper::font ("font");
  166. const Identifier DrawableText::ValueTreeWrapper::justification ("justification");
  167. const Identifier DrawableText::ValueTreeWrapper::topLeft ("topLeft");
  168. const Identifier DrawableText::ValueTreeWrapper::topRight ("topRight");
  169. const Identifier DrawableText::ValueTreeWrapper::bottomLeft ("bottomLeft");
  170. const Identifier DrawableText::ValueTreeWrapper::fontHeight ("fontHeight");
  171. const Identifier DrawableText::ValueTreeWrapper::fontHScale ("fontHScale");
  172. //==============================================================================
  173. DrawableText::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
  174. : ValueTreeWrapperBase (state_)
  175. {
  176. jassert (state.hasType (valueTreeType));
  177. }
  178. String DrawableText::ValueTreeWrapper::getText() const
  179. {
  180. return state [text].toString();
  181. }
  182. void DrawableText::ValueTreeWrapper::setText (const String& newText, UndoManager* undoManager)
  183. {
  184. state.setProperty (text, newText, undoManager);
  185. }
  186. Value DrawableText::ValueTreeWrapper::getTextValue (UndoManager* undoManager)
  187. {
  188. return state.getPropertyAsValue (text, undoManager);
  189. }
  190. Colour DrawableText::ValueTreeWrapper::getColour() const
  191. {
  192. return Colour::fromString (state [colour].toString());
  193. }
  194. void DrawableText::ValueTreeWrapper::setColour (const Colour& newColour, UndoManager* undoManager)
  195. {
  196. state.setProperty (colour, newColour.toString(), undoManager);
  197. }
  198. Justification DrawableText::ValueTreeWrapper::getJustification() const
  199. {
  200. return Justification ((int) state [justification]);
  201. }
  202. void DrawableText::ValueTreeWrapper::setJustification (const Justification& newJustification, UndoManager* undoManager)
  203. {
  204. state.setProperty (justification, newJustification.getFlags(), undoManager);
  205. }
  206. Font DrawableText::ValueTreeWrapper::getFont() const
  207. {
  208. return Font::fromString (state [font]);
  209. }
  210. void DrawableText::ValueTreeWrapper::setFont (const Font& newFont, UndoManager* undoManager)
  211. {
  212. state.setProperty (font, newFont.toString(), undoManager);
  213. }
  214. Value DrawableText::ValueTreeWrapper::getFontValue (UndoManager* undoManager)
  215. {
  216. return state.getPropertyAsValue (font, undoManager);
  217. }
  218. RelativeParallelogram DrawableText::ValueTreeWrapper::getBoundingBox() const
  219. {
  220. return RelativeParallelogram (state [topLeft].toString(), state [topRight].toString(), state [bottomLeft].toString());
  221. }
  222. void DrawableText::ValueTreeWrapper::setBoundingBox (const RelativeParallelogram& newBounds, UndoManager* undoManager)
  223. {
  224. state.setProperty (topLeft, newBounds.topLeft.toString(), undoManager);
  225. state.setProperty (topRight, newBounds.topRight.toString(), undoManager);
  226. state.setProperty (bottomLeft, newBounds.bottomLeft.toString(), undoManager);
  227. }
  228. RelativeCoordinate DrawableText::ValueTreeWrapper::getFontHeight() const
  229. {
  230. return state [fontHeight].toString();
  231. }
  232. void DrawableText::ValueTreeWrapper::setFontHeight (const RelativeCoordinate& coord, UndoManager* undoManager)
  233. {
  234. state.setProperty (fontHeight, coord.toString(), undoManager);
  235. }
  236. RelativeCoordinate DrawableText::ValueTreeWrapper::getFontHorizontalScale() const
  237. {
  238. return state [fontHScale].toString();
  239. }
  240. void DrawableText::ValueTreeWrapper::setFontHorizontalScale (const RelativeCoordinate& coord, UndoManager* undoManager)
  241. {
  242. state.setProperty (fontHScale, coord.toString(), undoManager);
  243. }
  244. //==============================================================================
  245. void DrawableText::refreshFromValueTree (const ValueTree& tree, ComponentBuilder&)
  246. {
  247. ValueTreeWrapper v (tree);
  248. setComponentID (v.getID());
  249. const RelativeParallelogram newBounds (v.getBoundingBox());
  250. const RelativeCoordinate newFontHeight (v.getFontHeight());
  251. const RelativeCoordinate newFontHScale (v.getFontHorizontalScale());
  252. const Colour newColour (v.getColour());
  253. const Justification newJustification (v.getJustification());
  254. const String newText (v.getText());
  255. const Font newFont (v.getFont());
  256. if (text != newText || font != newFont || justification != newJustification
  257. || colour != newColour || bounds != newBounds
  258. || newFontHeight != fontHeight || newFontHScale != fontHScale)
  259. {
  260. setBoundingBox (newBounds);
  261. setFontHeight (newFontHeight);
  262. setFontHorizontalScale (newFontHScale);
  263. setColour (newColour);
  264. setFont (newFont, false);
  265. setJustification (newJustification);
  266. setText (newText);
  267. }
  268. }
  269. ValueTree DrawableText::createValueTree (ComponentBuilder::ImageProvider*) const
  270. {
  271. ValueTree tree (valueTreeType);
  272. ValueTreeWrapper v (tree);
  273. v.setID (getComponentID());
  274. v.setText (text, nullptr);
  275. v.setFont (font, nullptr);
  276. v.setJustification (justification, nullptr);
  277. v.setColour (colour, nullptr);
  278. v.setBoundingBox (bounds, nullptr);
  279. v.setFontHeight (fontHeight, nullptr);
  280. v.setFontHorizontalScale (fontHScale, nullptr);
  281. return tree;
  282. }