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.

279 lines
9.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #pragma once
  18. //==============================================================================
  19. /**
  20. Template option tile button.
  21. The drawable button object class for the tile icons and buttons in the TemplateTileBrowser
  22. */
  23. class TemplateOptionButton : public DrawableButton
  24. {
  25. public:
  26. TemplateOptionButton (const String& buttonName, ButtonStyle buttonStyle, const char* thumbSvg)
  27. : DrawableButton (buttonName, buttonStyle)
  28. {
  29. // svg for thumbnail icon
  30. ScopedPointer<XmlElement> svg (XmlDocument::parse (thumbSvg));
  31. jassert (svg != nullptr);
  32. thumb = Drawable::createFromSVG (*svg);
  33. // svg for thumbnail background highlight
  34. ScopedPointer<XmlElement> backSvg (XmlDocument::parse (BinaryData::wizard_Highlight_svg));
  35. jassert (backSvg != nullptr);
  36. hoverBackground = Drawable::createFromSVG (*backSvg);
  37. name = buttonName;
  38. description = "<insert description>";
  39. }
  40. void paintButton (Graphics& g, bool isMouseOverButton, bool /*isButtonDown*/) override
  41. {
  42. const Rectangle<float> r (getLocalBounds().toFloat());
  43. const Colour buttonColour (0xffA35E93);
  44. if (isMouseOverButton)
  45. {
  46. if (getStyle() == ImageFitted)
  47. {
  48. hoverBackground->drawWithin (g, r, RectanglePlacement::centred, 1.0);
  49. thumb->drawWithin (g, r, RectanglePlacement::centred, 1.0);
  50. }
  51. else
  52. {
  53. g.setColour (buttonColour.withAlpha (0.3f));
  54. g.fillRoundedRectangle (r.reduced (2.0f, 2.0f), 10.0f);
  55. g.setColour (buttonColour);
  56. g.drawRoundedRectangle (r.reduced (2.0f, 2.0f), 10.0f, 2.0f);
  57. }
  58. }
  59. else
  60. {
  61. if (getStyle() == ImageFitted)
  62. {
  63. thumb->drawWithin (g, r, RectanglePlacement::centred, 1.0);
  64. }
  65. else
  66. {
  67. g.setColour (buttonColour);
  68. g.drawRoundedRectangle (r.reduced (2.0f, 2.0f), 10.0f, 2.0f);
  69. }
  70. }
  71. Rectangle<float> textTarget;
  72. // center the text for the text buttons or position the text in the image buttons
  73. if (getStyle() != ImageFitted)
  74. {
  75. textTarget = getLocalBounds().toFloat();
  76. }
  77. else
  78. {
  79. textTarget = RectanglePlacement (RectanglePlacement::centred).appliedTo (thumb->getDrawableBounds(), r);
  80. textTarget = textTarget.removeFromBottom (textTarget.getHeight() * 0.3f);
  81. }
  82. g.setColour (findColour (defaultTextColourId));
  83. g.drawText (name, textTarget, Justification::centred, true);
  84. }
  85. void resized() override
  86. {
  87. thumb->setBoundsToFit (0, 0, getWidth(), getHeight(), Justification::centred, false);
  88. }
  89. void setDescription (String descript) noexcept
  90. {
  91. description = descript;
  92. }
  93. String getDescription() const noexcept
  94. {
  95. return description;
  96. }
  97. private:
  98. ScopedPointer<Drawable> thumb, hoverBackground;
  99. String name, description;
  100. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemplateOptionButton)
  101. };
  102. //==============================================================================
  103. /**
  104. Project Template Component for front page.
  105. Features multiple icon buttons to select the type of project template
  106. */
  107. class TemplateTileBrowser : public Component,
  108. private Button::Listener
  109. {
  110. public:
  111. TemplateTileBrowser (WizardComp* projectWizard)
  112. {
  113. const int numWizardButtons = getNumWizards() - 1; // ( - 1 because the last one is blank)
  114. for (int i = 0; i < numWizardButtons; ++i)
  115. {
  116. ScopedPointer<NewProjectWizard> wizard (createWizardType (i));
  117. TemplateOptionButton* b = new TemplateOptionButton (wizard->getName(),
  118. TemplateOptionButton::ImageFitted,
  119. wizard->getIcon());
  120. optionButtons.add (b);
  121. addAndMakeVisible (b);
  122. b->setDescription (wizard->getDescription());
  123. b->addListener (this);
  124. }
  125. // Handle Open Project button functionality
  126. ApplicationCommandManager& commandManager = ProjucerApplication::getCommandManager();
  127. addAndMakeVisible (blankProjectButton = new TemplateOptionButton ("Create Blank Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg));
  128. addAndMakeVisible (exampleProjectButton = new TemplateOptionButton ("Open Example Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg));
  129. addAndMakeVisible (openProjectButton = new TemplateOptionButton ("Open Existing Project", TemplateOptionButton::ImageOnButtonBackground, BinaryData::wizard_Openfile_svg));
  130. blankProjectButton->addListener (this);
  131. exampleProjectButton->addListener (this);
  132. openProjectButton->setCommandToTrigger (&commandManager, CommandIDs::open, true);
  133. newProjectWizard = projectWizard;
  134. }
  135. void paint (Graphics& g) override
  136. {
  137. g.setColour (findColour (contentHeaderBackgroundColourId));
  138. g.fillRect (getLocalBounds().removeFromTop (60));
  139. g.setColour (Colours::white);
  140. g.setFont (20.0f);
  141. g.drawText ("Create New Project", 0, 0, getWidth(), 60, Justification::centred, true);
  142. auto descriptionBox = (getLocalBounds().reduced (30).removeFromBottom (50));
  143. g.setColour (findColour (defaultTextColourId));
  144. g.setFont (15.0f);
  145. for (int i = 0; i < optionButtons.size(); ++i)
  146. if (optionButtons.getUnchecked(i)->isOver())
  147. g.drawFittedText (optionButtons.getUnchecked(i)->getDescription(), descriptionBox, Justification::centred, 5, 1.0f);
  148. }
  149. void resized() override
  150. {
  151. auto allOpts = getLocalBounds().reduced (40, 60);
  152. allOpts.removeFromBottom (allOpts.getHeight() / 4);
  153. const auto numHorizIcons = 4;
  154. const auto optStep = allOpts.getWidth() / numHorizIcons;
  155. for (int i = 0; i < optionButtons.size(); ++i)
  156. {
  157. const auto yShift = i < numHorizIcons ? 0 : 1;
  158. optionButtons.getUnchecked(i)->setBounds (Rectangle<int> (allOpts.getX() + (i % numHorizIcons) * optStep,
  159. allOpts.getY() + yShift * allOpts.getHeight() / 2,
  160. optStep, allOpts.getHeight() / 2)
  161. .reduced (10, 10));
  162. }
  163. auto openButtonBounds = getLocalBounds();
  164. openButtonBounds.removeFromBottom (proportionOfHeight (0.12f));
  165. openButtonBounds = openButtonBounds.removeFromBottom (120);
  166. openButtonBounds.reduce (50, 40);
  167. blankProjectButton->setBounds (openButtonBounds.removeFromLeft (optStep - 20));
  168. exampleProjectButton->setBounds (openButtonBounds.removeFromRight (optStep - 20));
  169. openProjectButton->setBounds (openButtonBounds.reduced (18, 0));
  170. }
  171. void showWizard (const String& name)
  172. {
  173. newProjectWizard->projectType.setText (name);
  174. if (SlidingPanelComponent* parent = findParentComponentOfClass<SlidingPanelComponent>())
  175. parent->goToTab (1);
  176. else
  177. jassertfalse;
  178. }
  179. void createBlankProject()
  180. {
  181. showWizard (BlankAppWizard().getName());
  182. }
  183. void openExampleProject()
  184. {
  185. FileChooser fc ("Open File", findExamplesFolder());
  186. if (fc.browseForFileToOpen())
  187. ProjucerApplication::getApp().openFile (fc.getResult());
  188. }
  189. static File findExamplesFolder()
  190. {
  191. File appFolder (File::getSpecialLocation (File::currentApplicationFile));
  192. while (appFolder.exists()
  193. && appFolder.getParentDirectory() != appFolder)
  194. {
  195. File examples (appFolder.getSiblingFile ("examples"));
  196. if (examples.exists())
  197. return examples;
  198. appFolder = appFolder.getParentDirectory();
  199. }
  200. return {};
  201. }
  202. private:
  203. OwnedArray<TemplateOptionButton> optionButtons;
  204. NewProjectWizardClasses::WizardComp* newProjectWizard;
  205. ScopedPointer<TemplateOptionButton> blankProjectButton, openProjectButton, exampleProjectButton;
  206. void buttonClicked (Button* b) override
  207. {
  208. if (b == blankProjectButton)
  209. createBlankProject();
  210. else if (b == exampleProjectButton)
  211. openExampleProject();
  212. else if (dynamic_cast<TemplateOptionButton*> (b) != nullptr)
  213. showWizard (b->getButtonText());
  214. }
  215. void buttonStateChanged (Button*) override
  216. {
  217. repaint();
  218. }
  219. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemplateTileBrowser)
  220. };