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.

659 lines
23KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software 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 ViewportHandler : public ComponentTypeHandler
  18. {
  19. public:
  20. ViewportHandler()
  21. : ComponentTypeHandler ("Viewport", "Viewport", typeid (UpdatingViewport), 150, 150)
  22. {}
  23. Component* createNewComponent (JucerDocument*)
  24. {
  25. Viewport* const v = new UpdatingViewport ("new viewport");
  26. v->setViewedComponent (new ViewportDemoContentComp());
  27. return v;
  28. }
  29. XmlElement* createXmlFor (Component* comp, const ComponentLayout* layout)
  30. {
  31. Viewport* const v = dynamic_cast <Viewport*> (comp);
  32. XmlElement* const e = ComponentTypeHandler::createXmlFor (comp, layout);
  33. e->setAttribute ("vscroll", v->isVerticalScrollBarShown());
  34. e->setAttribute ("hscroll", v->isHorizontalScrollBarShown());
  35. e->setAttribute ("scrollbarThickness", v->getScrollBarThickness());
  36. e->setAttribute ("contentType", getViewportContentType (v));
  37. e->setAttribute ("jucerFile", getViewportJucerComponentFile (v));
  38. e->setAttribute ("contentClass", getViewportGenericComponentClass (v));
  39. e->setAttribute ("constructorParams", getViewportConstructorParams (v));
  40. return e;
  41. }
  42. bool restoreFromXml (const XmlElement& xml, Component* comp, const ComponentLayout* layout)
  43. {
  44. if (! ComponentTypeHandler::restoreFromXml (xml, comp, layout))
  45. return false;
  46. Viewport defaultViewport;
  47. Viewport* const v = dynamic_cast <Viewport*> (comp);
  48. v->setScrollBarsShown (xml.getBoolAttribute ("vscroll", defaultViewport.isVerticalScrollBarShown()),
  49. xml.getBoolAttribute ("hscroll", defaultViewport.isHorizontalScrollBarShown()));
  50. v->setScrollBarThickness (xml.getIntAttribute ("scrollbarThickness", defaultViewport.getScrollBarThickness()));
  51. setViewportJucerComponentFile (v, xml.getStringAttribute ("jucerFile", String::empty));
  52. setViewportGenericComponentClass (v, xml.getStringAttribute ("contentClass"));
  53. setViewportContentType (v, xml.getIntAttribute ("contentType", 0));
  54. setViewportConstructorParams (v, xml.getStringAttribute ("constructorParams"));
  55. return true;
  56. }
  57. void getEditableProperties (Component* component, JucerDocument& document, Array <PropertyComponent*>& properties)
  58. {
  59. ComponentTypeHandler::getEditableProperties (component, document, properties);
  60. Viewport* const v = dynamic_cast <Viewport*> (component);
  61. properties.add (new ViewportScrollbarShownProperty (v, document, true));
  62. properties.add (new ViewportScrollbarShownProperty (v, document, false));
  63. properties.add (new ViewportScrollbarSizeProperty (v, document));
  64. properties.add (new ViewportContentTypeProperty (v, document));
  65. if (getViewportContentType (v) == 1)
  66. {
  67. properties.add (new ViewportJucerFileProperty (v, document));
  68. properties.add (new ConstructorParamsProperty (v, document));
  69. }
  70. else if (getViewportContentType (v) == 2)
  71. {
  72. properties.add (new ViewportContentClassProperty (v, document));
  73. properties.add (new ConstructorParamsProperty (v, document));
  74. }
  75. }
  76. String getCreationParameters (Component* comp)
  77. {
  78. return quotedString (comp->getName());
  79. }
  80. void fillInCreationCode (GeneratedCode& code, Component* component, const String& memberVariableName)
  81. {
  82. Viewport defaultViewport;
  83. Viewport* const v = dynamic_cast <Viewport*> (component);
  84. ComponentTypeHandler::fillInCreationCode (code, component, memberVariableName);
  85. if (defaultViewport.isVerticalScrollBarShown() != v->isVerticalScrollBarShown()
  86. || defaultViewport.isHorizontalScrollBarShown() != v->isHorizontalScrollBarShown())
  87. {
  88. code.constructorCode
  89. << memberVariableName << "->setScrollBarsShown ("
  90. << CodeHelpers::boolLiteral (v->isVerticalScrollBarShown()) << ", "
  91. << CodeHelpers::boolLiteral (v->isHorizontalScrollBarShown()) << ");\n";
  92. }
  93. if (defaultViewport.getScrollBarThickness() != v->getScrollBarThickness())
  94. {
  95. code.constructorCode
  96. << memberVariableName << "->setScrollBarThickness ("
  97. << v->getScrollBarThickness() << ");\n";
  98. }
  99. if (getViewportContentType (v) != 0)
  100. {
  101. String className (getViewportGenericComponentClass (v));
  102. if (getViewportContentType (v) == 1)
  103. {
  104. File file;
  105. const String filename (getViewportJucerComponentFile (v));
  106. if (filename.isNotEmpty())
  107. file = code.document->getCppFile().getSiblingFile (filename);
  108. ScopedPointer<JucerDocument> doc (JucerDocument::createForCppFile (nullptr, file));
  109. if (doc != nullptr)
  110. {
  111. code.includeFilesCPP.add (doc->getHeaderFile()
  112. .getRelativePathFrom (code.document->getCppFile().getParentDirectory())
  113. .replaceCharacter ('\\', '/'));
  114. className = doc->getClassName();
  115. }
  116. else
  117. {
  118. className = String::empty;
  119. }
  120. }
  121. if (className.isNotEmpty())
  122. {
  123. code.constructorCode
  124. << memberVariableName << "->setViewedComponent (new "
  125. << className;
  126. if (getViewportConstructorParams (v).trim().isNotEmpty())
  127. {
  128. code.constructorCode << " (" << getViewportConstructorParams (v).trim() << "));\n";
  129. }
  130. else
  131. {
  132. code.constructorCode << "());\n";
  133. }
  134. }
  135. }
  136. code.constructorCode << "\n";
  137. }
  138. static void updateViewportContentComp (Viewport* vp)
  139. {
  140. if (getViewportContentType (vp) == 1)
  141. {
  142. JucerDocument* doc = findParentDocument (vp);
  143. TestComponent* tc = new TestComponent (doc, 0, false);
  144. tc->setFilename (getViewportJucerComponentFile (vp));
  145. tc->setToInitialSize();
  146. vp->setViewedComponent (tc);
  147. }
  148. else
  149. {
  150. vp->setViewedComponent (new ViewportDemoContentComp());
  151. }
  152. }
  153. static int getViewportContentType (Viewport* vp)
  154. {
  155. return vp->getProperties() ["contentType"];
  156. }
  157. static void setViewportContentType (Viewport* vp, int newValue)
  158. {
  159. if (newValue != getViewportContentType (vp))
  160. {
  161. vp->getProperties().set ("contentType", newValue);
  162. updateViewportContentComp (vp);
  163. }
  164. }
  165. static String getViewportJucerComponentFile (Viewport* vp)
  166. {
  167. return vp->getProperties() ["jucerFile"].toString();
  168. }
  169. static void setViewportJucerComponentFile (Viewport* vp, const String& file)
  170. {
  171. if (file != getViewportJucerComponentFile (vp))
  172. {
  173. vp->getProperties().set ("jucerFile", file);
  174. updateViewportContentComp (vp);
  175. }
  176. }
  177. static String getViewportGenericComponentClass (Viewport* vp)
  178. {
  179. return vp->getProperties() ["contentClass"].toString();
  180. }
  181. static void setViewportGenericComponentClass (Viewport* vp, const String& className)
  182. {
  183. if (className != getViewportGenericComponentClass (vp))
  184. {
  185. vp->getProperties().set ("contentClass", className);
  186. updateViewportContentComp (vp);
  187. }
  188. }
  189. static String getViewportConstructorParams (Viewport* vp)
  190. {
  191. return vp->getProperties() ["constructorParams"].toString();
  192. }
  193. static void setViewportConstructorParams (Viewport* vp, const String& newParams)
  194. {
  195. if (newParams != getViewportConstructorParams (vp))
  196. {
  197. vp->getProperties().set ("constructorParams", newParams);
  198. updateViewportContentComp (vp);
  199. }
  200. }
  201. private:
  202. //==============================================================================
  203. class UpdatingViewport : public Viewport
  204. {
  205. public:
  206. UpdatingViewport (const String& name)
  207. : Viewport (name)
  208. {
  209. }
  210. void parentHierarchyChanged()
  211. {
  212. Viewport::parentHierarchyChanged();
  213. updateViewportContentComp (this);
  214. }
  215. };
  216. //==============================================================================
  217. class ViewportDemoContentComp : public Component
  218. {
  219. public:
  220. ViewportDemoContentComp()
  221. {
  222. setSize (2048, 2048);
  223. }
  224. void paint (Graphics& g)
  225. {
  226. g.fillCheckerBoard (getLocalBounds(), 50, 50,
  227. Colours::lightgrey.withAlpha (0.5f),
  228. Colours::darkgrey.withAlpha (0.5f));
  229. }
  230. };
  231. //==============================================================================
  232. class ViewportScrollbarShownProperty : public ComponentBooleanProperty <Viewport>
  233. {
  234. public:
  235. ViewportScrollbarShownProperty (Viewport* comp, JucerDocument& document, const bool vertical_)
  236. : ComponentBooleanProperty <Viewport> (vertical_ ? "V scrollbar" : "H scrollbar",
  237. "enabled", "enabled",
  238. comp, document),
  239. vertical (vertical_)
  240. {
  241. }
  242. void setState (bool newState)
  243. {
  244. document.perform (new ViewportScrollbarChangeAction (component, *document.getComponentLayout(), vertical, newState),
  245. "Change Viewport scrollbar");
  246. }
  247. bool getState() const
  248. {
  249. return vertical ? component->isVerticalScrollBarShown()
  250. : component->isHorizontalScrollBarShown();
  251. }
  252. const bool vertical;
  253. private:
  254. class ViewportScrollbarChangeAction : public ComponentUndoableAction <Viewport>
  255. {
  256. public:
  257. ViewportScrollbarChangeAction (Viewport* const comp, ComponentLayout& layout, const bool vertical_, const bool newState_)
  258. : ComponentUndoableAction <Viewport> (comp, layout),
  259. vertical (vertical_),
  260. newState (newState_)
  261. {
  262. oldState = vertical ? comp->isVerticalScrollBarShown()
  263. : comp->isHorizontalScrollBarShown();
  264. }
  265. bool perform()
  266. {
  267. showCorrectTab();
  268. if (vertical)
  269. getComponent()->setScrollBarsShown (newState, getComponent()->isHorizontalScrollBarShown());
  270. else
  271. getComponent()->setScrollBarsShown (getComponent()->isVerticalScrollBarShown(), newState);
  272. changed();
  273. return true;
  274. }
  275. bool undo()
  276. {
  277. showCorrectTab();
  278. if (vertical)
  279. getComponent()->setScrollBarsShown (oldState, getComponent()->isHorizontalScrollBarShown());
  280. else
  281. getComponent()->setScrollBarsShown (getComponent()->isVerticalScrollBarShown(), oldState);
  282. changed();
  283. return true;
  284. }
  285. bool vertical, newState, oldState;
  286. };
  287. };
  288. //==============================================================================
  289. class ViewportScrollbarSizeProperty : public SliderPropertyComponent,
  290. public ChangeListener
  291. {
  292. public:
  293. ViewportScrollbarSizeProperty (Viewport* comp, JucerDocument& doc)
  294. : SliderPropertyComponent ("scrollbar size", 3.0, 30.0, 1.0, 1.0),
  295. component (comp),
  296. document (doc)
  297. {
  298. document.addChangeListener (this);
  299. }
  300. ~ViewportScrollbarSizeProperty()
  301. {
  302. document.removeChangeListener (this);
  303. }
  304. void setValue (double newValue)
  305. {
  306. document.getUndoManager().undoCurrentTransactionOnly();
  307. document.perform (new ViewportScrollbarSizeChangeAction (component, *document.getComponentLayout(), roundToInt (newValue)),
  308. "Change Viewport scrollbar size");
  309. }
  310. double getValue() const
  311. {
  312. return component->getScrollBarThickness();
  313. }
  314. void changeListenerCallback (ChangeBroadcaster*)
  315. {
  316. refresh();
  317. }
  318. Viewport* component;
  319. JucerDocument& document;
  320. private:
  321. class ViewportScrollbarSizeChangeAction : public ComponentUndoableAction <Viewport>
  322. {
  323. public:
  324. ViewportScrollbarSizeChangeAction (Viewport* const comp, ComponentLayout& layout, const int newState_)
  325. : ComponentUndoableAction <Viewport> (comp, layout),
  326. newState (newState_)
  327. {
  328. oldState = comp->getScrollBarThickness();
  329. }
  330. bool perform()
  331. {
  332. showCorrectTab();
  333. getComponent()->setScrollBarThickness (newState);
  334. changed();
  335. return true;
  336. }
  337. bool undo()
  338. {
  339. showCorrectTab();
  340. getComponent()->setScrollBarThickness (newState);
  341. changed();
  342. return true;
  343. }
  344. int newState, oldState;
  345. };
  346. };
  347. //==============================================================================
  348. class ViewportContentTypeProperty : public ComponentChoiceProperty <Viewport>
  349. {
  350. public:
  351. ViewportContentTypeProperty (Viewport* comp, JucerDocument& document)
  352. : ComponentChoiceProperty <Viewport> ("content", comp, document)
  353. {
  354. choices.add ("No content component");
  355. choices.add ("Jucer content component");
  356. choices.add ("Named content component");
  357. }
  358. void setIndex (int newIndex)
  359. {
  360. document.perform (new ViewportContentTypeChangeAction (component, *document.getComponentLayout(), newIndex),
  361. "Change Viewport content type");
  362. }
  363. int getIndex() const
  364. {
  365. return getViewportContentType (component);
  366. }
  367. private:
  368. class ViewportContentTypeChangeAction : public ComponentUndoableAction <Viewport>
  369. {
  370. public:
  371. ViewportContentTypeChangeAction (Viewport* const comp, ComponentLayout& layout, const int newValue_)
  372. : ComponentUndoableAction <Viewport> (comp, layout),
  373. newValue (newValue_)
  374. {
  375. oldValue = getViewportContentType (comp);
  376. }
  377. bool perform()
  378. {
  379. showCorrectTab();
  380. setViewportContentType (getComponent(), newValue);
  381. changed();
  382. layout.getDocument()->refreshAllPropertyComps();
  383. return true;
  384. }
  385. bool undo()
  386. {
  387. showCorrectTab();
  388. setViewportContentType (getComponent(), oldValue);
  389. changed();
  390. layout.getDocument()->refreshAllPropertyComps();
  391. return true;
  392. }
  393. int newValue, oldValue;
  394. };
  395. };
  396. //==============================================================================
  397. class ViewportJucerFileProperty : public FilePropertyComponent,
  398. public ChangeListener
  399. {
  400. public:
  401. ViewportJucerFileProperty (Viewport* const comp, JucerDocument& doc)
  402. : FilePropertyComponent ("Jucer file", false, true),
  403. component (comp),
  404. document (doc)
  405. {
  406. document.addChangeListener (this);
  407. }
  408. ~ViewportJucerFileProperty()
  409. {
  410. document.removeChangeListener (this);
  411. }
  412. void setFile (const File& newFile)
  413. {
  414. document.perform (new JucerCompFileChangeAction (component, *document.getComponentLayout(),
  415. newFile.getRelativePathFrom (document.getCppFile().getParentDirectory())
  416. .replaceCharacter ('\\', '/')),
  417. "Change Jucer component file");
  418. }
  419. File getFile() const
  420. {
  421. const String filename (getViewportJucerComponentFile (component));
  422. if (filename.isEmpty())
  423. return File::nonexistent;
  424. return document.getCppFile().getSiblingFile (filename);
  425. }
  426. void changeListenerCallback (ChangeBroadcaster*)
  427. {
  428. refresh();
  429. }
  430. private:
  431. Viewport* const component;
  432. JucerDocument& document;
  433. class JucerCompFileChangeAction : public ComponentUndoableAction <Viewport>
  434. {
  435. public:
  436. JucerCompFileChangeAction (Viewport* const comp, ComponentLayout& layout, const String& newState_)
  437. : ComponentUndoableAction <Viewport> (comp, layout),
  438. newState (newState_)
  439. {
  440. oldState = getViewportJucerComponentFile (comp);
  441. }
  442. bool perform()
  443. {
  444. showCorrectTab();
  445. setViewportJucerComponentFile (getComponent(), newState);
  446. changed();
  447. return true;
  448. }
  449. bool undo()
  450. {
  451. showCorrectTab();
  452. setViewportJucerComponentFile (getComponent(), oldState);
  453. changed();
  454. return true;
  455. }
  456. String newState, oldState;
  457. };
  458. };
  459. //==============================================================================
  460. class ViewportContentClassProperty : public ComponentTextProperty <Viewport>
  461. {
  462. public:
  463. ViewportContentClassProperty (Viewport* comp, JucerDocument& document)
  464. : ComponentTextProperty <Viewport> ("content class", 256, false, comp, document)
  465. {
  466. }
  467. void setText (const String& newText)
  468. {
  469. document.perform (new ViewportClassNameChangeAction (component, *document.getComponentLayout(), newText),
  470. "Change Viewport content class");
  471. }
  472. String getText() const
  473. {
  474. return getViewportGenericComponentClass (component);
  475. }
  476. private:
  477. class ViewportClassNameChangeAction : public ComponentUndoableAction <Viewport>
  478. {
  479. public:
  480. ViewportClassNameChangeAction (Viewport* const comp, ComponentLayout& layout, const String& newValue_)
  481. : ComponentUndoableAction <Viewport> (comp, layout),
  482. newValue (newValue_)
  483. {
  484. oldValue = getViewportGenericComponentClass (comp);
  485. }
  486. bool perform()
  487. {
  488. showCorrectTab();
  489. setViewportGenericComponentClass (getComponent(), newValue);
  490. changed();
  491. layout.getDocument()->refreshAllPropertyComps();
  492. return true;
  493. }
  494. bool undo()
  495. {
  496. showCorrectTab();
  497. setViewportGenericComponentClass (getComponent(), oldValue);
  498. changed();
  499. layout.getDocument()->refreshAllPropertyComps();
  500. return true;
  501. }
  502. String newValue, oldValue;
  503. };
  504. };
  505. //==============================================================================
  506. class ConstructorParamsProperty : public ComponentTextProperty <Viewport>
  507. {
  508. public:
  509. ConstructorParamsProperty (Viewport* comp, JucerDocument& document)
  510. : ComponentTextProperty <Viewport> ("constructor params", 512, false, comp, document)
  511. {
  512. }
  513. void setText (const String& newText)
  514. {
  515. document.perform (new ConstructorParamChangeAction (component, *document.getComponentLayout(), newText),
  516. "Change Viewport content constructor params");
  517. }
  518. String getText() const
  519. {
  520. return getViewportConstructorParams (component);
  521. }
  522. private:
  523. class ConstructorParamChangeAction : public ComponentUndoableAction <Viewport>
  524. {
  525. public:
  526. ConstructorParamChangeAction (Viewport* const comp, ComponentLayout& layout, const String& newValue_)
  527. : ComponentUndoableAction <Viewport> (comp, layout),
  528. newValue (newValue_)
  529. {
  530. oldValue = getViewportConstructorParams (comp);
  531. }
  532. bool perform()
  533. {
  534. showCorrectTab();
  535. setViewportConstructorParams (getComponent(), newValue);
  536. changed();
  537. layout.getDocument()->refreshAllPropertyComps();
  538. return true;
  539. }
  540. bool undo()
  541. {
  542. showCorrectTab();
  543. setViewportConstructorParams (getComponent(), oldValue);
  544. changed();
  545. layout.getDocument()->refreshAllPropertyComps();
  546. return true;
  547. }
  548. String newValue, oldValue;
  549. };
  550. };
  551. };