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) 2020 - 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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-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. auto te = dynamic_cast<TextEditor*> (component);
  92. jassert (te != nullptr);
  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. private:
  105. //==============================================================================
  106. class TextEditorMultiLineProperty : public ComponentChoiceProperty <TextEditor>
  107. {
  108. public:
  109. TextEditorMultiLineProperty (TextEditor* comp, JucerDocument& doc)
  110. : ComponentChoiceProperty <TextEditor> ("mode", comp, doc)
  111. {
  112. choices.add ("single line");
  113. choices.add ("multi-line, return key starts new line");
  114. choices.add ("multi-line, return key disabled");
  115. }
  116. void setIndex (int newIndex)
  117. {
  118. document.perform (new TextEditorMultilineChangeAction (component, *document.getComponentLayout(), newIndex),
  119. "Change TextEditor multiline mode");
  120. }
  121. int getIndex() const
  122. {
  123. return component->isMultiLine() ? (component->getReturnKeyStartsNewLine() ? 1 : 2) : 0;
  124. }
  125. private:
  126. class TextEditorMultilineChangeAction : public ComponentUndoableAction <TextEditor>
  127. {
  128. public:
  129. TextEditorMultilineChangeAction (TextEditor* const comp, ComponentLayout& l, const int newState_)
  130. : ComponentUndoableAction <TextEditor> (comp, l),
  131. newState (newState_)
  132. {
  133. oldState = comp->isMultiLine() ? (comp->getReturnKeyStartsNewLine() ? 1 : 2) : 0;
  134. }
  135. bool perform()
  136. {
  137. showCorrectTab();
  138. getComponent()->setMultiLine (newState > 0);
  139. getComponent()->setReturnKeyStartsNewLine (newState == 1);
  140. changed();
  141. return true;
  142. }
  143. bool undo()
  144. {
  145. showCorrectTab();
  146. getComponent()->setMultiLine (oldState > 0);
  147. getComponent()->setReturnKeyStartsNewLine (oldState == 1);
  148. changed();
  149. return true;
  150. }
  151. int newState, oldState;
  152. };
  153. };
  154. //==============================================================================
  155. class TextEditorReadOnlyProperty : public ComponentBooleanProperty <TextEditor>
  156. {
  157. public:
  158. TextEditorReadOnlyProperty (TextEditor* comp, JucerDocument& doc)
  159. : ComponentBooleanProperty <TextEditor> ("editable", "Editable", "Editable", comp, doc)
  160. {
  161. }
  162. void setState (bool newState)
  163. {
  164. document.perform (new TextEditorReadonlyChangeAction (component, *document.getComponentLayout(), ! newState),
  165. "Change TextEditor read-only mode");
  166. }
  167. bool getState() const { return ! component->isReadOnly(); }
  168. private:
  169. class TextEditorReadonlyChangeAction : public ComponentUndoableAction <TextEditor>
  170. {
  171. public:
  172. TextEditorReadonlyChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  173. : ComponentUndoableAction <TextEditor> (comp, l),
  174. newState (newState_)
  175. {
  176. oldState = comp->isReadOnly();
  177. }
  178. bool perform()
  179. {
  180. showCorrectTab();
  181. getComponent()->setReadOnly (newState);
  182. changed();
  183. return true;
  184. }
  185. bool undo()
  186. {
  187. showCorrectTab();
  188. getComponent()->setReadOnly (oldState);
  189. changed();
  190. return true;
  191. }
  192. bool newState, oldState;
  193. };
  194. };
  195. //==============================================================================
  196. class TextEditorScrollbarsProperty : public ComponentBooleanProperty <TextEditor>
  197. {
  198. public:
  199. TextEditorScrollbarsProperty (TextEditor* comp, JucerDocument& doc)
  200. : ComponentBooleanProperty <TextEditor> ("scrollbars", "Scrollbars enabled", "Scrollbars enabled", comp, doc)
  201. {
  202. }
  203. void setState (bool newState)
  204. {
  205. document.perform (new TextEditorScrollbarChangeAction (component, *document.getComponentLayout(), newState),
  206. "Change TextEditor scrollbars");
  207. }
  208. bool getState() const { return component->areScrollbarsShown(); }
  209. private:
  210. class TextEditorScrollbarChangeAction : public ComponentUndoableAction <TextEditor>
  211. {
  212. public:
  213. TextEditorScrollbarChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  214. : ComponentUndoableAction <TextEditor> (comp, l),
  215. newState (newState_)
  216. {
  217. oldState = comp->areScrollbarsShown();
  218. }
  219. bool perform()
  220. {
  221. showCorrectTab();
  222. getComponent()->setScrollbarsShown (newState);
  223. changed();
  224. return true;
  225. }
  226. bool undo()
  227. {
  228. showCorrectTab();
  229. getComponent()->setScrollbarsShown (oldState);
  230. changed();
  231. return true;
  232. }
  233. bool newState, oldState;
  234. };
  235. };
  236. //==============================================================================
  237. class TextEditorCaretProperty : public ComponentBooleanProperty <TextEditor>
  238. {
  239. public:
  240. TextEditorCaretProperty (TextEditor* comp, JucerDocument& doc)
  241. : ComponentBooleanProperty <TextEditor> ("caret", "Caret visible", "Caret visible", comp, doc)
  242. {
  243. }
  244. void setState (bool newState)
  245. {
  246. document.perform (new TextEditorCaretChangeAction (component, *document.getComponentLayout(), newState),
  247. "Change TextEditor caret");
  248. }
  249. bool getState() const { return component->isCaretVisible(); }
  250. private:
  251. class TextEditorCaretChangeAction : public ComponentUndoableAction <TextEditor>
  252. {
  253. public:
  254. TextEditorCaretChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  255. : ComponentUndoableAction <TextEditor> (comp, l),
  256. newState (newState_)
  257. {
  258. oldState = comp->isCaretVisible();
  259. }
  260. bool perform()
  261. {
  262. showCorrectTab();
  263. getComponent()->setCaretVisible (newState);
  264. changed();
  265. return true;
  266. }
  267. bool undo()
  268. {
  269. showCorrectTab();
  270. getComponent()->setCaretVisible (oldState);
  271. changed();
  272. return true;
  273. }
  274. bool newState, oldState;
  275. };
  276. };
  277. //==============================================================================
  278. class TextEditorPopupMenuProperty : public ComponentBooleanProperty <TextEditor>
  279. {
  280. public:
  281. TextEditorPopupMenuProperty (TextEditor* comp, JucerDocument& doc)
  282. : ComponentBooleanProperty <TextEditor> ("popup menu", "Popup menu enabled", "Popup menu enabled", comp, doc)
  283. {
  284. }
  285. void setState (bool newState)
  286. {
  287. document.perform (new TextEditorPopupMenuChangeAction (component, *document.getComponentLayout(), newState),
  288. "Change TextEditor popup menu");
  289. }
  290. bool getState() const { return component->isPopupMenuEnabled(); }
  291. private:
  292. class TextEditorPopupMenuChangeAction : public ComponentUndoableAction <TextEditor>
  293. {
  294. public:
  295. TextEditorPopupMenuChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  296. : ComponentUndoableAction <TextEditor> (comp, l),
  297. newState (newState_)
  298. {
  299. oldState = comp->isPopupMenuEnabled();
  300. }
  301. bool perform()
  302. {
  303. showCorrectTab();
  304. getComponent()->setPopupMenuEnabled (newState);
  305. changed();
  306. return true;
  307. }
  308. bool undo()
  309. {
  310. showCorrectTab();
  311. getComponent()->setPopupMenuEnabled (oldState);
  312. changed();
  313. return true;
  314. }
  315. bool newState, oldState;
  316. };
  317. };
  318. //==============================================================================
  319. class TextEditorInitialTextProperty : public ComponentTextProperty <TextEditor>
  320. {
  321. public:
  322. TextEditorInitialTextProperty (TextEditor* comp, JucerDocument& doc)
  323. : ComponentTextProperty <TextEditor> ("initial text", 10000, true, comp, doc)
  324. {}
  325. void setText (const String& newText) override
  326. {
  327. document.perform (new TextEditorInitialTextChangeAction (component, *document.getComponentLayout(), newText),
  328. "Change TextEditor initial text");
  329. }
  330. String getText() const override
  331. {
  332. return component->getProperties() ["initialText"];
  333. }
  334. private:
  335. class TextEditorInitialTextChangeAction : public ComponentUndoableAction <TextEditor>
  336. {
  337. public:
  338. TextEditorInitialTextChangeAction (TextEditor* const comp, ComponentLayout& l, const String& newState_)
  339. : ComponentUndoableAction <TextEditor> (comp, l),
  340. newState (newState_)
  341. {
  342. oldState = comp->getProperties() ["initialText"];
  343. }
  344. bool perform()
  345. {
  346. showCorrectTab();
  347. getComponent()->setText (newState, false);
  348. getComponent()->getProperties().set ("initialText", newState);
  349. changed();
  350. return true;
  351. }
  352. bool undo()
  353. {
  354. showCorrectTab();
  355. getComponent()->setText (oldState, false);
  356. getComponent()->getProperties().set ("initialText", oldState);
  357. changed();
  358. return true;
  359. }
  360. String newState, oldState;
  361. };
  362. };
  363. };