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.

244 lines
8.4KB

  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. ImageButton::ImageButton (const String& text_)
  19. : Button (text_),
  20. scaleImageToFit (true),
  21. preserveProportions (true),
  22. alphaThreshold (0)
  23. {
  24. }
  25. ImageButton::~ImageButton()
  26. {
  27. }
  28. void ImageButton::setImages (const bool resizeButtonNowToFitThisImage,
  29. const bool rescaleImagesWhenButtonSizeChanges,
  30. const bool preserveImageProportions,
  31. const Image& normalImage_,
  32. const float imageOpacityWhenNormal,
  33. const Colour& overlayColourWhenNormal,
  34. const Image& overImage_,
  35. const float imageOpacityWhenOver,
  36. const Colour& overlayColourWhenOver,
  37. const Image& downImage_,
  38. const float imageOpacityWhenDown,
  39. const Colour& overlayColourWhenDown,
  40. const float hitTestAlphaThreshold)
  41. {
  42. normalImage = normalImage_;
  43. overImage = overImage_;
  44. downImage = downImage_;
  45. if (resizeButtonNowToFitThisImage && normalImage.isValid())
  46. {
  47. imageBounds.setSize (normalImage.getWidth(),
  48. normalImage.getHeight());
  49. setSize (imageBounds.getWidth(), imageBounds.getHeight());
  50. }
  51. scaleImageToFit = rescaleImagesWhenButtonSizeChanges;
  52. preserveProportions = preserveImageProportions;
  53. normalOpacity = imageOpacityWhenNormal;
  54. normalOverlay = overlayColourWhenNormal;
  55. overOpacity = imageOpacityWhenOver;
  56. overOverlay = overlayColourWhenOver;
  57. downOpacity = imageOpacityWhenDown;
  58. downOverlay = overlayColourWhenDown;
  59. alphaThreshold = (uint8) jlimit (0, 0xff, roundToInt (255.0f * hitTestAlphaThreshold));
  60. repaint();
  61. }
  62. Image ImageButton::getCurrentImage() const
  63. {
  64. if (isDown() || getToggleState())
  65. return getDownImage();
  66. if (isOver())
  67. return getOverImage();
  68. return getNormalImage();
  69. }
  70. Image ImageButton::getNormalImage() const
  71. {
  72. return normalImage;
  73. }
  74. Image ImageButton::getOverImage() const
  75. {
  76. return overImage.isValid() ? overImage
  77. : normalImage;
  78. }
  79. Image ImageButton::getDownImage() const
  80. {
  81. return downImage.isValid() ? downImage
  82. : getOverImage();
  83. }
  84. void ImageButton::paintButton (Graphics& g,
  85. bool isMouseOverButton,
  86. bool isButtonDown)
  87. {
  88. if (! isEnabled())
  89. {
  90. isMouseOverButton = false;
  91. isButtonDown = false;
  92. }
  93. Image im (getCurrentImage());
  94. if (im.isValid())
  95. {
  96. const int iw = im.getWidth();
  97. const int ih = im.getHeight();
  98. int w = getWidth();
  99. int h = getHeight();
  100. int x = (w - iw) / 2;
  101. int y = (h - ih) / 2;
  102. if (scaleImageToFit)
  103. {
  104. if (preserveProportions)
  105. {
  106. int newW, newH;
  107. const float imRatio = ih / (float) iw;
  108. const float destRatio = h / (float) w;
  109. if (imRatio > destRatio)
  110. {
  111. newW = roundToInt (h / imRatio);
  112. newH = h;
  113. }
  114. else
  115. {
  116. newW = w;
  117. newH = roundToInt (w * imRatio);
  118. }
  119. x = (w - newW) / 2;
  120. y = (h - newH) / 2;
  121. w = newW;
  122. h = newH;
  123. }
  124. else
  125. {
  126. x = 0;
  127. y = 0;
  128. }
  129. }
  130. if (! scaleImageToFit)
  131. {
  132. w = iw;
  133. h = ih;
  134. }
  135. imageBounds.setBounds (x, y, w, h);
  136. const bool useDownImage = isButtonDown || getToggleState();
  137. getLookAndFeel().drawImageButton (g, &im, x, y, w, h,
  138. useDownImage ? downOverlay
  139. : (isMouseOverButton ? overOverlay
  140. : normalOverlay),
  141. useDownImage ? downOpacity
  142. : (isMouseOverButton ? overOpacity
  143. : normalOpacity),
  144. *this);
  145. }
  146. }
  147. bool ImageButton::hitTest (int x, int y)
  148. {
  149. if (alphaThreshold == 0)
  150. return true;
  151. Image im (getCurrentImage());
  152. return im.isNull() || ((! imageBounds.isEmpty())
  153. && alphaThreshold < im.getPixelAt (((x - imageBounds.getX()) * im.getWidth()) / imageBounds.getWidth(),
  154. ((y - imageBounds.getY()) * im.getHeight()) / imageBounds.getHeight()).getAlpha());
  155. }
  156. const Identifier ImageButton::Ids::tagType ("IMAGEBUTTON");
  157. const Identifier ImageButton::Ids::upImage ("upImage");
  158. const Identifier ImageButton::Ids::overImage ("overImage");
  159. const Identifier ImageButton::Ids::downImage ("downImage");
  160. const Identifier ImageButton::Ids::upOverlay ("upOverlay");
  161. const Identifier ImageButton::Ids::overOverlay ("overOverlay");
  162. const Identifier ImageButton::Ids::downOverlay ("downOverlay");
  163. const Identifier ImageButton::Ids::upOpacity ("upOpacity");
  164. const Identifier ImageButton::Ids::overOpacity ("overOpacity");
  165. const Identifier ImageButton::Ids::downOpacity ("downOpacity");
  166. namespace ImageButtonHelpers
  167. {
  168. static Colour getColourFromVar (const var& col)
  169. {
  170. return col.isString() ? Colour::fromString (col.toString())
  171. : Colours::transparentBlack;
  172. }
  173. static float getOpacityFromVar (const var& v)
  174. {
  175. return v.isVoid() ? 1.0f : static_cast<float> (v);
  176. }
  177. }
  178. void ImageButton::refreshFromValueTree (const ValueTree& state, ComponentBuilder& builder)
  179. {
  180. Button::refreshFromValueTree (state, builder);
  181. const var upImageIdentifier (state [Ids::upImage]),
  182. overImageIdentifier (state [Ids::overImage]),
  183. downImageIdentifier (state [Ids::downImage]);
  184. ComponentBuilder::ImageProvider* const imageProvider = builder.getImageProvider();
  185. jassert (imageProvider != nullptr || upImageIdentifier.isVoid());
  186. Image newUpImage, newOverImage, newDownImage;
  187. if (imageProvider != nullptr)
  188. {
  189. newUpImage = imageProvider->getImageForIdentifier (upImageIdentifier);
  190. newOverImage = imageProvider->getImageForIdentifier (overImageIdentifier);
  191. newDownImage = imageProvider->getImageForIdentifier (downImageIdentifier);
  192. }
  193. using namespace ImageButtonHelpers;
  194. setImages (false, true, true,
  195. newUpImage, getOpacityFromVar (state[Ids::upOpacity]), getColourFromVar (state[Ids::upOverlay]),
  196. newOverImage, getOpacityFromVar (state[Ids::overOpacity]), getColourFromVar (state[Ids::overOverlay]),
  197. newDownImage, getOpacityFromVar (state[Ids::downOpacity]), getColourFromVar (state[Ids::downOverlay]));
  198. }