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.

427 lines
16KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. class TextEditorHandler : public ComponentTypeHandler
  20. {
  21. public:
  22. TextEditorHandler()
  23. : ComponentTypeHandler ("Text Editor", "TextEditor", typeid (TextEditor), 150, 24)
  24. {
  25. registerColour (TextEditor::textColourId, "text", "textcol");
  26. registerColour (TextEditor::backgroundColourId, "background", "bkgcol");
  27. registerColour (TextEditor::highlightColourId, "highlight", "hilitecol");
  28. registerColour (TextEditor::outlineColourId, "outline", "outlinecol");
  29. registerColour (TextEditor::shadowColourId, "shadow", "shadowcol");
  30. registerColour (CaretComponent::caretColourId, "caret", "caretcol");
  31. }
  32. Component* createNewComponent (JucerDocument*)
  33. {
  34. return new TextEditor ("new text editor");
  35. }
  36. XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout)
  37. {
  38. XmlElement* e = ComponentTypeHandler::createXmlFor (comp, layout);
  39. TextEditor* te = (TextEditor*) comp;
  40. e->setAttribute ("initialText", comp->getProperties() ["initialText"].toString());
  41. e->setAttribute ("multiline", te->isMultiLine());
  42. e->setAttribute ("retKeyStartsLine", te->getReturnKeyStartsNewLine());
  43. e->setAttribute ("readonly", te->isReadOnly());
  44. e->setAttribute ("scrollbars", te->areScrollbarsShown());
  45. e->setAttribute ("caret", te->isCaretVisible());
  46. e->setAttribute ("popupmenu", te->isPopupMenuEnabled());
  47. return e;
  48. }
  49. bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout)
  50. {
  51. if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
  52. return false;
  53. TextEditor* te = (TextEditor*) comp;
  54. TextEditor defaultEditor;
  55. te->setMultiLine (xml.getBoolAttribute ("multiline", defaultEditor.isMultiLine()));
  56. te->setReturnKeyStartsNewLine (xml.getBoolAttribute ("retKeyStartsLine", defaultEditor.getReturnKeyStartsNewLine()));
  57. te->setReadOnly (xml.getBoolAttribute ("readonly", defaultEditor.isReadOnly()));
  58. te->setScrollbarsShown (xml.getBoolAttribute ("scrollbars", defaultEditor.areScrollbarsShown()));
  59. te->setCaretVisible (xml.getBoolAttribute ("caret", defaultEditor.isCaretVisible()));
  60. te->setPopupMenuEnabled (xml.getBoolAttribute ("popupmenu", defaultEditor.isPopupMenuEnabled()));
  61. const String initialText (xml.getStringAttribute ("initialText"));
  62. te->setText (initialText, false);
  63. te->getProperties().set ("initialText", initialText);
  64. return true;
  65. }
  66. void getEditableProperties (Component* component, JucerDocument& document, Array<PropertyComponent*>& props)
  67. {
  68. ComponentTypeHandler::getEditableProperties (component, document, props);
  69. TextEditor* const t = dynamic_cast<TextEditor*> (component);
  70. jassert (t != nullptr);
  71. props.add (new TextEditorInitialTextProperty (t, document));
  72. props.add (new TextEditorMultiLineProperty (t, document));
  73. props.add (new TextEditorReadOnlyProperty (t, document));
  74. props.add (new TextEditorScrollbarsProperty (t, document));
  75. props.add (new TextEditorCaretProperty (t, document));
  76. props.add (new TextEditorPopupMenuProperty (t, document));
  77. addColourProperties (t, document, props);
  78. }
  79. String getCreationParameters (GeneratedCode&, Component* component)
  80. {
  81. return quotedString (component->getName(), false);
  82. }
  83. void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName)
  84. {
  85. ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
  86. TextEditor* const te = dynamic_cast<TextEditor*> (component);
  87. jassert (te != 0);
  88. String s;
  89. s << memberVariableName << "->setMultiLine (" << CodeHelpers::boolLiteral (te->isMultiLine()) << ");\n"
  90. << memberVariableName << "->setReturnKeyStartsNewLine (" << CodeHelpers::boolLiteral (te->getReturnKeyStartsNewLine()) << ");\n"
  91. << memberVariableName << "->setReadOnly (" << CodeHelpers::boolLiteral (te->isReadOnly()) << ");\n"
  92. << memberVariableName << "->setScrollbarsShown (" << CodeHelpers::boolLiteral (te->areScrollbarsShown()) << ");\n"
  93. << memberVariableName << "->setCaretVisible (" << CodeHelpers::boolLiteral (te->isCaretVisible()) << ");\n"
  94. << memberVariableName << "->setPopupMenuEnabled (" << CodeHelpers::boolLiteral (te->isPopupMenuEnabled()) << ");\n"
  95. << getColourIntialisationCode (component, memberVariableName)
  96. << memberVariableName << "->setText (" << quotedString (te->getProperties() ["initialText"].toString(), code.shouldUseTransMacro()) << ");\n\n";
  97. code.constructorCode += s;
  98. }
  99. private:
  100. //==============================================================================
  101. class TextEditorMultiLineProperty : public ComponentChoiceProperty <TextEditor>
  102. {
  103. public:
  104. TextEditorMultiLineProperty (TextEditor* comp, JucerDocument& doc)
  105. : ComponentChoiceProperty <TextEditor> ("mode", comp, doc)
  106. {
  107. choices.add ("single line");
  108. choices.add ("multi-line, return key starts new line");
  109. choices.add ("multi-line, return key disabled");
  110. }
  111. void setIndex (int newIndex)
  112. {
  113. document.perform (new TextEditorMultilineChangeAction (component, *document.getComponentLayout(), newIndex),
  114. "Change TextEditor multiline mode");
  115. }
  116. int getIndex() const
  117. {
  118. return component->isMultiLine() ? (component->getReturnKeyStartsNewLine() ? 1 : 2) : 0;
  119. }
  120. private:
  121. class TextEditorMultilineChangeAction : public ComponentUndoableAction <TextEditor>
  122. {
  123. public:
  124. TextEditorMultilineChangeAction (TextEditor* const comp, ComponentLayout& l, const int newState_)
  125. : ComponentUndoableAction <TextEditor> (comp, l),
  126. newState (newState_)
  127. {
  128. oldState = comp->isMultiLine() ? (comp->getReturnKeyStartsNewLine() ? 1 : 2) : 0;
  129. }
  130. bool perform()
  131. {
  132. showCorrectTab();
  133. getComponent()->setMultiLine (newState > 0);
  134. getComponent()->setReturnKeyStartsNewLine (newState == 1);
  135. changed();
  136. return true;
  137. }
  138. bool undo()
  139. {
  140. showCorrectTab();
  141. getComponent()->setMultiLine (oldState > 0);
  142. getComponent()->setReturnKeyStartsNewLine (oldState == 1);
  143. changed();
  144. return true;
  145. }
  146. int newState, oldState;
  147. };
  148. };
  149. //==============================================================================
  150. class TextEditorReadOnlyProperty : public ComponentBooleanProperty <TextEditor>
  151. {
  152. public:
  153. TextEditorReadOnlyProperty (TextEditor* comp, JucerDocument& doc)
  154. : ComponentBooleanProperty <TextEditor> ("editable", "Editable", "Editable", comp, doc)
  155. {
  156. }
  157. void setState (bool newState)
  158. {
  159. document.perform (new TextEditorReadonlyChangeAction (component, *document.getComponentLayout(), ! newState),
  160. "Change TextEditor read-only mode");
  161. }
  162. bool getState() const { return ! component->isReadOnly(); }
  163. private:
  164. class TextEditorReadonlyChangeAction : public ComponentUndoableAction <TextEditor>
  165. {
  166. public:
  167. TextEditorReadonlyChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  168. : ComponentUndoableAction <TextEditor> (comp, l),
  169. newState (newState_)
  170. {
  171. oldState = comp->isReadOnly();
  172. }
  173. bool perform()
  174. {
  175. showCorrectTab();
  176. getComponent()->setReadOnly (newState);
  177. changed();
  178. return true;
  179. }
  180. bool undo()
  181. {
  182. showCorrectTab();
  183. getComponent()->setReadOnly (oldState);
  184. changed();
  185. return true;
  186. }
  187. bool newState, oldState;
  188. };
  189. };
  190. //==============================================================================
  191. class TextEditorScrollbarsProperty : public ComponentBooleanProperty <TextEditor>
  192. {
  193. public:
  194. TextEditorScrollbarsProperty (TextEditor* comp, JucerDocument& doc)
  195. : ComponentBooleanProperty <TextEditor> ("scrollbars", "Scrollbars enabled", "Scrollbars enabled", comp, doc)
  196. {
  197. }
  198. void setState (bool newState)
  199. {
  200. document.perform (new TextEditorScrollbarChangeAction (component, *document.getComponentLayout(), newState),
  201. "Change TextEditor scrollbars");
  202. }
  203. bool getState() const { return component->areScrollbarsShown(); }
  204. private:
  205. class TextEditorScrollbarChangeAction : public ComponentUndoableAction <TextEditor>
  206. {
  207. public:
  208. TextEditorScrollbarChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  209. : ComponentUndoableAction <TextEditor> (comp, l),
  210. newState (newState_)
  211. {
  212. oldState = comp->areScrollbarsShown();
  213. }
  214. bool perform()
  215. {
  216. showCorrectTab();
  217. getComponent()->setScrollbarsShown (newState);
  218. changed();
  219. return true;
  220. }
  221. bool undo()
  222. {
  223. showCorrectTab();
  224. getComponent()->setScrollbarsShown (oldState);
  225. changed();
  226. return true;
  227. }
  228. bool newState, oldState;
  229. };
  230. };
  231. //==============================================================================
  232. class TextEditorCaretProperty : public ComponentBooleanProperty <TextEditor>
  233. {
  234. public:
  235. TextEditorCaretProperty (TextEditor* comp, JucerDocument& doc)
  236. : ComponentBooleanProperty <TextEditor> ("caret", "Caret visible", "Caret visible", comp, doc)
  237. {
  238. }
  239. void setState (bool newState)
  240. {
  241. document.perform (new TextEditorCaretChangeAction (component, *document.getComponentLayout(), newState),
  242. "Change TextEditor caret");
  243. }
  244. bool getState() const { return component->isCaretVisible(); }
  245. private:
  246. class TextEditorCaretChangeAction : public ComponentUndoableAction <TextEditor>
  247. {
  248. public:
  249. TextEditorCaretChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  250. : ComponentUndoableAction <TextEditor> (comp, l),
  251. newState (newState_)
  252. {
  253. oldState = comp->isCaretVisible();
  254. }
  255. bool perform()
  256. {
  257. showCorrectTab();
  258. getComponent()->setCaretVisible (newState);
  259. changed();
  260. return true;
  261. }
  262. bool undo()
  263. {
  264. showCorrectTab();
  265. getComponent()->setCaretVisible (oldState);
  266. changed();
  267. return true;
  268. }
  269. bool newState, oldState;
  270. };
  271. };
  272. //==============================================================================
  273. class TextEditorPopupMenuProperty : public ComponentBooleanProperty <TextEditor>
  274. {
  275. public:
  276. TextEditorPopupMenuProperty (TextEditor* comp, JucerDocument& doc)
  277. : ComponentBooleanProperty <TextEditor> ("popup menu", "Popup menu enabled", "Popup menu enabled", comp, doc)
  278. {
  279. }
  280. void setState (bool newState)
  281. {
  282. document.perform (new TextEditorPopupMenuChangeAction (component, *document.getComponentLayout(), newState),
  283. "Change TextEditor popup menu");
  284. }
  285. bool getState() const { return component->isPopupMenuEnabled(); }
  286. private:
  287. class TextEditorPopupMenuChangeAction : public ComponentUndoableAction <TextEditor>
  288. {
  289. public:
  290. TextEditorPopupMenuChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  291. : ComponentUndoableAction <TextEditor> (comp, l),
  292. newState (newState_)
  293. {
  294. oldState = comp->isPopupMenuEnabled();
  295. }
  296. bool perform()
  297. {
  298. showCorrectTab();
  299. getComponent()->setPopupMenuEnabled (newState);
  300. changed();
  301. return true;
  302. }
  303. bool undo()
  304. {
  305. showCorrectTab();
  306. getComponent()->setPopupMenuEnabled (oldState);
  307. changed();
  308. return true;
  309. }
  310. bool newState, oldState;
  311. };
  312. };
  313. //==============================================================================
  314. class TextEditorInitialTextProperty : public ComponentTextProperty <TextEditor>
  315. {
  316. public:
  317. TextEditorInitialTextProperty (TextEditor* comp, JucerDocument& doc)
  318. : ComponentTextProperty <TextEditor> ("initial text", 10000, true, comp, doc)
  319. {}
  320. void setText (const String& newText) override
  321. {
  322. document.perform (new TextEditorInitialTextChangeAction (component, *document.getComponentLayout(), newText),
  323. "Change TextEditor initial text");
  324. }
  325. String getText() const override
  326. {
  327. return component->getProperties() ["initialText"];
  328. }
  329. private:
  330. class TextEditorInitialTextChangeAction : public ComponentUndoableAction <TextEditor>
  331. {
  332. public:
  333. TextEditorInitialTextChangeAction (TextEditor* const comp, ComponentLayout& l, const String& newState_)
  334. : ComponentUndoableAction <TextEditor> (comp, l),
  335. newState (newState_)
  336. {
  337. oldState = comp->getProperties() ["initialText"];
  338. }
  339. bool perform()
  340. {
  341. showCorrectTab();
  342. getComponent()->setText (newState, false);
  343. getComponent()->getProperties().set ("initialText", newState);
  344. changed();
  345. return true;
  346. }
  347. bool undo()
  348. {
  349. showCorrectTab();
  350. getComponent()->setText (oldState, false);
  351. getComponent()->getProperties().set ("initialText", oldState);
  352. changed();
  353. return true;
  354. }
  355. String newState, oldState;
  356. };
  357. };
  358. };