|
- /*
- ==============================================================================
-
- 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 (const ColourMessage* cm = dynamic_cast<const ColourMessage*> (&message))
- return cm->colour;
-
- return Colours::white;
- }
-
- private:
- 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()
- : flashAlpha (0.0f),
- colour (Colours::red)
- {
- }
-
- 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;
- Colour colour;
-
- 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,
- private Button::Listener
- {
- public:
- TimersAndEventsDemo()
- {
- setOpaque (true);
-
- // Create and add our FlashingComponents with some random colours and sizes
- for (int i = 0; i < numFlashingComponents; ++i)
- {
- FlashingComponent* 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.addListener (this);
- stopButton.setButtonText ("Stop");
-
- addAndMakeVisible (randomColourButton);
- randomColourButton.addListener (this);
- randomColourButton.setButtonText ("Set Random Colour");
-
- // lay out our components in a psudo random grid
- Rectangle<int> area (0, 100, 150, 150);
-
- for (int i = 0; i < flashingComponents.size(); ++i)
- {
- FlashingComponent* comp = flashingComponents.getUnchecked (i);
- Rectangle<int> 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()
- {
- stopButton.removeListener (this);
- randomColourButton.removeListener (this);
-
- for (int i = flashingComponents.size(); --i >= 0;)
- flashingComponents.getUnchecked (i)->removeChangeListener (this);
- }
-
- void paint (Graphics& g) override
- {
- g.fillAll (getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::windowBackground,
- Colours::darkgrey));
- }
-
- void paintOverChildren (Graphics& g) override
- {
- const Rectangle<int> 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
- {
- Rectangle<int> 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 buttonClicked (Button* button) override
- {
- if (button == &randomColourButton)
- {
- // 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()));
- }
- else if (button == &stopButton)
- {
- for (int i = 0; i < flashingComponents.size(); ++i)
- flashingComponents.getUnchecked (i)->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");
|