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.

313 lines
11KB

  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. #include "../../ProjectSaving/jucer_ProjectExporter.h"
  20. #include "../../Utility/UI/PropertyComponents/jucer_FilePathPropertyComponent.h"
  21. #include "../../Utility/Helpers/jucer_ValueWithDefaultWrapper.h"
  22. #include "jucer_NewProjectWizard.h"
  23. //==============================================================================
  24. class ItemHeader : public Component
  25. {
  26. public:
  27. ItemHeader (StringRef name, StringRef description, const char* iconSvgData)
  28. : nameLabel ({}, name),
  29. descriptionLabel ({}, description),
  30. icon (makeIcon (iconSvgData))
  31. {
  32. addAndMakeVisible (nameLabel);
  33. nameLabel.setFont (18.0f);
  34. nameLabel.setMinimumHorizontalScale (1.0f);
  35. addAndMakeVisible (descriptionLabel);
  36. descriptionLabel.setMinimumHorizontalScale (1.0f);
  37. }
  38. void resized() override
  39. {
  40. auto bounds = getLocalBounds();
  41. auto topSlice = bounds.removeFromTop (50);
  42. iconBounds = topSlice.removeFromRight (75);
  43. nameLabel.setBounds (topSlice);
  44. bounds.removeFromTop (10);
  45. descriptionLabel.setBounds (bounds.removeFromTop (50));
  46. bounds.removeFromTop (20);
  47. }
  48. void paint (Graphics& g) override
  49. {
  50. g.fillAll (findColour (secondaryBackgroundColourId));
  51. if (icon != nullptr)
  52. icon->drawWithin (g, iconBounds.toFloat(), RectanglePlacement::centred, 1.0f);
  53. }
  54. private:
  55. static std::unique_ptr<Drawable> makeIcon (const char* iconSvgData)
  56. {
  57. if (auto svg = XmlDocument::parse (iconSvgData))
  58. return Drawable::createFromSVG (*svg);
  59. return {};
  60. }
  61. Label nameLabel, descriptionLabel;
  62. Rectangle<int> iconBounds;
  63. std::unique_ptr<Drawable> icon;
  64. //==============================================================================
  65. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ItemHeader)
  66. };
  67. //==============================================================================
  68. class TemplateComponent : public Component
  69. {
  70. public:
  71. TemplateComponent (const NewProjectTemplates::ProjectTemplate& temp,
  72. std::function<void (std::unique_ptr<Project>)>&& createdCallback)
  73. : projectTemplate (temp),
  74. projectCreatedCallback (std::move (createdCallback)),
  75. header (projectTemplate.displayName, projectTemplate.description, projectTemplate.icon)
  76. {
  77. createProjectButton.onClick = [this]
  78. {
  79. FileChooser fc ("Save Project", NewProjectWizard::getLastWizardFolder());
  80. if (fc.browseForDirectory())
  81. {
  82. auto dir = fc.getResult();
  83. if (auto project = NewProjectWizard::createNewProject (projectTemplate,
  84. dir.getChildFile (projectNameValue.get().toString()),
  85. projectNameValue.get(),
  86. modulesValue.get(),
  87. exportersValue.get(),
  88. fileOptionsValue.get(),
  89. modulePathValue.getCurrentValue(),
  90. modulePathValue.getWrappedValueWithDefault().isUsingDefault()))
  91. {
  92. projectCreatedCallback (std::move (project));
  93. getAppSettings().lastWizardFolder = dir;
  94. }
  95. }
  96. };
  97. addAndMakeVisible (createProjectButton);
  98. addAndMakeVisible (header);
  99. modulePathValue.init ({ settingsTree, Ids::defaultJuceModulePath, nullptr },
  100. getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()),
  101. TargetOS::getThisOS());
  102. panel.addProperties (buildPropertyList());
  103. addAndMakeVisible (panel);
  104. }
  105. void resized() override
  106. {
  107. auto bounds = getLocalBounds().reduced (10);
  108. header.setBounds (bounds.removeFromTop (150));
  109. createProjectButton.setBounds (bounds.removeFromBottom (30).removeFromRight (150));
  110. bounds.removeFromBottom (5);
  111. panel.setBounds (bounds);
  112. }
  113. void paint (Graphics& g) override
  114. {
  115. g.fillAll (findColour (secondaryBackgroundColourId));
  116. }
  117. private:
  118. NewProjectTemplates::ProjectTemplate projectTemplate;
  119. std::function<void (std::unique_ptr<Project>)> projectCreatedCallback;
  120. ItemHeader header;
  121. TextButton createProjectButton { "Create Project..." };
  122. ValueTree settingsTree { "NewProjectSettings" };
  123. ValueWithDefault projectNameValue { settingsTree, Ids::name, nullptr, "NewProject" },
  124. modulesValue { settingsTree, Ids::dependencies_, nullptr, projectTemplate.requiredModules, "," },
  125. exportersValue { settingsTree, Ids::exporters, nullptr, StringArray (ProjectExporter::getCurrentPlatformExporterTypeInfo().identifier.toString()), "," },
  126. fileOptionsValue { settingsTree, Ids::file, nullptr, NewProjectTemplates::getVarForFileOption (projectTemplate.defaultFileOption) };
  127. ValueWithDefaultWrapper modulePathValue;
  128. PropertyPanel panel;
  129. //==============================================================================
  130. PropertyComponent* createProjectNamePropertyComponent()
  131. {
  132. return new TextPropertyComponent (projectNameValue, "Project Name", 1024, false);
  133. }
  134. PropertyComponent* createModulesPropertyComponent()
  135. {
  136. Array<var> moduleVars;
  137. var requiredModules;
  138. for (auto& m : getJUCEModules())
  139. {
  140. moduleVars.add (m);
  141. if (projectTemplate.requiredModules.contains (m))
  142. requiredModules.append (m);
  143. }
  144. modulesValue = requiredModules;
  145. return new MultiChoicePropertyComponent (modulesValue, "Modules",
  146. getJUCEModules(), moduleVars);
  147. }
  148. PropertyComponent* createModulePathPropertyComponent()
  149. {
  150. return new FilePathPropertyComponent (modulePathValue.getWrappedValueWithDefault(), "Path to Modules", true);
  151. }
  152. PropertyComponent* createExportersPropertyValue()
  153. {
  154. Array<var> exporterVars;
  155. StringArray exporterNames;
  156. for (auto& exporterTypeInfo : ProjectExporter::getExporterTypeInfos())
  157. {
  158. exporterVars.add (exporterTypeInfo.identifier.toString());
  159. exporterNames.add (exporterTypeInfo.displayName);
  160. }
  161. return new MultiChoicePropertyComponent (exportersValue, "Exporters", exporterNames, exporterVars);
  162. }
  163. PropertyComponent* createFileCreationOptionsPropertyComponent()
  164. {
  165. Array<var> optionVars;
  166. StringArray optionStrings;
  167. for (auto& opt : projectTemplate.fileOptionsAndFiles)
  168. {
  169. optionVars.add (NewProjectTemplates::getVarForFileOption (opt.first));
  170. optionStrings.add (NewProjectTemplates::getStringForFileOption (opt.first));
  171. }
  172. return new ChoicePropertyComponent (fileOptionsValue, "File Creation Options", optionStrings, optionVars);
  173. }
  174. Array<PropertyComponent*> buildPropertyList()
  175. {
  176. PropertyListBuilder builder;
  177. builder.add (createProjectNamePropertyComponent());
  178. builder.add (createModulesPropertyComponent());
  179. builder.add (createModulePathPropertyComponent());
  180. builder.add (createExportersPropertyValue());
  181. if (! projectTemplate.fileOptionsAndFiles.empty())
  182. builder.add (createFileCreationOptionsPropertyComponent());
  183. return builder.components;
  184. }
  185. //==============================================================================
  186. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemplateComponent)
  187. };
  188. //==============================================================================
  189. class ExampleComponent : public Component
  190. {
  191. public:
  192. ExampleComponent (const File& f, std::function<void (const File&)> selectedCallback)
  193. : exampleFile (f),
  194. metadata (parseJUCEHeaderMetadata (exampleFile)),
  195. exampleSelectedCallback (std::move (selectedCallback)),
  196. header (metadata[Ids::name].toString(), metadata[Ids::description].toString(), BinaryData::background_logo_svg),
  197. codeViewer (doc, &cppTokeniser)
  198. {
  199. addAndMakeVisible (header);
  200. openExampleButton.onClick = [this] { exampleSelectedCallback (exampleFile); };
  201. addAndMakeVisible (openExampleButton);
  202. setupCodeViewer();
  203. addAndMakeVisible (codeViewer);
  204. }
  205. void paint (Graphics& g) override
  206. {
  207. g.fillAll (findColour (secondaryBackgroundColourId));
  208. }
  209. void resized() override
  210. {
  211. auto bounds = getLocalBounds().reduced (10);
  212. header.setBounds (bounds.removeFromTop (125));
  213. openExampleButton.setBounds (bounds.removeFromBottom (30).removeFromRight (150));
  214. codeViewer.setBounds (bounds);
  215. }
  216. private:
  217. void setupCodeViewer()
  218. {
  219. auto fileString = exampleFile.loadFileAsString();
  220. doc.replaceAllContent (fileString);
  221. codeViewer.setScrollbarThickness (6);
  222. codeViewer.setReadOnly (true);
  223. getAppSettings().appearance.applyToCodeEditor (codeViewer);
  224. codeViewer.scrollToLine (findBestLineToScrollToForClass (StringArray::fromLines (fileString),
  225. metadata[Ids::name].toString(),
  226. metadata[Ids::type] == "AudioProcessor"));
  227. }
  228. //==============================================================================
  229. File exampleFile;
  230. var metadata;
  231. std::function<void (const File&)> exampleSelectedCallback;
  232. ItemHeader header;
  233. CPlusPlusCodeTokeniser cppTokeniser;
  234. CodeDocument doc;
  235. CodeEditorComponent codeViewer;
  236. TextButton openExampleButton { "Open Example..." };
  237. //==============================================================================
  238. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ExampleComponent)
  239. };