/* ============================================================================== This file is part of the JUCE library. Copyright (c) 2020 - Raw Material Software Limited JUCE is an open source library subject to commercial or open-source licensing. By using JUCE, you agree to the terms of both the JUCE 6 End-User License Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). End User License Agreement: www.juce.com/juce-6-licence Privacy Policy: www.juce.com/juce-privacy-policy Or: You may also use this code under the terms of the GPL v3 (see www.gnu.org/licenses). JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED. ============================================================================== */ namespace juce { DrawableButton::DrawableButton (const String& name, const DrawableButton::ButtonStyle buttonStyle) : Button (name), style (buttonStyle) { } DrawableButton::~DrawableButton() { } //============================================================================== static std::unique_ptr copyDrawableIfNotNull (const Drawable* const d) { if (d != nullptr) return d->createCopy(); return {}; } void DrawableButton::setImages (const Drawable* normal, const Drawable* over, const Drawable* down, const Drawable* disabled, const Drawable* normalOn, const Drawable* overOn, const Drawable* downOn, const Drawable* disabledOn) { jassert (normal != nullptr); // you really need to give it at least a normal image.. normalImage = copyDrawableIfNotNull (normal); overImage = copyDrawableIfNotNull (over); downImage = copyDrawableIfNotNull (down); disabledImage = copyDrawableIfNotNull (disabled); normalImageOn = copyDrawableIfNotNull (normalOn); overImageOn = copyDrawableIfNotNull (overOn); downImageOn = copyDrawableIfNotNull (downOn); disabledImageOn = copyDrawableIfNotNull (disabledOn); currentImage = nullptr; buttonStateChanged(); } //============================================================================== void DrawableButton::setButtonStyle (const DrawableButton::ButtonStyle newStyle) { if (style != newStyle) { style = newStyle; buttonStateChanged(); } } void DrawableButton::setEdgeIndent (const int numPixelsIndent) { edgeIndent = numPixelsIndent; repaint(); resized(); } Rectangle DrawableButton::getImageBounds() const { auto r = getLocalBounds(); if (style != ImageStretched) { auto indentX = jmin (edgeIndent, proportionOfWidth (0.3f)); auto indentY = jmin (edgeIndent, proportionOfHeight (0.3f)); if (shouldDrawButtonBackground()) { indentX = jmax (getWidth() / 4, indentX); indentY = jmax (getHeight() / 4, indentY); } else if (style == ImageAboveTextLabel) { r = r.withTrimmedBottom (jmin (16, proportionOfHeight (0.25f))); } else if (getStyle() == ImageBelowTextLabel) { r = r.withTrimmedTop (jmin (14, proportionOfHeight (0.25f))); } else if (getStyle() == ImageLeftOfTextLabel) { r = r.withTrimmedRight (proportionOfWidth (0.5f)); } else if (getStyle() == ImageRightOfTextLabel) { r = r.withTrimmedLeft (proportionOfWidth (0.5f)); } r = r.reduced (indentX, indentY); } return r.toFloat(); } void DrawableButton::resized() { Button::resized(); if (currentImage != nullptr) { if (style != ImageRaw) { int transformFlags = 0; if (style == ImageStretched) { transformFlags |= RectanglePlacement::stretchToFit; } else { transformFlags |= RectanglePlacement::centred; if (style == ImageOnButtonBackgroundOriginalSize) transformFlags |= RectanglePlacement::doNotResize; } currentImage->setTransformToFit (getImageBounds(), transformFlags); } } } void DrawableButton::buttonStateChanged() { repaint(); Drawable* imageToDraw = nullptr; float opacity = 1.0f; if (isEnabled()) { imageToDraw = getCurrentImage(); } else { imageToDraw = getToggleState() ? disabledImageOn.get() : disabledImage.get(); if (imageToDraw == nullptr) { opacity = 0.4f; imageToDraw = getNormalImage(); } } if (imageToDraw != currentImage) { removeChildComponent (currentImage); currentImage = imageToDraw; if (currentImage != nullptr) { currentImage->setInterceptsMouseClicks (false, false); currentImage->setAccessible(false); addAndMakeVisible (currentImage); resized(); } } if (currentImage != nullptr) currentImage->setAlpha (opacity); } void DrawableButton::enablementChanged() { Button::enablementChanged(); buttonStateChanged(); } void DrawableButton::colourChanged() { repaint(); } void DrawableButton::paintButton (Graphics& g, const bool shouldDrawButtonAsHighlighted, const bool shouldDrawButtonAsDown) { auto& lf = getLookAndFeel(); if (shouldDrawButtonBackground()) lf.drawButtonBackground (g, *this, findColour (getToggleState() ? TextButton::buttonOnColourId : TextButton::buttonColourId), shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown); else lf.drawDrawableButton (g, *this, shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown); } //============================================================================== Drawable* DrawableButton::getCurrentImage() const noexcept { if (isDown()) return getDownImage(); if (isOver()) return getOverImage(); return getNormalImage(); } Drawable* DrawableButton::getNormalImage() const noexcept { return (getToggleState() && normalImageOn != nullptr) ? normalImageOn.get() : normalImage.get(); } Drawable* DrawableButton::getOverImage() const noexcept { if (getToggleState()) { if (overImageOn != nullptr) return overImageOn.get(); if (normalImageOn != nullptr) return normalImageOn.get(); } return overImage != nullptr ? overImage.get() : normalImage.get(); } Drawable* DrawableButton::getDownImage() const noexcept { if (auto* d = getToggleState() ? downImageOn.get() : downImage.get()) return d; return getOverImage(); } } // namespace juce