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.

267 lines
9.6KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  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 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #pragma once
  20. //==============================================================================
  21. /**
  22. Template option tile button.
  23. The drawable button object class for the tile icons and buttons in the TemplateTileBrowser
  24. */
  25. class TemplateOptionButton : public DrawableButton
  26. {
  27. public:
  28. TemplateOptionButton (const String& buttonName, ButtonStyle buttonStyle, const char* thumbSvg)
  29. : DrawableButton (buttonName, buttonStyle)
  30. {
  31. // svg for thumbnail icon
  32. auto svg = parseXML (thumbSvg);
  33. jassert (svg != nullptr);
  34. thumb = Drawable::createFromSVG (*svg);
  35. // svg for thumbnail background highlight
  36. auto backSvg = parseXML (BinaryData::wizard_Highlight_svg);
  37. jassert (backSvg != nullptr);
  38. hoverBackground = Drawable::createFromSVG (*backSvg);
  39. name = buttonName;
  40. description = "<insert description>";
  41. }
  42. void paintButton (Graphics& g, bool isMouseOverButton, bool /*isButtonDown*/) override
  43. {
  44. const Rectangle<float> r (getLocalBounds().toFloat());
  45. const Colour buttonColour (0xffA35E93);
  46. if (isMouseOverButton)
  47. {
  48. if (getStyle() == ImageFitted)
  49. {
  50. hoverBackground->drawWithin (g, r, RectanglePlacement::centred, 1.0);
  51. thumb->drawWithin (g, r, RectanglePlacement::centred, 1.0);
  52. }
  53. else
  54. {
  55. g.setColour (buttonColour.withAlpha (0.3f));
  56. g.fillRoundedRectangle (r.reduced (2.0f, 2.0f), 10.0f);
  57. g.setColour (buttonColour);
  58. g.drawRoundedRectangle (r.reduced (2.0f, 2.0f), 10.0f, 2.0f);
  59. }
  60. }
  61. else
  62. {
  63. if (getStyle() == ImageFitted)
  64. {
  65. thumb->drawWithin (g, r, RectanglePlacement::centred, 1.0);
  66. }
  67. else
  68. {
  69. g.setColour (buttonColour);
  70. g.drawRoundedRectangle (r.reduced (2.0f, 2.0f), 10.0f, 2.0f);
  71. }
  72. }
  73. Rectangle<float> textTarget;
  74. // center the text for the text buttons or position the text in the image buttons
  75. if (getStyle() != ImageFitted)
  76. {
  77. textTarget = getLocalBounds().toFloat();
  78. }
  79. else
  80. {
  81. textTarget = RectanglePlacement (RectanglePlacement::centred).appliedTo (thumb->getDrawableBounds(), r);
  82. textTarget = textTarget.removeFromBottom (textTarget.getHeight() * 0.3f);
  83. }
  84. g.setColour (findColour (defaultTextColourId));
  85. g.drawText (name, textTarget, Justification::centred, true);
  86. }
  87. void resized() override
  88. {
  89. thumb->setBoundsToFit (getLocalBounds(), Justification::centred, false);
  90. }
  91. void setDescription (String descript) noexcept
  92. {
  93. description = descript;
  94. }
  95. String getDescription() const noexcept
  96. {
  97. return description;
  98. }
  99. private:
  100. void clicked() override
  101. {
  102. StringPairArray data;
  103. data.set ("label", getName());
  104. Analytics::getInstance()->logEvent ("Start Page Button", data, ProjucerAnalyticsEvent::startPageEvent);
  105. }
  106. using DrawableButton::clicked;
  107. std::unique_ptr<Drawable> thumb, hoverBackground;
  108. String name, description;
  109. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemplateOptionButton)
  110. };
  111. //==============================================================================
  112. /**
  113. Project Template Component for front page.
  114. Features multiple icon buttons to select the type of project template
  115. */
  116. class TemplateTileBrowser : public Component
  117. {
  118. public:
  119. TemplateTileBrowser (WizardComp* projectWizard)
  120. {
  121. const int numWizardButtons = getNumWizards() - 1; // ( - 1 because the last one is blank)
  122. for (int i = 0; i < numWizardButtons; ++i)
  123. {
  124. auto wizard = createWizardType (i);
  125. TemplateOptionButton* b = new TemplateOptionButton (wizard->getName(),
  126. TemplateOptionButton::ImageFitted,
  127. wizard->getIcon());
  128. optionButtons.add (b);
  129. addAndMakeVisible (b);
  130. b->setDescription (wizard->getDescription());
  131. b->onClick = [this, b] { showWizardButton (b); };
  132. b->onStateChange = [this] { repaint(); };
  133. }
  134. // Handle Open Project button functionality
  135. ApplicationCommandManager& commandManager = ProjucerApplication::getCommandManager();
  136. addAndMakeVisible (blankProjectButton);
  137. addAndMakeVisible (openProjectButton);
  138. addAndMakeVisible (browseDemosButton);
  139. addAndMakeVisible (viewTutorialsButton);
  140. blankProjectButton.onClick = [this] { createBlankProject(); };
  141. openProjectButton.setCommandToTrigger (&commandManager, CommandIDs::open, true);
  142. browseDemosButton.setCommandToTrigger (&commandManager, CommandIDs::launchDemoRunner, true);
  143. viewTutorialsButton.setCommandToTrigger (&commandManager, CommandIDs::showTutorials, true);
  144. newProjectWizard = projectWizard;
  145. }
  146. void paint (Graphics& g) override
  147. {
  148. g.setColour (findColour (contentHeaderBackgroundColourId));
  149. g.fillRect (getLocalBounds().removeFromTop (60));
  150. g.setColour (Colours::white);
  151. g.setFont (20.0f);
  152. g.drawText ("Create New Project", 0, 0, getWidth(), 60, Justification::centred, true);
  153. auto descriptionBox = (getLocalBounds().reduced (30).removeFromBottom (50));
  154. g.setColour (findColour (defaultTextColourId));
  155. g.setFont (15.0f);
  156. for (int i = 0; i < optionButtons.size(); ++i)
  157. if (optionButtons.getUnchecked(i)->isOver())
  158. g.drawFittedText (optionButtons.getUnchecked(i)->getDescription(), descriptionBox, Justification::centredBottom, 5, 1.0f);
  159. }
  160. void resized() override
  161. {
  162. auto bounds = getLocalBounds().reduced (40, 0);
  163. bounds.removeFromTop (60);
  164. {
  165. auto optionBounds = bounds.removeFromTop (roundToInt (bounds.getHeight() * 0.65f));
  166. auto topSlice = optionBounds.removeFromTop (optionBounds.getHeight() / 2).reduced (0, 10);
  167. auto bottomSlice = optionBounds.reduced (0, 10);
  168. const int numHorizontal = 4;
  169. for (int i = 0; i < optionButtons.size(); ++i)
  170. {
  171. auto& sliceToUse = (i < numHorizontal ? topSlice : bottomSlice);
  172. optionButtons.getUnchecked (i)->setBounds (sliceToUse.removeFromLeft (sliceToUse.getWidth() / (4 - (i % 4))).reduced (10, 0));
  173. }
  174. }
  175. bounds.removeFromTop (20);
  176. auto topButtonBounds = bounds.removeFromTop (50);
  177. openProjectButton.setBounds (topButtonBounds.reduced (80, 0));
  178. bounds.removeFromTop (10);
  179. auto bottomButtonBounds = bounds.removeFromTop (35);
  180. blankProjectButton.setBounds (bottomButtonBounds.removeFromLeft (bottomButtonBounds.getWidth() / 3).reduced (10, 0));
  181. browseDemosButton.setBounds (bottomButtonBounds.removeFromLeft (bottomButtonBounds.getWidth() / 2).reduced (10, 0));
  182. viewTutorialsButton.setBounds (bottomButtonBounds.removeFromLeft (bottomButtonBounds.getWidth()).reduced (10, 0));
  183. }
  184. void showWizard (const String& name)
  185. {
  186. newProjectWizard->projectType.setText (name);
  187. if (SlidingPanelComponent* parent = findParentComponentOfClass<SlidingPanelComponent>())
  188. parent->goToTab (1);
  189. else
  190. jassertfalse;
  191. }
  192. void createBlankProject()
  193. {
  194. showWizard (BlankAppWizard().getName());
  195. }
  196. private:
  197. OwnedArray<TemplateOptionButton> optionButtons;
  198. NewProjectWizardClasses::WizardComp* newProjectWizard;
  199. TemplateOptionButton blankProjectButton { "Create Blank Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg },
  200. openProjectButton { "Open Existing Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg },
  201. browseDemosButton { "Browse JUCE Demos", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg },
  202. viewTutorialsButton { "View JUCE Tutorials", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg };
  203. void showWizardButton (Button* b)
  204. {
  205. if (dynamic_cast<TemplateOptionButton*> (b) != nullptr)
  206. showWizard (b->getButtonText());
  207. }
  208. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemplateTileBrowser)
  209. };