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.

616 lines
26KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-12 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../JuceDemoHeader.h"
  19. //==============================================================================
  20. /** Custom Look And Feel subclasss.
  21. Simply override the methods you need to, anything else will be inherited from the base class.
  22. It's a good idea not to hard code your colours, use the findColour method along with appropriate
  23. ColourIds so you can set these on a per-component basis.
  24. */
  25. struct CustomLookAndFeel : public LookAndFeel_V3
  26. {
  27. void drawRoundThumb (Graphics& g, const float x, const float y,
  28. const float diameter, const Colour& colour, float outlineThickness)
  29. {
  30. const Rectangle<float> a (x, y, diameter, diameter);
  31. const float halfThickness = outlineThickness * 0.5f;
  32. Path p;
  33. p.addEllipse (x + halfThickness, y + halfThickness, diameter - outlineThickness, diameter - outlineThickness);
  34. const DropShadow ds (Colours::black, 1, Point<int> (0, 0));
  35. ds.drawForPath (g, p);
  36. g.setColour (colour);
  37. g.fillPath (p);
  38. g.setColour (colour.brighter());
  39. g.strokePath (p, PathStrokeType (outlineThickness));
  40. }
  41. void drawButtonBackground (Graphics& g, Button& button, const Colour& backgroundColour,
  42. bool isMouseOverButton, bool isButtonDown) override
  43. {
  44. Colour baseColour (backgroundColour.withMultipliedSaturation (button.hasKeyboardFocus (true) ? 1.3f : 0.9f)
  45. .withMultipliedAlpha (button.isEnabled() ? 0.9f : 0.5f));
  46. if (isButtonDown || isMouseOverButton)
  47. baseColour = baseColour.contrasting (isButtonDown ? 0.2f : 0.1f);
  48. const bool flatOnLeft = button.isConnectedOnLeft();
  49. const bool flatOnRight = button.isConnectedOnRight();
  50. const bool flatOnTop = button.isConnectedOnTop();
  51. const bool flatOnBottom = button.isConnectedOnBottom();
  52. const float width = button.getWidth() - 1.0f;
  53. const float height = button.getHeight() - 1.0f;
  54. if (width > 0 && height > 0)
  55. {
  56. const float cornerSize = jmin (15.0f, jmin (width, height) * 0.45f);
  57. const float lineThickness = cornerSize * 0.1f;
  58. const float halfThickness = lineThickness * 0.5f;
  59. Path outline;
  60. outline.addRoundedRectangle (0.5f + halfThickness, 0.5f + halfThickness, width - lineThickness, height - lineThickness,
  61. cornerSize, cornerSize,
  62. ! (flatOnLeft || flatOnTop),
  63. ! (flatOnRight || flatOnTop),
  64. ! (flatOnLeft || flatOnBottom),
  65. ! (flatOnRight || flatOnBottom));
  66. const Colour outlineColour (button.findColour (button.getToggleState() ? TextButton::textColourOnId
  67. : TextButton::textColourOffId));
  68. g.setColour (baseColour);
  69. g.fillPath (outline);
  70. if (! button.getToggleState())
  71. {
  72. g.setColour (outlineColour);
  73. g.strokePath (outline, PathStrokeType (lineThickness));
  74. }
  75. }
  76. }
  77. void drawTickBox (Graphics& g, Component& component,
  78. float x, float y, float w, float h,
  79. bool ticked,
  80. bool isEnabled,
  81. bool isMouseOverButton,
  82. bool isButtonDown) override
  83. {
  84. const float boxSize = w * 0.7f;
  85. bool isDownOrDragging = component.isEnabled() && (component.isMouseOverOrDragging() || component.isMouseButtonDown());
  86. const Colour colour (component.findColour (TextButton::buttonColourId).withMultipliedSaturation ((component.hasKeyboardFocus (false) || isDownOrDragging) ? 1.3f : 0.9f)
  87. .withMultipliedAlpha (component.isEnabled() ? 1.0f : 0.7f));
  88. drawRoundThumb (g, x, y + (h - boxSize) * 0.5f, boxSize, colour,
  89. isEnabled ? ((isButtonDown || isMouseOverButton) ? 1.1f : 0.5f) : 0.3f);
  90. if (ticked)
  91. {
  92. const Path tick (LookAndFeel_V2::getTickShape (6.0f));
  93. g.setColour (isEnabled ? findColour (TextButton::buttonOnColourId) : Colours::grey);
  94. const float scale = 9.0f;
  95. const AffineTransform trans (AffineTransform::scale (w / scale, h / scale)
  96. .translated (x - 2.5f, y + 1.0f));
  97. g.fillPath (tick, trans);
  98. }
  99. }
  100. void drawLinearSliderThumb (Graphics& g, int x, int y, int width, int height,
  101. float sliderPos, float minSliderPos, float maxSliderPos,
  102. const Slider::SliderStyle style, Slider& slider) override
  103. {
  104. const float sliderRadius = (float) (getSliderThumbRadius (slider) - 2);
  105. bool isDownOrDragging = slider.isEnabled() && (slider.isMouseOverOrDragging() || slider.isMouseButtonDown());
  106. Colour knobColour (slider.findColour (Slider::thumbColourId).withMultipliedSaturation ((slider.hasKeyboardFocus (false) || isDownOrDragging) ? 1.3f : 0.9f)
  107. .withMultipliedAlpha (slider.isEnabled() ? 1.0f : 0.7f));
  108. if (style == Slider::LinearHorizontal || style == Slider::LinearVertical)
  109. {
  110. float kx, ky;
  111. if (style == Slider::LinearVertical)
  112. {
  113. kx = x + width * 0.5f;
  114. ky = sliderPos;
  115. }
  116. else
  117. {
  118. kx = sliderPos;
  119. ky = y + height * 0.5f;
  120. }
  121. const float outlineThickness = slider.isEnabled() ? 0.8f : 0.3f;
  122. drawRoundThumb (g,
  123. kx - sliderRadius,
  124. ky - sliderRadius,
  125. sliderRadius * 2.0f,
  126. knobColour, outlineThickness);
  127. }
  128. else
  129. {
  130. // Just call the base class for the demo
  131. LookAndFeel_V2::drawLinearSliderThumb (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
  132. }
  133. }
  134. void drawLinearSlider (Graphics& g, int x, int y, int width, int height,
  135. float sliderPos, float minSliderPos, float maxSliderPos,
  136. const Slider::SliderStyle style, Slider& slider) override
  137. {
  138. g.fillAll (slider.findColour (Slider::backgroundColourId));
  139. if (style == Slider::LinearBar || style == Slider::LinearBarVertical)
  140. {
  141. const float fx = (float) x, fy = (float) y, fw = (float) width, fh = (float) height;
  142. Path p;
  143. if (style == Slider::LinearBarVertical)
  144. p.addRectangle (fx, sliderPos, fw, 1.0f + fh - sliderPos);
  145. else
  146. p.addRectangle (fx, fy, sliderPos - fx, fh);
  147. Colour baseColour (slider.findColour (Slider::rotarySliderFillColourId)
  148. .withMultipliedSaturation (slider.isEnabled() ? 1.0f : 0.5f)
  149. .withMultipliedAlpha (0.8f));
  150. g.setColour (baseColour);
  151. g.fillPath (p);
  152. const float lineThickness = jmin (15.0f, jmin (width, height) * 0.45f) * 0.1f;
  153. g.drawRect (slider.getLocalBounds().toFloat(), lineThickness);
  154. }
  155. else
  156. {
  157. drawLinearSliderBackground (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
  158. drawLinearSliderThumb (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
  159. }
  160. }
  161. void drawLinearSliderBackground (Graphics& g, int x, int y, int width, int height,
  162. float /*sliderPos*/,
  163. float /*minSliderPos*/,
  164. float /*maxSliderPos*/,
  165. const Slider::SliderStyle /*style*/, Slider& slider) override
  166. {
  167. const float sliderRadius = getSliderThumbRadius (slider) - 5.0f;
  168. Path on, off;
  169. if (slider.isHorizontal())
  170. {
  171. const float iy = x + width * 0.5f - sliderRadius * 0.5f;
  172. Rectangle<float> r (x - sliderRadius * 0.5f, iy, width + sliderRadius, sliderRadius);
  173. const float onW = r.getWidth() * ((float) slider.valueToProportionOfLength (slider.getValue()));
  174. on.addRectangle (r.removeFromLeft (onW));
  175. off.addRectangle (r);
  176. }
  177. else
  178. {
  179. const float ix = x + width * 0.5f - sliderRadius * 0.5f;
  180. Rectangle<float> r (ix, y - sliderRadius * 0.5f, sliderRadius, height + sliderRadius);
  181. const float onH = r.getHeight() * ((float) slider.valueToProportionOfLength (slider.getValue()));
  182. on.addRectangle (r.removeFromBottom (onH));
  183. off.addRectangle (r);
  184. }
  185. g.setColour (slider.findColour (Slider::rotarySliderFillColourId));
  186. g.fillPath (on);
  187. g.setColour (slider.findColour (Slider::trackColourId));
  188. g.fillPath (off);
  189. }
  190. void drawRotarySlider (Graphics& g, int x, int y, int width, int height, float sliderPos,
  191. float rotaryStartAngle, float rotaryEndAngle, Slider& slider) override
  192. {
  193. const float radius = jmin (width / 2, height / 2) - 2.0f;
  194. const float centreX = x + width * 0.5f;
  195. const float centreY = y + height * 0.5f;
  196. const float rx = centreX - radius;
  197. const float ry = centreY - radius;
  198. const float rw = radius * 2.0f;
  199. const float angle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle);
  200. const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled();
  201. if (slider.isEnabled())
  202. g.setColour (slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 1.0f : 0.7f));
  203. else
  204. g.setColour (Colour (0x80808080));
  205. {
  206. Path filledArc;
  207. filledArc.addPieSegment (rx, ry, rw, rw, rotaryStartAngle, angle, 0.0);
  208. g.fillPath (filledArc);
  209. }
  210. {
  211. const float lineThickness = jmin (15.0f, jmin (width, height) * 0.45f) * 0.1f;
  212. Path outlineArc;
  213. outlineArc.addPieSegment (rx, ry, rw, rw, rotaryStartAngle, rotaryEndAngle, 0.0);
  214. g.strokePath (outlineArc, PathStrokeType (lineThickness));
  215. }
  216. }
  217. };
  218. //==============================================================================
  219. /** Another really simple look and feel that is very flat and square.
  220. This inherits from CustomLookAndFeel above for the linear bar and slider backgrounds.
  221. */
  222. struct SquareLookAndFeel : public CustomLookAndFeel
  223. {
  224. void drawButtonBackground (Graphics& g, Button& button, const Colour& backgroundColour,
  225. bool isMouseOverButton, bool isButtonDown) override
  226. {
  227. Colour baseColour (backgroundColour.withMultipliedSaturation (button.hasKeyboardFocus (true) ? 1.3f : 0.9f)
  228. .withMultipliedAlpha (button.isEnabled() ? 0.9f : 0.5f));
  229. if (isButtonDown || isMouseOverButton)
  230. baseColour = baseColour.contrasting (isButtonDown ? 0.2f : 0.1f);
  231. const float width = button.getWidth() - 1.0f;
  232. const float height = button.getHeight() - 1.0f;
  233. if (width > 0 && height > 0)
  234. {
  235. g.setGradientFill (ColourGradient (baseColour, 0.0f, 0.0f,
  236. baseColour.darker (0.1f), 0.0f, height,
  237. false));
  238. g.fillRect (button.getLocalBounds());
  239. }
  240. }
  241. void drawTickBox (Graphics& g, Component& component,
  242. float x, float y, float w, float h,
  243. bool ticked,
  244. bool isEnabled,
  245. bool /*isMouseOverButton*/,
  246. bool /*isButtonDown*/) override
  247. {
  248. const float boxSize = w * 0.7f;
  249. bool isDownOrDragging = component.isEnabled() && (component.isMouseOverOrDragging() || component.isMouseButtonDown());
  250. const Colour colour (component.findColour (TextButton::buttonOnColourId).withMultipliedSaturation ((component.hasKeyboardFocus (false) || isDownOrDragging) ? 1.3f : 0.9f)
  251. .withMultipliedAlpha (component.isEnabled() ? 1.0f : 0.7f));
  252. g.setColour (colour);
  253. Rectangle<float> r (x, y + (h - boxSize) * 0.5f, boxSize, boxSize);
  254. g.fillRect (r);
  255. if (ticked)
  256. {
  257. const Path tick (LookAndFeel_V3::getTickShape (6.0f));
  258. g.setColour (isEnabled ? findColour (TextButton::buttonColourId) : Colours::grey);
  259. const AffineTransform trans (RectanglePlacement (RectanglePlacement::centred)
  260. .getTransformToFit (tick.getBounds(), r.reduced (r.getHeight() * 0.05f)));
  261. g.fillPath (tick, trans);
  262. }
  263. }
  264. void drawLinearSliderThumb (Graphics& g, int x, int y, int width, int height,
  265. float sliderPos, float minSliderPos, float maxSliderPos,
  266. const Slider::SliderStyle style, Slider& slider) override
  267. {
  268. const float sliderRadius = (float) getSliderThumbRadius (slider);
  269. bool isDownOrDragging = slider.isEnabled() && (slider.isMouseOverOrDragging() || slider.isMouseButtonDown());
  270. Colour knobColour (slider.findColour (Slider::rotarySliderFillColourId).withMultipliedSaturation ((slider.hasKeyboardFocus (false) || isDownOrDragging) ? 1.3f : 0.9f)
  271. .withMultipliedAlpha (slider.isEnabled() ? 1.0f : 0.7f));
  272. g.setColour (knobColour);
  273. if (style == Slider::LinearHorizontal || style == Slider::LinearVertical)
  274. {
  275. float kx, ky;
  276. if (style == Slider::LinearVertical)
  277. {
  278. kx = x + width * 0.5f;
  279. ky = sliderPos;
  280. g.fillRect (Rectangle<float> (kx - sliderRadius, ky - 2.5f, sliderRadius * 2.0f, 5.0f));
  281. }
  282. else
  283. {
  284. kx = sliderPos;
  285. ky = y + height * 0.5f;
  286. g.fillRect (Rectangle<float> (kx - 2.5f, ky - sliderRadius, 5.0f, sliderRadius * 2.0f));
  287. }
  288. }
  289. else
  290. {
  291. // Just call the base class for the demo
  292. LookAndFeel_V2::drawLinearSliderThumb (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
  293. }
  294. }
  295. void drawRotarySlider (Graphics& g, int x, int y, int width, int height, float sliderPos,
  296. float rotaryStartAngle, float rotaryEndAngle, Slider& slider) override
  297. {
  298. const float diameter = jmin (width, height) - 4.0f;
  299. const float radius = (diameter / 2.0f) * std::cos (float_Pi / 4.0f);
  300. const float centreX = x + width * 0.5f;
  301. const float centreY = y + height * 0.5f;
  302. const float rx = centreX - radius;
  303. const float ry = centreY - radius;
  304. const float rw = radius * 2.0f;
  305. const float angle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle);
  306. const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled();
  307. const Colour baseColour (slider.isEnabled() ? slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 0.8f : 1.0f)
  308. : Colour (0x80808080));
  309. Rectangle<float> r (rx, ry, rw, rw);
  310. AffineTransform t (AffineTransform::rotation (angle, r.getCentreX(), r.getCentreY()));
  311. float x1 = r.getTopLeft().getX(), y1 = r.getTopLeft().getY(), x2 = r.getBottomLeft().getX(), y2 = r.getBottomLeft().getY();
  312. t.transformPoints (x1, y1, x2, y2);
  313. g.setGradientFill (ColourGradient (baseColour, x1, y1,
  314. baseColour.darker (0.1f), x2, y2,
  315. false));
  316. Path knob;
  317. knob.addRectangle (r);
  318. g.fillPath (knob, t);
  319. Path needle;
  320. Rectangle<float> r2 (r * 0.1f);
  321. needle.addRectangle (r2.withPosition (Point<float> (r.getCentreX() - (r2.getWidth() / 2.0f), r.getY())));
  322. g.setColour (slider.findColour (Slider::rotarySliderOutlineColourId));
  323. g.fillPath (needle, AffineTransform::rotation (angle, r.getCentreX(), r.getCentreY()));
  324. }
  325. };
  326. //==============================================================================
  327. struct LookAndFeelDemoComponent : public Component
  328. {
  329. LookAndFeelDemoComponent()
  330. {
  331. addAndMakeVisible (rotarySlider);
  332. rotarySlider.setSliderStyle (Slider::RotaryHorizontalVerticalDrag);
  333. rotarySlider.setTextBoxStyle (Slider::NoTextBox, false, 0, 0);
  334. rotarySlider.setValue (2.5);
  335. addAndMakeVisible (verticalSlider);
  336. verticalSlider.setSliderStyle (Slider::LinearVertical);
  337. verticalSlider.setTextBoxStyle (Slider::NoTextBox, false, 90, 20);
  338. verticalSlider.setValue (6.2);
  339. addAndMakeVisible (barSlider);
  340. barSlider.setSliderStyle (Slider::LinearBar);
  341. barSlider.setValue (4.5);
  342. addAndMakeVisible (incDecSlider);
  343. incDecSlider.setSliderStyle (Slider::IncDecButtons);
  344. incDecSlider.setRange (0.0, 10.0, 1.0);
  345. incDecSlider.setIncDecButtonsMode (Slider::incDecButtonsDraggable_Horizontal);
  346. incDecSlider.setTextBoxStyle (Slider::TextBoxBelow, false, 90, 20);
  347. addAndMakeVisible (button1);
  348. button1.setButtonText ("Hello World!");
  349. addAndMakeVisible (button2);
  350. button2.setButtonText ("Hello World!");
  351. button2.setClickingTogglesState (true);
  352. button2.setToggleState (true, dontSendNotification);
  353. addAndMakeVisible (button3);
  354. button3.setButtonText ("Hello World!");
  355. addAndMakeVisible (button4);
  356. button4.setButtonText ("Toggle Me");
  357. button4.setToggleState (true, dontSendNotification);
  358. for (int i = 0; i < 3; ++i)
  359. {
  360. TextButton* b = radioButtons.add (new TextButton());
  361. addAndMakeVisible (b);
  362. b->setRadioGroupId (42);
  363. b->setClickingTogglesState (true);
  364. b->setButtonText ("Button " + String (i + 1));
  365. switch (i)
  366. {
  367. case 0: b->setConnectedEdges (Button::ConnectedOnRight); break;
  368. case 1: b->setConnectedEdges (Button::ConnectedOnRight + Button::ConnectedOnLeft); break;
  369. case 2: b->setConnectedEdges (Button::ConnectedOnLeft); break;
  370. default: break;
  371. }
  372. }
  373. radioButtons.getUnchecked (2)->setToggleState (true, dontSendNotification);
  374. }
  375. void resized() override
  376. {
  377. Rectangle<int> area (getLocalBounds().reduced (10));
  378. Rectangle<int> row (area.removeFromTop (100));
  379. rotarySlider.setBounds (row.removeFromLeft (100).reduced (5));
  380. verticalSlider.setBounds (row.removeFromLeft (100).reduced (5));
  381. barSlider.setBounds (row.removeFromLeft (100).reduced (5, 25));
  382. incDecSlider.setBounds (row.removeFromLeft (100).reduced (5, 28));
  383. row = area.removeFromTop (100);
  384. button1.setBounds (row.removeFromLeft (100).reduced (5));
  385. Rectangle<int> row2 (row.removeFromTop (row.getHeight() / 2).reduced (0, 10));
  386. button2.setBounds (row2.removeFromLeft (100).reduced (5, 0));
  387. button3.setBounds (row2.removeFromLeft (100).reduced (5, 0));
  388. button4.setBounds (row2.removeFromLeft (100).reduced (5, 0));
  389. row2 = (row.removeFromTop (row2.getHeight() + 20).reduced (5, 10));
  390. for (int i = 0; i < radioButtons.size(); ++i)
  391. radioButtons.getUnchecked (i)->setBounds (row2.removeFromLeft (100));
  392. }
  393. Slider rotarySlider, verticalSlider, barSlider, incDecSlider;
  394. TextButton button1, button2, button3;
  395. ToggleButton button4;
  396. OwnedArray<TextButton> radioButtons;
  397. };
  398. //==============================================================================
  399. class LookAndFeelDemo : public Component,
  400. private ComboBox::Listener,
  401. private Button::Listener
  402. {
  403. public:
  404. LookAndFeelDemo()
  405. {
  406. descriptionLabel.setMinimumHorizontalScale (1.0f);
  407. descriptionLabel.setText ("This demonstrates how to create a custom look and feel by overriding only the desired methods.\n\n"
  408. "Components can have their look and feel individually assigned or they will inherit it from their parent. "
  409. "Colours work in a similar way, they can be set for individual components or a look and feel as a whole.",
  410. dontSendNotification);
  411. addAndMakeVisible (descriptionLabel);
  412. addAndMakeVisible (lafBox);
  413. addAndMakeVisible (demoComp);
  414. addLookAndFeel (new LookAndFeel_V1(), "LookAndFeel_V1");
  415. addLookAndFeel (new LookAndFeel_V2(), "LookAndFeel_V2");
  416. addLookAndFeel (new LookAndFeel_V3(), "LookAndFeel_V3");
  417. CustomLookAndFeel* claf = new CustomLookAndFeel();
  418. addLookAndFeel (claf, "Custom Look And Feel");
  419. setupCustomLookAndFeelColours (*claf);
  420. SquareLookAndFeel* slaf = new SquareLookAndFeel();
  421. addLookAndFeel (slaf, "Square Look And Feel");
  422. setupSquareLookAndFeelColours (*slaf);
  423. lafBox.addListener (this);
  424. lafBox.setSelectedItemIndex (3);
  425. addAndMakeVisible (randomButton);
  426. randomButton.setButtonText ("Assign Randomly");
  427. randomButton.addListener (this);
  428. }
  429. void paint (Graphics& g) override
  430. {
  431. g.fillAll (Colour::greyLevel (0.4f));
  432. }
  433. void resized() override
  434. {
  435. Rectangle<int> r (getLocalBounds().reduced (10));
  436. demoComp.setBounds (r);
  437. descriptionLabel.setBounds (r.removeFromTop (200));
  438. lafBox.setBounds (r.removeFromTop (22).removeFromLeft (250));
  439. randomButton.setBounds (lafBox.getBounds().withX (lafBox.getRight() + 20).withWidth (140));
  440. demoComp.setBounds (r.withTrimmedTop (10));
  441. }
  442. private:
  443. Label descriptionLabel;
  444. ComboBox lafBox;
  445. TextButton randomButton;
  446. OwnedArray<LookAndFeel> lookAndFeels;
  447. LookAndFeelDemoComponent demoComp;
  448. void addLookAndFeel (LookAndFeel* laf, const String& name)
  449. {
  450. lookAndFeels.add (laf);
  451. lafBox.addItem (name, lafBox.getNumItems() + 1);
  452. }
  453. void setupCustomLookAndFeelColours (LookAndFeel& laf)
  454. {
  455. laf.setColour (Slider::thumbColourId, Colour::greyLevel (0.95f));
  456. laf.setColour (Slider::textBoxOutlineColourId, Colours::transparentWhite);
  457. laf.setColour (Slider::rotarySliderFillColourId, Colour (0xff00b5f6));
  458. laf.setColour (Slider::rotarySliderOutlineColourId, Colours::white);
  459. laf.setColour (TextButton::buttonColourId, Colours::white);
  460. laf.setColour (TextButton::textColourOffId, Colour (0xff00b5f6));
  461. laf.setColour (TextButton::buttonOnColourId, laf.findColour (TextButton::textColourOffId));
  462. laf.setColour (TextButton::textColourOnId, laf.findColour (TextButton::buttonColourId));
  463. }
  464. void setupSquareLookAndFeelColours (LookAndFeel& laf)
  465. {
  466. const Colour baseColour (Colours::red);
  467. laf.setColour (Slider::thumbColourId, Colour::greyLevel (0.95f));
  468. laf.setColour (Slider::textBoxOutlineColourId, Colours::transparentWhite);
  469. laf.setColour (Slider::rotarySliderFillColourId, baseColour);
  470. laf.setColour (Slider::rotarySliderOutlineColourId, Colours::white);
  471. laf.setColour (Slider::trackColourId, Colours::black);
  472. laf.setColour (TextButton::buttonColourId, Colours::white);
  473. laf.setColour (TextButton::textColourOffId, baseColour);
  474. laf.setColour (TextButton::buttonOnColourId, laf.findColour (TextButton::textColourOffId));
  475. laf.setColour (TextButton::textColourOnId, laf.findColour (TextButton::buttonColourId));
  476. }
  477. void setAllLookAndFeels (LookAndFeel* laf)
  478. {
  479. for (int i = 0; i < demoComp.getNumChildComponents(); ++i)
  480. if (Component* c = demoComp.getChildComponent (i))
  481. c->setLookAndFeel (laf);
  482. }
  483. void comboBoxChanged (ComboBox* comboBoxThatHasChanged) override
  484. {
  485. if (comboBoxThatHasChanged == &lafBox)
  486. setAllLookAndFeels (lookAndFeels[lafBox.getSelectedItemIndex()]);
  487. }
  488. void buttonClicked (Button* b) override
  489. {
  490. if (b == &randomButton)
  491. lafBox.setSelectedItemIndex (Random::getSystemRandom().nextInt (lafBox.getNumItems()));
  492. }
  493. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeelDemo);
  494. };
  495. // This static object will register this demo type in a global list of demos..
  496. static JuceDemoType<LookAndFeelDemo> demo ("10 Components: Look And Feel");