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.

594 lines
23KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 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. OldSchoolLookAndFeel::OldSchoolLookAndFeel()
  19. {
  20. setColour (TextButton::buttonColourId, Colour (0xffbbbbff));
  21. setColour (ListBox::outlineColourId, findColour (ComboBox::outlineColourId));
  22. setColour (ScrollBar::thumbColourId, Colour (0xffbbbbdd));
  23. setColour (ScrollBar::backgroundColourId, Colours::transparentBlack);
  24. setColour (Slider::thumbColourId, Colours::white);
  25. setColour (Slider::trackColourId, Colour (0x7f000000));
  26. setColour (Slider::textBoxOutlineColourId, Colours::grey);
  27. setColour (ProgressBar::backgroundColourId, Colours::white.withAlpha (0.6f));
  28. setColour (ProgressBar::foregroundColourId, Colours::green.withAlpha (0.7f));
  29. setColour (PopupMenu::backgroundColourId, Colour (0xffeef5f8));
  30. setColour (PopupMenu::highlightedBackgroundColourId, Colour (0xbfa4c2ce));
  31. setColour (PopupMenu::highlightedTextColourId, Colours::black);
  32. setColour (TextEditor::focusedOutlineColourId, findColour (TextButton::buttonColourId));
  33. scrollbarShadow.setShadowProperties (2.2f, 0.5f, 0, 0);
  34. }
  35. OldSchoolLookAndFeel::~OldSchoolLookAndFeel()
  36. {
  37. }
  38. //==============================================================================
  39. void OldSchoolLookAndFeel::drawButtonBackground (Graphics& g,
  40. Button& button,
  41. const Colour& backgroundColour,
  42. bool isMouseOverButton,
  43. bool isButtonDown)
  44. {
  45. const int width = button.getWidth();
  46. const int height = button.getHeight();
  47. const float indent = 2.0f;
  48. const int cornerSize = jmin (roundToInt (width * 0.4f),
  49. roundToInt (height * 0.4f));
  50. Path p;
  51. p.addRoundedRectangle (indent, indent,
  52. width - indent * 2.0f,
  53. height - indent * 2.0f,
  54. (float) cornerSize);
  55. Colour bc (backgroundColour.withMultipliedSaturation (0.3f));
  56. if (isMouseOverButton)
  57. {
  58. if (isButtonDown)
  59. bc = bc.brighter();
  60. else if (bc.getBrightness() > 0.5f)
  61. bc = bc.darker (0.1f);
  62. else
  63. bc = bc.brighter (0.1f);
  64. }
  65. g.setColour (bc);
  66. g.fillPath (p);
  67. g.setColour (bc.contrasting().withAlpha ((isMouseOverButton) ? 0.6f : 0.4f));
  68. g.strokePath (p, PathStrokeType ((isMouseOverButton) ? 2.0f : 1.4f));
  69. }
  70. void OldSchoolLookAndFeel::drawTickBox (Graphics& g,
  71. Component& /*component*/,
  72. float x, float y, float w, float h,
  73. const bool ticked,
  74. const bool isEnabled,
  75. const bool /*isMouseOverButton*/,
  76. const bool isButtonDown)
  77. {
  78. Path box;
  79. box.addRoundedRectangle (0.0f, 2.0f, 6.0f, 6.0f, 1.0f);
  80. g.setColour (isEnabled ? Colours::blue.withAlpha (isButtonDown ? 0.3f : 0.1f)
  81. : Colours::lightgrey.withAlpha (0.1f));
  82. AffineTransform trans (AffineTransform::scale (w / 9.0f, h / 9.0f).translated (x, y));
  83. g.fillPath (box, trans);
  84. g.setColour (Colours::black.withAlpha (0.6f));
  85. g.strokePath (box, PathStrokeType (0.9f), trans);
  86. if (ticked)
  87. {
  88. Path tick;
  89. tick.startNewSubPath (1.5f, 3.0f);
  90. tick.lineTo (3.0f, 6.0f);
  91. tick.lineTo (6.0f, 0.0f);
  92. g.setColour (isEnabled ? Colours::black : Colours::grey);
  93. g.strokePath (tick, PathStrokeType (2.5f), trans);
  94. }
  95. }
  96. void OldSchoolLookAndFeel::drawToggleButton (Graphics& g,
  97. ToggleButton& button,
  98. bool isMouseOverButton,
  99. bool isButtonDown)
  100. {
  101. if (button.hasKeyboardFocus (true))
  102. {
  103. g.setColour (button.findColour (TextEditor::focusedOutlineColourId));
  104. g.drawRect (0, 0, button.getWidth(), button.getHeight());
  105. }
  106. const int tickWidth = jmin (20, button.getHeight() - 4);
  107. drawTickBox (g, button, 4.0f, (button.getHeight() - tickWidth) * 0.5f,
  108. (float) tickWidth, (float) tickWidth,
  109. button.getToggleState(),
  110. button.isEnabled(),
  111. isMouseOverButton,
  112. isButtonDown);
  113. g.setColour (button.findColour (ToggleButton::textColourId));
  114. g.setFont (jmin (15.0f, button.getHeight() * 0.6f));
  115. if (! button.isEnabled())
  116. g.setOpacity (0.5f);
  117. const int textX = tickWidth + 5;
  118. g.drawFittedText (button.getButtonText(),
  119. textX, 4,
  120. button.getWidth() - textX - 2, button.getHeight() - 8,
  121. Justification::centredLeft, 10);
  122. }
  123. void OldSchoolLookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar,
  124. int width, int height,
  125. double progress, const String& textToShow)
  126. {
  127. if (progress < 0 || progress >= 1.0)
  128. {
  129. LookAndFeel::drawProgressBar (g, progressBar, width, height, progress, textToShow);
  130. }
  131. else
  132. {
  133. const Colour background (progressBar.findColour (ProgressBar::backgroundColourId));
  134. const Colour foreground (progressBar.findColour (ProgressBar::foregroundColourId));
  135. g.fillAll (background);
  136. g.setColour (foreground);
  137. g.fillRect (1, 1,
  138. jlimit (0, width - 2, roundToInt (progress * (width - 2))),
  139. height - 2);
  140. if (textToShow.isNotEmpty())
  141. {
  142. g.setColour (Colour::contrasting (background, foreground));
  143. g.setFont (height * 0.6f);
  144. g.drawText (textToShow, 0, 0, width, height, Justification::centred, false);
  145. }
  146. }
  147. }
  148. void OldSchoolLookAndFeel::drawScrollbarButton (Graphics& g,
  149. ScrollBar& bar,
  150. int width, int height,
  151. int buttonDirection,
  152. bool isScrollbarVertical,
  153. bool isMouseOverButton,
  154. bool isButtonDown)
  155. {
  156. if (isScrollbarVertical)
  157. width -= 2;
  158. else
  159. height -= 2;
  160. Path p;
  161. if (buttonDirection == 0)
  162. p.addTriangle (width * 0.5f, height * 0.2f,
  163. width * 0.1f, height * 0.7f,
  164. width * 0.9f, height * 0.7f);
  165. else if (buttonDirection == 1)
  166. p.addTriangle (width * 0.8f, height * 0.5f,
  167. width * 0.3f, height * 0.1f,
  168. width * 0.3f, height * 0.9f);
  169. else if (buttonDirection == 2)
  170. p.addTriangle (width * 0.5f, height * 0.8f,
  171. width * 0.1f, height * 0.3f,
  172. width * 0.9f, height * 0.3f);
  173. else if (buttonDirection == 3)
  174. p.addTriangle (width * 0.2f, height * 0.5f,
  175. width * 0.7f, height * 0.1f,
  176. width * 0.7f, height * 0.9f);
  177. if (isButtonDown)
  178. g.setColour (Colours::white);
  179. else if (isMouseOverButton)
  180. g.setColour (Colours::white.withAlpha (0.7f));
  181. else
  182. g.setColour (bar.findColour (ScrollBar::thumbColourId).withAlpha (0.5f));
  183. g.fillPath (p);
  184. g.setColour (Colours::black.withAlpha (0.5f));
  185. g.strokePath (p, PathStrokeType (0.5f));
  186. }
  187. void OldSchoolLookAndFeel::drawScrollbar (Graphics& g,
  188. ScrollBar& bar,
  189. int x, int y,
  190. int width, int height,
  191. bool isScrollbarVertical,
  192. int thumbStartPosition,
  193. int thumbSize,
  194. bool isMouseOver,
  195. bool isMouseDown)
  196. {
  197. g.fillAll (bar.findColour (ScrollBar::backgroundColourId));
  198. g.setColour (bar.findColour (ScrollBar::thumbColourId)
  199. .withAlpha ((isMouseOver || isMouseDown) ? 0.4f : 0.15f));
  200. if (thumbSize > 0.0f)
  201. {
  202. Rectangle<int> thumb;
  203. if (isScrollbarVertical)
  204. {
  205. width -= 2;
  206. g.fillRect (x + roundToInt (width * 0.35f), y,
  207. roundToInt (width * 0.3f), height);
  208. thumb.setBounds (x + 1, thumbStartPosition,
  209. width - 2, thumbSize);
  210. }
  211. else
  212. {
  213. height -= 2;
  214. g.fillRect (x, y + roundToInt (height * 0.35f),
  215. width, roundToInt (height * 0.3f));
  216. thumb.setBounds (thumbStartPosition, y + 1,
  217. thumbSize, height - 2);
  218. }
  219. g.setColour (bar.findColour (ScrollBar::thumbColourId)
  220. .withAlpha ((isMouseOver || isMouseDown) ? 0.95f : 0.7f));
  221. g.fillRect (thumb);
  222. g.setColour (Colours::black.withAlpha ((isMouseOver || isMouseDown) ? 0.4f : 0.25f));
  223. g.drawRect (thumb.getX(), thumb.getY(), thumb.getWidth(), thumb.getHeight());
  224. if (thumbSize > 16)
  225. {
  226. for (int i = 3; --i >= 0;)
  227. {
  228. const float linePos = thumbStartPosition + thumbSize / 2 + (i - 1) * 4.0f;
  229. g.setColour (Colours::black.withAlpha (0.15f));
  230. if (isScrollbarVertical)
  231. {
  232. g.drawLine (x + width * 0.2f, linePos, width * 0.8f, linePos);
  233. g.setColour (Colours::white.withAlpha (0.15f));
  234. g.drawLine (width * 0.2f, linePos - 1, width * 0.8f, linePos - 1);
  235. }
  236. else
  237. {
  238. g.drawLine (linePos, height * 0.2f, linePos, height * 0.8f);
  239. g.setColour (Colours::white.withAlpha (0.15f));
  240. g.drawLine (linePos - 1, height * 0.2f, linePos - 1, height * 0.8f);
  241. }
  242. }
  243. }
  244. }
  245. }
  246. ImageEffectFilter* OldSchoolLookAndFeel::getScrollbarEffect()
  247. {
  248. return &scrollbarShadow;
  249. }
  250. //==============================================================================
  251. void OldSchoolLookAndFeel::drawPopupMenuBackground (Graphics& g, int width, int height)
  252. {
  253. g.fillAll (findColour (PopupMenu::backgroundColourId));
  254. g.setColour (Colours::black.withAlpha (0.6f));
  255. g.drawRect (0, 0, width, height);
  256. }
  257. void OldSchoolLookAndFeel::drawMenuBarBackground (Graphics& g, int /*width*/, int /*height*/,
  258. bool, MenuBarComponent& menuBar)
  259. {
  260. g.fillAll (menuBar.findColour (PopupMenu::backgroundColourId));
  261. }
  262. //==============================================================================
  263. void OldSchoolLookAndFeel::drawTextEditorOutline (Graphics& g, int width, int height, TextEditor& textEditor)
  264. {
  265. if (textEditor.isEnabled())
  266. {
  267. g.setColour (textEditor.findColour (TextEditor::outlineColourId));
  268. g.drawRect (0, 0, width, height);
  269. }
  270. }
  271. //==============================================================================
  272. void OldSchoolLookAndFeel::drawComboBox (Graphics& g, int width, int height,
  273. const bool isButtonDown,
  274. int buttonX, int buttonY,
  275. int buttonW, int buttonH,
  276. ComboBox& box)
  277. {
  278. g.fillAll (box.findColour (ComboBox::backgroundColourId));
  279. g.setColour (box.findColour ((isButtonDown) ? ComboBox::buttonColourId
  280. : ComboBox::backgroundColourId));
  281. g.fillRect (buttonX, buttonY, buttonW, buttonH);
  282. g.setColour (box.findColour (ComboBox::outlineColourId));
  283. g.drawRect (0, 0, width, height);
  284. const float arrowX = 0.2f;
  285. const float arrowH = 0.3f;
  286. if (box.isEnabled())
  287. {
  288. Path p;
  289. p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.45f - arrowH),
  290. buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.45f,
  291. buttonX + buttonW * arrowX, buttonY + buttonH * 0.45f);
  292. p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.55f + arrowH),
  293. buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.55f,
  294. buttonX + buttonW * arrowX, buttonY + buttonH * 0.55f);
  295. g.setColour (box.findColour ((isButtonDown) ? ComboBox::backgroundColourId
  296. : ComboBox::buttonColourId));
  297. g.fillPath (p);
  298. }
  299. }
  300. const Font OldSchoolLookAndFeel::getComboBoxFont (ComboBox& box)
  301. {
  302. Font f (jmin (15.0f, box.getHeight() * 0.85f));
  303. f.setHorizontalScale (0.9f);
  304. return f;
  305. }
  306. //==============================================================================
  307. static void drawTriangle (Graphics& g, float x1, float y1, float x2, float y2, float x3, float y3, const Colour& fill, const Colour& outline) noexcept
  308. {
  309. Path p;
  310. p.addTriangle (x1, y1, x2, y2, x3, y3);
  311. g.setColour (fill);
  312. g.fillPath (p);
  313. g.setColour (outline);
  314. g.strokePath (p, PathStrokeType (0.3f));
  315. }
  316. void OldSchoolLookAndFeel::drawLinearSlider (Graphics& g,
  317. int x, int y,
  318. int w, int h,
  319. float sliderPos,
  320. float minSliderPos,
  321. float maxSliderPos,
  322. const Slider::SliderStyle style,
  323. Slider& slider)
  324. {
  325. g.fillAll (slider.findColour (Slider::backgroundColourId));
  326. if (style == Slider::LinearBar)
  327. {
  328. g.setColour (slider.findColour (Slider::thumbColourId));
  329. g.fillRect (x, y, (int) sliderPos - x, h);
  330. g.setColour (slider.findColour (Slider::textBoxTextColourId).withMultipliedAlpha (0.5f));
  331. g.drawRect (x, y, (int) sliderPos - x, h);
  332. }
  333. else
  334. {
  335. g.setColour (slider.findColour (Slider::trackColourId)
  336. .withMultipliedAlpha (slider.isEnabled() ? 1.0f : 0.3f));
  337. if (slider.isHorizontal())
  338. {
  339. g.fillRect (x, y + roundToInt (h * 0.6f),
  340. w, roundToInt (h * 0.2f));
  341. }
  342. else
  343. {
  344. g.fillRect (x + roundToInt (w * 0.5f - jmin (3.0f, w * 0.1f)), y,
  345. jmin (4, roundToInt (w * 0.2f)), h);
  346. }
  347. float alpha = 0.35f;
  348. if (slider.isEnabled())
  349. alpha = slider.isMouseOverOrDragging() ? 1.0f : 0.7f;
  350. const Colour fill (slider.findColour (Slider::thumbColourId).withAlpha (alpha));
  351. const Colour outline (Colours::black.withAlpha (slider.isEnabled() ? 0.7f : 0.35f));
  352. if (style == Slider::TwoValueVertical || style == Slider::ThreeValueVertical)
  353. {
  354. drawTriangle (g, x + w * 0.5f + jmin (4.0f, w * 0.3f), minSliderPos,
  355. x + w * 0.5f - jmin (8.0f, w * 0.4f), minSliderPos - 7.0f,
  356. x + w * 0.5f - jmin (8.0f, w * 0.4f), minSliderPos,
  357. fill, outline);
  358. drawTriangle (g, x + w * 0.5f + jmin (4.0f, w * 0.3f), maxSliderPos,
  359. x + w * 0.5f - jmin (8.0f, w * 0.4f), maxSliderPos,
  360. x + w * 0.5f - jmin (8.0f, w * 0.4f), maxSliderPos + 7.0f,
  361. fill, outline);
  362. }
  363. else if (style == Slider::TwoValueHorizontal || style == Slider::ThreeValueHorizontal)
  364. {
  365. drawTriangle (g, minSliderPos, y + h * 0.6f - jmin (4.0f, h * 0.3f),
  366. minSliderPos - 7.0f, y + h * 0.9f ,
  367. minSliderPos, y + h * 0.9f,
  368. fill, outline);
  369. drawTriangle (g, maxSliderPos, y + h * 0.6f - jmin (4.0f, h * 0.3f),
  370. maxSliderPos, y + h * 0.9f,
  371. maxSliderPos + 7.0f, y + h * 0.9f,
  372. fill, outline);
  373. }
  374. if (style == Slider::LinearHorizontal || style == Slider::ThreeValueHorizontal)
  375. {
  376. drawTriangle (g, sliderPos, y + h * 0.9f,
  377. sliderPos - 7.0f, y + h * 0.2f,
  378. sliderPos + 7.0f, y + h * 0.2f,
  379. fill, outline);
  380. }
  381. else if (style == Slider::LinearVertical || style == Slider::ThreeValueVertical)
  382. {
  383. drawTriangle (g, x + w * 0.5f - jmin (4.0f, w * 0.3f), sliderPos,
  384. x + w * 0.5f + jmin (8.0f, w * 0.4f), sliderPos - 7.0f,
  385. x + w * 0.5f + jmin (8.0f, w * 0.4f), sliderPos + 7.0f,
  386. fill, outline);
  387. }
  388. }
  389. }
  390. Button* OldSchoolLookAndFeel::createSliderButton (const bool isIncrement)
  391. {
  392. if (isIncrement)
  393. return new ArrowButton ("u", 0.75f, Colours::white.withAlpha (0.8f));
  394. else
  395. return new ArrowButton ("d", 0.25f, Colours::white.withAlpha (0.8f));
  396. }
  397. ImageEffectFilter* OldSchoolLookAndFeel::getSliderEffect()
  398. {
  399. return &scrollbarShadow;
  400. }
  401. int OldSchoolLookAndFeel::getSliderThumbRadius (Slider&)
  402. {
  403. return 8;
  404. }
  405. //==============================================================================
  406. void OldSchoolLookAndFeel::drawCornerResizer (Graphics& g,
  407. int w, int h,
  408. bool isMouseOver,
  409. bool isMouseDragging)
  410. {
  411. g.setColour ((isMouseOver || isMouseDragging) ? Colours::lightgrey
  412. : Colours::darkgrey);
  413. const float lineThickness = jmin (w, h) * 0.1f;
  414. for (float i = 0.0f; i < 1.0f; i += 0.3f)
  415. {
  416. g.drawLine (w * i,
  417. h + 1.0f,
  418. w + 1.0f,
  419. h * i,
  420. lineThickness);
  421. }
  422. }
  423. //==============================================================================
  424. Button* OldSchoolLookAndFeel::createDocumentWindowButton (int buttonType)
  425. {
  426. Path shape;
  427. if (buttonType == DocumentWindow::closeButton)
  428. {
  429. shape.addLineSegment (Line<float> (0.0f, 0.0f, 1.0f, 1.0f), 0.35f);
  430. shape.addLineSegment (Line<float> (1.0f, 0.0f, 0.0f, 1.0f), 0.35f);
  431. ShapeButton* const b = new ShapeButton ("close",
  432. Colour (0x7fff3333),
  433. Colour (0xd7ff3333),
  434. Colour (0xf7ff3333));
  435. b->setShape (shape, true, true, true);
  436. return b;
  437. }
  438. else if (buttonType == DocumentWindow::minimiseButton)
  439. {
  440. shape.addLineSegment (Line<float> (0.0f, 0.5f, 1.0f, 0.5f), 0.25f);
  441. DrawableButton* b = new DrawableButton ("minimise", DrawableButton::ImageFitted);
  442. DrawablePath dp;
  443. dp.setPath (shape);
  444. dp.setFill (Colours::black.withAlpha (0.3f));
  445. b->setImages (&dp);
  446. return b;
  447. }
  448. else if (buttonType == DocumentWindow::maximiseButton)
  449. {
  450. shape.addLineSegment (Line<float> (0.5f, 0.0f, 0.5f, 1.0f), 0.25f);
  451. shape.addLineSegment (Line<float> (0.0f, 0.5f, 1.0f, 0.5f), 0.25f);
  452. DrawableButton* b = new DrawableButton ("maximise", DrawableButton::ImageFitted);
  453. DrawablePath dp;
  454. dp.setPath (shape);
  455. dp.setFill (Colours::black.withAlpha (0.3f));
  456. b->setImages (&dp);
  457. return b;
  458. }
  459. jassertfalse;
  460. return nullptr;
  461. }
  462. void OldSchoolLookAndFeel::positionDocumentWindowButtons (DocumentWindow&,
  463. int titleBarX,
  464. int titleBarY,
  465. int titleBarW,
  466. int titleBarH,
  467. Button* minimiseButton,
  468. Button* maximiseButton,
  469. Button* closeButton,
  470. bool positionTitleBarButtonsOnLeft)
  471. {
  472. titleBarY += titleBarH / 8;
  473. titleBarH -= titleBarH / 4;
  474. const int buttonW = titleBarH;
  475. int x = positionTitleBarButtonsOnLeft ? titleBarX + 4
  476. : titleBarX + titleBarW - buttonW - 4;
  477. if (closeButton != nullptr)
  478. {
  479. closeButton->setBounds (x, titleBarY, buttonW, titleBarH);
  480. x += positionTitleBarButtonsOnLeft ? buttonW + buttonW / 5
  481. : -(buttonW + buttonW / 5);
  482. }
  483. if (positionTitleBarButtonsOnLeft)
  484. std::swap (minimiseButton, maximiseButton);
  485. if (maximiseButton != nullptr)
  486. {
  487. maximiseButton->setBounds (x, titleBarY - 2, buttonW, titleBarH);
  488. x += positionTitleBarButtonsOnLeft ? buttonW : -buttonW;
  489. }
  490. if (minimiseButton != nullptr)
  491. minimiseButton->setBounds (x, titleBarY - 2, buttonW, titleBarH);
  492. }