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.

251 lines
9.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 6 technical preview.
  4. Copyright (c) 2020 - Raw Material Software Limited
  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. using DrawableButton::clicked;
  95. std::unique_ptr<Drawable> thumb, hoverBackground;
  96. String name, description;
  97. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemplateOptionButton)
  98. };
  99. //==============================================================================
  100. /**
  101. Project Template Component for front page.
  102. Features multiple icon buttons to select the type of project template
  103. */
  104. class TemplateTileBrowser : public Component
  105. {
  106. public:
  107. TemplateTileBrowser (WizardComp* projectWizard)
  108. {
  109. const int numWizardButtons = getNumWizards() - 1; // ( - 1 because the last one is blank)
  110. for (int i = 0; i < numWizardButtons; ++i)
  111. {
  112. auto wizard = createWizardType (i);
  113. TemplateOptionButton* b = new TemplateOptionButton (wizard->getName(),
  114. TemplateOptionButton::ImageFitted,
  115. wizard->getIcon());
  116. optionButtons.add (b);
  117. addAndMakeVisible (b);
  118. b->setDescription (wizard->getDescription());
  119. b->onClick = [this, b] { showWizardButton (b); };
  120. b->onStateChange = [this] { repaint(); };
  121. }
  122. // Handle Open Project button functionality
  123. ApplicationCommandManager& commandManager = ProjucerApplication::getCommandManager();
  124. addAndMakeVisible (blankProjectButton);
  125. addAndMakeVisible (openProjectButton);
  126. addAndMakeVisible (browseDemosButton);
  127. addAndMakeVisible (viewTutorialsButton);
  128. blankProjectButton.onClick = [this] { createBlankProject(); };
  129. openProjectButton.setCommandToTrigger (&commandManager, CommandIDs::open, true);
  130. browseDemosButton.setCommandToTrigger (&commandManager, CommandIDs::launchDemoRunner, true);
  131. viewTutorialsButton.setCommandToTrigger (&commandManager, CommandIDs::showTutorials, true);
  132. newProjectWizard = projectWizard;
  133. }
  134. void paint (Graphics& g) override
  135. {
  136. g.setColour (findColour (contentHeaderBackgroundColourId));
  137. g.fillRect (getLocalBounds().removeFromTop (60));
  138. g.setColour (Colours::white);
  139. g.setFont (20.0f);
  140. g.drawText ("Create New Project", 0, 0, getWidth(), 60, Justification::centred, true);
  141. auto descriptionBox = (getLocalBounds().reduced (30).removeFromBottom (50));
  142. g.setColour (findColour (defaultTextColourId));
  143. g.setFont (15.0f);
  144. for (int i = 0; i < optionButtons.size(); ++i)
  145. if (optionButtons.getUnchecked(i)->isOver())
  146. g.drawFittedText (optionButtons.getUnchecked(i)->getDescription(), descriptionBox, Justification::centredBottom, 5, 1.0f);
  147. }
  148. void resized() override
  149. {
  150. auto bounds = getLocalBounds().reduced (40, 0);
  151. bounds.removeFromTop (60);
  152. {
  153. auto optionBounds = bounds.removeFromTop (roundToInt (bounds.getHeight() * 0.65f));
  154. auto topSlice = optionBounds.removeFromTop (optionBounds.getHeight() / 2).reduced (0, 10);
  155. auto bottomSlice = optionBounds.reduced (0, 10);
  156. const int numHorizontal = 4;
  157. for (int i = 0; i < optionButtons.size(); ++i)
  158. {
  159. auto& sliceToUse = (i < numHorizontal ? topSlice : bottomSlice);
  160. optionButtons.getUnchecked (i)->setBounds (sliceToUse.removeFromLeft (sliceToUse.getWidth() / (4 - (i % 4))).reduced (10, 0));
  161. }
  162. }
  163. bounds.removeFromTop (20);
  164. auto topButtonBounds = bounds.removeFromTop (50);
  165. openProjectButton.setBounds (topButtonBounds.reduced (80, 0));
  166. bounds.removeFromTop (10);
  167. auto bottomButtonBounds = bounds.removeFromTop (35);
  168. blankProjectButton.setBounds (bottomButtonBounds.removeFromLeft (bottomButtonBounds.getWidth() / 3).reduced (10, 0));
  169. browseDemosButton.setBounds (bottomButtonBounds.removeFromLeft (bottomButtonBounds.getWidth() / 2).reduced (10, 0));
  170. viewTutorialsButton.setBounds (bottomButtonBounds.removeFromLeft (bottomButtonBounds.getWidth()).reduced (10, 0));
  171. }
  172. void showWizard (const String& name)
  173. {
  174. newProjectWizard->projectType.setText (name);
  175. if (SlidingPanelComponent* parent = findParentComponentOfClass<SlidingPanelComponent>())
  176. parent->goToTab (1);
  177. else
  178. jassertfalse;
  179. }
  180. void createBlankProject()
  181. {
  182. showWizard (BlankAppWizard().getName());
  183. }
  184. private:
  185. OwnedArray<TemplateOptionButton> optionButtons;
  186. NewProjectWizardClasses::WizardComp* newProjectWizard;
  187. TemplateOptionButton blankProjectButton { "Create Blank Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg },
  188. openProjectButton { "Open Existing Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg },
  189. browseDemosButton { "Browse JUCE Demos", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg },
  190. viewTutorialsButton { "View JUCE Tutorials", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg };
  191. void showWizardButton (Button* b)
  192. {
  193. if (dynamic_cast<TemplateOptionButton*> (b) != nullptr)
  194. showWizard (b->getButtonText());
  195. }
  196. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemplateTileBrowser)
  197. };