git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
51
deps/juce/modules/juce_gui_basics/buttons/juce_ArrowButton.cpp
vendored
Normal file
51
deps/juce/modules/juce_gui_basics/buttons/juce_ArrowButton.cpp
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
ArrowButton::ArrowButton (const String& name, float arrowDirectionInRadians, Colour arrowColour)
|
||||
: Button (name), colour (arrowColour)
|
||||
{
|
||||
path.addTriangle (0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f);
|
||||
path.applyTransform (AffineTransform::rotation (MathConstants<float>::twoPi * arrowDirectionInRadians, 0.5f, 0.5f));
|
||||
}
|
||||
|
||||
ArrowButton::~ArrowButton() {}
|
||||
|
||||
void ArrowButton::paintButton (Graphics& g, bool /*shouldDrawButtonAsHighlighted*/, bool shouldDrawButtonAsDown)
|
||||
{
|
||||
Path p (path);
|
||||
|
||||
const float offset = shouldDrawButtonAsDown ? 1.0f : 0.0f;
|
||||
p.applyTransform (path.getTransformToScaleToFit (offset, offset, (float) getWidth() - 3.0f, (float) getHeight() - 3.0f, false));
|
||||
|
||||
DropShadow (Colours::black.withAlpha (0.3f), shouldDrawButtonAsDown ? 2 : 4, Point<int>()).drawForPath (g, p);
|
||||
|
||||
g.setColour (colour);
|
||||
g.fillPath (p);
|
||||
}
|
||||
|
||||
} // namespace juce
|
65
deps/juce/modules/juce_gui_basics/buttons/juce_ArrowButton.h
vendored
Normal file
65
deps/juce/modules/juce_gui_basics/buttons/juce_ArrowButton.h
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A button with an arrow in it.
|
||||
|
||||
@see Button
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API ArrowButton : public Button
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an ArrowButton.
|
||||
|
||||
@param buttonName the name to give the button
|
||||
@param arrowDirection the direction the arrow should point in, where 0.0 is
|
||||
pointing right, 0.25 is down, 0.5 is left, 0.75 is up
|
||||
@param arrowColour the colour to use for the arrow
|
||||
*/
|
||||
ArrowButton (const String& buttonName,
|
||||
float arrowDirection,
|
||||
Colour arrowColour);
|
||||
|
||||
/** Destructor. */
|
||||
~ArrowButton() override;
|
||||
|
||||
/** @internal */
|
||||
void paintButton (Graphics&, bool, bool) override;
|
||||
|
||||
private:
|
||||
Colour colour;
|
||||
Path path;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ArrowButton)
|
||||
};
|
||||
|
||||
} // namespace juce
|
792
deps/juce/modules/juce_gui_basics/buttons/juce_Button.cpp
vendored
Normal file
792
deps/juce/modules/juce_gui_basics/buttons/juce_Button.cpp
vendored
Normal file
@ -0,0 +1,792 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
struct Button::CallbackHelper : public Timer,
|
||||
public ApplicationCommandManagerListener,
|
||||
public Value::Listener,
|
||||
public KeyListener
|
||||
{
|
||||
CallbackHelper (Button& b) : button (b) {}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
button.repeatTimerCallback();
|
||||
}
|
||||
|
||||
bool keyStateChanged (bool, Component*) override
|
||||
{
|
||||
return button.keyStateChangedCallback();
|
||||
}
|
||||
|
||||
void valueChanged (Value& value) override
|
||||
{
|
||||
if (value.refersToSameSourceAs (button.isOn))
|
||||
button.setToggleState (button.isOn.getValue(), dontSendNotification, sendNotification);
|
||||
}
|
||||
|
||||
bool keyPressed (const KeyPress&, Component*) override
|
||||
{
|
||||
// returning true will avoid forwarding events for keys that we're using as shortcuts
|
||||
return button.isShortcutPressed();
|
||||
}
|
||||
|
||||
void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info) override
|
||||
{
|
||||
if (info.commandID == button.commandID
|
||||
&& (info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) == 0)
|
||||
button.flashButtonState();
|
||||
}
|
||||
|
||||
void applicationCommandListChanged() override
|
||||
{
|
||||
button.applicationCommandListChangeCallback();
|
||||
}
|
||||
|
||||
Button& button;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallbackHelper)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
Button::Button (const String& name) : Component (name), text (name)
|
||||
{
|
||||
callbackHelper.reset (new CallbackHelper (*this));
|
||||
|
||||
setWantsKeyboardFocus (true);
|
||||
isOn.addListener (callbackHelper.get());
|
||||
}
|
||||
|
||||
Button::~Button()
|
||||
{
|
||||
clearShortcuts();
|
||||
|
||||
if (commandManagerToUse != nullptr)
|
||||
commandManagerToUse->removeListener (callbackHelper.get());
|
||||
|
||||
isOn.removeListener (callbackHelper.get());
|
||||
callbackHelper.reset();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Button::setButtonText (const String& newText)
|
||||
{
|
||||
if (text != newText)
|
||||
{
|
||||
text = newText;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
void Button::setTooltip (const String& newTooltip)
|
||||
{
|
||||
SettableTooltipClient::setTooltip (newTooltip);
|
||||
generateTooltip = false;
|
||||
}
|
||||
|
||||
void Button::updateAutomaticTooltip (const ApplicationCommandInfo& info)
|
||||
{
|
||||
if (generateTooltip && commandManagerToUse != nullptr)
|
||||
{
|
||||
auto tt = info.description.isNotEmpty() ? info.description
|
||||
: info.shortName;
|
||||
|
||||
for (auto& kp : commandManagerToUse->getKeyMappings()->getKeyPressesAssignedToCommand (commandID))
|
||||
{
|
||||
auto key = kp.getTextDescription();
|
||||
|
||||
tt << " [";
|
||||
|
||||
if (key.length() == 1)
|
||||
tt << TRANS("shortcut") << ": '" << key << "']";
|
||||
else
|
||||
tt << key << ']';
|
||||
}
|
||||
|
||||
SettableTooltipClient::setTooltip (tt);
|
||||
}
|
||||
}
|
||||
|
||||
void Button::setConnectedEdges (int newFlags)
|
||||
{
|
||||
if (connectedEdgeFlags != newFlags)
|
||||
{
|
||||
connectedEdgeFlags = newFlags;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Button::setToggleState (bool shouldBeOn, NotificationType notification)
|
||||
{
|
||||
setToggleState (shouldBeOn, notification, notification);
|
||||
}
|
||||
|
||||
void Button::setToggleState (bool shouldBeOn, NotificationType clickNotification, NotificationType stateNotification)
|
||||
{
|
||||
if (shouldBeOn != lastToggleState)
|
||||
{
|
||||
WeakReference<Component> deletionWatcher (this);
|
||||
|
||||
if (shouldBeOn)
|
||||
{
|
||||
turnOffOtherButtonsInGroup (clickNotification, stateNotification);
|
||||
|
||||
if (deletionWatcher == nullptr)
|
||||
return;
|
||||
}
|
||||
|
||||
// This test is done so that if the value is void rather than explicitly set to
|
||||
// false, the value won't be changed unless the required value is true.
|
||||
if (getToggleState() != shouldBeOn)
|
||||
{
|
||||
isOn = shouldBeOn;
|
||||
|
||||
if (deletionWatcher == nullptr)
|
||||
return;
|
||||
}
|
||||
|
||||
lastToggleState = shouldBeOn;
|
||||
repaint();
|
||||
|
||||
if (clickNotification != dontSendNotification)
|
||||
{
|
||||
// async callbacks aren't possible here
|
||||
jassert (clickNotification != sendNotificationAsync);
|
||||
|
||||
sendClickMessage (ModifierKeys::currentModifiers);
|
||||
|
||||
if (deletionWatcher == nullptr)
|
||||
return;
|
||||
}
|
||||
|
||||
if (stateNotification != dontSendNotification)
|
||||
sendStateMessage();
|
||||
else
|
||||
buttonStateChanged();
|
||||
|
||||
if (auto* handler = getAccessibilityHandler())
|
||||
handler->notifyAccessibilityEvent (AccessibilityEvent::valueChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void Button::setToggleState (bool shouldBeOn, bool sendChange)
|
||||
{
|
||||
setToggleState (shouldBeOn, sendChange ? sendNotification : dontSendNotification);
|
||||
}
|
||||
|
||||
void Button::setClickingTogglesState (bool shouldToggle) noexcept
|
||||
{
|
||||
clickTogglesState = shouldToggle;
|
||||
|
||||
// if you've got clickTogglesState turned on, you shouldn't also connect the button
|
||||
// up to be a command invoker. Instead, your command handler must flip the state of whatever
|
||||
// it is that this button represents, and the button will update its state to reflect this
|
||||
// in the applicationCommandListChanged() method.
|
||||
jassert (commandManagerToUse == nullptr || ! clickTogglesState);
|
||||
}
|
||||
|
||||
bool Button::getClickingTogglesState() const noexcept
|
||||
{
|
||||
return clickTogglesState;
|
||||
}
|
||||
|
||||
void Button::setRadioGroupId (int newGroupId, NotificationType notification)
|
||||
{
|
||||
if (radioGroupId != newGroupId)
|
||||
{
|
||||
radioGroupId = newGroupId;
|
||||
|
||||
if (lastToggleState)
|
||||
turnOffOtherButtonsInGroup (notification, notification);
|
||||
|
||||
invalidateAccessibilityHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void Button::turnOffOtherButtonsInGroup (NotificationType clickNotification, NotificationType stateNotification)
|
||||
{
|
||||
if (auto* p = getParentComponent())
|
||||
{
|
||||
if (radioGroupId != 0)
|
||||
{
|
||||
WeakReference<Component> deletionWatcher (this);
|
||||
|
||||
for (auto* c : p->getChildren())
|
||||
{
|
||||
if (c != this)
|
||||
{
|
||||
if (auto b = dynamic_cast<Button*> (c))
|
||||
{
|
||||
if (b->getRadioGroupId() == radioGroupId)
|
||||
{
|
||||
b->setToggleState (false, clickNotification, stateNotification);
|
||||
|
||||
if (deletionWatcher == nullptr)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Button::enablementChanged()
|
||||
{
|
||||
updateState();
|
||||
repaint();
|
||||
}
|
||||
|
||||
Button::ButtonState Button::updateState()
|
||||
{
|
||||
return updateState (isMouseOver (true), isMouseButtonDown());
|
||||
}
|
||||
|
||||
Button::ButtonState Button::updateState (bool over, bool down)
|
||||
{
|
||||
ButtonState newState = buttonNormal;
|
||||
|
||||
if (isEnabled() && isVisible() && ! isCurrentlyBlockedByAnotherModalComponent())
|
||||
{
|
||||
if ((down && (over || (triggerOnMouseDown && buttonState == buttonDown))) || isKeyDown)
|
||||
newState = buttonDown;
|
||||
else if (over)
|
||||
newState = buttonOver;
|
||||
}
|
||||
|
||||
setState (newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
void Button::setState (ButtonState newState)
|
||||
{
|
||||
if (buttonState != newState)
|
||||
{
|
||||
buttonState = newState;
|
||||
repaint();
|
||||
|
||||
if (buttonState == buttonDown)
|
||||
{
|
||||
buttonPressTime = Time::getApproximateMillisecondCounter();
|
||||
lastRepeatTime = 0;
|
||||
}
|
||||
|
||||
sendStateMessage();
|
||||
}
|
||||
}
|
||||
|
||||
bool Button::isDown() const noexcept { return buttonState == buttonDown; }
|
||||
bool Button::isOver() const noexcept { return buttonState != buttonNormal; }
|
||||
|
||||
void Button::buttonStateChanged() {}
|
||||
|
||||
uint32 Button::getMillisecondsSinceButtonDown() const noexcept
|
||||
{
|
||||
auto now = Time::getApproximateMillisecondCounter();
|
||||
return now > buttonPressTime ? now - buttonPressTime : 0;
|
||||
}
|
||||
|
||||
void Button::setTriggeredOnMouseDown (bool isTriggeredOnMouseDown) noexcept
|
||||
{
|
||||
triggerOnMouseDown = isTriggeredOnMouseDown;
|
||||
}
|
||||
|
||||
bool Button::getTriggeredOnMouseDown() const noexcept
|
||||
{
|
||||
return triggerOnMouseDown;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Button::clicked()
|
||||
{
|
||||
}
|
||||
|
||||
void Button::clicked (const ModifierKeys&)
|
||||
{
|
||||
clicked();
|
||||
}
|
||||
|
||||
enum { clickMessageId = 0x2f3f4f99 };
|
||||
|
||||
void Button::triggerClick()
|
||||
{
|
||||
postCommandMessage (clickMessageId);
|
||||
}
|
||||
|
||||
void Button::internalClickCallback (const ModifierKeys& modifiers)
|
||||
{
|
||||
if (clickTogglesState)
|
||||
{
|
||||
const bool shouldBeOn = (radioGroupId != 0 || ! lastToggleState);
|
||||
|
||||
if (shouldBeOn != getToggleState())
|
||||
{
|
||||
setToggleState (shouldBeOn, sendNotification);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sendClickMessage (modifiers);
|
||||
}
|
||||
|
||||
void Button::flashButtonState()
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
needsToRelease = true;
|
||||
setState (buttonDown);
|
||||
callbackHelper->startTimer (100);
|
||||
}
|
||||
}
|
||||
|
||||
void Button::handleCommandMessage (int commandId)
|
||||
{
|
||||
if (commandId == clickMessageId)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
flashButtonState();
|
||||
internalClickCallback (ModifierKeys::currentModifiers);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Component::handleCommandMessage (commandId);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Button::addListener (Listener* l) { buttonListeners.add (l); }
|
||||
void Button::removeListener (Listener* l) { buttonListeners.remove (l); }
|
||||
|
||||
void Button::sendClickMessage (const ModifierKeys& modifiers)
|
||||
{
|
||||
Component::BailOutChecker checker (this);
|
||||
|
||||
if (commandManagerToUse != nullptr && commandID != 0)
|
||||
{
|
||||
ApplicationCommandTarget::InvocationInfo info (commandID);
|
||||
info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromButton;
|
||||
info.originatingComponent = this;
|
||||
|
||||
commandManagerToUse->invoke (info, true);
|
||||
}
|
||||
|
||||
clicked (modifiers);
|
||||
|
||||
if (checker.shouldBailOut())
|
||||
return;
|
||||
|
||||
buttonListeners.callChecked (checker, [this] (Listener& l) { l.buttonClicked (this); });
|
||||
|
||||
if (checker.shouldBailOut())
|
||||
return;
|
||||
|
||||
if (onClick != nullptr)
|
||||
onClick();
|
||||
}
|
||||
|
||||
void Button::sendStateMessage()
|
||||
{
|
||||
Component::BailOutChecker checker (this);
|
||||
|
||||
buttonStateChanged();
|
||||
|
||||
if (checker.shouldBailOut())
|
||||
return;
|
||||
|
||||
buttonListeners.callChecked (checker, [this] (Listener& l) { l.buttonStateChanged (this); });
|
||||
|
||||
if (checker.shouldBailOut())
|
||||
return;
|
||||
|
||||
if (onStateChange != nullptr)
|
||||
onStateChange();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Button::paint (Graphics& g)
|
||||
{
|
||||
if (needsToRelease && isEnabled())
|
||||
{
|
||||
needsToRelease = false;
|
||||
needsRepainting = true;
|
||||
}
|
||||
|
||||
paintButton (g, isOver(), isDown());
|
||||
lastStatePainted = buttonState;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Button::mouseEnter (const MouseEvent&) { updateState (true, false); }
|
||||
void Button::mouseExit (const MouseEvent&) { updateState (false, false); }
|
||||
|
||||
bool Button::isInDragToScrollViewport() const noexcept
|
||||
{
|
||||
if (auto* vp = findParentComponentOfClass<Viewport>())
|
||||
return vp->isScrollOnDragEnabled() && (vp->canScrollVertically() || vp->canScrollHorizontally());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Button::mouseDown (const MouseEvent& e)
|
||||
{
|
||||
isInDraggableViewport = isInDragToScrollViewport();
|
||||
isDraggingToScroll = false;
|
||||
updateState (true, true);
|
||||
|
||||
if (isDown())
|
||||
{
|
||||
if (autoRepeatDelay >= 0)
|
||||
callbackHelper->startTimer (autoRepeatDelay);
|
||||
|
||||
if (triggerOnMouseDown)
|
||||
internalClickCallback (e.mods);
|
||||
}
|
||||
}
|
||||
|
||||
void Button::mouseUp (const MouseEvent& e)
|
||||
{
|
||||
const auto wasDown = isDown();
|
||||
const auto wasOver = isOver();
|
||||
updateState (isMouseSourceOver (e), false);
|
||||
|
||||
if (wasDown && wasOver && ! triggerOnMouseDown && ! isDraggingToScroll)
|
||||
{
|
||||
if (lastStatePainted != buttonDown)
|
||||
flashButtonState();
|
||||
|
||||
WeakReference<Component> deletionWatcher (this);
|
||||
|
||||
internalClickCallback (e.mods);
|
||||
|
||||
if (deletionWatcher != nullptr)
|
||||
updateState (isMouseSourceOver (e), false);
|
||||
}
|
||||
}
|
||||
|
||||
void Button::mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
auto oldState = buttonState;
|
||||
updateState (isMouseSourceOver (e), true);
|
||||
|
||||
if (autoRepeatDelay >= 0 && buttonState != oldState && isDown())
|
||||
callbackHelper->startTimer (autoRepeatSpeed);
|
||||
|
||||
if (isInDraggableViewport && ! isDraggingToScroll)
|
||||
if (auto* vp = findParentComponentOfClass<Viewport>())
|
||||
isDraggingToScroll = vp->isCurrentlyScrollingOnDrag();
|
||||
}
|
||||
|
||||
bool Button::isMouseSourceOver (const MouseEvent& e)
|
||||
{
|
||||
if (e.source.isTouch() || e.source.isPen())
|
||||
return getLocalBounds().toFloat().contains (e.position);
|
||||
|
||||
return isMouseOver();
|
||||
}
|
||||
|
||||
void Button::focusGained (FocusChangeType)
|
||||
{
|
||||
updateState();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void Button::focusLost (FocusChangeType)
|
||||
{
|
||||
updateState();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void Button::visibilityChanged()
|
||||
{
|
||||
needsToRelease = false;
|
||||
updateState();
|
||||
}
|
||||
|
||||
void Button::parentHierarchyChanged()
|
||||
{
|
||||
auto* newKeySource = shortcuts.isEmpty() ? nullptr : getTopLevelComponent();
|
||||
|
||||
if (newKeySource != keySource.get())
|
||||
{
|
||||
if (keySource != nullptr)
|
||||
keySource->removeKeyListener (callbackHelper.get());
|
||||
|
||||
keySource = newKeySource;
|
||||
|
||||
if (keySource != nullptr)
|
||||
keySource->addKeyListener (callbackHelper.get());
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Button::setCommandToTrigger (ApplicationCommandManager* newCommandManager,
|
||||
CommandID newCommandID, bool generateTip)
|
||||
{
|
||||
commandID = newCommandID;
|
||||
generateTooltip = generateTip;
|
||||
|
||||
if (commandManagerToUse != newCommandManager)
|
||||
{
|
||||
if (commandManagerToUse != nullptr)
|
||||
commandManagerToUse->removeListener (callbackHelper.get());
|
||||
|
||||
commandManagerToUse = newCommandManager;
|
||||
|
||||
if (commandManagerToUse != nullptr)
|
||||
commandManagerToUse->addListener (callbackHelper.get());
|
||||
|
||||
// if you've got clickTogglesState turned on, you shouldn't also connect the button
|
||||
// up to be a command invoker. Instead, your command handler must flip the state of whatever
|
||||
// it is that this button represents, and the button will update its state to reflect this
|
||||
// in the applicationCommandListChanged() method.
|
||||
jassert (commandManagerToUse == nullptr || ! clickTogglesState);
|
||||
}
|
||||
|
||||
if (commandManagerToUse != nullptr)
|
||||
applicationCommandListChangeCallback();
|
||||
else
|
||||
setEnabled (true);
|
||||
}
|
||||
|
||||
void Button::applicationCommandListChangeCallback()
|
||||
{
|
||||
if (commandManagerToUse != nullptr)
|
||||
{
|
||||
ApplicationCommandInfo info (0);
|
||||
|
||||
if (commandManagerToUse->getTargetForCommand (commandID, info) != nullptr)
|
||||
{
|
||||
updateAutomaticTooltip (info);
|
||||
setEnabled ((info.flags & ApplicationCommandInfo::isDisabled) == 0);
|
||||
setToggleState ((info.flags & ApplicationCommandInfo::isTicked) != 0, dontSendNotification);
|
||||
}
|
||||
else
|
||||
{
|
||||
setEnabled (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Button::addShortcut (const KeyPress& key)
|
||||
{
|
||||
if (key.isValid())
|
||||
{
|
||||
jassert (! isRegisteredForShortcut (key)); // already registered!
|
||||
|
||||
shortcuts.add (key);
|
||||
parentHierarchyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Button::clearShortcuts()
|
||||
{
|
||||
shortcuts.clear();
|
||||
parentHierarchyChanged();
|
||||
}
|
||||
|
||||
bool Button::isShortcutPressed() const
|
||||
{
|
||||
if (isShowing() && ! isCurrentlyBlockedByAnotherModalComponent())
|
||||
for (auto& s : shortcuts)
|
||||
if (s.isCurrentlyDown())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Button::isRegisteredForShortcut (const KeyPress& key) const
|
||||
{
|
||||
for (auto& s : shortcuts)
|
||||
if (key == s)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Button::keyStateChangedCallback()
|
||||
{
|
||||
if (! isEnabled())
|
||||
return false;
|
||||
|
||||
const bool wasDown = isKeyDown;
|
||||
isKeyDown = isShortcutPressed();
|
||||
|
||||
if (autoRepeatDelay >= 0 && (isKeyDown && ! wasDown))
|
||||
callbackHelper->startTimer (autoRepeatDelay);
|
||||
|
||||
updateState();
|
||||
|
||||
if (isEnabled() && wasDown && ! isKeyDown)
|
||||
{
|
||||
internalClickCallback (ModifierKeys::currentModifiers);
|
||||
|
||||
// (return immediately - this button may now have been deleted)
|
||||
return true;
|
||||
}
|
||||
|
||||
return wasDown || isKeyDown;
|
||||
}
|
||||
|
||||
bool Button::keyPressed (const KeyPress& key)
|
||||
{
|
||||
if (isEnabled() && key.isKeyCode (KeyPress::returnKey))
|
||||
{
|
||||
triggerClick();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Button::setRepeatSpeed (int initialDelayMillisecs,
|
||||
int repeatMillisecs,
|
||||
int minimumDelayInMillisecs) noexcept
|
||||
{
|
||||
autoRepeatDelay = initialDelayMillisecs;
|
||||
autoRepeatSpeed = repeatMillisecs;
|
||||
autoRepeatMinimumDelay = jmin (autoRepeatSpeed, minimumDelayInMillisecs);
|
||||
}
|
||||
|
||||
void Button::repeatTimerCallback()
|
||||
{
|
||||
if (needsRepainting)
|
||||
{
|
||||
callbackHelper->stopTimer();
|
||||
updateState();
|
||||
needsRepainting = false;
|
||||
}
|
||||
else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState() == buttonDown)))
|
||||
{
|
||||
auto repeatSpeed = autoRepeatSpeed;
|
||||
|
||||
if (autoRepeatMinimumDelay >= 0)
|
||||
{
|
||||
auto timeHeldDown = jmin (1.0, getMillisecondsSinceButtonDown() / 4000.0);
|
||||
timeHeldDown *= timeHeldDown;
|
||||
|
||||
repeatSpeed = repeatSpeed + (int) (timeHeldDown * (autoRepeatMinimumDelay - repeatSpeed));
|
||||
}
|
||||
|
||||
repeatSpeed = jmax (1, repeatSpeed);
|
||||
|
||||
auto now = Time::getMillisecondCounter();
|
||||
|
||||
// if we've been blocked from repeating often enough, speed up the repeat timer to compensate..
|
||||
if (lastRepeatTime != 0 && (int) (now - lastRepeatTime) > repeatSpeed * 2)
|
||||
repeatSpeed = jmax (1, repeatSpeed / 2);
|
||||
|
||||
lastRepeatTime = now;
|
||||
callbackHelper->startTimer (repeatSpeed);
|
||||
|
||||
internalClickCallback (ModifierKeys::currentModifiers);
|
||||
}
|
||||
else if (! needsToRelease)
|
||||
{
|
||||
callbackHelper->stopTimer();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class ButtonAccessibilityHandler : public AccessibilityHandler
|
||||
{
|
||||
public:
|
||||
explicit ButtonAccessibilityHandler (Button& buttonToWrap, AccessibilityRole roleIn)
|
||||
: AccessibilityHandler (buttonToWrap,
|
||||
isRadioButton (buttonToWrap) ? AccessibilityRole::radioButton : buttonToWrap.getClickingTogglesState() ? AccessibilityRole::toggleButton : roleIn,
|
||||
getAccessibilityActions (buttonToWrap, roleIn)),
|
||||
button (buttonToWrap)
|
||||
{
|
||||
}
|
||||
|
||||
AccessibleState getCurrentState() const override
|
||||
{
|
||||
auto state = AccessibilityHandler::getCurrentState();
|
||||
|
||||
if (isToggleButton (getRole()) || isRadioButton (button) || button.getClickingTogglesState())
|
||||
{
|
||||
state = state.withCheckable();
|
||||
|
||||
if (button.getToggleState())
|
||||
state = state.withChecked();
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
String getTitle() const override
|
||||
{
|
||||
auto title = AccessibilityHandler::getTitle();
|
||||
|
||||
if (title.isEmpty())
|
||||
return button.getButtonText();
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
String getHelp() const override { return button.getTooltip(); }
|
||||
|
||||
private:
|
||||
static bool isToggleButton (AccessibilityRole role) noexcept
|
||||
{
|
||||
return role == AccessibilityRole::toggleButton;
|
||||
}
|
||||
|
||||
static bool isRadioButton (const Button& button) noexcept
|
||||
{
|
||||
return button.getRadioGroupId() != 0;
|
||||
}
|
||||
|
||||
static AccessibilityActions getAccessibilityActions (Button& button, AccessibilityRole role)
|
||||
{
|
||||
auto actions = AccessibilityActions().addAction (AccessibilityActionType::press,
|
||||
[&button] { button.triggerClick(); });
|
||||
|
||||
if (isToggleButton (role) || button.getClickingTogglesState())
|
||||
actions = actions.addAction (AccessibilityActionType::toggle,
|
||||
[&button] { button.setToggleState (! button.getToggleState(), sendNotification); });
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
Button& button;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonAccessibilityHandler)
|
||||
};
|
||||
|
||||
std::unique_ptr<AccessibilityHandler> Button::createAccessibilityHandler()
|
||||
{
|
||||
return std::make_unique<ButtonAccessibilityHandler> (*this, AccessibilityRole::button);
|
||||
}
|
||||
|
||||
} // namespace juce
|
528
deps/juce/modules/juce_gui_basics/buttons/juce_Button.h
vendored
Normal file
528
deps/juce/modules/juce_gui_basics/buttons/juce_Button.h
vendored
Normal file
@ -0,0 +1,528 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A base class for buttons.
|
||||
|
||||
This contains all the logic for button behaviours such as enabling/disabling,
|
||||
responding to shortcut keystrokes, auto-repeating when held down, toggle-buttons
|
||||
and radio groups, etc.
|
||||
|
||||
@see TextButton, DrawableButton, ToggleButton
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API Button : public Component,
|
||||
public SettableTooltipClient
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates a button.
|
||||
|
||||
@param buttonName the text to put in the button (the component's name is also
|
||||
initially set to this string, but these can be changed later
|
||||
using the setName() and setButtonText() methods)
|
||||
*/
|
||||
explicit Button (const String& buttonName);
|
||||
|
||||
public:
|
||||
/** Destructor. */
|
||||
~Button() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the button's text.
|
||||
@see getButtonText
|
||||
*/
|
||||
void setButtonText (const String& newText);
|
||||
|
||||
/** Returns the text displayed in the button.
|
||||
@see setButtonText
|
||||
*/
|
||||
const String& getButtonText() const { return text; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if the button is currently being held down.
|
||||
@see isOver
|
||||
*/
|
||||
bool isDown() const noexcept;
|
||||
|
||||
/** Returns true if the mouse is currently over the button.
|
||||
This will be also be true if the button is being held down.
|
||||
@see isDown
|
||||
*/
|
||||
bool isOver() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** A button has an on/off state associated with it, and this changes that.
|
||||
|
||||
By default buttons are 'off' and for simple buttons that you click to perform
|
||||
an action you won't change this. Toggle buttons, however will want to
|
||||
change their state when turned on or off.
|
||||
|
||||
@param shouldBeOn whether to set the button's toggle state to be on or
|
||||
off. If it's a member of a button group, this will
|
||||
always try to turn it on, and to turn off any other
|
||||
buttons in the group
|
||||
@param notification determines the behaviour if the value changes - this
|
||||
can invoke a synchronous call to clicked(), but
|
||||
sendNotificationAsync is not supported
|
||||
@see getToggleState, setRadioGroupId
|
||||
*/
|
||||
void setToggleState (bool shouldBeOn, NotificationType notification);
|
||||
|
||||
/** Returns true if the button is 'on'.
|
||||
|
||||
By default buttons are 'off' and for simple buttons that you click to perform
|
||||
an action you won't change this. Toggle buttons, however will want to
|
||||
change their state when turned on or off.
|
||||
|
||||
@see setToggleState
|
||||
*/
|
||||
bool getToggleState() const noexcept { return isOn.getValue(); }
|
||||
|
||||
/** Returns the Value object that represents the button's toggle state.
|
||||
|
||||
You can use this Value object to connect the button's state to external values or setters,
|
||||
either by taking a copy of the Value, or by using Value::referTo() to make it point to
|
||||
your own Value object.
|
||||
|
||||
@see getToggleState, Value
|
||||
*/
|
||||
Value& getToggleStateValue() noexcept { return isOn; }
|
||||
|
||||
/** This tells the button to automatically flip the toggle state when
|
||||
the button is clicked.
|
||||
|
||||
If set to true, then before the clicked() callback occurs, the toggle-state
|
||||
of the button is flipped.
|
||||
*/
|
||||
void setClickingTogglesState (bool shouldAutoToggleOnClick) noexcept;
|
||||
|
||||
/** Returns true if this button is set to be an automatic toggle-button.
|
||||
This returns the last value that was passed to setClickingTogglesState().
|
||||
*/
|
||||
bool getClickingTogglesState() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Enables the button to act as a member of a mutually-exclusive group
|
||||
of 'radio buttons'.
|
||||
|
||||
If the group ID is set to a non-zero number, then this button will
|
||||
act as part of a group of buttons with the same ID, only one of
|
||||
which can be 'on' at the same time. Note that when it's part of
|
||||
a group, clicking a toggle-button that's 'on' won't turn it off.
|
||||
|
||||
To find other buttons with the same ID, this button will search through
|
||||
its sibling components for ToggleButtons, so all the buttons for a
|
||||
particular group must be placed inside the same parent component.
|
||||
|
||||
Set the group ID back to zero if you want it to act as a normal toggle
|
||||
button again.
|
||||
|
||||
The notification argument lets you specify how other buttons should react
|
||||
to being turned on or off in response to this call.
|
||||
|
||||
@see getRadioGroupId
|
||||
*/
|
||||
void setRadioGroupId (int newGroupId, NotificationType notification = sendNotification);
|
||||
|
||||
/** Returns the ID of the group to which this button belongs.
|
||||
(See setRadioGroupId() for an explanation of this).
|
||||
*/
|
||||
int getRadioGroupId() const noexcept { return radioGroupId; }
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Used to receive callbacks when a button is clicked.
|
||||
|
||||
@see Button::addListener, Button::removeListener
|
||||
*/
|
||||
class JUCE_API Listener
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~Listener() = default;
|
||||
|
||||
/** Called when the button is clicked. */
|
||||
virtual void buttonClicked (Button*) = 0;
|
||||
|
||||
/** Called when the button's state changes. */
|
||||
virtual void buttonStateChanged (Button*) {}
|
||||
};
|
||||
|
||||
/** Registers a listener to receive events when this button's state changes.
|
||||
If the listener is already registered, this will not register it again.
|
||||
@see removeListener
|
||||
*/
|
||||
void addListener (Listener* newListener);
|
||||
|
||||
/** Removes a previously-registered button listener
|
||||
@see addListener
|
||||
*/
|
||||
void removeListener (Listener* listener);
|
||||
|
||||
//==============================================================================
|
||||
/** You can assign a lambda to this callback object to have it called when the button is clicked. */
|
||||
std::function<void()> onClick;
|
||||
|
||||
/** You can assign a lambda to this callback object to have it called when the button's state changes. */
|
||||
std::function<void()> onStateChange;
|
||||
|
||||
//==============================================================================
|
||||
/** Causes the button to act as if it's been clicked.
|
||||
|
||||
This will asynchronously make the button draw itself going down and up, and
|
||||
will then call back the clicked() method as if mouse was clicked on it.
|
||||
|
||||
@see clicked
|
||||
*/
|
||||
virtual void triggerClick();
|
||||
|
||||
//==============================================================================
|
||||
/** Sets a command ID for this button to automatically invoke when it's clicked.
|
||||
|
||||
When the button is pressed, it will use the given manager to trigger the
|
||||
command ID.
|
||||
|
||||
Obviously be careful that the ApplicationCommandManager doesn't get deleted
|
||||
before this button is. To disable the command triggering, call this method and
|
||||
pass nullptr as the command manager.
|
||||
|
||||
If generateTooltip is true, then the button's tooltip will be automatically
|
||||
generated based on the name of this command and its current shortcut key.
|
||||
|
||||
@see addShortcut, getCommandID
|
||||
*/
|
||||
void setCommandToTrigger (ApplicationCommandManager* commandManagerToUse,
|
||||
CommandID commandID,
|
||||
bool generateTooltip);
|
||||
|
||||
/** Returns the command ID that was set by setCommandToTrigger(). */
|
||||
CommandID getCommandID() const noexcept { return commandID; }
|
||||
|
||||
//==============================================================================
|
||||
/** Assigns a shortcut key to trigger the button.
|
||||
|
||||
The button registers itself with its top-level parent component for keypresses.
|
||||
|
||||
Note that a different way of linking buttons to keypresses is by using the
|
||||
setCommandToTrigger() method to invoke a command.
|
||||
|
||||
@see clearShortcuts
|
||||
*/
|
||||
void addShortcut (const KeyPress&);
|
||||
|
||||
/** Removes all key shortcuts that had been set for this button.
|
||||
@see addShortcut
|
||||
*/
|
||||
void clearShortcuts();
|
||||
|
||||
/** Returns true if the given keypress is a shortcut for this button.
|
||||
@see addShortcut
|
||||
*/
|
||||
bool isRegisteredForShortcut (const KeyPress&) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Sets an auto-repeat speed for the button when it is held down.
|
||||
|
||||
(Auto-repeat is disabled by default).
|
||||
|
||||
@param initialDelayInMillisecs how long to wait after the mouse is pressed before
|
||||
triggering the next click. If this is zero, auto-repeat
|
||||
is disabled
|
||||
@param repeatDelayInMillisecs the frequently subsequent repeated clicks should be
|
||||
triggered
|
||||
@param minimumDelayInMillisecs if this is greater than 0, the auto-repeat speed will
|
||||
get faster, the longer the button is held down, up to the
|
||||
minimum interval specified here
|
||||
*/
|
||||
void setRepeatSpeed (int initialDelayInMillisecs,
|
||||
int repeatDelayInMillisecs,
|
||||
int minimumDelayInMillisecs = -1) noexcept;
|
||||
|
||||
/** Sets whether the button click should happen when the mouse is pressed or released.
|
||||
|
||||
By default the button is only considered to have been clicked when the mouse is
|
||||
released, but setting this to true will make it call the clicked() method as soon
|
||||
as the button is pressed.
|
||||
|
||||
This is useful if the button is being used to show a pop-up menu, as it allows
|
||||
the click to be used as a drag onto the menu.
|
||||
*/
|
||||
void setTriggeredOnMouseDown (bool isTriggeredOnMouseDown) noexcept;
|
||||
|
||||
/** Returns whether the button click happens when the mouse is pressed or released.
|
||||
@see setTriggeredOnMouseDown
|
||||
*/
|
||||
bool getTriggeredOnMouseDown() const noexcept;
|
||||
|
||||
/** Returns the number of milliseconds since the last time the button
|
||||
went into the 'down' state.
|
||||
*/
|
||||
uint32 getMillisecondsSinceButtonDown() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the tooltip for this button.
|
||||
@see TooltipClient, TooltipWindow
|
||||
*/
|
||||
void setTooltip (const String& newTooltip) override;
|
||||
|
||||
//==============================================================================
|
||||
/** A combination of these flags are used by setConnectedEdges(). */
|
||||
enum ConnectedEdgeFlags
|
||||
{
|
||||
ConnectedOnLeft = 1,
|
||||
ConnectedOnRight = 2,
|
||||
ConnectedOnTop = 4,
|
||||
ConnectedOnBottom = 8
|
||||
};
|
||||
|
||||
/** Hints about which edges of the button might be connected to adjoining buttons.
|
||||
|
||||
The value passed in is a bitwise combination of any of the values in the
|
||||
ConnectedEdgeFlags enum.
|
||||
|
||||
E.g. if you are placing two buttons adjacent to each other, you could use this to
|
||||
indicate which edges are touching, and the LookAndFeel might choose to drawn them
|
||||
without rounded corners on the edges that connect. It's only a hint, so the
|
||||
LookAndFeel can choose to ignore it if it's not relevant for this type of
|
||||
button.
|
||||
*/
|
||||
void setConnectedEdges (int connectedEdgeFlags);
|
||||
|
||||
/** Returns the set of flags passed into setConnectedEdges(). */
|
||||
int getConnectedEdgeFlags() const noexcept { return connectedEdgeFlags; }
|
||||
|
||||
/** Indicates whether the button adjoins another one on its left edge.
|
||||
@see setConnectedEdges
|
||||
*/
|
||||
bool isConnectedOnLeft() const noexcept { return (connectedEdgeFlags & ConnectedOnLeft) != 0; }
|
||||
|
||||
/** Indicates whether the button adjoins another one on its right edge.
|
||||
@see setConnectedEdges
|
||||
*/
|
||||
bool isConnectedOnRight() const noexcept { return (connectedEdgeFlags & ConnectedOnRight) != 0; }
|
||||
|
||||
/** Indicates whether the button adjoins another one on its top edge.
|
||||
@see setConnectedEdges
|
||||
*/
|
||||
bool isConnectedOnTop() const noexcept { return (connectedEdgeFlags & ConnectedOnTop) != 0; }
|
||||
|
||||
/** Indicates whether the button adjoins another one on its bottom edge.
|
||||
@see setConnectedEdges
|
||||
*/
|
||||
bool isConnectedOnBottom() const noexcept { return (connectedEdgeFlags & ConnectedOnBottom) != 0; }
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Used by setState(). */
|
||||
enum ButtonState
|
||||
{
|
||||
buttonNormal,
|
||||
buttonOver,
|
||||
buttonDown
|
||||
};
|
||||
|
||||
/** Can be used to force the button into a particular state.
|
||||
|
||||
This only changes the button's appearance, it won't trigger a click, or stop any mouse-clicks
|
||||
from happening.
|
||||
|
||||
The state that you set here will only last until it is automatically changed when the mouse
|
||||
enters or exits the button, or the mouse-button is pressed or released.
|
||||
*/
|
||||
void setState (ButtonState newState);
|
||||
|
||||
/** Returns the button's current over/down/up state. */
|
||||
ButtonState getState() const noexcept { return buttonState; }
|
||||
|
||||
//==============================================================================
|
||||
/** This abstract base class is implemented by LookAndFeel classes to provide
|
||||
button-drawing functionality.
|
||||
*/
|
||||
struct JUCE_API LookAndFeelMethods
|
||||
{
|
||||
virtual ~LookAndFeelMethods() = default;
|
||||
|
||||
virtual void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour,
|
||||
bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) = 0;
|
||||
|
||||
virtual Font getTextButtonFont (TextButton&, int buttonHeight) = 0;
|
||||
virtual int getTextButtonWidthToFitText (TextButton&, int buttonHeight) = 0;
|
||||
|
||||
/** Draws the text for a TextButton. */
|
||||
virtual void drawButtonText (Graphics&, TextButton&,
|
||||
bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) = 0;
|
||||
|
||||
/** Draws the contents of a standard ToggleButton. */
|
||||
virtual void drawToggleButton (Graphics&, ToggleButton&,
|
||||
bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) = 0;
|
||||
|
||||
virtual void changeToggleButtonWidthToFitText (ToggleButton&) = 0;
|
||||
|
||||
virtual void drawTickBox (Graphics&, Component&, float x, float y, float w, float h,
|
||||
bool ticked, bool isEnabled,
|
||||
bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) = 0;
|
||||
|
||||
virtual void drawDrawableButton (Graphics&, DrawableButton&,
|
||||
bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
#ifndef DOXYGEN
|
||||
[[deprecated ("This method's parameters have changed.")]]
|
||||
void setToggleState (bool, bool);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** This method is called when the button has been clicked.
|
||||
|
||||
Subclasses can override this to perform whatever actions they need to do.
|
||||
In general, you wouldn't use this method to receive clicks, but should get your callbacks
|
||||
by attaching a std::function to the onClick callback, or adding a Button::Listener.
|
||||
@see triggerClick, onClick
|
||||
*/
|
||||
virtual void clicked();
|
||||
|
||||
/** This method is called when the button has been clicked.
|
||||
|
||||
By default it just calls clicked(), but you might want to override it to handle
|
||||
things like clicking when a modifier key is pressed, etc.
|
||||
|
||||
@see ModifierKeys
|
||||
*/
|
||||
virtual void clicked (const ModifierKeys& modifiers);
|
||||
|
||||
/** Subclasses should override this to actually paint the button's contents.
|
||||
|
||||
It's better to use this than the paint method, because it gives you information
|
||||
about the over/down state of the button.
|
||||
|
||||
@param g the graphics context to use
|
||||
@param shouldDrawButtonAsHighlighted true if the button is either in the 'over' or 'down' state
|
||||
@param shouldDrawButtonAsDown true if the button should be drawn in the 'down' position
|
||||
*/
|
||||
virtual void paintButton (Graphics& g,
|
||||
bool shouldDrawButtonAsHighlighted,
|
||||
bool shouldDrawButtonAsDown) = 0;
|
||||
|
||||
/** Called when the button's up/down/over state changes.
|
||||
|
||||
Subclasses can override this if they need to do something special when the button
|
||||
goes up or down.
|
||||
|
||||
@see isDown, isOver
|
||||
*/
|
||||
virtual void buttonStateChanged();
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
virtual void internalClickCallback (const ModifierKeys&);
|
||||
/** @internal */
|
||||
void handleCommandMessage (int commandId) override;
|
||||
/** @internal */
|
||||
void mouseEnter (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void mouseExit (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void mouseDown (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void mouseDrag (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
void mouseUp (const MouseEvent&) override;
|
||||
/** @internal */
|
||||
bool keyPressed (const KeyPress&) override;
|
||||
/** @internal */
|
||||
using Component::keyStateChanged;
|
||||
/** @internal */
|
||||
void paint (Graphics&) override;
|
||||
/** @internal */
|
||||
void parentHierarchyChanged() override;
|
||||
/** @internal */
|
||||
void visibilityChanged() override;
|
||||
/** @internal */
|
||||
void focusGained (FocusChangeType) override;
|
||||
/** @internal */
|
||||
void focusLost (FocusChangeType) override;
|
||||
/** @internal */
|
||||
void enablementChanged() override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Array<KeyPress> shortcuts;
|
||||
WeakReference<Component> keySource;
|
||||
String text;
|
||||
ListenerList<Listener> buttonListeners;
|
||||
|
||||
struct CallbackHelper;
|
||||
std::unique_ptr<CallbackHelper> callbackHelper;
|
||||
uint32 buttonPressTime = 0, lastRepeatTime = 0;
|
||||
ApplicationCommandManager* commandManagerToUse = nullptr;
|
||||
int autoRepeatDelay = -1, autoRepeatSpeed = 0, autoRepeatMinimumDelay = -1;
|
||||
int radioGroupId = 0, connectedEdgeFlags = 0;
|
||||
CommandID commandID = {};
|
||||
ButtonState buttonState = buttonNormal, lastStatePainted = buttonNormal;
|
||||
|
||||
Value isOn;
|
||||
bool lastToggleState = false;
|
||||
bool clickTogglesState = false;
|
||||
bool needsToRelease = false;
|
||||
bool needsRepainting = false;
|
||||
bool isKeyDown = false;
|
||||
bool triggerOnMouseDown = false;
|
||||
bool generateTooltip = false;
|
||||
bool isInDraggableViewport = false ,isDraggingToScroll = false;
|
||||
|
||||
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
|
||||
|
||||
void repeatTimerCallback();
|
||||
bool keyStateChangedCallback();
|
||||
void applicationCommandListChangeCallback();
|
||||
void updateAutomaticTooltip (const ApplicationCommandInfo&);
|
||||
|
||||
ButtonState updateState();
|
||||
ButtonState updateState (bool isOver, bool isDown);
|
||||
bool isShortcutPressed() const;
|
||||
void turnOffOtherButtonsInGroup (NotificationType click, NotificationType state);
|
||||
|
||||
void flashButtonState();
|
||||
void sendClickMessage (const ModifierKeys&);
|
||||
void sendStateMessage();
|
||||
void setToggleState (bool shouldBeOn, NotificationType click, NotificationType state);
|
||||
|
||||
bool isMouseSourceOver (const MouseEvent& e);
|
||||
|
||||
bool isInDragToScrollViewport() const noexcept;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Button)
|
||||
};
|
||||
|
||||
|
||||
} // namespace juce
|
253
deps/juce/modules/juce_gui_basics/buttons/juce_DrawableButton.cpp
vendored
Normal file
253
deps/juce/modules/juce_gui_basics/buttons/juce_DrawableButton.cpp
vendored
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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<Drawable> 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<float> 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
|
200
deps/juce/modules/juce_gui_basics/buttons/juce_DrawableButton.h
vendored
Normal file
200
deps/juce/modules/juce_gui_basics/buttons/juce_DrawableButton.h
vendored
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A button that displays a Drawable.
|
||||
|
||||
Up to three Drawable objects can be given to this button, to represent the
|
||||
'normal', 'over' and 'down' states.
|
||||
|
||||
@see Button
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API DrawableButton : public Button
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
enum ButtonStyle
|
||||
{
|
||||
ImageFitted, /**< The button will just display the images, but will resize and centre them to fit inside it. */
|
||||
ImageRaw, /**< The button will just display the images in their normal size and position.
|
||||
This leaves it up to the caller to make sure the images are the correct size and position for the button. */
|
||||
ImageAboveTextLabel, /**< Draws the button as a text label across the bottom with the image resized and scaled to fit above it. */
|
||||
ImageOnButtonBackground, /**< Draws the button as a standard rounded-rectangle button with the image on top. The image will be resized
|
||||
to match the button's proportions.
|
||||
Note that if you use this style, the colour IDs that control the button colour are
|
||||
TextButton::buttonColourId and TextButton::buttonOnColourId. */
|
||||
ImageOnButtonBackgroundOriginalSize, /** Same as ImageOnButtonBackground, but keeps the original image size. */
|
||||
ImageStretched, /**< Fills the button with a stretched version of the image. */
|
||||
ImageBelowTextLabel, /**< Draws the button as a text label across the top with the image resized and scaled to fit below it. */
|
||||
ImageLeftOfTextLabel, /**< Draws the button as a text label on the right with the image resized and scaled to fit beside it. */
|
||||
ImageRightOfTextLabel /**< Draws the button as a text label on the left with the image resized and scaled to fit beside it. */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Creates a DrawableButton.
|
||||
|
||||
After creating one of these, use setImages() to specify the drawables to use.
|
||||
|
||||
@param buttonName the name to give the component
|
||||
@param buttonStyle the layout to use
|
||||
|
||||
@see ButtonStyle, setButtonStyle, setImages
|
||||
*/
|
||||
DrawableButton (const String& buttonName,
|
||||
ButtonStyle buttonStyle);
|
||||
|
||||
/** Destructor. */
|
||||
~DrawableButton() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Sets up the images to draw for the various button states.
|
||||
|
||||
The button will keep its own internal copies of these drawables.
|
||||
|
||||
@param normalImage the thing to draw for the button's 'normal' state. An internal copy
|
||||
will be made of the object passed-in if it is non-null.
|
||||
@param overImage the thing to draw for the button's 'over' state - if this is
|
||||
null, the button's normal image will be used when the mouse is
|
||||
over it. An internal copy will be made of the object passed-in
|
||||
if it is non-null.
|
||||
@param downImage the thing to draw for the button's 'down' state - if this is
|
||||
null, the 'over' image will be used instead (or the normal image
|
||||
as a last resort). An internal copy will be made of the object
|
||||
passed-in if it is non-null.
|
||||
@param disabledImage an image to draw when the button is disabled. If this is null,
|
||||
the normal image will be drawn with a reduced opacity instead.
|
||||
An internal copy will be made of the object passed-in if it is
|
||||
non-null.
|
||||
@param normalImageOn same as the normalImage, but this is used when the button's toggle
|
||||
state is 'on'. If this is nullptr, the normal image is used instead
|
||||
@param overImageOn same as the overImage, but this is used when the button's toggle
|
||||
state is 'on'. If this is nullptr, the normalImageOn is drawn instead
|
||||
@param downImageOn same as the downImage, but this is used when the button's toggle
|
||||
state is 'on'. If this is nullptr, the overImageOn is drawn instead
|
||||
@param disabledImageOn same as the disabledImage, but this is used when the button's toggle
|
||||
state is 'on'. If this is nullptr, the normal image will be drawn instead
|
||||
with a reduced opacity
|
||||
*/
|
||||
void setImages (const Drawable* normalImage,
|
||||
const Drawable* overImage = nullptr,
|
||||
const Drawable* downImage = nullptr,
|
||||
const Drawable* disabledImage = nullptr,
|
||||
const Drawable* normalImageOn = nullptr,
|
||||
const Drawable* overImageOn = nullptr,
|
||||
const Drawable* downImageOn = nullptr,
|
||||
const Drawable* disabledImageOn = nullptr);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the button's style.
|
||||
@see ButtonStyle
|
||||
*/
|
||||
void setButtonStyle (ButtonStyle newStyle);
|
||||
|
||||
/** Returns the current style. */
|
||||
ButtonStyle getStyle() const noexcept { return style; }
|
||||
|
||||
//==============================================================================
|
||||
/** Gives the button an optional amount of space around the edge of the drawable.
|
||||
By default there's a gap of about 3 pixels.
|
||||
*/
|
||||
void setEdgeIndent (int numPixelsIndent);
|
||||
|
||||
/** Returns the current edge indent size. */
|
||||
int getEdgeIndent() const noexcept { return edgeIndent; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the image that the button is currently displaying. */
|
||||
Drawable* getCurrentImage() const noexcept;
|
||||
|
||||
/** Returns the image that the button will use for its normal state. */
|
||||
Drawable* getNormalImage() const noexcept;
|
||||
/** Returns the image that the button will use when the mouse is over it. */
|
||||
Drawable* getOverImage() const noexcept;
|
||||
/** Returns the image that the button will use when the mouse is held down on it. */
|
||||
Drawable* getDownImage() const noexcept;
|
||||
|
||||
/** Can be overridden to specify a custom position for the image within the button. */
|
||||
virtual Rectangle<float> getImageBounds() const;
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the link.
|
||||
|
||||
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
|
||||
methods.
|
||||
|
||||
Note that when the ImageOnButtonBackground style is used, the colour IDs that control
|
||||
the button colour are TextButton::buttonColourId and TextButton::buttonOnColourId.
|
||||
|
||||
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
|
||||
*/
|
||||
enum ColourIds
|
||||
{
|
||||
textColourId = 0x1004010, /**< The colour to use for the button's text label. */
|
||||
textColourOnId = 0x1004013, /**< The colour to use for the button's text when the button's toggle state is "on". */
|
||||
|
||||
backgroundColourId = 0x1004011, /**< The colour used to fill the button's background (when
|
||||
the button is toggled 'off'). Note that if you use the
|
||||
ImageOnButtonBackground style, you should use TextButton::buttonColourId
|
||||
to change the button's colour. */
|
||||
backgroundOnColourId = 0x1004012, /**< The colour used to fill the button's background (when
|
||||
the button is toggled 'on'). Note that if you use the
|
||||
ImageOnButtonBackground style, you should use TextButton::buttonOnColourId
|
||||
to change the button's colour. */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void paintButton (Graphics&, bool, bool) override;
|
||||
/** @internal */
|
||||
void buttonStateChanged() override;
|
||||
/** @internal */
|
||||
void resized() override;
|
||||
/** @internal */
|
||||
void enablementChanged() override;
|
||||
/** @internal */
|
||||
void colourChanged() override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
bool shouldDrawButtonBackground() const { return style == ImageOnButtonBackground || style == ImageOnButtonBackgroundOriginalSize; }
|
||||
|
||||
//==============================================================================
|
||||
ButtonStyle style;
|
||||
std::unique_ptr<Drawable> normalImage, overImage, downImage, disabledImage,
|
||||
normalImageOn, overImageOn, downImageOn, disabledImageOn;
|
||||
Drawable* currentImage = nullptr;
|
||||
int edgeIndent = 3;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DrawableButton)
|
||||
};
|
||||
|
||||
} // namespace juce
|
124
deps/juce/modules/juce_gui_basics/buttons/juce_HyperlinkButton.cpp
vendored
Normal file
124
deps/juce/modules/juce_gui_basics/buttons/juce_HyperlinkButton.cpp
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
HyperlinkButton::HyperlinkButton (const String& linkText,
|
||||
const URL& linkURL)
|
||||
: Button (linkText),
|
||||
url (linkURL),
|
||||
font (14.0f, Font::underlined),
|
||||
resizeFont (true),
|
||||
justification (Justification::centred)
|
||||
{
|
||||
setMouseCursor (MouseCursor::PointingHandCursor);
|
||||
setTooltip (linkURL.toString (false));
|
||||
}
|
||||
|
||||
HyperlinkButton::HyperlinkButton()
|
||||
: Button (String()),
|
||||
font (14.0f, Font::underlined),
|
||||
resizeFont (true),
|
||||
justification (Justification::centred)
|
||||
{
|
||||
setMouseCursor (MouseCursor::PointingHandCursor);
|
||||
}
|
||||
|
||||
HyperlinkButton::~HyperlinkButton()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void HyperlinkButton::setFont (const Font& newFont,
|
||||
const bool resizeToMatchComponentHeight,
|
||||
Justification justificationType)
|
||||
{
|
||||
font = newFont;
|
||||
resizeFont = resizeToMatchComponentHeight;
|
||||
justification = justificationType;
|
||||
repaint();
|
||||
}
|
||||
|
||||
void HyperlinkButton::setURL (const URL& newURL) noexcept
|
||||
{
|
||||
url = newURL;
|
||||
setTooltip (newURL.toString (false));
|
||||
}
|
||||
|
||||
Font HyperlinkButton::getFontToUse() const
|
||||
{
|
||||
if (resizeFont)
|
||||
return font.withHeight ((float) getHeight() * 0.7f);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
void HyperlinkButton::changeWidthToFitText()
|
||||
{
|
||||
setSize (getFontToUse().getStringWidth (getButtonText()) + 6, getHeight());
|
||||
}
|
||||
|
||||
void HyperlinkButton::setJustificationType (Justification newJustification)
|
||||
{
|
||||
if (justification != newJustification)
|
||||
{
|
||||
justification = newJustification;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
void HyperlinkButton::colourChanged()
|
||||
{
|
||||
repaint();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void HyperlinkButton::clicked()
|
||||
{
|
||||
if (url.isWellFormed())
|
||||
url.launchInDefaultBrowser();
|
||||
}
|
||||
|
||||
void HyperlinkButton::paintButton (Graphics& g,
|
||||
bool shouldDrawButtonAsHighlighted,
|
||||
bool shouldDrawButtonAsDown)
|
||||
{
|
||||
const Colour textColour (findColour (textColourId));
|
||||
|
||||
if (isEnabled())
|
||||
g.setColour ((shouldDrawButtonAsHighlighted) ? textColour.darker ((shouldDrawButtonAsDown) ? 1.3f : 0.4f)
|
||||
: textColour);
|
||||
else
|
||||
g.setColour (textColour.withMultipliedAlpha (0.4f));
|
||||
|
||||
g.setFont (getFontToUse());
|
||||
|
||||
g.drawText (getButtonText(), getLocalBounds().reduced (1, 0),
|
||||
justification.getOnlyHorizontalFlags() | Justification::verticallyCentred,
|
||||
true);
|
||||
}
|
||||
|
||||
} // namespace juce
|
127
deps/juce/modules/juce_gui_basics/buttons/juce_HyperlinkButton.h
vendored
Normal file
127
deps/juce/modules/juce_gui_basics/buttons/juce_HyperlinkButton.h
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A button showing an underlined weblink, that will launch the link
|
||||
when it's clicked.
|
||||
|
||||
@see Button
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API HyperlinkButton : public Button
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a HyperlinkButton.
|
||||
|
||||
@param linkText the text that will be displayed in the button - this is
|
||||
also set as the Component's name, but the text can be
|
||||
changed later with the Button::setButtonText() method
|
||||
@param linkURL the URL to launch when the user clicks the button
|
||||
*/
|
||||
HyperlinkButton (const String& linkText,
|
||||
const URL& linkURL);
|
||||
|
||||
/** Creates a HyperlinkButton. */
|
||||
HyperlinkButton();
|
||||
|
||||
/** Destructor. */
|
||||
~HyperlinkButton() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the font to use for the text.
|
||||
|
||||
If resizeToMatchComponentHeight is true, the font's height will be adjusted
|
||||
to match the size of the component.
|
||||
*/
|
||||
void setFont (const Font& newFont,
|
||||
bool resizeToMatchComponentHeight,
|
||||
Justification justificationType = Justification::horizontallyCentred);
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the link.
|
||||
|
||||
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
|
||||
methods.
|
||||
|
||||
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
|
||||
*/
|
||||
enum ColourIds
|
||||
{
|
||||
textColourId = 0x1001f00, /**< The colour to use for the URL text. */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the URL that the button will trigger. */
|
||||
void setURL (const URL& newURL) noexcept;
|
||||
|
||||
/** Returns the URL that the button will trigger. */
|
||||
const URL& getURL() const noexcept { return url; }
|
||||
|
||||
//==============================================================================
|
||||
/** Resizes the button horizontally to fit snugly around the text.
|
||||
|
||||
This won't affect the button's height.
|
||||
*/
|
||||
void changeWidthToFitText();
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the style of justification to be used for positioning the text.
|
||||
(The default is Justification::centred)
|
||||
*/
|
||||
void setJustificationType (Justification justification);
|
||||
|
||||
/** Returns the type of justification, as set in setJustificationType(). */
|
||||
Justification getJustificationType() const noexcept { return justification; }
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void clicked() override;
|
||||
/** @internal */
|
||||
void colourChanged() override;
|
||||
/** @internal */
|
||||
void paintButton (Graphics&, bool, bool) override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
using Button::clicked;
|
||||
Font getFontToUse() const;
|
||||
|
||||
//==============================================================================
|
||||
URL url;
|
||||
Font font;
|
||||
bool resizeFont;
|
||||
Justification justification;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HyperlinkButton)
|
||||
};
|
||||
|
||||
} // namespace juce
|
208
deps/juce/modules/juce_gui_basics/buttons/juce_ImageButton.cpp
vendored
Normal file
208
deps/juce/modules/juce_gui_basics/buttons/juce_ImageButton.cpp
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
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,
|
||||
Colour overlayColourWhenNormal,
|
||||
const Image& overImage_,
|
||||
const float imageOpacityWhenOver,
|
||||
Colour overlayColourWhenOver,
|
||||
const Image& downImage_,
|
||||
const float imageOpacityWhenDown,
|
||||
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();
|
||||
}
|
||||
|
||||
void ImageButton::setHitTestAlphaThreshold(float thresh)
|
||||
{
|
||||
alphaThreshold = (uint8) jlimit (0, 0xff, roundToInt (255.0f * thresh));
|
||||
}
|
||||
|
||||
float ImageButton::getHitTestAlphaThreshold() const
|
||||
{
|
||||
return alphaThreshold / 255.0f;
|
||||
}
|
||||
|
||||
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 shouldDrawButtonAsHighlighted,
|
||||
bool shouldDrawButtonAsDown)
|
||||
{
|
||||
if (! isEnabled())
|
||||
{
|
||||
shouldDrawButtonAsHighlighted = false;
|
||||
shouldDrawButtonAsDown = 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 = (float) ih / (float) iw;
|
||||
const float destRatio = (float) h / (float) w;
|
||||
|
||||
if (imRatio > destRatio)
|
||||
{
|
||||
newW = roundToInt ((float) h / imRatio);
|
||||
newH = h;
|
||||
}
|
||||
else
|
||||
{
|
||||
newW = w;
|
||||
newH = roundToInt ((float) 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 = shouldDrawButtonAsDown || getToggleState();
|
||||
|
||||
getLookAndFeel().drawImageButton (g, &im, x, y, w, h,
|
||||
useDownImage ? downOverlay
|
||||
: (shouldDrawButtonAsHighlighted ? overOverlay
|
||||
: normalOverlay),
|
||||
useDownImage ? downOpacity
|
||||
: (shouldDrawButtonAsHighlighted ? overOpacity
|
||||
: normalOpacity),
|
||||
*this);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageButton::hitTest (int x, int y)
|
||||
{
|
||||
if (! Component::hitTest (x, y)) // handle setInterceptsMouseClicks
|
||||
return false;
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
} // namespace juce
|
164
deps/juce/modules/juce_gui_basics/buttons/juce_ImageButton.h
vendored
Normal file
164
deps/juce/modules/juce_gui_basics/buttons/juce_ImageButton.h
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
As the title suggests, this is a button containing an image.
|
||||
|
||||
The colour and transparency of the image can be set to vary when the
|
||||
button state changes.
|
||||
|
||||
@see Button, ShapeButton, TextButton
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API ImageButton : public Button
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an ImageButton.
|
||||
|
||||
Use setImage() to specify the image to use. The colours and opacities that
|
||||
are specified here can be changed later using setImages().
|
||||
|
||||
@param name the name to give the component
|
||||
*/
|
||||
explicit ImageButton (const String& name = String());
|
||||
|
||||
/** Destructor. */
|
||||
~ImageButton() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Sets up the images to draw in various states.
|
||||
|
||||
@param resizeButtonNowToFitThisImage if true, the button will be immediately
|
||||
resized to the same dimensions as the normal image
|
||||
@param rescaleImagesWhenButtonSizeChanges if true, the image will be rescaled to fit the
|
||||
button when the button's size changes
|
||||
@param preserveImageProportions if true then any rescaling of the image to fit
|
||||
the button will keep the image's x and y proportions
|
||||
correct - i.e. it won't distort its shape, although
|
||||
this might create gaps around the edges
|
||||
@param normalImage the image to use when the button is in its normal state.
|
||||
button no longer needs it.
|
||||
@param imageOpacityWhenNormal the opacity to use when drawing the normal image.
|
||||
@param overlayColourWhenNormal an overlay colour to use to fill the alpha channel of the
|
||||
normal image - if this colour is transparent, no overlay
|
||||
will be drawn. The overlay will be drawn over the top of the
|
||||
image, so you can basically add a solid or semi-transparent
|
||||
colour to the image to brighten or darken it
|
||||
@param overImage the image to use when the mouse is over the button. If
|
||||
you want to use the same image as was set in the normalImage
|
||||
parameter, this value can be a null image.
|
||||
@param imageOpacityWhenOver the opacity to use when drawing the image when the mouse
|
||||
is over the button
|
||||
@param overlayColourWhenOver an overlay colour to use to fill the alpha channel of the
|
||||
image when the mouse is over - if this colour is transparent,
|
||||
no overlay will be drawn
|
||||
@param downImage an image to use when the button is pressed down. If set
|
||||
to a null image, the 'over' image will be drawn instead (or the
|
||||
normal image if there isn't an 'over' image either).
|
||||
@param imageOpacityWhenDown the opacity to use when drawing the image when the button
|
||||
is pressed
|
||||
@param overlayColourWhenDown an overlay colour to use to fill the alpha channel of the
|
||||
image when the button is pressed down - if this colour is
|
||||
transparent, no overlay will be drawn
|
||||
@param hitTestAlphaThreshold if set to zero, the mouse is considered to be over the button
|
||||
whenever it's inside the button's bounding rectangle. If
|
||||
set to values higher than 0, the mouse will only be
|
||||
considered to be over the image when the value of the
|
||||
image's alpha channel at that position is greater than
|
||||
this level.
|
||||
*/
|
||||
void setImages (bool resizeButtonNowToFitThisImage,
|
||||
bool rescaleImagesWhenButtonSizeChanges,
|
||||
bool preserveImageProportions,
|
||||
const Image& normalImage,
|
||||
float imageOpacityWhenNormal,
|
||||
Colour overlayColourWhenNormal,
|
||||
const Image& overImage,
|
||||
float imageOpacityWhenOver,
|
||||
Colour overlayColourWhenOver,
|
||||
const Image& downImage,
|
||||
float imageOpacityWhenDown,
|
||||
Colour overlayColourWhenDown,
|
||||
float hitTestAlphaThreshold = 0.0f);
|
||||
|
||||
/** Returns the currently set 'normal' image. */
|
||||
Image getNormalImage() const;
|
||||
|
||||
/** Returns the image that's drawn when the mouse is over the button.
|
||||
|
||||
If a valid 'over' image has been set, this will return it; otherwise it'll
|
||||
just return the normal image.
|
||||
*/
|
||||
Image getOverImage() const;
|
||||
|
||||
/** Returns the image that's drawn when the button is held down.
|
||||
|
||||
If a valid 'down' image has been set, this will return it; otherwise it'll
|
||||
return the 'over' image or normal image, depending on what's available.
|
||||
*/
|
||||
Image getDownImage() const;
|
||||
|
||||
void setHitTestAlphaThreshold(float thresh);
|
||||
float getHitTestAlphaThreshold() const;
|
||||
|
||||
//==============================================================================
|
||||
/** This abstract base class is implemented by LookAndFeel classes. */
|
||||
struct JUCE_API LookAndFeelMethods
|
||||
{
|
||||
virtual ~LookAndFeelMethods() = default;
|
||||
|
||||
virtual void drawImageButton (Graphics&, Image*,
|
||||
int imageX, int imageY, int imageW, int imageH,
|
||||
const Colour& overlayColour, float imageOpacity, ImageButton&) = 0;
|
||||
};
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
bool hitTest (int x, int y) override;
|
||||
/** @internal */
|
||||
void paintButton (Graphics&, bool, bool) override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
bool scaleImageToFit, preserveProportions;
|
||||
uint8 alphaThreshold;
|
||||
Rectangle<int> imageBounds;
|
||||
Image normalImage, overImage, downImage;
|
||||
float normalOpacity, overOpacity, downOpacity;
|
||||
Colour normalOverlay, overOverlay, downOverlay;
|
||||
|
||||
Image getCurrentImage() const;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ImageButton)
|
||||
};
|
||||
|
||||
} // namespace juce
|
137
deps/juce/modules/juce_gui_basics/buttons/juce_ShapeButton.cpp
vendored
Normal file
137
deps/juce/modules/juce_gui_basics/buttons/juce_ShapeButton.cpp
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
ShapeButton::ShapeButton (const String& t, Colour n, Colour o, Colour d)
|
||||
: Button (t),
|
||||
normalColour (n), overColour (o), downColour (d),
|
||||
normalColourOn (n), overColourOn (o), downColourOn (d),
|
||||
useOnColours(false),
|
||||
maintainShapeProportions (false),
|
||||
outlineWidth (0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
ShapeButton::~ShapeButton() {}
|
||||
|
||||
void ShapeButton::setColours (Colour newNormalColour, Colour newOverColour, Colour newDownColour)
|
||||
{
|
||||
normalColour = newNormalColour;
|
||||
overColour = newOverColour;
|
||||
downColour = newDownColour;
|
||||
}
|
||||
|
||||
void ShapeButton::setOnColours (Colour newNormalColourOn, Colour newOverColourOn, Colour newDownColourOn)
|
||||
{
|
||||
normalColourOn = newNormalColourOn;
|
||||
overColourOn = newOverColourOn;
|
||||
downColourOn = newDownColourOn;
|
||||
}
|
||||
|
||||
void ShapeButton::shouldUseOnColours (bool shouldUse)
|
||||
{
|
||||
useOnColours = shouldUse;
|
||||
}
|
||||
|
||||
void ShapeButton::setOutline (Colour newOutlineColour, const float newOutlineWidth)
|
||||
{
|
||||
outlineColour = newOutlineColour;
|
||||
outlineWidth = newOutlineWidth;
|
||||
}
|
||||
|
||||
void ShapeButton::setBorderSize (BorderSize<int> newBorder)
|
||||
{
|
||||
border = newBorder;
|
||||
}
|
||||
|
||||
void ShapeButton::setShape (const Path& newShape,
|
||||
const bool resizeNowToFitThisShape,
|
||||
const bool maintainShapeProportions_,
|
||||
const bool hasShadow)
|
||||
{
|
||||
shape = newShape;
|
||||
maintainShapeProportions = maintainShapeProportions_;
|
||||
|
||||
shadow.setShadowProperties (DropShadow (Colours::black.withAlpha (0.5f), 3, Point<int>()));
|
||||
setComponentEffect (hasShadow ? &shadow : nullptr);
|
||||
|
||||
if (resizeNowToFitThisShape)
|
||||
{
|
||||
auto newBounds = shape.getBounds();
|
||||
|
||||
if (hasShadow)
|
||||
newBounds = newBounds.expanded (4.0f);
|
||||
|
||||
shape.applyTransform (AffineTransform::translation (-newBounds.getX(),
|
||||
-newBounds.getY()));
|
||||
|
||||
setSize (1 + (int) (newBounds.getWidth() + outlineWidth) + border.getLeftAndRight(),
|
||||
1 + (int) (newBounds.getHeight() + outlineWidth) + border.getTopAndBottom());
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
void ShapeButton::paintButton (Graphics& g, bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown)
|
||||
{
|
||||
if (! isEnabled())
|
||||
{
|
||||
shouldDrawButtonAsHighlighted = false;
|
||||
shouldDrawButtonAsDown = false;
|
||||
}
|
||||
|
||||
auto r = border.subtractedFrom (getLocalBounds())
|
||||
.toFloat()
|
||||
.reduced (outlineWidth * 0.5f);
|
||||
|
||||
if (getComponentEffect() != nullptr)
|
||||
r = r.reduced (2.0f);
|
||||
|
||||
if (shouldDrawButtonAsDown)
|
||||
{
|
||||
const float sizeReductionWhenPressed = 0.04f;
|
||||
|
||||
r = r.reduced (sizeReductionWhenPressed * r.getWidth(),
|
||||
sizeReductionWhenPressed * r.getHeight());
|
||||
}
|
||||
|
||||
auto trans = shape.getTransformToScaleToFit (r, maintainShapeProportions);
|
||||
|
||||
if (shouldDrawButtonAsDown) g.setColour (getToggleState() && useOnColours ? downColourOn : downColour);
|
||||
else if (shouldDrawButtonAsHighlighted) g.setColour (getToggleState() && useOnColours ? overColourOn : overColour);
|
||||
else g.setColour (getToggleState() && useOnColours ? normalColourOn : normalColour);
|
||||
|
||||
g.fillPath (shape, trans);
|
||||
|
||||
if (outlineWidth > 0.0f)
|
||||
{
|
||||
g.setColour (outlineColour);
|
||||
g.strokePath (shape, PathStrokeType (outlineWidth), trans);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace juce
|
126
deps/juce/modules/juce_gui_basics/buttons/juce_ShapeButton.h
vendored
Normal file
126
deps/juce/modules/juce_gui_basics/buttons/juce_ShapeButton.h
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A button that contains a filled shape.
|
||||
|
||||
@see Button, ImageButton, TextButton, ArrowButton
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API ShapeButton : public Button
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a ShapeButton.
|
||||
|
||||
@param name a name to give the component - see Component::setName()
|
||||
@param normalColour the colour to fill the shape with when the mouse isn't over
|
||||
@param overColour the colour to use when the mouse is over the shape
|
||||
@param downColour the colour to use when the button is in the pressed-down state
|
||||
*/
|
||||
ShapeButton (const String& name,
|
||||
Colour normalColour,
|
||||
Colour overColour,
|
||||
Colour downColour);
|
||||
|
||||
/** Destructor. */
|
||||
~ShapeButton() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the shape to use.
|
||||
|
||||
@param newShape the shape to use
|
||||
@param resizeNowToFitThisShape if true, the button will be resized to fit the shape's bounds
|
||||
@param maintainShapeProportions if true, the shape's proportions will be kept fixed when
|
||||
the button is resized
|
||||
@param hasDropShadow if true, the button will be given a drop-shadow effect
|
||||
*/
|
||||
void setShape (const Path& newShape,
|
||||
bool resizeNowToFitThisShape,
|
||||
bool maintainShapeProportions,
|
||||
bool hasDropShadow);
|
||||
|
||||
/** Set the colours to use for drawing the shape.
|
||||
|
||||
@param normalColour the colour to fill the shape with when the mouse isn't over
|
||||
@param overColour the colour to use when the mouse is over the shape
|
||||
@param downColour the colour to use when the button is in the pressed-down state
|
||||
*/
|
||||
void setColours (Colour normalColour,
|
||||
Colour overColour,
|
||||
Colour downColour);
|
||||
|
||||
/** Sets the colours to use for drawing the shape when the button's toggle state is 'on'. To enable this behaviour, use the
|
||||
shouldUseOnColours() method.
|
||||
|
||||
@param normalColourOn the colour to fill the shape with when the mouse isn't over and the button's toggle state is 'on'
|
||||
@param overColourOn the colour to use when the mouse is over the shape and the button's toggle state is 'on'
|
||||
@param downColourOn the colour to use when the button is in the pressed-down state and the button's toggle state is 'on'
|
||||
*/
|
||||
void setOnColours (Colour normalColourOn,
|
||||
Colour overColourOn,
|
||||
Colour downColourOn);
|
||||
|
||||
/** Set whether the button should use the 'on' set of colours when its toggle state is 'on'.
|
||||
By default these will be the same as the normal colours but the setOnColours method can be
|
||||
used to provide a different set of colours.
|
||||
*/
|
||||
void shouldUseOnColours (bool shouldUse);
|
||||
|
||||
/** Sets up an outline to draw around the shape.
|
||||
|
||||
@param outlineColour the colour to use
|
||||
@param outlineStrokeWidth the thickness of line to draw
|
||||
*/
|
||||
void setOutline (Colour outlineColour, float outlineStrokeWidth);
|
||||
|
||||
/** This lets you specify a border to be left around the edge of the button when
|
||||
drawing the shape.
|
||||
*/
|
||||
void setBorderSize (BorderSize<int> border);
|
||||
|
||||
/** @internal */
|
||||
void paintButton (Graphics&, bool, bool) override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Colour normalColour, overColour, downColour,
|
||||
normalColourOn, overColourOn, downColourOn, outlineColour;
|
||||
bool useOnColours;
|
||||
DropShadowEffect shadow;
|
||||
Path shape;
|
||||
BorderSize<int> border;
|
||||
bool maintainShapeProportions;
|
||||
float outlineWidth;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ShapeButton)
|
||||
};
|
||||
|
||||
} // namespace juce
|
77
deps/juce/modules/juce_gui_basics/buttons/juce_TextButton.cpp
vendored
Normal file
77
deps/juce/modules/juce_gui_basics/buttons/juce_TextButton.cpp
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
TextButton::TextButton() : Button (String())
|
||||
{
|
||||
}
|
||||
|
||||
TextButton::TextButton (const String& name) : Button (name)
|
||||
{
|
||||
}
|
||||
|
||||
TextButton::TextButton (const String& name, const String& toolTip) : Button (name)
|
||||
{
|
||||
setTooltip (toolTip);
|
||||
}
|
||||
|
||||
TextButton::~TextButton()
|
||||
{
|
||||
}
|
||||
|
||||
void TextButton::paintButton (Graphics& g, bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown)
|
||||
{
|
||||
auto& lf = getLookAndFeel();
|
||||
|
||||
lf.drawButtonBackground (g, *this,
|
||||
findColour (getToggleState() ? buttonOnColourId : buttonColourId),
|
||||
shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);
|
||||
|
||||
lf.drawButtonText (g, *this, shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);
|
||||
}
|
||||
|
||||
void TextButton::colourChanged()
|
||||
{
|
||||
repaint();
|
||||
}
|
||||
|
||||
void TextButton::changeWidthToFitText()
|
||||
{
|
||||
changeWidthToFitText (getHeight());
|
||||
}
|
||||
|
||||
void TextButton::changeWidthToFitText (const int newHeight)
|
||||
{
|
||||
setSize (getBestWidthForHeight (newHeight), newHeight);
|
||||
}
|
||||
|
||||
int TextButton::getBestWidthForHeight (int buttonHeight)
|
||||
{
|
||||
return getLookAndFeel().getTextButtonWidthToFitText (*this, buttonHeight);
|
||||
}
|
||||
|
||||
} // namespace juce
|
109
deps/juce/modules/juce_gui_basics/buttons/juce_TextButton.h
vendored
Normal file
109
deps/juce/modules/juce_gui_basics/buttons/juce_TextButton.h
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A button that uses the standard lozenge-shaped background with a line of
|
||||
text on it.
|
||||
|
||||
@see Button, DrawableButton
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API TextButton : public Button
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a TextButton. */
|
||||
TextButton();
|
||||
|
||||
/** Creates a TextButton.
|
||||
@param buttonName the text to put in the button (the component's name is also
|
||||
initially set to this string, but these can be changed later
|
||||
using the setName() and setButtonText() methods)
|
||||
*/
|
||||
explicit TextButton (const String& buttonName);
|
||||
|
||||
/** Creates a TextButton.
|
||||
@param buttonName the text to put in the button (the component's name is also
|
||||
initially set to this string, but these can be changed later
|
||||
using the setName() and setButtonText() methods)
|
||||
@param toolTip an optional string to use as a tooltip
|
||||
*/
|
||||
TextButton (const String& buttonName, const String& toolTip);
|
||||
|
||||
/** Destructor. */
|
||||
~TextButton() override;
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the button.
|
||||
|
||||
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
|
||||
methods.
|
||||
|
||||
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
|
||||
*/
|
||||
enum ColourIds
|
||||
{
|
||||
buttonColourId = 0x1000100, /**< The colour used to fill the button shape (when the button is toggled
|
||||
'off'). The look-and-feel class might re-interpret this to add
|
||||
effects, etc. */
|
||||
buttonOnColourId = 0x1000101, /**< The colour used to fill the button shape (when the button is toggled
|
||||
'on'). The look-and-feel class might re-interpret this to add
|
||||
effects, etc. */
|
||||
textColourOffId = 0x1000102, /**< The colour to use for the button's text when the button's toggle state is "off". */
|
||||
textColourOnId = 0x1000103 /**< The colour to use for the button's text.when the button's toggle state is "on". */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Changes this button's width to fit neatly around its current text, without
|
||||
changing its height.
|
||||
*/
|
||||
void changeWidthToFitText();
|
||||
|
||||
/** Resizes the button's width to fit neatly around its current text, and gives it
|
||||
the specified height.
|
||||
*/
|
||||
void changeWidthToFitText (int newHeight);
|
||||
|
||||
/** Returns the width that the LookAndFeel suggests would be best for this button if it
|
||||
had the given height.
|
||||
*/
|
||||
int getBestWidthForHeight (int buttonHeight);
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void paintButton (Graphics&, bool, bool) override;
|
||||
/** @internal */
|
||||
void colourChanged() override;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextButton)
|
||||
};
|
||||
|
||||
} // namespace juce
|
65
deps/juce/modules/juce_gui_basics/buttons/juce_ToggleButton.cpp
vendored
Normal file
65
deps/juce/modules/juce_gui_basics/buttons/juce_ToggleButton.cpp
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
ToggleButton::ToggleButton()
|
||||
: Button (String())
|
||||
{
|
||||
setClickingTogglesState (true);
|
||||
}
|
||||
|
||||
ToggleButton::ToggleButton (const String& buttonText)
|
||||
: Button (buttonText)
|
||||
{
|
||||
setClickingTogglesState (true);
|
||||
}
|
||||
|
||||
ToggleButton::~ToggleButton()
|
||||
{
|
||||
}
|
||||
|
||||
void ToggleButton::paintButton (Graphics& g, bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown)
|
||||
{
|
||||
getLookAndFeel().drawToggleButton (g, *this, shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);
|
||||
}
|
||||
|
||||
void ToggleButton::changeWidthToFitText()
|
||||
{
|
||||
getLookAndFeel().changeToggleButtonWidthToFitText (*this);
|
||||
}
|
||||
|
||||
void ToggleButton::colourChanged()
|
||||
{
|
||||
repaint();
|
||||
}
|
||||
|
||||
std::unique_ptr<AccessibilityHandler> ToggleButton::createAccessibilityHandler()
|
||||
{
|
||||
return std::make_unique<ButtonAccessibilityHandler> (*this, AccessibilityRole::toggleButton);
|
||||
}
|
||||
|
||||
} // namespace juce
|
92
deps/juce/modules/juce_gui_basics/buttons/juce_ToggleButton.h
vendored
Normal file
92
deps/juce/modules/juce_gui_basics/buttons/juce_ToggleButton.h
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A button that can be toggled on/off.
|
||||
|
||||
All buttons can be toggle buttons, but this lets you create one of the
|
||||
standard ones which has a tick-box and a text label next to it.
|
||||
|
||||
@see Button, DrawableButton, TextButton
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API ToggleButton : public Button
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a ToggleButton. */
|
||||
ToggleButton();
|
||||
|
||||
/** Creates a ToggleButton.
|
||||
|
||||
@param buttonText the text to put in the button (the component's name is also
|
||||
initially set to this string, but these can be changed later
|
||||
using the setName() and setButtonText() methods)
|
||||
*/
|
||||
explicit ToggleButton (const String& buttonText);
|
||||
|
||||
/** Destructor. */
|
||||
~ToggleButton() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Resizes the button to fit neatly around its current text.
|
||||
The button's height won't be affected, only its width.
|
||||
*/
|
||||
void changeWidthToFitText();
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the button.
|
||||
|
||||
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
|
||||
methods.
|
||||
|
||||
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
|
||||
*/
|
||||
enum ColourIds
|
||||
{
|
||||
textColourId = 0x1006501, /**< The colour to use for the button's text. */
|
||||
tickColourId = 0x1006502, /**< The colour to use for the tick mark. */
|
||||
tickDisabledColourId = 0x1006503 /**< The colour to use for the disabled tick mark and/or outline. */
|
||||
};
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void paintButton (Graphics&, bool, bool) override;
|
||||
/** @internal */
|
||||
void colourChanged() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ToggleButton)
|
||||
};
|
||||
|
||||
} // namespace juce
|
113
deps/juce/modules/juce_gui_basics/buttons/juce_ToolbarButton.cpp
vendored
Normal file
113
deps/juce/modules/juce_gui_basics/buttons/juce_ToolbarButton.cpp
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
ToolbarButton::ToolbarButton (const int iid, const String& buttonText,
|
||||
std::unique_ptr<Drawable> normalIm,
|
||||
std::unique_ptr<Drawable> toggledOnIm)
|
||||
: ToolbarItemComponent (iid, buttonText, true),
|
||||
normalImage (std::move (normalIm)),
|
||||
toggledOnImage (std::move (toggledOnIm))
|
||||
{
|
||||
jassert (normalImage != nullptr);
|
||||
}
|
||||
|
||||
ToolbarButton::~ToolbarButton()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool ToolbarButton::getToolbarItemSizes (int toolbarDepth, bool /*isToolbarVertical*/, int& preferredSize, int& minSize, int& maxSize)
|
||||
{
|
||||
preferredSize = minSize = maxSize = toolbarDepth;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ToolbarButton::paintButtonArea (Graphics&, int /*width*/, int /*height*/, bool /*isMouseOver*/, bool /*isMouseDown*/)
|
||||
{
|
||||
}
|
||||
|
||||
void ToolbarButton::contentAreaChanged (const Rectangle<int>&)
|
||||
{
|
||||
buttonStateChanged();
|
||||
}
|
||||
|
||||
void ToolbarButton::setCurrentImage (Drawable* const newImage)
|
||||
{
|
||||
if (newImage != currentImage)
|
||||
{
|
||||
removeChildComponent (currentImage);
|
||||
currentImage = newImage;
|
||||
|
||||
if (currentImage != nullptr)
|
||||
{
|
||||
enablementChanged();
|
||||
addAndMakeVisible (currentImage);
|
||||
updateDrawable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ToolbarButton::updateDrawable()
|
||||
{
|
||||
if (currentImage != nullptr)
|
||||
{
|
||||
currentImage->setInterceptsMouseClicks (false, false);
|
||||
currentImage->setTransformToFit (getContentArea().toFloat(), RectanglePlacement::centred);
|
||||
currentImage->setAlpha (isEnabled() ? 1.0f : 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolbarButton::resized()
|
||||
{
|
||||
ToolbarItemComponent::resized();
|
||||
updateDrawable();
|
||||
}
|
||||
|
||||
void ToolbarButton::enablementChanged()
|
||||
{
|
||||
ToolbarItemComponent::enablementChanged();
|
||||
updateDrawable();
|
||||
}
|
||||
|
||||
Drawable* ToolbarButton::getImageToUse() const
|
||||
{
|
||||
if (getStyle() == Toolbar::textOnly)
|
||||
return nullptr;
|
||||
|
||||
if (getToggleState() && toggledOnImage != nullptr)
|
||||
return toggledOnImage.get();
|
||||
|
||||
return normalImage.get();
|
||||
}
|
||||
|
||||
void ToolbarButton::buttonStateChanged()
|
||||
{
|
||||
setCurrentImage (getImageToUse());
|
||||
}
|
||||
|
||||
} // namespace juce
|
98
deps/juce/modules/juce_gui_basics/buttons/juce_ToolbarButton.h
vendored
Normal file
98
deps/juce/modules/juce_gui_basics/buttons/juce_ToolbarButton.h
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A type of button designed to go on a toolbar.
|
||||
|
||||
This simple button can have two Drawable objects specified - one for normal
|
||||
use and another one (optionally) for the button's "on" state if it's a
|
||||
toggle button.
|
||||
|
||||
@see Toolbar, ToolbarItemFactory, ToolbarItemComponent, Drawable, Button
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API ToolbarButton : public ToolbarItemComponent
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a ToolbarButton.
|
||||
|
||||
@param itemId the ID for this toolbar item type. This is passed through to the
|
||||
ToolbarItemComponent constructor
|
||||
@param labelText the text to display on the button (if the toolbar is using a style
|
||||
that shows text labels). This is passed through to the
|
||||
ToolbarItemComponent constructor
|
||||
@param normalImage a drawable object that the button should use as its icon. The object
|
||||
that is passed-in here will be kept by this object and will be
|
||||
deleted when no longer needed or when this button is deleted.
|
||||
@param toggledOnImage a drawable object that the button can use as its icon if the button
|
||||
is in a toggled-on state (see the Button::getToggleState() method). If
|
||||
nullptr is passed-in here, then the normal image will be used instead,
|
||||
regardless of the toggle state. The object that is passed-in here will be
|
||||
owned by this object and will be deleted when no longer needed or when
|
||||
this button is deleted.
|
||||
*/
|
||||
ToolbarButton (int itemId,
|
||||
const String& labelText,
|
||||
std::unique_ptr<Drawable> normalImage,
|
||||
std::unique_ptr<Drawable> toggledOnImage);
|
||||
|
||||
/** Destructor. */
|
||||
~ToolbarButton() override;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
bool getToolbarItemSizes (int toolbarDepth, bool isToolbarVertical, int& preferredSize,
|
||||
int& minSize, int& maxSize) override;
|
||||
/** @internal */
|
||||
void paintButtonArea (Graphics&, int width, int height, bool isMouseOver, bool isMouseDown) override;
|
||||
/** @internal */
|
||||
void contentAreaChanged (const Rectangle<int>&) override;
|
||||
/** @internal */
|
||||
void buttonStateChanged() override;
|
||||
/** @internal */
|
||||
void resized() override;
|
||||
/** @internal */
|
||||
void enablementChanged() override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
std::unique_ptr<Drawable> normalImage, toggledOnImage;
|
||||
Drawable* currentImage = nullptr;
|
||||
|
||||
void updateDrawable();
|
||||
Drawable* getImageToUse() const;
|
||||
void setCurrentImage (Drawable*);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ToolbarButton)
|
||||
};
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user