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
7.7KB

  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. DrawableButton::DrawableButton (const String& name, const DrawableButton::ButtonStyle buttonStyle)
  19. : Button (name),
  20. style (buttonStyle),
  21. currentImage (nullptr),
  22. edgeIndent (3)
  23. {
  24. }
  25. DrawableButton::~DrawableButton()
  26. {
  27. }
  28. //==============================================================================
  29. static Drawable* copyDrawableIfNotNull (const Drawable* const d)
  30. {
  31. return d != nullptr ? d->createCopy() : nullptr;
  32. }
  33. void DrawableButton::setImages (const Drawable* normal,
  34. const Drawable* over,
  35. const Drawable* down,
  36. const Drawable* disabled,
  37. const Drawable* normalOn,
  38. const Drawable* overOn,
  39. const Drawable* downOn,
  40. const Drawable* disabledOn)
  41. {
  42. jassert (normal != nullptr); // you really need to give it at least a normal image..
  43. normalImage = copyDrawableIfNotNull (normal);
  44. overImage = copyDrawableIfNotNull (over);
  45. downImage = copyDrawableIfNotNull (down);
  46. disabledImage = copyDrawableIfNotNull (disabled);
  47. normalImageOn = copyDrawableIfNotNull (normalOn);
  48. overImageOn = copyDrawableIfNotNull (overOn);
  49. downImageOn = copyDrawableIfNotNull (downOn);
  50. disabledImageOn = copyDrawableIfNotNull (disabledOn);
  51. buttonStateChanged();
  52. }
  53. //==============================================================================
  54. void DrawableButton::setButtonStyle (const DrawableButton::ButtonStyle newStyle)
  55. {
  56. if (style != newStyle)
  57. {
  58. style = newStyle;
  59. buttonStateChanged();
  60. }
  61. }
  62. void DrawableButton::setEdgeIndent (const int numPixelsIndent)
  63. {
  64. edgeIndent = numPixelsIndent;
  65. repaint();
  66. resized();
  67. }
  68. void DrawableButton::resized()
  69. {
  70. Button::resized();
  71. if (currentImage != nullptr)
  72. {
  73. if (style == ImageRaw)
  74. {
  75. currentImage->setOriginWithOriginalSize (Point<float>());
  76. }
  77. else if (style == ImageStretched)
  78. {
  79. currentImage->setTransformToFit (getLocalBounds().toFloat(), RectanglePlacement::stretchToFit);
  80. }
  81. else
  82. {
  83. Rectangle<int> imageSpace;
  84. const int indentX = jmin (edgeIndent, proportionOfWidth (0.3f));
  85. const int indentY = jmin (edgeIndent, proportionOfHeight (0.3f));
  86. if (style == ImageOnButtonBackground)
  87. {
  88. imageSpace = getLocalBounds().reduced (jmax (getWidth() / 4, indentX),
  89. jmax (getHeight() / 4, indentY));
  90. }
  91. else
  92. {
  93. const int textH = (style == ImageAboveTextLabel) ? jmin (16, proportionOfHeight (0.25f)) : 0;
  94. imageSpace.setBounds (indentX, indentY,
  95. getWidth() - indentX * 2,
  96. getHeight() - indentY * 2 - textH);
  97. }
  98. currentImage->setTransformToFit (imageSpace.toFloat(), RectanglePlacement::centred);
  99. }
  100. }
  101. }
  102. void DrawableButton::buttonStateChanged()
  103. {
  104. repaint();
  105. Drawable* imageToDraw = nullptr;
  106. float opacity = 1.0f;
  107. if (isEnabled())
  108. {
  109. imageToDraw = getCurrentImage();
  110. }
  111. else
  112. {
  113. imageToDraw = getToggleState() ? disabledImageOn
  114. : disabledImage;
  115. if (imageToDraw == nullptr)
  116. {
  117. opacity = 0.4f;
  118. imageToDraw = getNormalImage();
  119. }
  120. }
  121. if (imageToDraw != currentImage)
  122. {
  123. removeChildComponent (currentImage);
  124. currentImage = imageToDraw;
  125. if (currentImage != nullptr)
  126. {
  127. currentImage->setInterceptsMouseClicks (false, false);
  128. addAndMakeVisible (currentImage);
  129. DrawableButton::resized();
  130. }
  131. }
  132. if (currentImage != nullptr)
  133. currentImage->setAlpha (opacity);
  134. }
  135. void DrawableButton::enablementChanged()
  136. {
  137. Button::enablementChanged();
  138. buttonStateChanged();
  139. }
  140. void DrawableButton::colourChanged()
  141. {
  142. repaint();
  143. }
  144. void DrawableButton::paintButton (Graphics& g,
  145. const bool isMouseOverButton,
  146. const bool isButtonDown)
  147. {
  148. if (style == ImageOnButtonBackground)
  149. {
  150. getLookAndFeel().drawButtonBackground (g, *this,
  151. findColour (getToggleState() ? TextButton::buttonOnColourId
  152. : TextButton::buttonColourId),
  153. isMouseOverButton,
  154. isButtonDown);
  155. }
  156. else
  157. {
  158. g.fillAll (findColour (getToggleState() ? backgroundOnColourId
  159. : backgroundColourId));
  160. const int textH = (style == ImageAboveTextLabel)
  161. ? jmin (16, proportionOfHeight (0.25f))
  162. : 0;
  163. if (textH > 0)
  164. {
  165. g.setFont ((float) textH);
  166. g.setColour (findColour (DrawableButton::textColourId)
  167. .withMultipliedAlpha (isEnabled() ? 1.0f : 0.4f));
  168. g.drawFittedText (getButtonText(),
  169. 2, getHeight() - textH - 1,
  170. getWidth() - 4, textH,
  171. Justification::centred, 1);
  172. }
  173. }
  174. }
  175. //==============================================================================
  176. Drawable* DrawableButton::getCurrentImage() const noexcept
  177. {
  178. if (isDown()) return getDownImage();
  179. if (isOver()) return getOverImage();
  180. return getNormalImage();
  181. }
  182. Drawable* DrawableButton::getNormalImage() const noexcept
  183. {
  184. return (getToggleState() && normalImageOn != nullptr) ? normalImageOn
  185. : normalImage;
  186. }
  187. Drawable* DrawableButton::getOverImage() const noexcept
  188. {
  189. if (getToggleState())
  190. {
  191. if (overImageOn != nullptr) return overImageOn;
  192. if (normalImageOn != nullptr) return normalImageOn;
  193. }
  194. return overImage != nullptr ? overImage : normalImage;
  195. }
  196. Drawable* DrawableButton::getDownImage() const noexcept
  197. {
  198. Drawable* const d = getToggleState() ? downImageOn : downImage;
  199. return d != nullptr ? d : getOverImage();
  200. }