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.

322 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. fontSizeControlPoint (other.fontSizeControlPoint),
  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. setFontSizeControlPoint (RelativePoint (RelativeParallelogram::getPointForInternalCoord (resolvedPoints,
  66. Point<float> (font.getHorizontalScale() * font.getHeight(), font.getHeight()))));
  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::setFontSizeControlPoint (const RelativePoint& newPoint)
  85. {
  86. if (fontSizeControlPoint != newPoint)
  87. {
  88. fontSizeControlPoint = newPoint;
  89. refreshBounds();
  90. }
  91. }
  92. void DrawableText::refreshBounds()
  93. {
  94. if (bounds.isDynamic() || fontSizeControlPoint.isDynamic())
  95. {
  96. Drawable::Positioner<DrawableText>* const p = new Drawable::Positioner<DrawableText> (*this);
  97. setPositioner (p);
  98. p->apply();
  99. }
  100. else
  101. {
  102. setPositioner (0);
  103. recalculateCoordinates (0);
  104. }
  105. }
  106. bool DrawableText::registerCoordinates (RelativeCoordinatePositionerBase& pos)
  107. {
  108. bool ok = pos.addPoint (bounds.topLeft);
  109. ok = pos.addPoint (bounds.topRight) && ok;
  110. ok = pos.addPoint (bounds.bottomLeft) && ok;
  111. return pos.addPoint (fontSizeControlPoint) && ok;
  112. }
  113. void DrawableText::recalculateCoordinates (Expression::Scope* scope)
  114. {
  115. bounds.resolveThreePoints (resolvedPoints, scope);
  116. const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
  117. const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
  118. const Point<float> fontCoords (RelativeParallelogram::getInternalCoordForPoint (resolvedPoints, fontSizeControlPoint.resolve (scope)));
  119. const float fontHeight = jlimit (0.01f, jmax (0.01f, h), fontCoords.getY());
  120. const float fontWidth = jlimit (0.01f, jmax (0.01f, w), fontCoords.getX());
  121. scaledFont = font;
  122. scaledFont.setHeight (fontHeight);
  123. scaledFont.setHorizontalScale (fontWidth / fontHeight);
  124. setBoundsToEnclose (getDrawableBounds());
  125. repaint();
  126. }
  127. const AffineTransform DrawableText::getArrangementAndTransform (GlyphArrangement& glyphs) const
  128. {
  129. const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
  130. const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
  131. glyphs.addFittedText (scaledFont, text, 0, 0, w, h, justification, 0x100000);
  132. return AffineTransform::fromTargetPoints (0, 0, resolvedPoints[0].getX(), resolvedPoints[0].getY(),
  133. w, 0, resolvedPoints[1].getX(), resolvedPoints[1].getY(),
  134. 0, h, resolvedPoints[2].getX(), resolvedPoints[2].getY());
  135. }
  136. //==============================================================================
  137. void DrawableText::paint (Graphics& g)
  138. {
  139. transformContextToCorrectOrigin (g);
  140. g.setColour (colour);
  141. GlyphArrangement ga;
  142. const AffineTransform transform (getArrangementAndTransform (ga));
  143. ga.draw (g, transform);
  144. }
  145. Rectangle<float> DrawableText::getDrawableBounds() const
  146. {
  147. return RelativeParallelogram::getBoundingBox (resolvedPoints);
  148. }
  149. Drawable* DrawableText::createCopy() const
  150. {
  151. return new DrawableText (*this);
  152. }
  153. //==============================================================================
  154. const Identifier DrawableText::valueTreeType ("Text");
  155. const Identifier DrawableText::ValueTreeWrapper::text ("text");
  156. const Identifier DrawableText::ValueTreeWrapper::colour ("colour");
  157. const Identifier DrawableText::ValueTreeWrapper::font ("font");
  158. const Identifier DrawableText::ValueTreeWrapper::justification ("justification");
  159. const Identifier DrawableText::ValueTreeWrapper::topLeft ("topLeft");
  160. const Identifier DrawableText::ValueTreeWrapper::topRight ("topRight");
  161. const Identifier DrawableText::ValueTreeWrapper::bottomLeft ("bottomLeft");
  162. const Identifier DrawableText::ValueTreeWrapper::fontSizeAnchor ("fontSizeAnchor");
  163. //==============================================================================
  164. DrawableText::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
  165. : ValueTreeWrapperBase (state_)
  166. {
  167. jassert (state.hasType (valueTreeType));
  168. }
  169. String DrawableText::ValueTreeWrapper::getText() const
  170. {
  171. return state [text].toString();
  172. }
  173. void DrawableText::ValueTreeWrapper::setText (const String& newText, UndoManager* undoManager)
  174. {
  175. state.setProperty (text, newText, undoManager);
  176. }
  177. Value DrawableText::ValueTreeWrapper::getTextValue (UndoManager* undoManager)
  178. {
  179. return state.getPropertyAsValue (text, undoManager);
  180. }
  181. Colour DrawableText::ValueTreeWrapper::getColour() const
  182. {
  183. return Colour::fromString (state [colour].toString());
  184. }
  185. void DrawableText::ValueTreeWrapper::setColour (const Colour& newColour, UndoManager* undoManager)
  186. {
  187. state.setProperty (colour, newColour.toString(), undoManager);
  188. }
  189. Justification DrawableText::ValueTreeWrapper::getJustification() const
  190. {
  191. return Justification ((int) state [justification]);
  192. }
  193. void DrawableText::ValueTreeWrapper::setJustification (const Justification& newJustification, UndoManager* undoManager)
  194. {
  195. state.setProperty (justification, newJustification.getFlags(), undoManager);
  196. }
  197. Font DrawableText::ValueTreeWrapper::getFont() const
  198. {
  199. return Font::fromString (state [font]);
  200. }
  201. void DrawableText::ValueTreeWrapper::setFont (const Font& newFont, UndoManager* undoManager)
  202. {
  203. state.setProperty (font, newFont.toString(), undoManager);
  204. }
  205. Value DrawableText::ValueTreeWrapper::getFontValue (UndoManager* undoManager)
  206. {
  207. return state.getPropertyAsValue (font, undoManager);
  208. }
  209. RelativeParallelogram DrawableText::ValueTreeWrapper::getBoundingBox() const
  210. {
  211. return RelativeParallelogram (state [topLeft].toString(), state [topRight].toString(), state [bottomLeft].toString());
  212. }
  213. void DrawableText::ValueTreeWrapper::setBoundingBox (const RelativeParallelogram& newBounds, UndoManager* undoManager)
  214. {
  215. state.setProperty (topLeft, newBounds.topLeft.toString(), undoManager);
  216. state.setProperty (topRight, newBounds.topRight.toString(), undoManager);
  217. state.setProperty (bottomLeft, newBounds.bottomLeft.toString(), undoManager);
  218. }
  219. RelativePoint DrawableText::ValueTreeWrapper::getFontSizeControlPoint() const
  220. {
  221. return state [fontSizeAnchor].toString();
  222. }
  223. void DrawableText::ValueTreeWrapper::setFontSizeControlPoint (const RelativePoint& p, UndoManager* undoManager)
  224. {
  225. state.setProperty (fontSizeAnchor, p.toString(), undoManager);
  226. }
  227. //==============================================================================
  228. void DrawableText::refreshFromValueTree (const ValueTree& tree, ComponentBuilder&)
  229. {
  230. ValueTreeWrapper v (tree);
  231. setComponentID (v.getID());
  232. const RelativeParallelogram newBounds (v.getBoundingBox());
  233. const RelativePoint newFontPoint (v.getFontSizeControlPoint());
  234. const Colour newColour (v.getColour());
  235. const Justification newJustification (v.getJustification());
  236. const String newText (v.getText());
  237. const Font newFont (v.getFont());
  238. if (text != newText || font != newFont || justification != newJustification
  239. || colour != newColour || bounds != newBounds || newFontPoint != fontSizeControlPoint)
  240. {
  241. setBoundingBox (newBounds);
  242. setFontSizeControlPoint (newFontPoint);
  243. setColour (newColour);
  244. setFont (newFont, false);
  245. setJustification (newJustification);
  246. setText (newText);
  247. }
  248. }
  249. ValueTree DrawableText::createValueTree (ComponentBuilder::ImageProvider*) const
  250. {
  251. ValueTree tree (valueTreeType);
  252. ValueTreeWrapper v (tree);
  253. v.setID (getComponentID());
  254. v.setText (text, nullptr);
  255. v.setFont (font, nullptr);
  256. v.setJustification (justification, nullptr);
  257. v.setColour (colour, nullptr);
  258. v.setBoundingBox (bounds, nullptr);
  259. v.setFontSizeControlPoint (fontSizeControlPoint, nullptr);
  260. return tree;
  261. }
  262. END_JUCE_NAMESPACE