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.

243 lines
6.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace juce
  20. {
  21. DrawableButton::DrawableButton (const String& name, const DrawableButton::ButtonStyle buttonStyle)
  22. : Button (name), style (buttonStyle)
  23. {
  24. }
  25. DrawableButton::~DrawableButton()
  26. {
  27. }
  28. //==============================================================================
  29. static std::unique_ptr<Drawable> copyDrawableIfNotNull (const Drawable* const d)
  30. {
  31. if (d != nullptr)
  32. return d->createCopy();
  33. return {};
  34. }
  35. void DrawableButton::setImages (const Drawable* normal,
  36. const Drawable* over,
  37. const Drawable* down,
  38. const Drawable* disabled,
  39. const Drawable* normalOn,
  40. const Drawable* overOn,
  41. const Drawable* downOn,
  42. const Drawable* disabledOn)
  43. {
  44. jassert (normal != nullptr); // you really need to give it at least a normal image..
  45. normalImage = copyDrawableIfNotNull (normal);
  46. overImage = copyDrawableIfNotNull (over);
  47. downImage = copyDrawableIfNotNull (down);
  48. disabledImage = copyDrawableIfNotNull (disabled);
  49. normalImageOn = copyDrawableIfNotNull (normalOn);
  50. overImageOn = copyDrawableIfNotNull (overOn);
  51. downImageOn = copyDrawableIfNotNull (downOn);
  52. disabledImageOn = copyDrawableIfNotNull (disabledOn);
  53. currentImage = nullptr;
  54. buttonStateChanged();
  55. }
  56. //==============================================================================
  57. void DrawableButton::setButtonStyle (const DrawableButton::ButtonStyle newStyle)
  58. {
  59. if (style != newStyle)
  60. {
  61. style = newStyle;
  62. buttonStateChanged();
  63. }
  64. }
  65. void DrawableButton::setEdgeIndent (const int numPixelsIndent)
  66. {
  67. edgeIndent = numPixelsIndent;
  68. repaint();
  69. resized();
  70. }
  71. Rectangle<float> DrawableButton::getImageBounds() const
  72. {
  73. auto r = getLocalBounds();
  74. if (style != ImageStretched)
  75. {
  76. auto indentX = jmin (edgeIndent, proportionOfWidth (0.3f));
  77. auto indentY = jmin (edgeIndent, proportionOfHeight (0.3f));
  78. if (shouldDrawButtonBackground())
  79. {
  80. indentX = jmax (getWidth() / 4, indentX);
  81. indentY = jmax (getHeight() / 4, indentY);
  82. }
  83. else if (style == ImageAboveTextLabel)
  84. {
  85. r = r.withTrimmedBottom (jmin (16, proportionOfHeight (0.25f)));
  86. }
  87. r = r.reduced (indentX, indentY);
  88. }
  89. return r.toFloat();
  90. }
  91. void DrawableButton::resized()
  92. {
  93. Button::resized();
  94. if (currentImage != nullptr)
  95. {
  96. if (style != ImageRaw)
  97. {
  98. int transformFlags = 0;
  99. if (style == ImageStretched)
  100. {
  101. transformFlags |= RectanglePlacement::stretchToFit;
  102. }
  103. else
  104. {
  105. transformFlags |= RectanglePlacement::centred;
  106. if (style == ImageOnButtonBackgroundOriginalSize)
  107. transformFlags |= RectanglePlacement::doNotResize;
  108. }
  109. currentImage->setTransformToFit (getImageBounds(), transformFlags);
  110. }
  111. }
  112. }
  113. void DrawableButton::buttonStateChanged()
  114. {
  115. repaint();
  116. Drawable* imageToDraw = nullptr;
  117. float opacity = 1.0f;
  118. if (isEnabled())
  119. {
  120. imageToDraw = getCurrentImage();
  121. }
  122. else
  123. {
  124. imageToDraw = getToggleState() ? disabledImageOn.get()
  125. : disabledImage.get();
  126. if (imageToDraw == nullptr)
  127. {
  128. opacity = 0.4f;
  129. imageToDraw = getNormalImage();
  130. }
  131. }
  132. if (imageToDraw != currentImage)
  133. {
  134. removeChildComponent (currentImage);
  135. currentImage = imageToDraw;
  136. if (currentImage != nullptr)
  137. {
  138. currentImage->setInterceptsMouseClicks (false, false);
  139. addAndMakeVisible (currentImage);
  140. resized();
  141. }
  142. }
  143. if (currentImage != nullptr)
  144. currentImage->setAlpha (opacity);
  145. }
  146. void DrawableButton::enablementChanged()
  147. {
  148. Button::enablementChanged();
  149. buttonStateChanged();
  150. }
  151. void DrawableButton::colourChanged()
  152. {
  153. repaint();
  154. }
  155. void DrawableButton::paintButton (Graphics& g,
  156. const bool shouldDrawButtonAsHighlighted,
  157. const bool shouldDrawButtonAsDown)
  158. {
  159. auto& lf = getLookAndFeel();
  160. if (shouldDrawButtonBackground())
  161. lf.drawButtonBackground (g, *this,
  162. findColour (getToggleState() ? TextButton::buttonOnColourId
  163. : TextButton::buttonColourId),
  164. shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);
  165. else
  166. lf.drawDrawableButton (g, *this, shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);
  167. }
  168. //==============================================================================
  169. Drawable* DrawableButton::getCurrentImage() const noexcept
  170. {
  171. if (isDown()) return getDownImage();
  172. if (isOver()) return getOverImage();
  173. return getNormalImage();
  174. }
  175. Drawable* DrawableButton::getNormalImage() const noexcept
  176. {
  177. return (getToggleState() && normalImageOn != nullptr) ? normalImageOn.get()
  178. : normalImage.get();
  179. }
  180. Drawable* DrawableButton::getOverImage() const noexcept
  181. {
  182. if (getToggleState())
  183. {
  184. if (overImageOn != nullptr) return overImageOn.get();
  185. if (normalImageOn != nullptr) return normalImageOn.get();
  186. }
  187. return overImage != nullptr ? overImage.get() : normalImage.get();
  188. }
  189. Drawable* DrawableButton::getDownImage() const noexcept
  190. {
  191. if (auto* d = getToggleState() ? downImageOn.get() : downImage.get())
  192. return d;
  193. return getOverImage();
  194. }
  195. } // namespace juce