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.

941 lines
34KB

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