1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
JUCE/examples/Demo/Source/Demos/TimersAndEventsDemo.cpp

246 lines
8 KiB
C++

/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
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 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-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.
==============================================================================
*/
#include "../JuceDemoHeader.h"
//==============================================================================
/** Simple message that holds a Colour. */
struct ColourMessage : public Message
{
ColourMessage (Colour col) : colour (col)
{
}
/** Returns the colour of a ColourMessage of white if the message is not a ColourMessage. */
static Colour getColour (const Message& message)
{
if (auto* cm = dynamic_cast<const ColourMessage*> (&message))
return cm->colour;
return Colours::white;
}
Colour colour;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ColourMessage)
};
//==============================================================================
/** Simple component that can be triggered to flash.
The flash will then fade using a Timer to repaint itself and will send a change
message once it is finished.
*/
class FlashingComponent : public Component,
public MessageListener,
public ChangeBroadcaster,
private Timer
{
public:
FlashingComponent()
{
}
void startFlashing()
{
flashAlpha = 1.0f;
startTimerHz (25);
}
/** Stops this component flashing without sending a change message. */
void stopFlashing()
{
flashAlpha = 0.0f;
stopTimer();
repaint();
}
/** Sets the colour of the component. */
void setFlashColour (const Colour newColour)
{
colour = newColour;
repaint();
}
/** Draws our component. */
void paint (Graphics& g) override
{
g.setColour (colour.overlaidWith (Colours::white.withAlpha (flashAlpha)));
g.fillEllipse (getLocalBounds().toFloat());
}
/** Custom mouse handler to trigger a flash. */
void mouseDown (const MouseEvent&) override
{
startFlashing();
}
/** Message listener callback used to change our colour */
void handleMessage (const Message& message) override
{
setFlashColour (ColourMessage::getColour (message));
}
private:
float flashAlpha = 0;
Colour colour { Colours::red };
void timerCallback() override
{
// Reduce the alpha level of the flash slightly so it fades out
flashAlpha -= 0.075f;
if (flashAlpha < 0.05f)
{
stopFlashing();
sendChangeMessage();
// Once we've finsihed flashing send a change message to trigger the next component to flash
}
repaint();
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlashingComponent)
};
//==============================================================================
class TimersAndEventsDemo : public Component,
private ChangeListener
{
public:
TimersAndEventsDemo()
{
setOpaque (true);
// Create and add our FlashingComponents with some random colours and sizes
for (int i = 0; i < numFlashingComponents; ++i)
{
auto* newFlasher = new FlashingComponent();
flashingComponents.add (newFlasher);
newFlasher->setFlashColour (getRandomBrightColour());
newFlasher->addChangeListener (this);
const int diameter = 25 + random.nextInt (75);
newFlasher->setSize (diameter, diameter);
addAndMakeVisible (newFlasher);
}
addAndMakeVisible (stopButton);
stopButton.setButtonText ("Stop");
stopButton.onClick = [this]() { stopButtonClicked(); };
addAndMakeVisible (randomColourButton);
randomColourButton.setButtonText ("Set Random Colour");
randomColourButton.onClick = [this]() { randomColourButtonClicked(); };
// lay out our components in a psudo random grid
Rectangle<int> area (0, 100, 150, 150);
for (auto* comp : flashingComponents)
{
auto buttonArea = area.withSize (comp->getWidth(), comp->getHeight());
buttonArea.translate (random.nextInt (area.getWidth() - comp->getWidth()),
random.nextInt (area.getHeight() - comp->getHeight()));
comp->setBounds (buttonArea);
area.translate (area.getWidth(), 0);
// if we go off the right start a new row
if (area.getRight() > (800 - area.getWidth()))
{
area.translate (0, area.getWidth());
area.setX (0);
}
}
}
~TimersAndEventsDemo()
{
for (auto* fc : flashingComponents)
fc->removeChangeListener (this);
}
void paint (Graphics& g) override
{
g.fillAll (getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::windowBackground,
Colours::darkgrey));
}
void paintOverChildren (Graphics& g) override
{
auto explanationArea = getLocalBounds().removeFromTop (100);
AttributedString s;
s.append ("Click on a circle to make it flash. When it has finished flashing it will send a message which causes the next circle to flash");
s.append (newLine);
s.append ("Click the \"Set Random Colour\" button to change the colour of one of the circles.");
s.append (newLine);
s.setFont (Font (16.0f));
s.setColour (getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::defaultText, Colours::lightgrey));
s.draw (g, explanationArea.reduced (10).toFloat());
}
void resized() override
{
auto area = getLocalBounds().removeFromBottom (40);
randomColourButton.setBounds (area.removeFromLeft (166).reduced (8));
stopButton.setBounds (area.removeFromRight (166).reduced (8));
}
private:
enum { numFlashingComponents = 9 };
OwnedArray<FlashingComponent> flashingComponents;
TextButton randomColourButton, stopButton;
Random random;
void changeListenerCallback (ChangeBroadcaster* source) override
{
for (int i = 0; i < flashingComponents.size(); ++i)
if (source == flashingComponents.getUnchecked (i))
flashingComponents.getUnchecked ((i + 1) % flashingComponents.size())->startFlashing();
}
void randomColourButtonClicked()
{
// Here we post a new ColourMessage with a random colour to a random flashing component.
// This will send a message to the component asynchronously and trigger its handleMessage callback
flashingComponents.getUnchecked (random.nextInt (flashingComponents.size()))->postMessage (new ColourMessage (getRandomBrightColour()));
}
void stopButtonClicked()
{
for (auto* fc : flashingComponents)
fc->stopFlashing();
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimersAndEventsDemo)
};
// This static object will register this demo type in a global list of demos..
static JuceDemoType<TimersAndEventsDemo> demo ("40 Timers & Events");