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.

563 lines
17KB

  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. #ifndef __JUCER_PAINTELEMENTTEXT_JUCEHEADER__
  19. #define __JUCER_PAINTELEMENTTEXT_JUCEHEADER__
  20. #include "jucer_ColouredElement.h"
  21. #include "../properties/jucer_FontPropertyComponent.h"
  22. #include "../properties/jucer_JustificationProperty.h"
  23. //==============================================================================
  24. class PaintElementText : public ColouredElement
  25. {
  26. public:
  27. PaintElementText (PaintRoutine* owner)
  28. : ColouredElement (owner, "Text", false, false),
  29. text ("Your text goes here"),
  30. font (15.0f),
  31. typefaceName (FontPropertyComponent::getDefaultFont()),
  32. justification (Justification::centred)
  33. {
  34. fillType.colour = Colours::black;
  35. position.rect.setWidth (200);
  36. position.rect.setHeight (30);
  37. }
  38. //==============================================================================
  39. void draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea)
  40. {
  41. fillType.setFillType (g, getDocument(), parentArea);
  42. font = FontPropertyComponent::applyNameToFont (typefaceName, font);
  43. g.setFont (font);
  44. g.drawText (replaceStringTranslations (text, owner->getDocument()),
  45. position.getRectangle (parentArea, layout), justification, true);
  46. }
  47. static String replaceStringTranslations (String s, JucerDocument* document)
  48. {
  49. s = s.replace ("%%getName()%%", document->getComponentName());
  50. s = s.replace ("%%getButtonText()%%", document->getComponentName());
  51. return s;
  52. }
  53. void getEditableProperties (Array <PropertyComponent*>& properties)
  54. {
  55. ColouredElement::getEditableProperties (properties);
  56. properties.add (new TextProperty (this));
  57. properties.add (new FontNameProperty (this));
  58. properties.add (new FontStyleProperty (this));
  59. properties.add (new FontSizeProperty (this));
  60. properties.add (new TextJustificationProperty (this));
  61. properties.add (new TextToPathProperty (this));
  62. }
  63. void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode)
  64. {
  65. if (! fillType.isInvisible())
  66. {
  67. String r;
  68. fillType.fillInGeneratedCode (code, paintMethodCode);
  69. String x, y, w, h;
  70. positionToCode (position, code.document->getComponentLayout(), x, y, w, h);
  71. r << "g.setFont ("
  72. << FontPropertyComponent::getCompleteFontCode (font, typefaceName)
  73. << ");\ng.drawText ("
  74. << quotedString (text)
  75. << ",\n "
  76. << x << ", " << y << ", " << w << ", " << h
  77. << ",\n "
  78. << CodeHelpers::justificationToCode (justification)
  79. << ", true);\n\n";
  80. paintMethodCode += r;
  81. }
  82. }
  83. static const char* getTagName() noexcept { return "TEXT"; }
  84. XmlElement* createXml() const
  85. {
  86. XmlElement* e = new XmlElement (getTagName());
  87. position.applyToXml (*e);
  88. addColourAttributes (e);
  89. e->setAttribute ("text", text);
  90. e->setAttribute ("fontname", typefaceName);
  91. e->setAttribute ("fontsize", roundToInt (font.getHeight() * 100.0) / 100.0);
  92. e->setAttribute ("bold", font.isBold());
  93. e->setAttribute ("italic", font.isItalic());
  94. e->setAttribute ("justification", justification.getFlags());
  95. return e;
  96. }
  97. bool loadFromXml (const XmlElement& xml)
  98. {
  99. if (xml.hasTagName (getTagName()))
  100. {
  101. position.restoreFromXml (xml, position);
  102. loadColourAttributes (xml);
  103. text = xml.getStringAttribute ("text", "Hello World");
  104. typefaceName = xml.getStringAttribute ("fontname", FontPropertyComponent::getDefaultFont());
  105. font.setHeight ((float) xml.getDoubleAttribute ("fontsize", 15.0));
  106. font.setBold (xml.getBoolAttribute ("bold", false));
  107. font.setItalic (xml.getBoolAttribute ("italic", false));
  108. justification = Justification (xml.getIntAttribute ("justification", Justification::centred));
  109. return true;
  110. }
  111. jassertfalse;
  112. return false;
  113. }
  114. //==============================================================================
  115. const String& getText() const noexcept { return text; }
  116. class SetTextAction : public PaintElementUndoableAction <PaintElementText>
  117. {
  118. public:
  119. SetTextAction (PaintElementText* const element, const String& newText_)
  120. : PaintElementUndoableAction <PaintElementText> (element),
  121. newText (newText_),
  122. oldText (element->getText())
  123. {
  124. }
  125. bool perform()
  126. {
  127. showCorrectTab();
  128. getElement()->setText (newText, false);
  129. return true;
  130. }
  131. bool undo()
  132. {
  133. showCorrectTab();
  134. getElement()->setText (oldText, false);
  135. return true;
  136. }
  137. private:
  138. String newText, oldText;
  139. };
  140. void setText (const String& t, const bool undoable)
  141. {
  142. if (t != text)
  143. {
  144. if (undoable)
  145. {
  146. perform (new SetTextAction (this, t),
  147. "Change text element text");
  148. }
  149. else
  150. {
  151. text = t;
  152. changed();
  153. }
  154. }
  155. }
  156. //==============================================================================
  157. const Font& getFont() const { return font; }
  158. class SetFontAction : public PaintElementUndoableAction <PaintElementText>
  159. {
  160. public:
  161. SetFontAction (PaintElementText* const element, const Font& newFont_)
  162. : PaintElementUndoableAction <PaintElementText> (element),
  163. newFont (newFont_),
  164. oldFont (element->getFont())
  165. {
  166. }
  167. bool perform()
  168. {
  169. showCorrectTab();
  170. getElement()->setFont (newFont, false);
  171. return true;
  172. }
  173. bool undo()
  174. {
  175. showCorrectTab();
  176. getElement()->setFont (oldFont, false);
  177. return true;
  178. }
  179. private:
  180. Font newFont, oldFont;
  181. };
  182. void setFont (const Font& newFont, const bool undoable)
  183. {
  184. if (font != newFont)
  185. {
  186. if (undoable)
  187. {
  188. perform (new SetFontAction (this, newFont),
  189. "Change text element font");
  190. }
  191. else
  192. {
  193. font = newFont;
  194. changed();
  195. }
  196. }
  197. }
  198. //==============================================================================
  199. class SetTypefaceAction : public PaintElementUndoableAction <PaintElementText>
  200. {
  201. public:
  202. SetTypefaceAction (PaintElementText* const element, const String& newValue_)
  203. : PaintElementUndoableAction <PaintElementText> (element),
  204. newValue (newValue_),
  205. oldValue (element->getTypefaceName())
  206. {
  207. }
  208. bool perform()
  209. {
  210. showCorrectTab();
  211. getElement()->setTypefaceName (newValue, false);
  212. return true;
  213. }
  214. bool undo()
  215. {
  216. showCorrectTab();
  217. getElement()->setTypefaceName (oldValue, false);
  218. return true;
  219. }
  220. private:
  221. String newValue, oldValue;
  222. };
  223. void setTypefaceName (const String& newFontName, const bool undoable)
  224. {
  225. if (undoable)
  226. {
  227. perform (new SetTypefaceAction (this, newFontName),
  228. "Change text element typeface");
  229. }
  230. else
  231. {
  232. typefaceName = newFontName;
  233. changed();
  234. }
  235. }
  236. String getTypefaceName() const noexcept { return typefaceName; }
  237. //==============================================================================
  238. const Justification& getJustification() const noexcept { return justification; }
  239. class SetJustifyAction : public PaintElementUndoableAction <PaintElementText>
  240. {
  241. public:
  242. SetJustifyAction (PaintElementText* const element, const Justification& newValue_)
  243. : PaintElementUndoableAction <PaintElementText> (element),
  244. newValue (newValue_),
  245. oldValue (element->getJustification())
  246. {
  247. }
  248. bool perform()
  249. {
  250. showCorrectTab();
  251. getElement()->setJustification (newValue, false);
  252. return true;
  253. }
  254. bool undo()
  255. {
  256. showCorrectTab();
  257. getElement()->setJustification (oldValue, false);
  258. return true;
  259. }
  260. private:
  261. Justification newValue, oldValue;
  262. };
  263. void setJustification (const Justification& j, const bool undoable)
  264. {
  265. if (justification.getFlags() != j.getFlags())
  266. {
  267. if (undoable)
  268. {
  269. perform (new SetJustifyAction (this, j),
  270. "Change text element justification");
  271. }
  272. else
  273. {
  274. justification = j;
  275. changed();
  276. }
  277. }
  278. }
  279. void convertToPath()
  280. {
  281. font = FontPropertyComponent::applyNameToFont (typefaceName, font);
  282. const Rectangle<int> r (getCurrentAbsoluteBounds());
  283. GlyphArrangement arr;
  284. arr.addCurtailedLineOfText (font, text,
  285. 0.0f, 0.0f, (float) r.getWidth(),
  286. true);
  287. arr.justifyGlyphs (0, arr.getNumGlyphs(),
  288. (float) r.getX(), (float) r.getY(),
  289. (float) r.getWidth(), (float) r.getHeight(),
  290. justification);
  291. Path path;
  292. arr.createPath (path);
  293. convertToNewPathElement (path);
  294. }
  295. private:
  296. String text;
  297. Font font;
  298. String typefaceName;
  299. Justification justification;
  300. Array <Justification> justificationTypes;
  301. //==============================================================================
  302. class TextProperty : public TextPropertyComponent,
  303. public ChangeListener
  304. {
  305. public:
  306. TextProperty (PaintElementText* const e)
  307. : TextPropertyComponent ("text", 2048, false),
  308. element (e)
  309. {
  310. element->getDocument()->addChangeListener (this);
  311. }
  312. ~TextProperty()
  313. {
  314. element->getDocument()->removeChangeListener (this);
  315. }
  316. void setText (const String& newText) { element->setText (newText, true); }
  317. String getText() const { return element->getText(); }
  318. void changeListenerCallback (ChangeBroadcaster*) { refresh(); }
  319. private:
  320. PaintElementText* const element;
  321. };
  322. //==============================================================================
  323. class FontNameProperty : public FontPropertyComponent,
  324. public ChangeListener
  325. {
  326. public:
  327. FontNameProperty (PaintElementText* const e)
  328. : FontPropertyComponent ("font"),
  329. element (e)
  330. {
  331. element->getDocument()->addChangeListener (this);
  332. }
  333. ~FontNameProperty()
  334. {
  335. element->getDocument()->removeChangeListener (this);
  336. }
  337. void setTypefaceName (const String& newFontName) { element->setTypefaceName (newFontName, true); }
  338. String getTypefaceName() const { return element->getTypefaceName(); }
  339. void changeListenerCallback (ChangeBroadcaster*) { refresh(); }
  340. private:
  341. PaintElementText* const element;
  342. };
  343. //==============================================================================
  344. class FontStyleProperty : public ChoicePropertyComponent,
  345. public ChangeListener
  346. {
  347. public:
  348. FontStyleProperty (PaintElementText* const e)
  349. : ChoicePropertyComponent ("style"),
  350. element (e)
  351. {
  352. element->getDocument()->addChangeListener (this);
  353. choices.add ("normal");
  354. choices.add ("bold");
  355. choices.add ("italic");
  356. choices.add ("bold + italic");
  357. }
  358. ~FontStyleProperty()
  359. {
  360. element->getDocument()->removeChangeListener (this);
  361. }
  362. void setIndex (int newIndex)
  363. {
  364. Font f (element->getFont());
  365. f.setBold (newIndex == 1 || newIndex == 3);
  366. f.setItalic (newIndex == 2 || newIndex == 3);
  367. element->setFont (f, true);
  368. }
  369. int getIndex() const
  370. {
  371. if (element->getFont().isBold() && element->getFont().isItalic())
  372. return 3;
  373. else if (element->getFont().isBold())
  374. return 1;
  375. else if (element->getFont().isItalic())
  376. return 2;
  377. return 0;
  378. }
  379. void changeListenerCallback (ChangeBroadcaster*) { refresh(); }
  380. private:
  381. PaintElementText* const element;
  382. };
  383. //==============================================================================
  384. class FontSizeProperty : public SliderPropertyComponent,
  385. public ChangeListener
  386. {
  387. public:
  388. FontSizeProperty (PaintElementText* const e)
  389. : SliderPropertyComponent ("size", 1.0, 250.0, 0.1, 0.3),
  390. element (e)
  391. {
  392. element->getDocument()->addChangeListener (this);
  393. }
  394. ~FontSizeProperty()
  395. {
  396. element->getDocument()->removeChangeListener (this);
  397. }
  398. void setValue (double newValue)
  399. {
  400. element->getDocument()->getUndoManager().undoCurrentTransactionOnly();
  401. Font f (element->getFont());
  402. f.setHeight ((float) newValue);
  403. element->setFont (f, true);
  404. }
  405. double getValue() const
  406. {
  407. return element->getFont().getHeight();
  408. }
  409. void changeListenerCallback (ChangeBroadcaster*) { refresh(); }
  410. private:
  411. PaintElementText* const element;
  412. };
  413. //==============================================================================
  414. class TextJustificationProperty : public JustificationProperty,
  415. public ChangeListener
  416. {
  417. public:
  418. TextJustificationProperty (PaintElementText* const e)
  419. : JustificationProperty ("layout", false),
  420. element (e)
  421. {
  422. element->getDocument()->addChangeListener (this);
  423. }
  424. ~TextJustificationProperty()
  425. {
  426. element->getDocument()->removeChangeListener (this);
  427. }
  428. void setJustification (const Justification& newJustification)
  429. {
  430. element->setJustification (newJustification, true);
  431. }
  432. const Justification getJustification() const
  433. {
  434. return element->getJustification();
  435. }
  436. void changeListenerCallback (ChangeBroadcaster*) { refresh(); }
  437. private:
  438. PaintElementText* const element;
  439. };
  440. //==============================================================================
  441. class TextToPathProperty : public ButtonPropertyComponent
  442. {
  443. public:
  444. TextToPathProperty (PaintElementText* const e)
  445. : ButtonPropertyComponent ("path", false),
  446. element (e)
  447. {
  448. }
  449. void buttonClicked()
  450. {
  451. element->convertToPath();
  452. }
  453. String getButtonText() const
  454. {
  455. return "convert text to a path";
  456. }
  457. private:
  458. PaintElementText* const element;
  459. };
  460. };
  461. #endif // __JUCER_PAINTELEMENTTEXT_JUCEHEADER__