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.

661 lines
23KB

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