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.

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