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.

434 lines
16KB

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