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.

259 lines
9.3KB

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