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.

425 lines
16KB

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