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.4KB

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