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.

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