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.

231 lines
6.7KB

  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 (style == ImageOnButtonBackground)
  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. currentImage->setOriginWithOriginalSize (Point<float>());
  98. else
  99. currentImage->setTransformToFit (getImageBounds(),
  100. style == ImageStretched ? RectanglePlacement::stretchToFit
  101. : RectanglePlacement::centred);
  102. }
  103. }
  104. void DrawableButton::buttonStateChanged()
  105. {
  106. repaint();
  107. Drawable* imageToDraw = nullptr;
  108. float opacity = 1.0f;
  109. if (isEnabled())
  110. {
  111. imageToDraw = getCurrentImage();
  112. }
  113. else
  114. {
  115. imageToDraw = getToggleState() ? disabledImageOn.get()
  116. : disabledImage.get();
  117. if (imageToDraw == nullptr)
  118. {
  119. opacity = 0.4f;
  120. imageToDraw = getNormalImage();
  121. }
  122. }
  123. if (imageToDraw != currentImage)
  124. {
  125. removeChildComponent (currentImage);
  126. currentImage = imageToDraw;
  127. if (currentImage != nullptr)
  128. {
  129. currentImage->setInterceptsMouseClicks (false, false);
  130. addAndMakeVisible (currentImage);
  131. resized();
  132. }
  133. }
  134. if (currentImage != nullptr)
  135. currentImage->setAlpha (opacity);
  136. }
  137. void DrawableButton::enablementChanged()
  138. {
  139. Button::enablementChanged();
  140. buttonStateChanged();
  141. }
  142. void DrawableButton::colourChanged()
  143. {
  144. repaint();
  145. }
  146. void DrawableButton::paintButton (Graphics& g,
  147. const bool shouldDrawButtonAsHighlighted,
  148. const bool shouldDrawButtonAsDown)
  149. {
  150. auto& lf = getLookAndFeel();
  151. if (style == ImageOnButtonBackground)
  152. lf.drawButtonBackground (g, *this,
  153. findColour (getToggleState() ? TextButton::buttonOnColourId
  154. : TextButton::buttonColourId),
  155. shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);
  156. else
  157. lf.drawDrawableButton (g, *this, shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);
  158. }
  159. //==============================================================================
  160. Drawable* DrawableButton::getCurrentImage() const noexcept
  161. {
  162. if (isDown()) return getDownImage();
  163. if (isOver()) return getOverImage();
  164. return getNormalImage();
  165. }
  166. Drawable* DrawableButton::getNormalImage() const noexcept
  167. {
  168. return (getToggleState() && normalImageOn != nullptr) ? normalImageOn.get()
  169. : normalImage.get();
  170. }
  171. Drawable* DrawableButton::getOverImage() const noexcept
  172. {
  173. if (getToggleState())
  174. {
  175. if (overImageOn != nullptr) return overImageOn.get();
  176. if (normalImageOn != nullptr) return normalImageOn.get();
  177. }
  178. return overImage != nullptr ? overImage.get() : normalImage.get();
  179. }
  180. Drawable* DrawableButton::getDownImage() const noexcept
  181. {
  182. if (auto* d = getToggleState() ? downImageOn.get() : downImage.get())
  183. return d;
  184. return getOverImage();
  185. }
  186. } // namespace juce