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.

195 lines
6.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. ImageButton::ImageButton (const String& text_)
  20. : Button (text_),
  21. scaleImageToFit (true),
  22. preserveProportions (true),
  23. alphaThreshold (0)
  24. {
  25. }
  26. ImageButton::~ImageButton()
  27. {
  28. }
  29. void ImageButton::setImages (const bool resizeButtonNowToFitThisImage,
  30. const bool rescaleImagesWhenButtonSizeChanges,
  31. const bool preserveImageProportions,
  32. const Image& normalImage_,
  33. const float imageOpacityWhenNormal,
  34. Colour overlayColourWhenNormal,
  35. const Image& overImage_,
  36. const float imageOpacityWhenOver,
  37. Colour overlayColourWhenOver,
  38. const Image& downImage_,
  39. const float imageOpacityWhenDown,
  40. Colour overlayColourWhenDown,
  41. const float hitTestAlphaThreshold)
  42. {
  43. normalImage = normalImage_;
  44. overImage = overImage_;
  45. downImage = downImage_;
  46. if (resizeButtonNowToFitThisImage && normalImage.isValid())
  47. {
  48. imageBounds.setSize (normalImage.getWidth(),
  49. normalImage.getHeight());
  50. setSize (imageBounds.getWidth(), imageBounds.getHeight());
  51. }
  52. scaleImageToFit = rescaleImagesWhenButtonSizeChanges;
  53. preserveProportions = preserveImageProportions;
  54. normalOpacity = imageOpacityWhenNormal;
  55. normalOverlay = overlayColourWhenNormal;
  56. overOpacity = imageOpacityWhenOver;
  57. overOverlay = overlayColourWhenOver;
  58. downOpacity = imageOpacityWhenDown;
  59. downOverlay = overlayColourWhenDown;
  60. alphaThreshold = (uint8) jlimit (0, 0xff, roundToInt (255.0f * hitTestAlphaThreshold));
  61. repaint();
  62. }
  63. Image ImageButton::getCurrentImage() const
  64. {
  65. if (isDown() || getToggleState())
  66. return getDownImage();
  67. if (isOver())
  68. return getOverImage();
  69. return getNormalImage();
  70. }
  71. Image ImageButton::getNormalImage() const
  72. {
  73. return normalImage;
  74. }
  75. Image ImageButton::getOverImage() const
  76. {
  77. return overImage.isValid() ? overImage
  78. : normalImage;
  79. }
  80. Image ImageButton::getDownImage() const
  81. {
  82. return downImage.isValid() ? downImage
  83. : getOverImage();
  84. }
  85. void ImageButton::paintButton (Graphics& g,
  86. bool isMouseOverButton,
  87. bool isButtonDown)
  88. {
  89. if (! isEnabled())
  90. {
  91. isMouseOverButton = false;
  92. isButtonDown = false;
  93. }
  94. Image im (getCurrentImage());
  95. if (im.isValid())
  96. {
  97. const int iw = im.getWidth();
  98. const int ih = im.getHeight();
  99. int w = getWidth();
  100. int h = getHeight();
  101. int x = (w - iw) / 2;
  102. int y = (h - ih) / 2;
  103. if (scaleImageToFit)
  104. {
  105. if (preserveProportions)
  106. {
  107. int newW, newH;
  108. const float imRatio = ih / (float) iw;
  109. const float destRatio = h / (float) w;
  110. if (imRatio > destRatio)
  111. {
  112. newW = roundToInt (h / imRatio);
  113. newH = h;
  114. }
  115. else
  116. {
  117. newW = w;
  118. newH = roundToInt (w * imRatio);
  119. }
  120. x = (w - newW) / 2;
  121. y = (h - newH) / 2;
  122. w = newW;
  123. h = newH;
  124. }
  125. else
  126. {
  127. x = 0;
  128. y = 0;
  129. }
  130. }
  131. if (! scaleImageToFit)
  132. {
  133. w = iw;
  134. h = ih;
  135. }
  136. imageBounds.setBounds (x, y, w, h);
  137. const bool useDownImage = isButtonDown || getToggleState();
  138. getLookAndFeel().drawImageButton (g, &im, x, y, w, h,
  139. useDownImage ? downOverlay
  140. : (isMouseOverButton ? overOverlay
  141. : normalOverlay),
  142. useDownImage ? downOpacity
  143. : (isMouseOverButton ? overOpacity
  144. : normalOpacity),
  145. *this);
  146. }
  147. }
  148. bool ImageButton::hitTest (int x, int y)
  149. {
  150. if (! Component::hitTest (x, y)) // handle setInterceptsMouseClicks
  151. return false;
  152. if (alphaThreshold == 0)
  153. return true;
  154. Image im (getCurrentImage());
  155. return im.isNull() || ((! imageBounds.isEmpty())
  156. && alphaThreshold < im.getPixelAt (((x - imageBounds.getX()) * im.getWidth()) / imageBounds.getWidth(),
  157. ((y - imageBounds.getY()) * im.getHeight()) / imageBounds.getHeight()).getAlpha());
  158. }