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.

1021 lines
38KB

  1. /*
  2. ==============================================================================
  3. This is an automatically generated file!
  4. Be careful when adding custom code to these files, as only the code within
  5. the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
  6. and re-saved.
  7. Created for JUCE version: JUCE v2.0.16
  8. ------------------------------------------------------------------------------
  9. JUCE is copyright 2004-11 by Raw Material Software ltd.
  10. ==============================================================================
  11. */
  12. //[CppHeaders] You can add your own extra header files here...
  13. #include "../Project Saving/jucer_ProjectExporter.h"
  14. #include "jucer_Module.h"
  15. #include "../Application/jucer_JuceUpdater.h"
  16. //[/CppHeaders]
  17. #include "jucer_ProjectInformationComponent.h"
  18. //[MiscUserDefs] You can add your own user definitions and misc code here...
  19. //==============================================================================
  20. class ModulesPanel : public PropertyComponent,
  21. public FilenameComponentListener,
  22. public ButtonListener
  23. {
  24. public:
  25. ModulesPanel (Project& project_)
  26. : PropertyComponent ("Modules", 500),
  27. project (project_),
  28. modulesLocation ("modules", ModuleList::getLocalModulesFolder (&project),
  29. true, true, false, "*", String::empty,
  30. "Select a folder containing your JUCE modules..."),
  31. modulesLabel (String::empty, "Module source folder:"),
  32. updateModulesButton ("Check for module updates..."),
  33. moduleListBox (moduleList),
  34. copyingMessage (project_, moduleList)
  35. {
  36. moduleList.rescan (ModuleList::getLocalModulesFolder (&project));
  37. addAndMakeVisible (&modulesLocation);
  38. modulesLocation.setBounds ("150, 3, parent.width - 180, 28");
  39. modulesLocation.addListener (this);
  40. modulesLabel.attachToComponent (&modulesLocation, true);
  41. addAndMakeVisible (&updateModulesButton);
  42. updateModulesButton.setBounds ("parent.width - 175, 3, parent.width - 4, 28");
  43. updateModulesButton.addListener (this);
  44. moduleListBox.setOwner (this);
  45. addAndMakeVisible (&moduleListBox);
  46. moduleListBox.setBounds ("4, 31, parent.width / 2 - 4, parent.height - 32");
  47. addAndMakeVisible (&copyingMessage);
  48. copyingMessage.setBounds ("4, parent.height - 30, parent.width - 4, parent.height - 1");
  49. copyingMessage.refresh();
  50. }
  51. void filenameComponentChanged (FilenameComponent*)
  52. {
  53. moduleList.rescan (modulesLocation.getCurrentFile());
  54. modulesLocation.setCurrentFile (moduleList.getModulesFolder(), false, false);
  55. ModuleList::setLocalModulesFolder (moduleList.getModulesFolder());
  56. moduleListBox.refresh();
  57. }
  58. void buttonClicked (Button*)
  59. {
  60. JuceUpdater::show (moduleList, getTopLevelComponent(), "");
  61. filenameComponentChanged (nullptr);
  62. }
  63. bool isEnabled (const ModuleList::Module* m) const
  64. {
  65. return project.isModuleEnabled (m->uid);
  66. }
  67. void setEnabled (const ModuleList::Module* m, bool enable)
  68. {
  69. if (enable)
  70. project.addModule (m->uid, true);
  71. else
  72. project.removeModule (m->uid);
  73. refresh();
  74. }
  75. bool areDependenciesMissing (const ModuleList::Module* m)
  76. {
  77. return moduleList.getExtraDependenciesNeeded (project, *m).size() > 0;
  78. }
  79. void selectionChanged (const ModuleList::Module* selectedModule)
  80. {
  81. settings = nullptr;
  82. if (selectedModule != nullptr)
  83. {
  84. addAndMakeVisible (settings = new ModuleSettingsPanel (project, moduleList, selectedModule->uid));
  85. settings->setBounds ("parent.width / 2 + 1, 31, parent.width - 3, parent.height - 32");
  86. }
  87. copyingMessage.refresh();
  88. }
  89. void refresh()
  90. {
  91. moduleListBox.refresh();
  92. if (settings != nullptr)
  93. settings->refreshAll();
  94. copyingMessage.refresh();
  95. }
  96. void paint (Graphics& g) // (overridden to avoid drawing the name)
  97. {
  98. getLookAndFeel().drawPropertyComponentBackground (g, getWidth(), getHeight(), *this);
  99. }
  100. //==============================================================================
  101. class ModuleSelectionListBox : public ListBox,
  102. public ListBoxModel
  103. {
  104. public:
  105. ModuleSelectionListBox (ModuleList& list_)
  106. : list (list_), owner (nullptr)
  107. {
  108. setColour (ListBox::backgroundColourId, Colours::white.withAlpha (0.4f));
  109. setTooltip ("Use this list to select which modules should be included in your app.\n"
  110. "Any modules which have missing dependencies will be shown in red.");
  111. }
  112. void setOwner (ModulesPanel* owner_)
  113. {
  114. owner = owner_;
  115. setModel (this);
  116. }
  117. void refresh()
  118. {
  119. updateContent();
  120. repaint();
  121. }
  122. int getNumRows()
  123. {
  124. return list.modules.size();
  125. }
  126. void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected)
  127. {
  128. if (rowIsSelected)
  129. g.fillAll (findColour (TextEditor::highlightColourId));
  130. const ModuleList::Module* const m = list.modules [rowNumber];
  131. if (m != nullptr)
  132. {
  133. const float tickSize = height * 0.7f;
  134. getLookAndFeel().drawTickBox (g, *this, (height - tickSize) / 2, (height - tickSize) / 2, tickSize, tickSize,
  135. owner->isEnabled (m), true, false, false);
  136. if (owner->isEnabled (m) && owner->areDependenciesMissing (m))
  137. g.setColour (Colours::red);
  138. else
  139. g.setColour (Colours::black);
  140. g.setFont (height * 0.7f, Font::bold);
  141. g.drawFittedText (m->uid, height, 0, 200, height, Justification::centredLeft, 1);
  142. g.setFont (height * 0.55f, Font::italic);
  143. g.drawText (m->name, height + 200, 0, width - height - 200, height, Justification::centredLeft, true);
  144. }
  145. }
  146. void listBoxItemClicked (int row, const MouseEvent& e)
  147. {
  148. if (e.x < getRowHeight())
  149. flipRow (row);
  150. }
  151. void listBoxItemDoubleClicked (int row, const MouseEvent& e)
  152. {
  153. flipRow (row);
  154. }
  155. void returnKeyPressed (int row)
  156. {
  157. flipRow (row);
  158. }
  159. void selectedRowsChanged (int lastRowSelected)
  160. {
  161. owner->selectionChanged (list.modules [lastRowSelected]);
  162. }
  163. void flipRow (int row)
  164. {
  165. const ModuleList::Module* const m = list.modules [row];
  166. if (m != nullptr)
  167. owner->setEnabled (m, ! owner->isEnabled (m));
  168. }
  169. private:
  170. ModuleList& list;
  171. ModulesPanel* owner;
  172. };
  173. //==============================================================================
  174. class ModuleSettingsPanel : public PropertyPanel
  175. {
  176. public:
  177. ModuleSettingsPanel (Project& project_, ModuleList& moduleList_, const String& moduleID_)
  178. : project (project_), moduleList (moduleList_), moduleID (moduleID_)
  179. {
  180. refreshAll();
  181. }
  182. void refreshAll()
  183. {
  184. setEnabled (project.isModuleEnabled (moduleID));
  185. clear();
  186. PropertyListBuilder props;
  187. ScopedPointer<LibraryModule> module (moduleList.loadModule (moduleID));
  188. if (module != nullptr)
  189. {
  190. props.add (new ModuleInfoComponent (project, moduleList, moduleID));
  191. if (project.isModuleEnabled (moduleID))
  192. {
  193. const ModuleList::Module* m = moduleList.findModuleInfo (moduleID);
  194. if (m != nullptr && moduleList.getExtraDependenciesNeeded (project, *m).size() > 0)
  195. props.add (new MissingDependenciesComponent (project, moduleList, moduleID));
  196. }
  197. props.add (new BooleanPropertyComponent (project.shouldShowAllModuleFilesInProject (moduleID),
  198. "Add source to project", "Make module files browsable in projects"),
  199. "If this is enabled, then the entire source tree from this module will be shown inside your project, "
  200. "making it easy to browse/edit the module's classes. If disabled, then only the minimum number of files "
  201. "required to compile it will appear inside your project.");
  202. props.add (new BooleanPropertyComponent (project.shouldCopyModuleFilesLocally (moduleID),
  203. "Create local copy", "Copy the module into the project folder"),
  204. "If this is enabled, then a local copy of the entire module will be made inside your project (in the auto-generated JuceLibraryFiles folder), "
  205. "so that your project will be self-contained, and won't need to contain any references to files in other folders. "
  206. "This also means that you can check the module into your source-control system to make sure it is always in sync with your own code.");
  207. StringArray possibleValues;
  208. possibleValues.add ("(Use Default)");
  209. possibleValues.add ("Enabled");
  210. possibleValues.add ("Disabled");
  211. Array<var> mappings;
  212. mappings.add (Project::configFlagDefault);
  213. mappings.add (Project::configFlagEnabled);
  214. mappings.add (Project::configFlagDisabled);
  215. OwnedArray <Project::ConfigFlag> flags;
  216. module->getConfigFlags (project, flags);
  217. for (int i = 0; i < flags.size(); ++i)
  218. {
  219. ChoicePropertyComponent* c = new ChoicePropertyComponent (flags[i]->value, flags[i]->symbol, possibleValues, mappings);
  220. c->setTooltip (flags[i]->description);
  221. c->setPreferredHeight (22);
  222. props.add (c);
  223. }
  224. }
  225. addProperties (props.components);
  226. }
  227. private:
  228. Project& project;
  229. ModuleList& moduleList;
  230. String moduleID;
  231. //==============================================================================
  232. class ModuleInfoComponent : public PropertyComponent
  233. {
  234. public:
  235. ModuleInfoComponent (Project& project_, ModuleList& moduleList_, const String& moduleID_)
  236. : PropertyComponent ("Module", 100), project (project_), moduleList (moduleList_), moduleID (moduleID_)
  237. {
  238. }
  239. void refresh() {}
  240. void paint (Graphics& g)
  241. {
  242. g.setColour (Colours::white.withAlpha (0.4f));
  243. g.fillRect (0, 0, getWidth(), getHeight() - 1);
  244. const ModuleList::Module* module = moduleList.findModuleInfo (moduleID);
  245. if (module != nullptr)
  246. {
  247. String text;
  248. text << module->name << newLine << "Version: " << module->version << newLine << newLine
  249. << module->description;
  250. GlyphArrangement ga;
  251. ga.addJustifiedText (Font (13.0f), text, 4.0f, 16.0f, getWidth() - 8.0f, Justification::topLeft);
  252. g.setColour (Colours::black);
  253. ga.draw (g);
  254. }
  255. }
  256. private:
  257. Project& project;
  258. ModuleList& moduleList;
  259. String moduleID;
  260. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModuleInfoComponent);
  261. };
  262. //==============================================================================
  263. class MissingDependenciesComponent : public PropertyComponent,
  264. public ButtonListener
  265. {
  266. public:
  267. MissingDependenciesComponent (Project& project_, ModuleList& moduleList_, const String& moduleID_)
  268. : PropertyComponent ("Dependencies", 100),
  269. project (project_), moduleList (moduleList_), moduleID (moduleID_),
  270. fixButton ("Enable Required Modules")
  271. {
  272. const ModuleList::Module* module = moduleList.findModuleInfo (moduleID);
  273. if (module != nullptr)
  274. missingDependencies = moduleList.getExtraDependenciesNeeded (project, *module);
  275. addAndMakeVisible (&fixButton);
  276. fixButton.setColour (TextButton::buttonColourId, Colours::red);
  277. fixButton.setColour (TextButton::textColourOffId, Colours::white);
  278. fixButton.setBounds ("right - 160, parent.height - 26, parent.width - 8, top + 22");
  279. fixButton.addListener (this);
  280. }
  281. void refresh() {}
  282. void paint (Graphics& g)
  283. {
  284. g.setColour (Colours::white.withAlpha (0.4f));
  285. g.fillRect (0, 0, getWidth(), getHeight() - 1);
  286. String text ("This module requires the following dependencies:\n");
  287. text << missingDependencies.joinIntoString (", ");
  288. GlyphArrangement ga;
  289. ga.addJustifiedText (Font (13.0f), text, 4.0f, 16.0f, getWidth() - 8.0f, Justification::topLeft);
  290. g.setColour (Colours::red);
  291. ga.draw (g);
  292. }
  293. void buttonClicked (Button*)
  294. {
  295. bool isModuleCopiedLocally = project.shouldCopyModuleFilesLocally (moduleID).getValue();
  296. for (int i = missingDependencies.size(); --i >= 0;)
  297. project.addModule (missingDependencies[i], isModuleCopiedLocally);
  298. ModulesPanel* mp = findParentComponentOfClass<ModulesPanel>();
  299. if (mp != nullptr)
  300. mp->refresh();
  301. }
  302. private:
  303. Project& project;
  304. ModuleList& moduleList;
  305. String moduleID;
  306. StringArray missingDependencies;
  307. TextButton fixButton;
  308. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MissingDependenciesComponent);
  309. };
  310. };
  311. //==============================================================================
  312. class ModuleCopyingInfo : public Component,
  313. public ButtonListener,
  314. public Timer
  315. {
  316. public:
  317. ModuleCopyingInfo (Project& project_, ModuleList& list_)
  318. : project (project_), list (list_),
  319. copyModeButton ("Set Copying Mode...")
  320. {
  321. addAndMakeVisible (&copyModeButton);
  322. copyModeButton.setBounds ("4, parent.height / 2 - 10, 160, parent.height / 2 + 10");
  323. copyModeButton.addListener (this);
  324. startTimer (1500);
  325. }
  326. void paint (Graphics& g)
  327. {
  328. g.setFont (11.0f);
  329. g.setColour (Colours::darkred);
  330. g.drawFittedText (getName(), copyModeButton.getRight() + 10, 0,
  331. getWidth() - copyModeButton.getRight() - 16, getHeight(),
  332. Justification::centredRight, 4);
  333. }
  334. void refresh()
  335. {
  336. int numCopied, numNonCopied;
  337. countCopiedModules (numCopied, numNonCopied);
  338. String newName;
  339. if (numCopied > 0 && numNonCopied > 0)
  340. newName = "Warning! Some of your modules are set to use local copies, and others are using remote references.\n"
  341. "This may create problems if some modules expect to share the same parent folder, so you may "
  342. "want to make sure that they are all either copied or not.";
  343. if (newName != getName())
  344. {
  345. setName (newName);
  346. repaint();
  347. }
  348. }
  349. void countCopiedModules (int& numCopied, int& numNonCopied)
  350. {
  351. numCopied = numNonCopied = 0;
  352. for (int i = list.modules.size(); --i >= 0;)
  353. {
  354. const String moduleID (list.modules.getUnchecked(i)->uid);
  355. if (project.isModuleEnabled (moduleID))
  356. {
  357. if (project.shouldCopyModuleFilesLocally (moduleID).getValue())
  358. ++numCopied;
  359. else
  360. ++numNonCopied;
  361. }
  362. }
  363. }
  364. void buttonClicked (Button*)
  365. {
  366. PopupMenu menu;
  367. menu.addItem (1, "Enable local copying for all modules");
  368. menu.addItem (2, "Disable local copying for all modules");
  369. menu.showMenuAsync (PopupMenu::Options().withTargetComponent (&copyModeButton),
  370. ModalCallbackFunction::forComponent (copyMenuItemChosen, this));
  371. }
  372. static void copyMenuItemChosen (int resultCode, ModuleCopyingInfo* comp)
  373. {
  374. if (resultCode > 0 && comp != nullptr)
  375. comp->setCopyModeForAllModules (resultCode == 1);
  376. }
  377. void setCopyModeForAllModules (bool copyEnabled)
  378. {
  379. for (int i = list.modules.size(); --i >= 0;)
  380. project.shouldCopyModuleFilesLocally (list.modules.getUnchecked(i)->uid) = copyEnabled;
  381. refresh();
  382. }
  383. void timerCallback()
  384. {
  385. refresh();
  386. }
  387. private:
  388. Project& project;
  389. ModuleList& list;
  390. TextButton copyModeButton;
  391. };
  392. private:
  393. Project& project;
  394. ModuleList moduleList;
  395. FilenameComponent modulesLocation;
  396. Label modulesLabel;
  397. TextButton updateModulesButton;
  398. ModuleSelectionListBox moduleListBox;
  399. ModuleCopyingInfo copyingMessage;
  400. ScopedPointer<ModuleSettingsPanel> settings;
  401. };
  402. //==============================================================================
  403. class ProjectSettingsComponent : public Component
  404. {
  405. public:
  406. ProjectSettingsComponent (Project& project_)
  407. : project (project_),
  408. exporters ("Export Targets", "Add a New Exporter...", true, false)
  409. {
  410. addAndMakeVisible (&mainProjectInfoPanel);
  411. addAndMakeVisible (&modulesPanelGroup);
  412. addAndMakeVisible (&exporters);
  413. mainProjectInfoPanel.fillBackground = true;
  414. modulesPanelGroup.fillBackground = true;
  415. }
  416. void updateSize (int width)
  417. {
  418. width = jmax (550, width - 6);
  419. int y = 0;
  420. y += mainProjectInfoPanel.updateSize (y, width);
  421. y += modulesPanelGroup.updateSize (y, width);
  422. y += exporters.updateSize (y, width);
  423. setSize (width, y);
  424. }
  425. void parentSizeChanged()
  426. {
  427. updateSize (getParentWidth());
  428. }
  429. void visibilityChanged()
  430. {
  431. if (isVisible())
  432. createAllPanels();
  433. }
  434. void createModulesPanel()
  435. {
  436. PropertyListBuilder props;
  437. props.add (new ModulesPanel (project));
  438. modulesPanelGroup.setProperties (props);
  439. modulesPanelGroup.setName ("Modules");
  440. }
  441. void createProjectPanel()
  442. {
  443. PropertyListBuilder props;
  444. project.createPropertyEditors (props);
  445. mainProjectInfoPanel.setProperties (props);
  446. mainProjectInfoPanel.setName ("Project Settings");
  447. lastProjectType = project.getProjectTypeValue().getValue();
  448. }
  449. void createExportersPanel()
  450. {
  451. exporters.clear();
  452. for (Project::ExporterIterator exporter (project); exporter.next();)
  453. {
  454. PropertyGroup* exporterGroup = exporters.createGroup();
  455. exporterGroup->fillBackground = true;
  456. exporterGroup->addDeleteButton ("exporter " + String (exporter.index), "Deletes this export target.");
  457. PropertyListBuilder props;
  458. exporter->createPropertyEditors (props);
  459. PropertyGroupList* configList = new PropertyGroupList ("Configurations", "Add a New Configuration", false, true);
  460. props.add (configList);
  461. exporterGroup->setProperties (props);
  462. configList->createNewButton.setName ("newconfig " + String (exporter.index));
  463. for (ProjectExporter::ConfigIterator config (*exporter); config.next();)
  464. {
  465. PropertyGroup* configGroup = configList->createGroup();
  466. if (exporter->getNumConfigurations() > 1)
  467. configGroup->addDeleteButton ("config " + String (exporter.index) + "/" + String (config.index), "Deletes this configuration.");
  468. PropertyListBuilder configProps;
  469. config->createPropertyEditors (configProps);
  470. configGroup->setProperties (configProps);
  471. }
  472. }
  473. }
  474. void createAllPanels()
  475. {
  476. createProjectPanel();
  477. createModulesPanel();
  478. createExportersPanel();
  479. updateNames();
  480. updateSize (getWidth());
  481. }
  482. bool needsFullUpdate() const
  483. {
  484. if (exporters.groups.size() != project.getNumExporters()
  485. || lastProjectType != project.getProjectTypeValue().getValue())
  486. return true;
  487. for (int i = exporters.groups.size(); --i >= 0;)
  488. {
  489. ScopedPointer <ProjectExporter> exp (project.createExporter (i));
  490. jassert (exp != nullptr);
  491. if (exp != nullptr)
  492. {
  493. PropertyGroupList* configList = dynamic_cast <PropertyGroupList*> (exporters.groups.getUnchecked(i)->properties.getLast());
  494. if (configList != nullptr && configList->groups.size() != exp->getNumConfigurations())
  495. return true;
  496. }
  497. }
  498. return false;
  499. }
  500. void updateNames()
  501. {
  502. for (int i = exporters.groups.size(); --i >= 0;)
  503. {
  504. PropertyGroup& exporterGroup = *exporters.groups.getUnchecked(i);
  505. ScopedPointer <ProjectExporter> exp (project.createExporter (i));
  506. jassert (exp != nullptr);
  507. if (exp != nullptr)
  508. {
  509. exporterGroup.setName (exp->getName());
  510. exporterGroup.repaint();
  511. PropertyGroupList* configList = dynamic_cast <PropertyGroupList*> (exporterGroup.properties.getLast());
  512. if (configList != nullptr)
  513. {
  514. for (int j = configList->groups.size(); --j >= 0;)
  515. {
  516. PropertyGroup& configGroup = *configList->groups.getUnchecked(j);
  517. configGroup.setName ("Configuration: " + exp->getConfiguration (j)->getName().quoted());
  518. configGroup.repaint();
  519. }
  520. }
  521. }
  522. }
  523. }
  524. void update()
  525. {
  526. if (needsFullUpdate())
  527. createAllPanels();
  528. else
  529. updateNames();
  530. }
  531. void deleteButtonClicked (const String& name)
  532. {
  533. if (name.startsWith ("config"))
  534. {
  535. int exporterIndex = name.upToLastOccurrenceOf ("/", false, false).getTrailingIntValue();
  536. int configIndex = name.getTrailingIntValue();
  537. ScopedPointer<ProjectExporter> exporter (project.createExporter (exporterIndex));
  538. jassert (exporter != nullptr);
  539. if (exporter != nullptr)
  540. exporter->deleteConfiguration (configIndex);
  541. }
  542. else
  543. {
  544. project.deleteExporter (name.getTrailingIntValue());
  545. }
  546. }
  547. static void newExporterMenuItemChosen (int resultCode, ProjectSettingsComponent* settingsComp)
  548. {
  549. if (resultCode > 0 && settingsComp != nullptr)
  550. settingsComp->project.addNewExporter (ProjectExporter::getExporterNames() [resultCode - 1]);
  551. }
  552. void createNewExporter (TextButton& button)
  553. {
  554. PopupMenu menu;
  555. const StringArray exporters (ProjectExporter::getExporterNames());
  556. for (int i = 0; i < exporters.size(); ++i)
  557. menu.addItem (i + 1, "Create a new " + exporters[i] + " target");
  558. menu.showMenuAsync (PopupMenu::Options().withTargetComponent (&button),
  559. ModalCallbackFunction::forComponent (newExporterMenuItemChosen, this));
  560. }
  561. void createNewConfig (int exporterIndex)
  562. {
  563. ScopedPointer<ProjectExporter> exp (project.createExporter (exporterIndex));
  564. jassert (exp != nullptr);
  565. if (exp != nullptr)
  566. exp->addNewConfiguration (nullptr);
  567. }
  568. void newItemButtonClicked (TextButton& button)
  569. {
  570. if (button.getName().containsIgnoreCase ("export"))
  571. createNewExporter (button);
  572. else if (button.getName().containsIgnoreCase ("newconfig"))
  573. createNewConfig (button.getName().getTrailingIntValue());
  574. }
  575. private:
  576. //==============================================================================
  577. class PropertyGroup : public Component,
  578. public ButtonListener
  579. {
  580. public:
  581. PropertyGroup()
  582. : deleteButton ("Delete"), fillBackground (false)
  583. {
  584. deleteButton.addListener (this);
  585. }
  586. void addDeleteButton (const String& name, const String& tooltip)
  587. {
  588. addAndMakeVisible (&deleteButton);
  589. deleteButton.setBounds ("right - 55, 11, parent.width - 10, 26");
  590. deleteButton.setColour (TextButton::buttonColourId, Colour (0xa0fcbdbd));
  591. deleteButton.setColour (TextButton::textColourOffId, Colours::darkred);
  592. deleteButton.setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight);
  593. deleteButton.setName (name);
  594. deleteButton.setTooltip (tooltip);
  595. }
  596. void setProperties (const PropertyListBuilder& newProps)
  597. {
  598. properties.clear();
  599. properties.addArray (newProps.components);
  600. for (int i = properties.size(); --i >= 0;)
  601. addAndMakeVisible (properties.getUnchecked(i));
  602. }
  603. int updateSize (int y, int width)
  604. {
  605. int height = fillBackground ? 36 : 32;
  606. for (int i = 0; i < properties.size(); ++i)
  607. {
  608. PropertyComponent* pp = properties.getUnchecked(i);
  609. PropertyGroupList* pgl = dynamic_cast <PropertyGroupList*> (pp);
  610. if (pgl != nullptr)
  611. pgl->updateSize (height, width - 20);
  612. pp->setBounds (10, height, width - 20, pp->getPreferredHeight());
  613. height += pp->getHeight();
  614. }
  615. height += 16;
  616. setBounds (0, y, width, height);
  617. return height;
  618. }
  619. void paint (Graphics& g)
  620. {
  621. if (fillBackground)
  622. {
  623. g.setColour (Colours::white.withAlpha (0.3f));
  624. g.fillRect (0, 28, getWidth(), getHeight() - 38);
  625. g.setColour (Colours::black.withAlpha (0.4f));
  626. g.drawRect (0, 28, getWidth(), getHeight() - 38);
  627. }
  628. g.setFont (14.0f, Font::bold);
  629. g.setColour (Colours::black);
  630. g.drawFittedText (getName(), 12, 0, getWidth() - 16, 26, Justification::bottomLeft, 1);
  631. }
  632. void buttonClicked (Button*)
  633. {
  634. ProjectSettingsComponent* psc = findParentComponentOfClass<ProjectSettingsComponent>();
  635. if (psc != nullptr)
  636. psc->deleteButtonClicked (deleteButton.getName());
  637. }
  638. OwnedArray<PropertyComponent> properties;
  639. TextButton deleteButton;
  640. bool fillBackground;
  641. };
  642. //==============================================================================
  643. class PropertyGroupList : public PropertyComponent,
  644. public ButtonListener
  645. {
  646. public:
  647. PropertyGroupList (const String& title, const String& newButtonText,
  648. bool triggerOnMouseDown, bool hideNameAndPutButtonAtBottom)
  649. : PropertyComponent (title), createNewButton (newButtonText),
  650. dontDisplayName (hideNameAndPutButtonAtBottom)
  651. {
  652. addAndMakeVisible (&createNewButton);
  653. createNewButton.setColour (TextButton::buttonColourId, Colours::lightgreen.withAlpha (0.5f));
  654. createNewButton.setBounds (hideNameAndPutButtonAtBottom ? "right - 140, parent.height - 25, parent.width - 10, top + 20"
  655. : "right - 140, 30, parent.width - 10, top + 20");
  656. createNewButton.setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight);
  657. createNewButton.addListener (this);
  658. createNewButton.setTriggeredOnMouseDown (triggerOnMouseDown);
  659. }
  660. int updateSize (int ourY, int width)
  661. {
  662. int y = dontDisplayName ? 10 : 55;
  663. for (int i = 0; i < groups.size(); ++i)
  664. y += groups.getUnchecked(i)->updateSize (y, width);
  665. y = jmax (y, 100);
  666. setBounds (0, ourY, width, y);
  667. if (dontDisplayName)
  668. y += 25;
  669. setPreferredHeight (y);
  670. return y;
  671. }
  672. void paint (Graphics& g)
  673. {
  674. if (! dontDisplayName)
  675. {
  676. g.setFont (17.0f, Font::bold);
  677. g.setColour (Colours::black);
  678. g.drawFittedText (getName(), 0, 30, getWidth(), 20, Justification::centred, 1);
  679. }
  680. }
  681. void clear()
  682. {
  683. groups.clear();
  684. }
  685. void refresh() {}
  686. PropertyGroup* createGroup()
  687. {
  688. PropertyGroup* p = new PropertyGroup();
  689. groups.add (p);
  690. addAndMakeVisible (p);
  691. return p;
  692. }
  693. void buttonClicked (Button*)
  694. {
  695. ProjectSettingsComponent* psc = findParentComponentOfClass<ProjectSettingsComponent>();
  696. if (psc != nullptr)
  697. psc->newItemButtonClicked (createNewButton);
  698. }
  699. OwnedArray<PropertyGroup> groups;
  700. TextButton createNewButton;
  701. bool dontDisplayName;
  702. };
  703. Project& project;
  704. var lastProjectType;
  705. PropertyGroup mainProjectInfoPanel, modulesPanelGroup;
  706. PropertyGroupList exporters;
  707. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectSettingsComponent);
  708. };
  709. //[/MiscUserDefs]
  710. //==============================================================================
  711. ProjectInformationComponent::ProjectInformationComponent (Project& project_)
  712. : project (project_)
  713. {
  714. //[Constructor_pre]
  715. //[/Constructor_pre]
  716. addChildAndSetID (&viewport, "ykdBpb");
  717. addChildAndSetID (&openProjectButton, "a550a652e2666ee7");
  718. addChildAndSetID (&saveAndOpenButton, "dRGMyYx");
  719. addChildAndSetID (&rollover, "QqLJBF");
  720. initialiseComponentState();
  721. openProjectButton.addListener (this);
  722. saveAndOpenButton.addListener (this);
  723. //[UserPreSize]
  724. viewport.setViewedComponent (new ProjectSettingsComponent (project), true);
  725. #if JUCE_MAC || JUCE_WINDOWS
  726. openProjectButton.setCommandToTrigger (commandManager, CommandIDs::openInIDE, true);
  727. openProjectButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::openInIDE));
  728. saveAndOpenButton.setCommandToTrigger (commandManager, CommandIDs::saveAndOpenInIDE, true);
  729. saveAndOpenButton.setButtonText (commandManager->getNameOfCommand (CommandIDs::saveAndOpenInIDE));
  730. #else
  731. openProjectButton.setVisible (false);
  732. saveAndOpenButton.setVisible (false);
  733. #endif
  734. //[/UserPreSize]
  735. setSize (808, 638);
  736. //[Constructor]
  737. project.addChangeListener (this);
  738. //[/Constructor]
  739. }
  740. ProjectInformationComponent::~ProjectInformationComponent()
  741. {
  742. //[Destructor]
  743. project.removeChangeListener (this);
  744. //[/Destructor]
  745. }
  746. //==============================================================================
  747. void ProjectInformationComponent::buttonClicked (Button* buttonThatWasClicked)
  748. {
  749. //[UserbuttonClicked_Pre]
  750. //[/UserbuttonClicked_Pre]
  751. if (buttonThatWasClicked == &openProjectButton)
  752. {
  753. //[UserButtonCode_openProjectButton] -- add your button handler code here..
  754. //[/UserButtonCode_openProjectButton]
  755. }
  756. else if (buttonThatWasClicked == &saveAndOpenButton)
  757. {
  758. //[UserButtonCode_saveAndOpenButton] -- add your button handler code here..
  759. //[/UserButtonCode_saveAndOpenButton]
  760. }
  761. //[UserbuttonClicked_Post]
  762. //[/UserbuttonClicked_Post]
  763. }
  764. void ProjectInformationComponent::paint (Graphics& g)
  765. {
  766. //[UserPaint]
  767. g.setTiledImageFill (ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, BinaryData::brushed_aluminium_pngSize),
  768. 0, 0, 1.0f);
  769. g.fillAll();
  770. drawRecessedShadows (g, getWidth(), getHeight(), 14);
  771. //[/UserPaint]
  772. }
  773. //[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
  774. void ProjectInformationComponent::changeListenerCallback (ChangeBroadcaster*)
  775. {
  776. dynamic_cast<ProjectSettingsComponent*> (viewport.getViewedComponent())->update();
  777. }
  778. //[/MiscUserCode]
  779. //==============================================================================
  780. //======================= Jucer Information Section ==========================
  781. //==============================================================================
  782. #if 0
  783. /* This section stores the metadata for this component - edit it at your own risk!
  784. JUCER_COMPONENT_METADATA_START
  785. <COMPONENT id="tO9EG1a" className="ProjectInformationComponent" width="808"
  786. height="638" background="f6f9ff" parentClasses="public Component, public ChangeListener"
  787. constructorParams="Project&amp; project_" memberInitialisers="project (project_)">
  788. <COMPONENTS>
  789. <VIEWPORT id="ykdBpb" memberName="viewport" position="8, 8, parent.width - 8, parent.height - 74"
  790. scrollBarV="1" scrollBarH="1" scrollbarWidth="16"/>
  791. <TEXTBUTTON id="a550a652e2666ee7" memberName="openProjectButton" focusOrder="0"
  792. text="Open Project in " createCallback="1" radioGroup="0" connectedLeft="0"
  793. connectedRight="0" connectedTop="0" connectedBottom="0" backgroundColour="FFDDDDFF"
  794. textColour="" backgroundColourOn="" textColourOn="" position="8, parent.height - 34, left + 227, top + 24"/>
  795. <TEXTBUTTON id="dRGMyYx" name="" memberName="saveAndOpenButton" position="8, parent.height - 65, left + 227, top + 24"
  796. text="Save And Open in" createCallback="1" radioGroup="0" connectedLeft="0"
  797. connectedRight="0" connectedTop="0" connectedBottom="0" backgroundColour="FFDDDDFF"/>
  798. <GENERICCOMPONENT id="QqLJBF" memberName="rollover" position="246, parent.height - 68, parent.width - 8, parent.height - 4"
  799. class="RolloverHelpComp" canBeAggregated="1" constructorParams=""/>
  800. </COMPONENTS>
  801. <MARKERS_X/>
  802. <MARKERS_Y/>
  803. <METHODS paint="1"/>
  804. </COMPONENT>
  805. JUCER_COMPONENT_METADATA_END
  806. */
  807. #endif
  808. void ProjectInformationComponent::initialiseComponentState()
  809. {
  810. BinaryData::ImageProvider imageProvider;
  811. ComponentBuilder::initialiseFromValueTree (*this, getComponentState(), &imageProvider);
  812. }
  813. ValueTree ProjectInformationComponent::getComponentState()
  814. {
  815. const unsigned char data[] =
  816. "COMPONENT\0\x01\x08id\0\x01\t\x05tO9EG1a\0""className\0\x01\x1d\x05ProjectInformationComponent\0width\0\x01\x05\x05""808\0height\0\x01\x05\x05""638\0""background\0\x01\x08\x05""f6f9ff\0parentClasses\0\x01)\x05public Component, public ChangeListener\0"
  817. "constructorParams\0\x01\x13\x05Project& project_\0memberInitialisers\0\x01\x14\x05project (project_)\0\x01\x04""COMPONENTS\0\0\x01\x04VIEWPORT\0\x01\x06id\0\x01\x08\x05ykdBpb\0memberName\0\x01\n\x05viewport\0position\0\x01,\x05""8, 8, parent.width - "
  818. "8, parent.height - 74\0scrollBarV\0\x01\x03\x05""1\0scrollBarH\0\x01\x03\x05""1\0scrollbarWidth\0\x01\x04\x05""16\0\0TEXTBUTTON\0\x01\x0fid\0\x01\x12\x05""a550a652e2666ee7\0memberName\0\x01\x13\x05openProjectButton\0""focusOrder\0\x01\x03\x05""0\0tex"
  819. "t\0\x01\x12\x05Open Project in \0""createCallback\0\x01\x03\x05""1\0radioGroup\0\x01\x03\x05""0\0""connectedLeft\0\x01\x03\x05""0\0""connectedRight\0\x01\x03\x05""0\0""connectedTop\0\x01\x03\x05""0\0""connectedBottom\0\x01\x03\x05""0\0""backgroundCol"
  820. "our\0\x01\n\x05""FFDDDDFF\0textColour\0\x01\x02\x05\0""backgroundColourOn\0\x01\x02\x05\0textColourOn\0\x01\x02\x05\0position\0\x01-\x05""8, parent.height - 34, left + 227, top + 24\0\0TEXTBUTTON\0\x01\x0cid\0\x01\t\x05""dRGMyYx\0name\0\x01\x02\x05\0"
  821. "memberName\0\x01\x13\x05saveAndOpenButton\0position\0\x01-\x05""8, parent.height - 65, left + 227, top + 24\0text\0\x01\x12\x05Save And Open in\0""createCallback\0\x01\x03\x05""1\0radioGroup\0\x01\x03\x05""0\0""connectedLeft\0\x01\x03\x05""0\0""conne"
  822. "ctedRight\0\x01\x03\x05""0\0""connectedTop\0\x01\x03\x05""0\0""connectedBottom\0\x01\x03\x05""0\0""backgroundColour\0\x01\n\x05""FFDDDDFF\0\0GENERICCOMPONENT\0\x01\x06id\0\x01\x08\x05QqLJBF\0memberName\0\x01\n\x05rollover\0position\0\x01>\x05""246, p"
  823. "arent.height - 68, parent.width - 8, parent.height - 4\0""class\0\x01\x12\x05RolloverHelpComp\0""canBeAggregated\0\x01\x03\x05""1\0""constructorParams\0\x01\x02\x05\0\0MARKERS_X\0\0\0MARKERS_Y\0\0\0METHODS\0\x01\x01paint\0\x01\x03\x05""1\0\0";
  824. return ValueTree::readFromData (data, sizeof (data));
  825. }