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.

431 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*) override
  33. {
  34. return new TextEditor ("new text editor");
  35. }
  36. XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout) override
  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) override
  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,
  67. Array<PropertyComponent*>& props, bool multipleSelected) override
  68. {
  69. ComponentTypeHandler::getEditableProperties (component, document, props, multipleSelected);
  70. if (multipleSelected)
  71. return;
  72. if (auto* t = dynamic_cast<TextEditor*> (component))
  73. {
  74. props.add (new TextEditorInitialTextProperty (t, document));
  75. props.add (new TextEditorMultiLineProperty (t, document));
  76. props.add (new TextEditorReadOnlyProperty (t, document));
  77. props.add (new TextEditorScrollbarsProperty (t, document));
  78. props.add (new TextEditorCaretProperty (t, document));
  79. props.add (new TextEditorPopupMenuProperty (t, document));
  80. addColourProperties (t, document, props);
  81. }
  82. }
  83. String getCreationParameters (GeneratedCode&, Component* component) override
  84. {
  85. return quotedString (component->getName(), false);
  86. }
  87. void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName) override
  88. {
  89. ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
  90. TextEditor* const te = dynamic_cast<TextEditor*> (component);
  91. jassert (te != 0);
  92. String s;
  93. s << memberVariableName << "->setMultiLine (" << CodeHelpers::boolLiteral (te->isMultiLine()) << ");\n"
  94. << memberVariableName << "->setReturnKeyStartsNewLine (" << CodeHelpers::boolLiteral (te->getReturnKeyStartsNewLine()) << ");\n"
  95. << memberVariableName << "->setReadOnly (" << CodeHelpers::boolLiteral (te->isReadOnly()) << ");\n"
  96. << memberVariableName << "->setScrollbarsShown (" << CodeHelpers::boolLiteral (te->areScrollbarsShown()) << ");\n"
  97. << memberVariableName << "->setCaretVisible (" << CodeHelpers::boolLiteral (te->isCaretVisible()) << ");\n"
  98. << memberVariableName << "->setPopupMenuEnabled (" << CodeHelpers::boolLiteral (te->isPopupMenuEnabled()) << ");\n"
  99. << getColourIntialisationCode (component, memberVariableName)
  100. << memberVariableName << "->setText (" << quotedString (te->getProperties() ["initialText"].toString(), code.shouldUseTransMacro()) << ");\n\n";
  101. code.constructorCode += s;
  102. }
  103. private:
  104. //==============================================================================
  105. class TextEditorMultiLineProperty : public ComponentChoiceProperty <TextEditor>
  106. {
  107. public:
  108. TextEditorMultiLineProperty (TextEditor* comp, JucerDocument& doc)
  109. : ComponentChoiceProperty <TextEditor> ("mode", comp, doc)
  110. {
  111. choices.add ("single line");
  112. choices.add ("multi-line, return key starts new line");
  113. choices.add ("multi-line, return key disabled");
  114. }
  115. void setIndex (int newIndex)
  116. {
  117. document.perform (new TextEditorMultilineChangeAction (component, *document.getComponentLayout(), newIndex),
  118. "Change TextEditor multiline mode");
  119. }
  120. int getIndex() const
  121. {
  122. return component->isMultiLine() ? (component->getReturnKeyStartsNewLine() ? 1 : 2) : 0;
  123. }
  124. private:
  125. class TextEditorMultilineChangeAction : public ComponentUndoableAction <TextEditor>
  126. {
  127. public:
  128. TextEditorMultilineChangeAction (TextEditor* const comp, ComponentLayout& l, const int newState_)
  129. : ComponentUndoableAction <TextEditor> (comp, l),
  130. newState (newState_)
  131. {
  132. oldState = comp->isMultiLine() ? (comp->getReturnKeyStartsNewLine() ? 1 : 2) : 0;
  133. }
  134. bool perform()
  135. {
  136. showCorrectTab();
  137. getComponent()->setMultiLine (newState > 0);
  138. getComponent()->setReturnKeyStartsNewLine (newState == 1);
  139. changed();
  140. return true;
  141. }
  142. bool undo()
  143. {
  144. showCorrectTab();
  145. getComponent()->setMultiLine (oldState > 0);
  146. getComponent()->setReturnKeyStartsNewLine (oldState == 1);
  147. changed();
  148. return true;
  149. }
  150. int newState, oldState;
  151. };
  152. };
  153. //==============================================================================
  154. class TextEditorReadOnlyProperty : public ComponentBooleanProperty <TextEditor>
  155. {
  156. public:
  157. TextEditorReadOnlyProperty (TextEditor* comp, JucerDocument& doc)
  158. : ComponentBooleanProperty <TextEditor> ("editable", "Editable", "Editable", comp, doc)
  159. {
  160. }
  161. void setState (bool newState)
  162. {
  163. document.perform (new TextEditorReadonlyChangeAction (component, *document.getComponentLayout(), ! newState),
  164. "Change TextEditor read-only mode");
  165. }
  166. bool getState() const { return ! component->isReadOnly(); }
  167. private:
  168. class TextEditorReadonlyChangeAction : public ComponentUndoableAction <TextEditor>
  169. {
  170. public:
  171. TextEditorReadonlyChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  172. : ComponentUndoableAction <TextEditor> (comp, l),
  173. newState (newState_)
  174. {
  175. oldState = comp->isReadOnly();
  176. }
  177. bool perform()
  178. {
  179. showCorrectTab();
  180. getComponent()->setReadOnly (newState);
  181. changed();
  182. return true;
  183. }
  184. bool undo()
  185. {
  186. showCorrectTab();
  187. getComponent()->setReadOnly (oldState);
  188. changed();
  189. return true;
  190. }
  191. bool newState, oldState;
  192. };
  193. };
  194. //==============================================================================
  195. class TextEditorScrollbarsProperty : public ComponentBooleanProperty <TextEditor>
  196. {
  197. public:
  198. TextEditorScrollbarsProperty (TextEditor* comp, JucerDocument& doc)
  199. : ComponentBooleanProperty <TextEditor> ("scrollbars", "Scrollbars enabled", "Scrollbars enabled", comp, doc)
  200. {
  201. }
  202. void setState (bool newState)
  203. {
  204. document.perform (new TextEditorScrollbarChangeAction (component, *document.getComponentLayout(), newState),
  205. "Change TextEditor scrollbars");
  206. }
  207. bool getState() const { return component->areScrollbarsShown(); }
  208. private:
  209. class TextEditorScrollbarChangeAction : public ComponentUndoableAction <TextEditor>
  210. {
  211. public:
  212. TextEditorScrollbarChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  213. : ComponentUndoableAction <TextEditor> (comp, l),
  214. newState (newState_)
  215. {
  216. oldState = comp->areScrollbarsShown();
  217. }
  218. bool perform()
  219. {
  220. showCorrectTab();
  221. getComponent()->setScrollbarsShown (newState);
  222. changed();
  223. return true;
  224. }
  225. bool undo()
  226. {
  227. showCorrectTab();
  228. getComponent()->setScrollbarsShown (oldState);
  229. changed();
  230. return true;
  231. }
  232. bool newState, oldState;
  233. };
  234. };
  235. //==============================================================================
  236. class TextEditorCaretProperty : public ComponentBooleanProperty <TextEditor>
  237. {
  238. public:
  239. TextEditorCaretProperty (TextEditor* comp, JucerDocument& doc)
  240. : ComponentBooleanProperty <TextEditor> ("caret", "Caret visible", "Caret visible", comp, doc)
  241. {
  242. }
  243. void setState (bool newState)
  244. {
  245. document.perform (new TextEditorCaretChangeAction (component, *document.getComponentLayout(), newState),
  246. "Change TextEditor caret");
  247. }
  248. bool getState() const { return component->isCaretVisible(); }
  249. private:
  250. class TextEditorCaretChangeAction : public ComponentUndoableAction <TextEditor>
  251. {
  252. public:
  253. TextEditorCaretChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  254. : ComponentUndoableAction <TextEditor> (comp, l),
  255. newState (newState_)
  256. {
  257. oldState = comp->isCaretVisible();
  258. }
  259. bool perform()
  260. {
  261. showCorrectTab();
  262. getComponent()->setCaretVisible (newState);
  263. changed();
  264. return true;
  265. }
  266. bool undo()
  267. {
  268. showCorrectTab();
  269. getComponent()->setCaretVisible (oldState);
  270. changed();
  271. return true;
  272. }
  273. bool newState, oldState;
  274. };
  275. };
  276. //==============================================================================
  277. class TextEditorPopupMenuProperty : public ComponentBooleanProperty <TextEditor>
  278. {
  279. public:
  280. TextEditorPopupMenuProperty (TextEditor* comp, JucerDocument& doc)
  281. : ComponentBooleanProperty <TextEditor> ("popup menu", "Popup menu enabled", "Popup menu enabled", comp, doc)
  282. {
  283. }
  284. void setState (bool newState)
  285. {
  286. document.perform (new TextEditorPopupMenuChangeAction (component, *document.getComponentLayout(), newState),
  287. "Change TextEditor popup menu");
  288. }
  289. bool getState() const { return component->isPopupMenuEnabled(); }
  290. private:
  291. class TextEditorPopupMenuChangeAction : public ComponentUndoableAction <TextEditor>
  292. {
  293. public:
  294. TextEditorPopupMenuChangeAction (TextEditor* const comp, ComponentLayout& l, const bool newState_)
  295. : ComponentUndoableAction <TextEditor> (comp, l),
  296. newState (newState_)
  297. {
  298. oldState = comp->isPopupMenuEnabled();
  299. }
  300. bool perform()
  301. {
  302. showCorrectTab();
  303. getComponent()->setPopupMenuEnabled (newState);
  304. changed();
  305. return true;
  306. }
  307. bool undo()
  308. {
  309. showCorrectTab();
  310. getComponent()->setPopupMenuEnabled (oldState);
  311. changed();
  312. return true;
  313. }
  314. bool newState, oldState;
  315. };
  316. };
  317. //==============================================================================
  318. class TextEditorInitialTextProperty : public ComponentTextProperty <TextEditor>
  319. {
  320. public:
  321. TextEditorInitialTextProperty (TextEditor* comp, JucerDocument& doc)
  322. : ComponentTextProperty <TextEditor> ("initial text", 10000, true, comp, doc)
  323. {}
  324. void setText (const String& newText) override
  325. {
  326. document.perform (new TextEditorInitialTextChangeAction (component, *document.getComponentLayout(), newText),
  327. "Change TextEditor initial text");
  328. }
  329. String getText() const override
  330. {
  331. return component->getProperties() ["initialText"];
  332. }
  333. private:
  334. class TextEditorInitialTextChangeAction : public ComponentUndoableAction <TextEditor>
  335. {
  336. public:
  337. TextEditorInitialTextChangeAction (TextEditor* const comp, ComponentLayout& l, const String& newState_)
  338. : ComponentUndoableAction <TextEditor> (comp, l),
  339. newState (newState_)
  340. {
  341. oldState = comp->getProperties() ["initialText"];
  342. }
  343. bool perform()
  344. {
  345. showCorrectTab();
  346. getComponent()->setText (newState, false);
  347. getComponent()->getProperties().set ("initialText", newState);
  348. changed();
  349. return true;
  350. }
  351. bool undo()
  352. {
  353. showCorrectTab();
  354. getComponent()->setText (oldState, false);
  355. getComponent()->getProperties().set ("initialText", oldState);
  356. changed();
  357. return true;
  358. }
  359. String newState, oldState;
  360. };
  361. };
  362. };