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.

247 lines
7.0KB

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