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.

280 lines
8.8KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - 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 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-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. #include "jucer_HeaderComponent.h"
  19. #include "../../Application/jucer_Application.h"
  20. #include "../../ProjectSaving/jucer_ProjectExporter.h"
  21. #include "../../Project/UI/jucer_ProjectContentComponent.h"
  22. //==============================================================================
  23. HeaderComponent::HeaderComponent (ProjectContentComponent* pcc)
  24. : projectContentComponent (pcc)
  25. {
  26. setTitle ("Header");
  27. setFocusContainerType (FocusContainerType::focusContainer);
  28. addAndMakeVisible (configLabel);
  29. addAndMakeVisible (exporterBox);
  30. exporterBox.onChange = [this] { updateExporterButton(); };
  31. juceIcon.setImage (ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize), RectanglePlacement::centred);
  32. addAndMakeVisible (juceIcon);
  33. addAndMakeVisible (userAvatar);
  34. userAvatar.addChangeListener (this);
  35. projectNameLabel.setText ({}, dontSendNotification);
  36. addAndMakeVisible (projectNameLabel);
  37. initialiseButtons();
  38. }
  39. //==============================================================================
  40. void HeaderComponent::resized()
  41. {
  42. auto bounds = getLocalBounds();
  43. configLabel.setFont ({ (float) bounds.getHeight() / 3.0f });
  44. {
  45. auto headerBounds = bounds.removeFromLeft (tabsWidth);
  46. const int buttonSize = 25;
  47. auto buttonBounds = headerBounds.removeFromRight (buttonSize);
  48. projectSettingsButton.setBounds (buttonBounds.removeFromBottom (buttonSize).reduced (2));
  49. juceIcon.setBounds (headerBounds.removeFromLeft (headerBounds.getHeight()).reduced (2));
  50. headerBounds.removeFromRight (5);
  51. projectNameLabel.setBounds (headerBounds);
  52. }
  53. {
  54. auto exporterWidth = jmin (400, bounds.getWidth() / 2);
  55. Rectangle<int> exporterBounds (0, 0, exporterWidth, bounds.getHeight());
  56. exporterBounds.setCentre (bounds.getCentre());
  57. saveAndOpenInIDEButton.setBounds (exporterBounds.removeFromRight (exporterBounds.getHeight()).reduced (2));
  58. exporterBounds.removeFromRight (5);
  59. exporterBox.setBounds (exporterBounds.removeFromBottom (roundToInt ((float) exporterBounds.getHeight() / 1.8f)));
  60. configLabel.setBounds (exporterBounds);
  61. }
  62. userAvatar.setBounds (bounds.removeFromRight (userAvatar.isDisplaingGPLLogo() ? roundToInt ((float) bounds.getHeight() * 1.9f)
  63. : bounds.getHeight()).reduced (2));
  64. }
  65. void HeaderComponent::paint (Graphics& g)
  66. {
  67. g.fillAll (findColour (backgroundColourId));
  68. }
  69. //==============================================================================
  70. void HeaderComponent::setCurrentProject (Project* newProject)
  71. {
  72. stopTimer();
  73. repaint();
  74. projectNameLabel.setText ({}, dontSendNotification);
  75. project = newProject;
  76. if (project != nullptr)
  77. {
  78. exportersTree = project->getExporters();
  79. exportersTree.addListener (this);
  80. updateExporters();
  81. projectNameValue.referTo (project->getProjectValue (Ids::name));
  82. projectNameValue.addListener (this);
  83. updateName();
  84. }
  85. }
  86. //==============================================================================
  87. void HeaderComponent::updateExporters()
  88. {
  89. auto selectedExporter = getSelectedExporter();
  90. exporterBox.clear();
  91. auto preferredExporterIndex = -1;
  92. int i = 0;
  93. for (Project::ExporterIterator exporter (*project); exporter.next(); ++i)
  94. {
  95. auto exporterName = exporter->getUniqueName();
  96. exporterBox.addItem (exporterName, i + 1);
  97. if (selectedExporter != nullptr && exporterName == selectedExporter->getUniqueName())
  98. exporterBox.setSelectedId (i + 1);
  99. if (exporterName.contains (ProjectExporter::getCurrentPlatformExporterTypeInfo().displayName) && preferredExporterIndex == -1)
  100. preferredExporterIndex = i;
  101. }
  102. if (exporterBox.getSelectedItemIndex() == -1)
  103. {
  104. if (preferredExporterIndex == -1)
  105. {
  106. i = 0;
  107. for (Project::ExporterIterator exporter (*project); exporter.next(); ++i)
  108. {
  109. if (exporter->canLaunchProject())
  110. {
  111. preferredExporterIndex = i;
  112. break;
  113. }
  114. }
  115. }
  116. exporterBox.setSelectedItemIndex (preferredExporterIndex != -1 ? preferredExporterIndex : 0);
  117. }
  118. updateExporterButton();
  119. }
  120. std::unique_ptr<ProjectExporter> HeaderComponent::getSelectedExporter() const
  121. {
  122. if (project != nullptr)
  123. {
  124. int i = 0;
  125. auto selectedIndex = exporterBox.getSelectedItemIndex();
  126. for (Project::ExporterIterator exporter (*project); exporter.next();)
  127. if (i++ == selectedIndex)
  128. return std::move (exporter.exporter);
  129. }
  130. return nullptr;
  131. }
  132. bool HeaderComponent::canCurrentExporterLaunchProject() const
  133. {
  134. if (project != nullptr)
  135. {
  136. if (auto selectedExporter = getSelectedExporter())
  137. {
  138. for (Project::ExporterIterator exporter (*project); exporter.next();)
  139. if (exporter->canLaunchProject() && exporter->getUniqueName() == selectedExporter->getUniqueName())
  140. return true;
  141. }
  142. }
  143. return false;
  144. }
  145. //==============================================================================
  146. void HeaderComponent::sidebarTabsWidthChanged (int newWidth)
  147. {
  148. tabsWidth = newWidth;
  149. resized();
  150. }
  151. //==============================================================================
  152. void HeaderComponent::changeListenerCallback (ChangeBroadcaster* source)
  153. {
  154. if (source == &userAvatar)
  155. resized();
  156. }
  157. void HeaderComponent::valueChanged (Value&)
  158. {
  159. updateName();
  160. }
  161. void HeaderComponent::timerCallback()
  162. {
  163. repaint();
  164. }
  165. //==============================================================================
  166. void HeaderComponent::initialiseButtons()
  167. {
  168. addAndMakeVisible (projectSettingsButton);
  169. projectSettingsButton.onClick = [this] { projectContentComponent->showProjectSettings(); };
  170. addAndMakeVisible (saveAndOpenInIDEButton);
  171. saveAndOpenInIDEButton.setBackgroundColour (Colours::white);
  172. saveAndOpenInIDEButton.setIconInset (7);
  173. saveAndOpenInIDEButton.onClick = [this]
  174. {
  175. if (project == nullptr)
  176. return;
  177. if (! project->isSaveAndExportDisabled())
  178. {
  179. projectContentComponent->openInSelectedIDE (true);
  180. return;
  181. }
  182. auto setWarningVisible = [this] (const Identifier& identifier)
  183. {
  184. auto child = project->getProjectMessages().getChildWithName (ProjectMessages::Ids::warning)
  185. .getChildWithName (identifier);
  186. if (child.isValid())
  187. child.setProperty (ProjectMessages::Ids::isVisible, true, nullptr);
  188. };
  189. if (project->hasIncompatibleLicenseTypeAndSplashScreenSetting())
  190. setWarningVisible (ProjectMessages::Ids::incompatibleLicense);
  191. if (project->isFileModificationCheckPending())
  192. setWarningVisible (ProjectMessages::Ids::jucerFileModified);
  193. };
  194. updateExporterButton();
  195. }
  196. void HeaderComponent::updateName()
  197. {
  198. if (project != nullptr)
  199. projectNameLabel.setText (project->getDocumentTitle(), dontSendNotification);
  200. }
  201. void HeaderComponent::updateExporterButton()
  202. {
  203. if (auto selectedExporter = getSelectedExporter())
  204. {
  205. auto selectedName = selectedExporter->getUniqueName();
  206. for (auto info : ProjectExporter::getExporterTypeInfos())
  207. {
  208. if (selectedName.contains (info.displayName))
  209. {
  210. saveAndOpenInIDEButton.setImage (info.icon);
  211. saveAndOpenInIDEButton.repaint();
  212. saveAndOpenInIDEButton.setEnabled (canCurrentExporterLaunchProject());
  213. }
  214. }
  215. }
  216. }