Audio plugin host https://kx.studio/carla
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.

631 lines
25KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software 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. LookAndFeel_V3::LookAndFeel_V3()
  18. {
  19. setColour (TreeView::selectedItemBackgroundColourId, Colour (0x301111ee));
  20. const Colour textButtonColour (0xffeeeeff);
  21. setColour (TextButton::buttonColourId, textButtonColour);
  22. setColour (ComboBox::buttonColourId, textButtonColour);
  23. setColour (TextEditor::outlineColourId, Colours::transparentBlack);
  24. setColour (TabbedButtonBar::tabOutlineColourId, Colour (0xff999999));
  25. setColour (TabbedComponent::outlineColourId, Colour (0xff999999));
  26. setColour (Slider::trackColourId, Colour (0xbbffffff));
  27. setColour (Slider::thumbColourId, Colour (0xffddddff));
  28. setColour (BubbleComponent::backgroundColourId, Colour (0xeeeeeedd));
  29. setColour (ScrollBar::thumbColourId, Colour::greyLevel (0.8f).contrasting().withAlpha (0.13f));
  30. }
  31. LookAndFeel_V3::~LookAndFeel_V3() {}
  32. bool LookAndFeel_V3::areScrollbarButtonsVisible() { return false; }
  33. void LookAndFeel_V3::drawStretchableLayoutResizerBar (Graphics& g, int /*w*/, int /*h*/, bool /*isVerticalBar*/,
  34. bool isMouseOver, bool isMouseDragging)
  35. {
  36. if (isMouseOver || isMouseDragging)
  37. g.fillAll (Colours::yellow.withAlpha (0.4f));
  38. }
  39. void LookAndFeel_V3::drawScrollbar (Graphics& g, ScrollBar& scrollbar, int x, int y, int width, int height,
  40. bool isScrollbarVertical, int thumbStartPosition, int thumbSize, bool isMouseOver, bool isMouseDown)
  41. {
  42. Path thumbPath;
  43. if (thumbSize > 0)
  44. {
  45. const float thumbIndent = (isScrollbarVertical ? width : height) * 0.25f;
  46. const float thumbIndentx2 = thumbIndent * 2.0f;
  47. if (isScrollbarVertical)
  48. thumbPath.addRoundedRectangle (x + thumbIndent, thumbStartPosition + thumbIndent,
  49. width - thumbIndentx2, thumbSize - thumbIndentx2, (width - thumbIndentx2) * 0.5f);
  50. else
  51. thumbPath.addRoundedRectangle (thumbStartPosition + thumbIndent, y + thumbIndent,
  52. thumbSize - thumbIndentx2, height - thumbIndentx2, (height - thumbIndentx2) * 0.5f);
  53. }
  54. Colour thumbCol (scrollbar.findColour (ScrollBar::thumbColourId, true));
  55. if (isMouseOver || isMouseDown)
  56. thumbCol = thumbCol.withMultipliedAlpha (2.0f);
  57. g.setColour (thumbCol);
  58. g.fillPath (thumbPath);
  59. g.setColour (thumbCol.contrasting ((isMouseOver || isMouseDown) ? 0.2f : 0.1f));
  60. g.strokePath (thumbPath, PathStrokeType (1.0f));
  61. }
  62. void LookAndFeel_V3::drawConcertinaPanelHeader (Graphics& g, const Rectangle<int>& area,
  63. bool isMouseOver, bool /*isMouseDown*/,
  64. ConcertinaPanel&, Component& panel)
  65. {
  66. const Colour bkg (Colours::grey);
  67. g.setGradientFill (ColourGradient (Colours::white.withAlpha (isMouseOver ? 0.4f : 0.2f), 0, (float) area.getY(),
  68. Colours::darkgrey.withAlpha (0.1f), 0, (float) area.getBottom(), false));
  69. g.fillAll();
  70. g.setColour (bkg.contrasting().withAlpha (0.1f));
  71. g.fillRect (area.withHeight (1));
  72. g.fillRect (area.withTop (area.getBottom() - 1));
  73. g.setColour (bkg.contrasting());
  74. g.setFont (Font (area.getHeight() * 0.6f).boldened());
  75. g.drawFittedText (panel.getName(), 4, 0, area.getWidth() - 6, area.getHeight(), Justification::centredLeft, 1);
  76. }
  77. static void drawButtonShape (Graphics& g, const Path& outline, Colour baseColour, float height)
  78. {
  79. const float mainBrightness = baseColour.getBrightness();
  80. const float mainAlpha = baseColour.getFloatAlpha();
  81. g.setGradientFill (ColourGradient (baseColour.brighter (0.2f), 0.0f, 0.0f,
  82. baseColour.darker (0.25f), 0.0f, height, false));
  83. g.fillPath (outline);
  84. g.setColour (Colours::white.withAlpha (0.4f * mainAlpha * mainBrightness * mainBrightness));
  85. g.strokePath (outline, PathStrokeType (1.0f), AffineTransform::translation (0.0f, 1.0f)
  86. .scaled (1.0f, (height - 1.6f) / height));
  87. g.setColour (Colours::black.withAlpha (0.4f * mainAlpha));
  88. g.strokePath (outline, PathStrokeType (1.0f));
  89. }
  90. void LookAndFeel_V3::drawButtonBackground (Graphics& g, Button& button, const Colour& backgroundColour,
  91. bool isMouseOverButton, bool isButtonDown)
  92. {
  93. Colour baseColour (backgroundColour.withMultipliedSaturation (button.hasKeyboardFocus (true) ? 1.3f : 0.9f)
  94. .withMultipliedAlpha (button.isEnabled() ? 0.9f : 0.5f));
  95. if (isButtonDown || isMouseOverButton)
  96. baseColour = baseColour.contrasting (isButtonDown ? 0.2f : 0.1f);
  97. const bool flatOnLeft = button.isConnectedOnLeft();
  98. const bool flatOnRight = button.isConnectedOnRight();
  99. const bool flatOnTop = button.isConnectedOnTop();
  100. const bool flatOnBottom = button.isConnectedOnBottom();
  101. const float width = button.getWidth() - 1.0f;
  102. const float height = button.getHeight() - 1.0f;
  103. if (width > 0 && height > 0)
  104. {
  105. const float cornerSize = 4.0f;
  106. Path outline;
  107. outline.addRoundedRectangle (0.5f, 0.5f, width, height, cornerSize, cornerSize,
  108. ! (flatOnLeft || flatOnTop),
  109. ! (flatOnRight || flatOnTop),
  110. ! (flatOnLeft || flatOnBottom),
  111. ! (flatOnRight || flatOnBottom));
  112. drawButtonShape (g, outline, baseColour, height);
  113. }
  114. }
  115. void LookAndFeel_V3::drawTableHeaderBackground (Graphics& g, TableHeaderComponent& header)
  116. {
  117. Rectangle<int> r (header.getLocalBounds());
  118. g.setColour (Colours::black.withAlpha (0.5f));
  119. g.fillRect (r.removeFromBottom (1));
  120. g.setColour (Colours::white.withAlpha (0.6f));
  121. g.fillRect (r);
  122. g.setColour (Colours::black.withAlpha (0.5f));
  123. for (int i = header.getNumColumns (true); --i >= 0;)
  124. g.fillRect (header.getColumnPosition (i).removeFromRight (1));
  125. }
  126. int LookAndFeel_V3::getTabButtonOverlap (int /*tabDepth*/) { return -1; }
  127. int LookAndFeel_V3::getTabButtonSpaceAroundImage() { return 0; }
  128. void LookAndFeel_V3::createTabTextLayout (const TabBarButton& button, float length, float depth,
  129. Colour colour, TextLayout& textLayout)
  130. {
  131. Font font (depth * 0.5f);
  132. font.setUnderline (button.hasKeyboardFocus (false));
  133. AttributedString s;
  134. s.setJustification (Justification::centred);
  135. s.append (button.getButtonText().trim(), font, colour);
  136. textLayout.createLayout (s, length);
  137. }
  138. void LookAndFeel_V3::drawTabButton (TabBarButton& button, Graphics& g, bool isMouseOver, bool isMouseDown)
  139. {
  140. const Rectangle<int> activeArea (button.getActiveArea());
  141. const TabbedButtonBar::Orientation o = button.getTabbedButtonBar().getOrientation();
  142. const Colour bkg (button.getTabBackgroundColour());
  143. if (button.getToggleState())
  144. {
  145. g.setColour (bkg);
  146. }
  147. else
  148. {
  149. Point<int> p1, p2;
  150. switch (o)
  151. {
  152. case TabbedButtonBar::TabsAtBottom: p1 = activeArea.getBottomLeft(); p2 = activeArea.getTopLeft(); break;
  153. case TabbedButtonBar::TabsAtTop: p1 = activeArea.getTopLeft(); p2 = activeArea.getBottomLeft(); break;
  154. case TabbedButtonBar::TabsAtRight: p1 = activeArea.getTopRight(); p2 = activeArea.getTopLeft(); break;
  155. case TabbedButtonBar::TabsAtLeft: p1 = activeArea.getTopLeft(); p2 = activeArea.getTopRight(); break;
  156. default: jassertfalse; break;
  157. }
  158. g.setGradientFill (ColourGradient (bkg.brighter (0.2f), (float) p1.x, (float) p1.y,
  159. bkg.darker (0.1f), (float) p2.x, (float) p2.y, false));
  160. }
  161. g.fillRect (activeArea);
  162. g.setColour (button.findColour (TabbedButtonBar::tabOutlineColourId));
  163. Rectangle<int> r (activeArea);
  164. if (o != TabbedButtonBar::TabsAtBottom) g.fillRect (r.removeFromTop (1));
  165. if (o != TabbedButtonBar::TabsAtTop) g.fillRect (r.removeFromBottom (1));
  166. if (o != TabbedButtonBar::TabsAtRight) g.fillRect (r.removeFromLeft (1));
  167. if (o != TabbedButtonBar::TabsAtLeft) g.fillRect (r.removeFromRight (1));
  168. const float alpha = button.isEnabled() ? ((isMouseOver || isMouseDown) ? 1.0f : 0.8f) : 0.3f;
  169. Colour col (bkg.contrasting().withMultipliedAlpha (alpha));
  170. if (TabbedButtonBar* bar = button.findParentComponentOfClass<TabbedButtonBar>())
  171. {
  172. if (button.isFrontTab() && bar->isColourSpecified (TabbedButtonBar::frontTextColourId))
  173. col = bar->findColour (TabbedButtonBar::frontTextColourId);
  174. else if (bar->isColourSpecified (TabbedButtonBar::tabTextColourId))
  175. col = bar->findColour (TabbedButtonBar::tabTextColourId);
  176. }
  177. const Rectangle<float> area (button.getTextArea().toFloat());
  178. float length = area.getWidth();
  179. float depth = area.getHeight();
  180. if (button.getTabbedButtonBar().isVertical())
  181. std::swap (length, depth);
  182. TextLayout textLayout;
  183. createTabTextLayout (button, length, depth, col, textLayout);
  184. AffineTransform t;
  185. switch (o)
  186. {
  187. case TabbedButtonBar::TabsAtLeft: t = t.rotated (float_Pi * -0.5f).translated (area.getX(), area.getBottom()); break;
  188. case TabbedButtonBar::TabsAtRight: t = t.rotated (float_Pi * 0.5f).translated (area.getRight(), area.getY()); break;
  189. case TabbedButtonBar::TabsAtTop:
  190. case TabbedButtonBar::TabsAtBottom: t = t.translated (area.getX(), area.getY()); break;
  191. default: jassertfalse; break;
  192. }
  193. g.addTransform (t);
  194. textLayout.draw (g, Rectangle<float> (length, depth));
  195. }
  196. void LookAndFeel_V3::drawTabAreaBehindFrontButton (TabbedButtonBar& bar, Graphics& g, const int w, const int h)
  197. {
  198. const float shadowSize = 0.15f;
  199. Rectangle<int> shadowRect, line;
  200. ColourGradient gradient (Colours::black.withAlpha (bar.isEnabled() ? 0.08f : 0.04f), 0, 0,
  201. Colours::transparentBlack, 0, 0, false);
  202. switch (bar.getOrientation())
  203. {
  204. case TabbedButtonBar::TabsAtLeft:
  205. gradient.point1.x = (float) w;
  206. gradient.point2.x = w * (1.0f - shadowSize);
  207. shadowRect.setBounds ((int) gradient.point2.x, 0, w - (int) gradient.point2.x, h);
  208. line.setBounds (w - 1, 0, 1, h);
  209. break;
  210. case TabbedButtonBar::TabsAtRight:
  211. gradient.point2.x = w * shadowSize;
  212. shadowRect.setBounds (0, 0, (int) gradient.point2.x, h);
  213. line.setBounds (0, 0, 1, h);
  214. break;
  215. case TabbedButtonBar::TabsAtTop:
  216. gradient.point1.y = (float) h;
  217. gradient.point2.y = h * (1.0f - shadowSize);
  218. shadowRect.setBounds (0, (int) gradient.point2.y, w, h - (int) gradient.point2.y);
  219. line.setBounds (0, h - 1, w, 1);
  220. break;
  221. case TabbedButtonBar::TabsAtBottom:
  222. gradient.point2.y = h * shadowSize;
  223. shadowRect.setBounds (0, 0, w, (int) gradient.point2.y);
  224. line.setBounds (0, 0, w, 1);
  225. break;
  226. default: break;
  227. }
  228. g.setGradientFill (gradient);
  229. g.fillRect (shadowRect.expanded (2, 2));
  230. g.setColour (bar.findColour (TabbedButtonBar::tabOutlineColourId));
  231. g.fillRect (line);
  232. }
  233. void LookAndFeel_V3::drawTextEditorOutline (Graphics& g, int width, int height, TextEditor& textEditor)
  234. {
  235. if (textEditor.isEnabled())
  236. {
  237. if (textEditor.hasKeyboardFocus (true) && ! textEditor.isReadOnly())
  238. {
  239. g.setColour (textEditor.findColour (TextEditor::focusedOutlineColourId));
  240. g.drawRect (0, 0, width, height, 2);
  241. }
  242. else
  243. {
  244. g.setColour (textEditor.findColour (TextEditor::outlineColourId));
  245. g.drawRect (0, 0, width, height);
  246. }
  247. }
  248. }
  249. void LookAndFeel_V3::drawTreeviewPlusMinusBox (Graphics& g, const Rectangle<float>& area,
  250. Colour backgroundColour, bool isOpen, bool isMouseOver)
  251. {
  252. Path p;
  253. p.addTriangle (0.0f, 0.0f, 1.0f, isOpen ? 0.0f : 0.5f, isOpen ? 0.5f : 0.0f, 1.0f);
  254. g.setColour (backgroundColour.contrasting().withAlpha (isMouseOver ? 0.5f : 0.3f));
  255. g.fillPath (p, p.getTransformToScaleToFit (area.reduced (2, area.getHeight() / 4), true));
  256. }
  257. bool LookAndFeel_V3::areLinesDrawnForTreeView (TreeView&)
  258. {
  259. return false;
  260. }
  261. int LookAndFeel_V3::getTreeViewIndentSize (TreeView&)
  262. {
  263. return 20;
  264. }
  265. void LookAndFeel_V3::drawComboBox (Graphics& g, int width, int height, const bool /*isButtonDown*/,
  266. int buttonX, int buttonY, int buttonW, int buttonH, ComboBox& box)
  267. {
  268. g.fillAll (box.findColour (ComboBox::backgroundColourId));
  269. const Colour buttonColour (box.findColour (ComboBox::buttonColourId));
  270. if (box.isEnabled() && box.hasKeyboardFocus (false))
  271. {
  272. g.setColour (buttonColour);
  273. g.drawRect (0, 0, width, height, 2);
  274. }
  275. else
  276. {
  277. g.setColour (box.findColour (ComboBox::outlineColourId));
  278. g.drawRect (0, 0, width, height);
  279. }
  280. const float arrowX = 0.3f;
  281. const float arrowH = 0.2f;
  282. Path p;
  283. p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.45f - arrowH),
  284. buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.45f,
  285. buttonX + buttonW * arrowX, buttonY + buttonH * 0.45f);
  286. p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.55f + arrowH),
  287. buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.55f,
  288. buttonX + buttonW * arrowX, buttonY + buttonH * 0.55f);
  289. g.setColour (box.findColour (ComboBox::arrowColourId).withMultipliedAlpha (box.isEnabled() ? 1.0f : 0.3f));
  290. g.fillPath (p);
  291. }
  292. void LookAndFeel_V3::drawLinearSlider (Graphics& g, int x, int y, int width, int height,
  293. float sliderPos, float minSliderPos, float maxSliderPos,
  294. const Slider::SliderStyle style, Slider& slider)
  295. {
  296. g.fillAll (slider.findColour (Slider::backgroundColourId));
  297. if (style == Slider::LinearBar || style == Slider::LinearBarVertical)
  298. {
  299. const float fx = (float) x, fy = (float) y, fw = (float) width, fh = (float) height;
  300. Path p;
  301. if (style == Slider::LinearBarVertical)
  302. p.addRectangle (fx, sliderPos, fw, 1.0f + fh - sliderPos);
  303. else
  304. p.addRectangle (fx, fy, sliderPos - fx, fh);
  305. Colour baseColour (slider.findColour (Slider::thumbColourId)
  306. .withMultipliedSaturation (slider.isEnabled() ? 1.0f : 0.5f)
  307. .withMultipliedAlpha (0.8f));
  308. g.setGradientFill (ColourGradient (baseColour.brighter (0.08f), 0.0f, 0.0f,
  309. baseColour.darker (0.08f), 0.0f, (float) height, false));
  310. g.fillPath (p);
  311. g.setColour (baseColour.darker (0.2f));
  312. if (style == Slider::LinearBarVertical)
  313. g.fillRect (fx, sliderPos, fw, 1.0f);
  314. else
  315. g.fillRect (sliderPos, fy, 1.0f, fh);
  316. }
  317. else
  318. {
  319. drawLinearSliderBackground (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
  320. drawLinearSliderThumb (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
  321. }
  322. }
  323. void LookAndFeel_V3::drawLinearSliderBackground (Graphics& g, int x, int y, int width, int height,
  324. float /*sliderPos*/,
  325. float /*minSliderPos*/,
  326. float /*maxSliderPos*/,
  327. const Slider::SliderStyle /*style*/, Slider& slider)
  328. {
  329. const float sliderRadius = (float) (getSliderThumbRadius (slider) - 2);
  330. const Colour trackColour (slider.findColour (Slider::trackColourId));
  331. const Colour gradCol1 (trackColour.overlaidWith (Colour (slider.isEnabled() ? 0x13000000 : 0x09000000)));
  332. const Colour gradCol2 (trackColour.overlaidWith (Colour (0x06000000)));
  333. Path indent;
  334. if (slider.isHorizontal())
  335. {
  336. const float iy = y + height * 0.5f - sliderRadius * 0.5f;
  337. g.setGradientFill (ColourGradient (gradCol1, 0.0f, iy,
  338. gradCol2, 0.0f, iy + sliderRadius, false));
  339. indent.addRoundedRectangle (x - sliderRadius * 0.5f, iy, width + sliderRadius, sliderRadius, 5.0f);
  340. }
  341. else
  342. {
  343. const float ix = x + width * 0.5f - sliderRadius * 0.5f;
  344. g.setGradientFill (ColourGradient (gradCol1, ix, 0.0f,
  345. gradCol2, ix + sliderRadius, 0.0f, false));
  346. indent.addRoundedRectangle (ix, y - sliderRadius * 0.5f, sliderRadius, height + sliderRadius, 5.0f);
  347. }
  348. g.fillPath (indent);
  349. g.setColour (trackColour.contrasting (0.5f));
  350. g.strokePath (indent, PathStrokeType (0.5f));
  351. }
  352. void LookAndFeel_V3::drawPopupMenuBackground (Graphics& g, int width, int height)
  353. {
  354. g.fillAll (findColour (PopupMenu::backgroundColourId));
  355. (void) width; (void) height;
  356. #if ! JUCE_MAC
  357. g.setColour (findColour (PopupMenu::textColourId).withAlpha (0.6f));
  358. g.drawRect (0, 0, width, height);
  359. #endif
  360. }
  361. void LookAndFeel_V3::drawMenuBarBackground (Graphics& g, int width, int height,
  362. bool, MenuBarComponent& menuBar)
  363. {
  364. const Colour colour (menuBar.findColour (PopupMenu::backgroundColourId));
  365. Rectangle<int> r (width, height);
  366. g.setColour (colour.contrasting (0.15f));
  367. g.fillRect (r.removeFromTop (1));
  368. g.fillRect (r.removeFromBottom (1));
  369. g.setGradientFill (ColourGradient (colour, 0, 0, colour.darker (0.08f), 0, (float) height, false));
  370. g.fillRect (r);
  371. }
  372. void LookAndFeel_V3::drawKeymapChangeButton (Graphics& g, int width, int height,
  373. Button& button, const String& keyDescription)
  374. {
  375. const Colour textColour (button.findColour (0x100ad01 /*KeyMappingEditorComponent::textColourId*/, true));
  376. if (keyDescription.isNotEmpty())
  377. {
  378. if (button.isEnabled())
  379. {
  380. g.setColour (textColour.withAlpha (button.isDown() ? 0.4f : (button.isOver() ? 0.2f : 0.1f)));
  381. g.fillRoundedRectangle (button.getLocalBounds().toFloat(), 4.0f);
  382. g.drawRoundedRectangle (button.getLocalBounds().toFloat(), 4.0f, 1.0f);
  383. }
  384. g.setColour (textColour);
  385. g.setFont (height * 0.6f);
  386. g.drawFittedText (keyDescription, 4, 0, width - 8, height, Justification::centred, 1);
  387. }
  388. else
  389. {
  390. const float thickness = 7.0f;
  391. const float indent = 22.0f;
  392. Path p;
  393. p.addEllipse (0.0f, 0.0f, 100.0f, 100.0f);
  394. p.addRectangle (indent, 50.0f - thickness, 100.0f - indent * 2.0f, thickness * 2.0f);
  395. p.addRectangle (50.0f - thickness, indent, thickness * 2.0f, 50.0f - indent - thickness);
  396. p.addRectangle (50.0f - thickness, 50.0f + thickness, thickness * 2.0f, 50.0f - indent - thickness);
  397. p.setUsingNonZeroWinding (false);
  398. g.setColour (textColour.darker(0.1f).withAlpha (button.isDown() ? 0.7f : (button.isOver() ? 0.5f : 0.3f)));
  399. g.fillPath (p, p.getTransformToScaleToFit (2.0f, 2.0f, width - 4.0f, height - 4.0f, true));
  400. }
  401. if (button.hasKeyboardFocus (false))
  402. {
  403. g.setColour (textColour.withAlpha (0.4f));
  404. g.drawRect (0, 0, width, height);
  405. }
  406. }
  407. class LookAndFeel_V3_DocumentWindowButton : public Button
  408. {
  409. public:
  410. LookAndFeel_V3_DocumentWindowButton (const String& name, Colour c, const Path& normal, const Path& toggled)
  411. : Button (name), colour (c), normalShape (normal), toggledShape (toggled)
  412. {
  413. }
  414. void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) override
  415. {
  416. Colour background (Colours::grey);
  417. if (ResizableWindow* rw = findParentComponentOfClass<ResizableWindow>())
  418. background = rw->getBackgroundColour();
  419. const float cx = getWidth() * 0.5f, cy = getHeight() * 0.5f;
  420. const float diam = jmin (cx, cy) * (isButtonDown ? 0.60f : 0.65f);
  421. g.setColour (background);
  422. g.fillEllipse (cx - diam, cy - diam, diam * 2.0f, diam * 2.0f);
  423. Colour c (background.contrasting (colour, 0.6f));
  424. if (! isEnabled())
  425. c = c.withAlpha (0.6f);
  426. else if (isMouseOverButton)
  427. c = c.brighter();
  428. g.setColour (c);
  429. g.drawEllipse (cx - diam, cy - diam, diam * 2.0f, diam * 2.0f, diam * 0.2f);
  430. Path& p = getToggleState() ? toggledShape : normalShape;
  431. float scale = 0.55f;
  432. g.fillPath (p, p.getTransformToScaleToFit (cx - diam * scale, cy - diam * scale,
  433. diam * 2.0f * scale, diam * 2.0f * scale, true));
  434. }
  435. private:
  436. Colour colour;
  437. Path normalShape, toggledShape;
  438. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel_V3_DocumentWindowButton)
  439. };
  440. Button* LookAndFeel_V3::createDocumentWindowButton (int buttonType)
  441. {
  442. Path shape;
  443. const float crossThickness = 0.25f;
  444. if (buttonType == DocumentWindow::closeButton)
  445. {
  446. shape.addLineSegment (Line<float> (0.0f, 0.0f, 1.0f, 1.0f), crossThickness * 1.4f);
  447. shape.addLineSegment (Line<float> (1.0f, 0.0f, 0.0f, 1.0f), crossThickness * 1.4f);
  448. return new LookAndFeel_V3_DocumentWindowButton ("close", Colour (0xffdd1100), shape, shape);
  449. }
  450. if (buttonType == DocumentWindow::minimiseButton)
  451. {
  452. shape.addLineSegment (Line<float> (0.0f, 0.5f, 1.0f, 0.5f), crossThickness);
  453. return new LookAndFeel_V3_DocumentWindowButton ("minimise", Colour (0xffaa8811), shape, shape);
  454. }
  455. if (buttonType == DocumentWindow::maximiseButton)
  456. {
  457. shape.addLineSegment (Line<float> (0.5f, 0.0f, 0.5f, 1.0f), crossThickness);
  458. shape.addLineSegment (Line<float> (0.0f, 0.5f, 1.0f, 0.5f), crossThickness);
  459. Path fullscreenShape;
  460. fullscreenShape.startNewSubPath (45.0f, 100.0f);
  461. fullscreenShape.lineTo (0.0f, 100.0f);
  462. fullscreenShape.lineTo (0.0f, 0.0f);
  463. fullscreenShape.lineTo (100.0f, 0.0f);
  464. fullscreenShape.lineTo (100.0f, 45.0f);
  465. fullscreenShape.addRectangle (45.0f, 45.0f, 100.0f, 100.0f);
  466. PathStrokeType (30.0f).createStrokedPath (fullscreenShape, fullscreenShape);
  467. return new LookAndFeel_V3_DocumentWindowButton ("maximise", Colour (0xff119911), shape, fullscreenShape);
  468. }
  469. jassertfalse;
  470. return nullptr;
  471. }
  472. Path LookAndFeel_V3::getTickShape (const float height)
  473. {
  474. static const unsigned char pathData[]
  475. = { 110,109,32,210,202,64,126,183,148,64,108,39,244,247,64,245,76,124,64,108,178,131,27,65,246,76,252,64,108,175,242,4,65,246,76,252,
  476. 64,108,236,5,68,65,0,0,160,180,108,240,150,90,65,21,136,52,63,108,48,59,16,65,0,0,32,65,108,32,210,202,64,126,183,148,64, 99,101,0,0 };
  477. Path p;
  478. p.loadPathFromData (pathData, sizeof (pathData));
  479. p.scaleToFit (0, 0, height * 2.0f, height, true);
  480. return p;
  481. }
  482. Path LookAndFeel_V3::getCrossShape (const float height)
  483. {
  484. static const unsigned char pathData[]
  485. = { 110,109,88,57,198,65,29,90,171,65,108,63,53,154,65,8,172,126,65,108,76,55,198,65,215,163,38,65,108,141,151,175,65,82,184,242,64,108,117,147,131,65,90,100,81,65,108,184,30,47,65,82,184,242,64,108,59,223,1,65,215,163,38,65,108,84,227,89,65,8,172,126,65,
  486. 108,35,219,1,65,29,90,171,65,108,209,34,47,65,231,251,193,65,108,117,147,131,65,207,247,149,65,108,129,149,175,65,231,251,193,65,99,101,0,0 };
  487. Path p;
  488. p.loadPathFromData (pathData, sizeof (pathData));
  489. p.scaleToFit (0, 0, height * 2.0f, height, true);
  490. return p;
  491. }