/* ============================================================================== This file is part of the JUCE library - "Jules' Utility Class Extensions" Copyright 2004-11 by Raw Material Software Ltd. ------------------------------------------------------------------------------ JUCE can be redistributed and/or modified under the terms of the GNU General Public License (Version 2), as published by the Free Software Foundation. A copy of the license is included in the JUCE distribution, or can be found online at www.gnu.org/licenses. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ------------------------------------------------------------------------------ To release a closed-source product which uses JUCE, commercial licenses are available: visit www.rawmaterialsoftware.com/juce for more information. ============================================================================== */ ImageButton::ImageButton (const String& text_) : Button (text_), scaleImageToFit (true), preserveProportions (true), alphaThreshold (0) { } ImageButton::~ImageButton() { } void ImageButton::setImages (const bool resizeButtonNowToFitThisImage, const bool rescaleImagesWhenButtonSizeChanges, const bool preserveImageProportions, const Image& normalImage_, const float imageOpacityWhenNormal, const Colour& overlayColourWhenNormal, const Image& overImage_, const float imageOpacityWhenOver, const Colour& overlayColourWhenOver, const Image& downImage_, const float imageOpacityWhenDown, const Colour& overlayColourWhenDown, const float hitTestAlphaThreshold) { normalImage = normalImage_; overImage = overImage_; downImage = downImage_; if (resizeButtonNowToFitThisImage && normalImage.isValid()) { imageBounds.setSize (normalImage.getWidth(), normalImage.getHeight()); setSize (imageBounds.getWidth(), imageBounds.getHeight()); } scaleImageToFit = rescaleImagesWhenButtonSizeChanges; preserveProportions = preserveImageProportions; normalOpacity = imageOpacityWhenNormal; normalOverlay = overlayColourWhenNormal; overOpacity = imageOpacityWhenOver; overOverlay = overlayColourWhenOver; downOpacity = imageOpacityWhenDown; downOverlay = overlayColourWhenDown; alphaThreshold = (uint8) jlimit (0, 0xff, roundToInt (255.0f * hitTestAlphaThreshold)); repaint(); } Image ImageButton::getCurrentImage() const { if (isDown() || getToggleState()) return getDownImage(); if (isOver()) return getOverImage(); return getNormalImage(); } Image ImageButton::getNormalImage() const { return normalImage; } Image ImageButton::getOverImage() const { return overImage.isValid() ? overImage : normalImage; } Image ImageButton::getDownImage() const { return downImage.isValid() ? downImage : getOverImage(); } void ImageButton::paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) { if (! isEnabled()) { isMouseOverButton = false; isButtonDown = false; } Image im (getCurrentImage()); if (im.isValid()) { const int iw = im.getWidth(); const int ih = im.getHeight(); int w = getWidth(); int h = getHeight(); int x = (w - iw) / 2; int y = (h - ih) / 2; if (scaleImageToFit) { if (preserveProportions) { int newW, newH; const float imRatio = ih / (float) iw; const float destRatio = h / (float) w; if (imRatio > destRatio) { newW = roundToInt (h / imRatio); newH = h; } else { newW = w; newH = roundToInt (w * imRatio); } x = (w - newW) / 2; y = (h - newH) / 2; w = newW; h = newH; } else { x = 0; y = 0; } } if (! scaleImageToFit) { w = iw; h = ih; } imageBounds.setBounds (x, y, w, h); const bool useDownImage = isButtonDown || getToggleState(); getLookAndFeel().drawImageButton (g, &im, x, y, w, h, useDownImage ? downOverlay : (isMouseOverButton ? overOverlay : normalOverlay), useDownImage ? downOpacity : (isMouseOverButton ? overOpacity : normalOpacity), *this); } } bool ImageButton::hitTest (int x, int y) { if (alphaThreshold == 0) return true; Image im (getCurrentImage()); return im.isNull() || ((! imageBounds.isEmpty()) && alphaThreshold < im.getPixelAt (((x - imageBounds.getX()) * im.getWidth()) / imageBounds.getWidth(), ((y - imageBounds.getY()) * im.getHeight()) / imageBounds.getHeight()).getAlpha()); } const Identifier ImageButton::Ids::tagType ("IMAGEBUTTON"); const Identifier ImageButton::Ids::upImage ("upImage"); const Identifier ImageButton::Ids::overImage ("overImage"); const Identifier ImageButton::Ids::downImage ("downImage"); const Identifier ImageButton::Ids::upOverlay ("upOverlay"); const Identifier ImageButton::Ids::overOverlay ("overOverlay"); const Identifier ImageButton::Ids::downOverlay ("downOverlay"); const Identifier ImageButton::Ids::upOpacity ("upOpacity"); const Identifier ImageButton::Ids::overOpacity ("overOpacity"); const Identifier ImageButton::Ids::downOpacity ("downOpacity"); namespace ImageButtonHelpers { static Colour getColourFromVar (const var& col) { return col.isString() ? Colour::fromString (col.toString()) : Colours::transparentBlack; } static float getOpacityFromVar (const var& v) { return v.isVoid() ? 1.0f : static_cast (v); } } void ImageButton::refreshFromValueTree (const ValueTree& state, ComponentBuilder& builder) { Button::refreshFromValueTree (state, builder); const var upImageIdentifier (state [Ids::upImage]), overImageIdentifier (state [Ids::overImage]), downImageIdentifier (state [Ids::downImage]); ComponentBuilder::ImageProvider* const imageProvider = builder.getImageProvider(); jassert (imageProvider != nullptr || upImageIdentifier.isVoid()); Image newUpImage, newOverImage, newDownImage; if (imageProvider != nullptr) { newUpImage = imageProvider->getImageForIdentifier (upImageIdentifier); newOverImage = imageProvider->getImageForIdentifier (overImageIdentifier); newDownImage = imageProvider->getImageForIdentifier (downImageIdentifier); } using namespace ImageButtonHelpers; setImages (false, true, true, newUpImage, getOpacityFromVar (state[Ids::upOpacity]), getColourFromVar (state[Ids::upOverlay]), newOverImage, getOpacityFromVar (state[Ids::overOpacity]), getColourFromVar (state[Ids::overOverlay]), newDownImage, getOpacityFromVar (state[Ids::downOpacity]), getColourFromVar (state[Ids::downOverlay])); }