First Commit

This commit is contained in:
Legaeli
2025-10-22 09:20:23 +02:00
commit a36f2ca925
4393 changed files with 1570219 additions and 0 deletions
@@ -0,0 +1,120 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#include <JuceHeader.h>
#include "../../../Assets/DemoUtilities.h"
#include "JUCEDemos.h"
#include "../../../Assets/AudioLiveScrollingDisplay.h"
//==============================================================================
#include "IntroScreen.h"
#include "../../../Audio/AudioAppDemo.h"
#include "../../../Audio/AudioLatencyDemo.h"
#include "../../../Audio/AudioPlaybackDemo.h"
#include "../../../Audio/AudioRecordingDemo.h"
#include "../../../Audio/AudioSettingsDemo.h"
#include "../../../Audio/AudioSynthesiserDemo.h"
#include "../../../Audio/AudioWorkgroupDemo.h"
#include "../../../Audio/MidiDemo.h"
#include "../../../Audio/MPEDemo.h"
#include "../../../Audio/PluckedStringsDemo.h"
#include "../../../Audio/SimpleFFTDemo.h"
#include "../../../DSP/ConvolutionDemo.h"
#include "../../../DSP/FIRFilterDemo.h"
#include "../../../DSP/GainDemo.h"
#include "../../../DSP/IIRFilterDemo.h"
#include "../../../DSP/OscillatorDemo.h"
#include "../../../DSP/OverdriveDemo.h"
#if JUCE_USE_SIMD
#include "../../../DSP/SIMDRegisterDemo.h"
#endif
#include "../../../DSP/StateVariableFilterDemo.h"
#include "../../../DSP/WaveShaperTanhDemo.h"
#include "../../../Utilities/Box2DDemo.h"
#include "../../../Utilities/CryptographyDemo.h"
#include "../../../Utilities/JavaScriptDemo.h"
#include "../../../Utilities/LiveConstantDemo.h"
#include "../../../Utilities/MultithreadingDemo.h"
#include "../../../Utilities/NetworkingDemo.h"
#include "../../../Utilities/OSCDemo.h"
#include "../../../Utilities/SystemInfoDemo.h"
#include "../../../Utilities/TimersAndEventsDemo.h"
#include "../../../Utilities/UnitTestsDemo.h"
#include "../../../Utilities/ValueTreesDemo.h"
#include "../../../Utilities/XMLandJSONDemo.h"
void registerDemos_One() noexcept
{
REGISTER_DEMO (AudioAppDemo, Audio, false)
REGISTER_DEMO (AudioLatencyDemo, Audio, false)
REGISTER_DEMO (AudioPlaybackDemo, Audio, false)
REGISTER_DEMO (AudioRecordingDemo, Audio, false)
REGISTER_DEMO (AudioSettingsDemo, Audio, false)
REGISTER_DEMO (AudioSynthesiserDemo, Audio, false)
REGISTER_DEMO (AudioWorkgroupDemo, Audio, false)
REGISTER_DEMO (MidiDemo, Audio, false)
REGISTER_DEMO (MPEDemo, Audio, false)
REGISTER_DEMO (PluckedStringsDemo, Audio, false)
REGISTER_DEMO (SimpleFFTDemo, Audio, false)
REGISTER_DEMO (ConvolutionDemo, DSP, false)
REGISTER_DEMO (FIRFilterDemo, DSP, false)
REGISTER_DEMO (GainDemo, DSP, false)
REGISTER_DEMO (IIRFilterDemo, DSP, false)
REGISTER_DEMO (OscillatorDemo, DSP, false)
REGISTER_DEMO (OverdriveDemo, DSP, false)
#if JUCE_USE_SIMD
REGISTER_DEMO (SIMDRegisterDemo, DSP, false)
#endif
REGISTER_DEMO (StateVariableFilterDemo, DSP, false)
REGISTER_DEMO (WaveShaperTanhDemo, DSP, false)
REGISTER_DEMO (Box2DDemo, Utilities, false)
#if JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
REGISTER_DEMO (ChildProcessDemo, Utilities, false)
#endif
REGISTER_DEMO (CryptographyDemo, Utilities, false)
REGISTER_DEMO (JavaScriptDemo, Utilities, false)
REGISTER_DEMO (LiveConstantDemo, Utilities, false)
REGISTER_DEMO (MultithreadingDemo, Utilities, false)
REGISTER_DEMO (NetworkingDemo, Utilities, false)
REGISTER_DEMO (OSCDemo, Utilities, false)
REGISTER_DEMO (SystemInfoDemo, Utilities, false)
REGISTER_DEMO (TimersAndEventsDemo, Utilities, false)
REGISTER_DEMO (UnitTestsDemo, Utilities, false)
REGISTER_DEMO (ValueTreesDemo, Utilities, false)
REGISTER_DEMO (XMLandJSONDemo, Utilities, false)
}
Component* createIntroDemo()
{
return new IntroScreen();
}
bool isComponentIntroDemo (Component* comp) noexcept
{
return (dynamic_cast<IntroScreen*> (comp) != nullptr);
}
@@ -0,0 +1,122 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#include <JuceHeader.h>
#include "../../../Assets/DemoUtilities.h"
#include "JUCEDemos.h"
#include "../../../Assets/AudioLiveScrollingDisplay.h"
//==============================================================================
#if JUCE_MAC || JUCE_WINDOWS || JUCE_IOS || JUCE_ANDROID
#include "../../../GUI/AccessibilityDemo.h"
#endif
#include "../../../GUI/AnimationAppDemo.h"
#include "../../../GUI/AnimationEasingDemo.h"
#include "../../../GUI/AnimatorsDemo.h"
#include "../../../GUI/BouncingBallWavetableDemo.h"
#if JUCE_USE_CAMERA && ! (JUCE_LINUX || JUCE_BSD)
#include "../../../GUI/CameraDemo.h"
#endif
#if ! JUCE_ANDROID
#include "../../../GUI/CodeEditorDemo.h"
#endif
#include "../../../GUI/ComponentDemo.h"
#include "../../../GUI/ComponentTransformsDemo.h"
#include "../../../GUI/DialogsDemo.h"
#include "../../../GUI/FlexBoxDemo.h"
#include "../../../GUI/FontsDemo.h"
#include "../../../GUI/GraphicsDemo.h"
#include "../../../GUI/GridDemo.h"
#include "../../../GUI/ImagesDemo.h"
#include "../../../GUI/KeyMappingsDemo.h"
#include "../../../GUI/LookAndFeelDemo.h"
#include "../../../GUI/MDIDemo.h"
#include "../../../GUI/MenusDemo.h"
#include "../../../GUI/MultiTouchDemo.h"
#if JUCE_OPENGL
#include "../../../GUI/OpenGLAppDemo.h"
#include "../../../GUI/OpenGLDemo.h"
#include "../../../GUI/OpenGLDemo2D.h"
#endif
#include "../../../GUI/PropertiesDemo.h"
#if ! (JUCE_LINUX || JUCE_BSD)
#include "../../../GUI/VideoDemo.h"
#endif
#include "../../../GUI/WebBrowserDemo.h"
#include "../../../GUI/WidgetsDemo.h"
#include "../../../GUI/WindowsDemo.h"
void registerDemos_Two() noexcept
{
#if JUCE_MAC || JUCE_WINDOWS || JUCE_IOS || JUCE_ANDROID
REGISTER_DEMO (AccessibilityDemo, GUI, false)
#endif
REGISTER_DEMO (AnimationAppDemo, GUI, false)
REGISTER_DEMO (AnimationEasingDemo, GUI, false)
REGISTER_DEMO (AnimatorsDemo, GUI, false)
REGISTER_DEMO (BouncingBallWavetableDemo, GUI, false)
#if JUCE_USE_CAMERA && ! (JUCE_LINUX || JUCE_BSD)
REGISTER_DEMO (CameraDemo, GUI, true)
#endif
#if ! JUCE_ANDROID
REGISTER_DEMO (CodeEditorDemo, GUI, false)
#endif
REGISTER_DEMO (ComponentDemo, GUI, false)
REGISTER_DEMO (ComponentTransformsDemo, GUI, false)
REGISTER_DEMO (DialogsDemo, GUI, false)
REGISTER_DEMO (FlexBoxDemo, GUI, false)
REGISTER_DEMO (FontsDemo, GUI, false)
REGISTER_DEMO (GraphicsDemo, GUI, false)
REGISTER_DEMO (GridDemo, GUI, false)
REGISTER_DEMO (ImagesDemo, GUI, false)
REGISTER_DEMO (KeyMappingsDemo, GUI, false)
REGISTER_DEMO (LookAndFeelDemo, GUI, false)
REGISTER_DEMO (MDIDemo, GUI, false)
REGISTER_DEMO (MenusDemo, GUI, false)
REGISTER_DEMO (MultiTouchDemo, GUI, false)
#if JUCE_OPENGL
REGISTER_DEMO (OpenGLAppDemo, GUI, true)
REGISTER_DEMO (OpenGLDemo2D, GUI, true)
REGISTER_DEMO (OpenGLDemo, GUI, true)
#endif
REGISTER_DEMO (PropertiesDemo, GUI, false)
#if ! (JUCE_LINUX || JUCE_BSD)
REGISTER_DEMO (VideoDemo, GUI, true)
#endif
#if JUCE_WEB_BROWSER
REGISTER_DEMO (WebBrowserDemo, GUI, true)
#endif
REGISTER_DEMO (WidgetsDemo, GUI, false)
REGISTER_DEMO (WindowsDemo, GUI, false)
}
CodeEditorComponent::ColourScheme getDarkColourScheme()
{
return getDarkCodeEditorColourScheme();
}
CodeEditorComponent::ColourScheme getLightColourScheme()
{
return getLightCodeEditorColourScheme();
}
@@ -0,0 +1,127 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#pragma once
//==============================================================================
class IntroScreen final : public Component
{
public:
IntroScreen()
{
setOpaque (true);
addAndMakeVisible (versionLabel);
addAndMakeVisible (linkButton);
addAndMakeVisible (logo);
versionLabel.setText (String ("{version} built on {date}")
.replace ("{version}", SystemStats::getJUCEVersion())
.replace ("{date}", String (__DATE__).replace (" ", " ")),
dontSendNotification);
linkButton.setColour (HyperlinkButton::textColourId, Colours::lightblue);
setTitle ("Home");
setFocusContainerType (FocusContainerType::focusContainer);
}
void paint (Graphics& g) override
{
g.fillAll (getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour::windowBackground));
}
void resized() override
{
auto area = getLocalBounds().reduced (10);
auto bottomSlice = area.removeFromBottom (24);
linkButton.setBounds (bottomSlice.removeFromRight (getWidth() / 4));
versionLabel.setBounds (bottomSlice);
logo.setBounds (area);
}
private:
Label versionLabel;
HyperlinkButton linkButton { "www.juce.com", { "http://www.juce.com" } };
//==============================================================================
struct LogoDrawComponent final : public Component,
private Timer
{
LogoDrawComponent()
{
setTitle ("JUCE Logo");
startTimerHz (30); // repaint at 30 fps
}
void paint (Graphics& g) override
{
Path wavePath;
auto waveStep = 10.0f;
auto waveY = (float) getHeight() * 0.5f;
int i = 0;
for (auto x = waveStep * 0.5f; x < (float) getWidth(); x += waveStep)
{
auto y1 = waveY + (float) getHeight() * 0.05f * std::sin ((float) i * 0.38f + elapsed);
auto y2 = waveY + (float) getHeight() * 0.10f * std::sin ((float) i * 0.20f + elapsed * 2.0f);
wavePath.addLineSegment ({ x, y1, x, y2 }, 2.0f);
wavePath.addEllipse (x - waveStep * 0.3f, y1 - waveStep * 0.3f, waveStep * 0.6f, waveStep * 0.6f);
wavePath.addEllipse (x - waveStep * 0.3f, y2 - waveStep * 0.3f, waveStep * 0.6f, waveStep * 0.6f);
++i;
}
g.setColour (Colour::greyLevel (0.4f));
g.fillPath (wavePath);
g.setColour (Colour (0xc4f39082));
g.fillPath (logoPath, RectanglePlacement (RectanglePlacement::centred)
.getTransformToFit (logoPath.getBounds(),
getLocalBounds().reduced (20, getHeight() / 4).toFloat()));
}
void timerCallback() override
{
repaint();
elapsed += 0.02f;
}
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
{
return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::image);
}
Path logoPath { getJUCELogoPath() };
float elapsed = 0.0f;
};
LogoDrawComponent logo;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (IntroScreen)
};
@@ -0,0 +1,174 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#include <JuceHeader.h>
#include "../../../Assets/DemoUtilities.h"
#include "JUCEDemos.h"
//==============================================================================
std::vector<JUCEDemos::DemoCategory>& JUCEDemos::getCategories()
{
static std::vector<DemoCategory> categories;
return categories;
}
JUCEDemos::DemoCategory& JUCEDemos::getCategory (const String& name)
{
auto& categories = getCategories();
for (auto& c : categories)
if (c.name == name)
return c;
std::vector<FileAndCallback> fc;
categories.push_back ({ name, fc });
return categories.back();
}
void JUCEDemos::registerDemo (std::function<Component*()> constructorCallback, const String& filePath, const String& category, bool isHeavyweight)
{
#if JUCE_MAC
auto f = File::getSpecialLocation (File::currentExecutableFile)
.getParentDirectory().getSiblingFile ("Resources");
#else
auto f = findExamplesDirectoryFromExecutable (File::getSpecialLocation (File::currentApplicationFile));
#endif
#if ! (JUCE_ANDROID || JUCE_IOS)
if (f == File())
{
jassertfalse;
return;
}
#endif
getCategory (category).demos.push_back ({ f.getChildFile (filePath), constructorCallback, isHeavyweight });
}
File JUCEDemos::findExamplesDirectoryFromExecutable (File exec)
{
int numTries = 15;
auto exampleDir = exec.getSiblingFile ("examples");
if (exampleDir.exists())
return exampleDir;
while (exec.getFileName() != "examples" && numTries-- > 0)
exec = exec.getParentDirectory();
if (exec.getFileName() == "examples")
return exec;
return {};
}
//==============================================================================
static String getCurrentDefaultAudioDeviceName (AudioDeviceManager& deviceManager, bool isInput)
{
auto* deviceType = deviceManager.getCurrentDeviceTypeObject();
jassert (deviceType != nullptr);
if (deviceType != nullptr)
{
auto deviceNames = deviceType->getDeviceNames();
return deviceNames [deviceType->getDefaultDeviceIndex (isInput)];
}
return {};
}
// (returns a shared AudioDeviceManager object that all the demos can use)
AudioDeviceManager& getSharedAudioDeviceManager (int numInputChannels, int numOutputChannels)
{
if (sharedAudioDeviceManager == nullptr)
sharedAudioDeviceManager.reset (new AudioDeviceManager());
auto* currentDevice = sharedAudioDeviceManager->getCurrentAudioDevice();
if (numInputChannels < 0)
numInputChannels = (currentDevice != nullptr ? currentDevice->getActiveInputChannels().countNumberOfSetBits() : 1);
if (numOutputChannels < 0)
numOutputChannels = (currentDevice != nullptr ? currentDevice->getActiveOutputChannels().countNumberOfSetBits() : 2);
if (numInputChannels > 0 && ! RuntimePermissions::isGranted (RuntimePermissions::recordAudio))
{
RuntimePermissions::request (RuntimePermissions::recordAudio,
[numInputChannels, numOutputChannels] (bool granted)
{
if (granted)
getSharedAudioDeviceManager (numInputChannels, numOutputChannels);
});
numInputChannels = 0;
}
if (sharedAudioDeviceManager->getCurrentAudioDevice() != nullptr)
{
auto setup = sharedAudioDeviceManager->getAudioDeviceSetup();
auto numInputs = jmax (numInputChannels, setup.inputChannels.countNumberOfSetBits());
auto numOutputs = jmax (numOutputChannels, setup.outputChannels.countNumberOfSetBits());
auto oldInputs = setup.inputChannels.countNumberOfSetBits();
auto oldOutputs = setup.outputChannels.countNumberOfSetBits();
if (oldInputs != numInputs || oldOutputs != numOutputs)
{
if (oldInputs == 0 && oldOutputs == 0)
{
sharedAudioDeviceManager->initialise (numInputChannels, numOutputChannels, nullptr, true, {}, nullptr);
}
else
{
setup.useDefaultInputChannels = setup.useDefaultOutputChannels = false;
setup.inputChannels.clear();
setup.outputChannels.clear();
setup.inputChannels.setRange (0, numInputs, true);
setup.outputChannels.setRange (0, numOutputs, true);
if (oldInputs == 0 && numInputs > 0 && setup.inputDeviceName.isEmpty())
setup.inputDeviceName = getCurrentDefaultAudioDeviceName (*sharedAudioDeviceManager, true);
if (oldOutputs == 0 && numOutputs > 0 && setup.outputDeviceName.isEmpty())
setup.outputDeviceName = getCurrentDefaultAudioDeviceName (*sharedAudioDeviceManager, false);
sharedAudioDeviceManager->setAudioDeviceSetup (setup, false);
}
}
}
else
{
sharedAudioDeviceManager->initialise (numInputChannels, numOutputChannels, nullptr, true, {}, nullptr);
}
return *sharedAudioDeviceManager;
}
//==============================================================================
void registerAllDemos() noexcept
{
registerDemos_One();
registerDemos_Two();
}
@@ -0,0 +1,79 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#pragma once
//==============================================================================
#define FILE_EXT .h
#define EXPAND(x) x
#define CREATE_FILEPATH(DemoName, category) JUCE_STRINGIFY(EXPAND(category)/EXPAND(DemoName)EXPAND(FILE_EXT))
#define REGISTER_DEMO(DemoName, category, heavyweight) JUCEDemos::registerDemo ([] { return new DemoName(); }, CREATE_FILEPATH(DemoName, category), JUCE_STRINGIFY (category), heavyweight);
//==============================================================================
struct JUCEDemos
{
struct FileAndCallback
{
File demoFile;
std::function<Component*()> callback;
bool isHeavyweight;
};
struct DemoCategory
{
String name;
std::vector<FileAndCallback> demos;
};
static std::vector<DemoCategory>& getCategories();
static DemoCategory& getCategory (const String& name);
static void registerDemo (std::function<Component*()> constructorCallback, const String& filePath, const String& category, bool isHeavyweight);
static File findExamplesDirectoryFromExecutable (File exec);
};
void registerDemos_One() noexcept;
void registerDemos_Two() noexcept;
//==============================================================================
void registerAllDemos() noexcept;
Component* createIntroDemo();
bool isComponentIntroDemo (Component*) noexcept;
CodeEditorComponent::ColourScheme getDarkColourScheme();
CodeEditorComponent::ColourScheme getLightColourScheme();
//==============================================================================
extern std::unique_ptr<AudioDeviceManager> sharedAudioDeviceManager;
AudioDeviceManager& getSharedAudioDeviceManager (int numInputChannels = -1, int numOutputChannels = -1);
ApplicationCommandManager& getGlobalCommandManager();
// A function in this demo is called from the DemoRunner's entry point
#if JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
#include "../../../Utilities/ChildProcessDemo.h"
#endif
Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

@@ -0,0 +1,181 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#include <JuceHeader.h>
#include "../../Assets/DemoUtilities.h"
#include "UI/MainComponent.h"
//==============================================================================
#if JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
// Just add a simple icon to the Window system tray area or Mac menu bar..
struct DemoTaskbarComponent final : public SystemTrayIconComponent,
private Timer
{
DemoTaskbarComponent()
{
setIconImage (getImageFromAssets ("juce_icon.png"),
getImageFromAssets ("juce_icon_template.png"));
setIconTooltip ("JUCE demo runner!");
}
void mouseDown (const MouseEvent&) override
{
// On OSX, there can be problems launching a menu when we're not the foreground
// process, so just in case, we'll first make our process active, and then use a
// timer to wait a moment before opening our menu, which gives the OS some time to
// get its act together and bring our windows to the front.
Process::makeForegroundProcess();
startTimer (50);
}
// This is invoked when the menu is clicked or dismissed
static void menuInvocationCallback (int chosenItemID, DemoTaskbarComponent*)
{
if (chosenItemID == 1)
JUCEApplication::getInstance()->systemRequestedQuit();
}
void timerCallback() override
{
stopTimer();
PopupMenu m;
m.addItem (1, "Quit");
// It's always better to open menus asynchronously when possible.
m.showMenuAsync (PopupMenu::Options(),
ModalCallbackFunction::forComponent (menuInvocationCallback, this));
}
};
#endif
std::unique_ptr<AudioDeviceManager> sharedAudioDeviceManager;
//==============================================================================
class DemoRunnerApplication final : public JUCEApplication
{
public:
//==============================================================================
DemoRunnerApplication() {}
~DemoRunnerApplication() override
{
sharedAudioDeviceManager.reset();
}
const String getApplicationName() override { return ProjectInfo::projectName; }
const String getApplicationVersion() override { return ProjectInfo::versionString; }
bool moreThanOneInstanceAllowed() override { return true; }
//==============================================================================
void initialise (const String& commandLine) override
{
registerAllDemos();
#if JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
// (This function call is for one of the demos, which involves launching a child process)
if (invokeChildProcessDemo (commandLine))
return;
#else
ignoreUnused (commandLine);
#endif
mainWindow.reset (new MainAppWindow (getApplicationName()));
}
bool backButtonPressed() override { mainWindow->getMainComponent().getSidePanel().showOrHide (false); return true; }
void shutdown() override { mainWindow = nullptr; }
//==============================================================================
void systemRequestedQuit() override { quit(); }
void anotherInstanceStarted (const String&) override {}
ApplicationCommandManager& getGlobalCommandManager() { return commandManager; }
private:
class MainAppWindow final : public DocumentWindow
{
public:
MainAppWindow (const String& name)
: DocumentWindow (name, Desktop::getInstance().getDefaultLookAndFeel()
.findColour (ResizableWindow::backgroundColourId),
DocumentWindow::allButtons)
{
setUsingNativeTitleBar (true);
setResizable (true, false);
setResizeLimits (400, 400, 10000, 10000);
#if JUCE_IOS || JUCE_ANDROID
setFullScreen (true);
auto& desktop = Desktop::getInstance();
desktop.setOrientationsEnabled (Desktop::allOrientations);
desktop.setKioskModeComponent (this);
#else
setBounds ((int) (0.1f * (float) getParentWidth()),
(int) (0.1f * (float) getParentHeight()),
jmax (850, (int) (0.5f * (float) getParentWidth())),
jmax (600, (int) (0.7f * (float) getParentHeight())));
#endif
setContentOwned (new MainComponent(), false);
setVisible (true);
#if JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
taskbarIcon.reset (new DemoTaskbarComponent());
#endif
}
void closeButtonPressed() override { JUCEApplication::getInstance()->systemRequestedQuit(); }
#if JUCE_IOS || JUCE_ANDROID
void parentSizeChanged() override
{
getMainComponent().resized();
}
#endif
//==============================================================================
MainComponent& getMainComponent() { return *dynamic_cast<MainComponent*> (getContentComponent()); }
private:
std::unique_ptr<Component> taskbarIcon;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainAppWindow)
};
std::unique_ptr<MainAppWindow> mainWindow;
ApplicationCommandManager commandManager;
};
ApplicationCommandManager& getGlobalCommandManager()
{
return dynamic_cast<DemoRunnerApplication*> (JUCEApplication::getInstance())->getGlobalCommandManager();
}
//==============================================================================
// This macro generates the main() routine that launches the app.
START_JUCE_APPLICATION (DemoRunnerApplication)
@@ -0,0 +1,219 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#include "DemoContentComponent.h"
#include "SettingsContent.h"
#include "MainComponent.h"
//==============================================================================
struct DemoContent final : public Component
{
DemoContent() noexcept {}
void resized() override
{
if (comp != nullptr)
comp->setBounds (getLocalBounds());
}
void setComponent (Component* newComponent)
{
comp.reset (newComponent);
if (comp != nullptr)
{
addAndMakeVisible (comp.get());
resized();
}
}
Component* getComponent() const noexcept { return comp.get(); }
void showHomeScreen() { setComponent (createIntroDemo()); }
private:
std::unique_ptr<Component> comp;
};
//==============================================================================
#if ! (JUCE_ANDROID || JUCE_IOS)
struct CodeContent final : public Component
{
CodeContent()
{
addAndMakeVisible (codeEditor);
codeEditor.setReadOnly (true);
codeEditor.setScrollbarThickness (8);
updateLookAndFeel();
}
void resized() override
{
codeEditor.setBounds (getLocalBounds());
}
void setDefaultCodeContent()
{
document.replaceAllContent ("\n/*******************************************************************************\n"
" Select one of the demos from the side panel on the left to see\n"
" its code here and an instance running in the \"Demo\" tab!\n"
"*******************************************************************************/\n");
}
void updateLookAndFeel()
{
auto* v4 = dynamic_cast<LookAndFeel_V4*> (&Desktop::getInstance().getDefaultLookAndFeel());
if (v4 != nullptr && (v4->getCurrentColourScheme() != LookAndFeel_V4::getLightColourScheme()))
codeEditor.setColourScheme (getDarkColourScheme());
else
codeEditor.setColourScheme (getLightColourScheme());
}
void lookAndFeelChanged() override
{
updateLookAndFeel();
}
CodeDocument document;
CPlusPlusCodeTokeniser cppTokensier;
CodeEditorComponent codeEditor { document, &cppTokensier };
};
#endif
//==============================================================================
DemoContentComponent::DemoContentComponent (Component& mainComponent, std::function<void (bool)> callback)
: TabbedComponent (TabbedButtonBar::Orientation::TabsAtTop),
demoChangedCallback (std::move (callback))
{
demoContent.reset (new DemoContent());
addTab ("Demo", Colours::transparentBlack, demoContent.get(), false);
#if ! (JUCE_ANDROID || JUCE_IOS)
codeContent.reset (new CodeContent());
addTab ("Code", Colours::transparentBlack, codeContent.get(), false);
#endif
addTab ("Settings", Colours::transparentBlack, new SettingsContent (dynamic_cast<MainComponent&> (mainComponent)), true);
setTabBarDepth (40);
updateLookAndFeel();
}
DemoContentComponent::~DemoContentComponent()
{
}
void DemoContentComponent::resized()
{
TabbedComponent::resized();
if (tabBarIndent > 0)
getTabbedButtonBar().setBounds (getTabbedButtonBar().getBounds().withTrimmedLeft (tabBarIndent));
}
void DemoContentComponent::setDemo (const String& category, int selectedDemoIndex)
{
if ((currentDemoCategory == category)
&& (currentDemoIndex == selectedDemoIndex))
return;
auto demo = JUCEDemos::getCategory (category).demos[(size_t) selectedDemoIndex];
#if ! (JUCE_ANDROID || JUCE_IOS)
codeContent->document.replaceAllContent (trimPIP (demo.demoFile.loadFileAsString()));
codeContent->codeEditor.scrollToLine (0);
#endif
auto* content = demo.callback();
demoContent->setComponent (content);
demoChangedCallback (demo.isHeavyweight);
ensureDemoIsShowing();
currentDemoCategory = category;
currentDemoIndex = selectedDemoIndex;
}
bool DemoContentComponent::isShowingHomeScreen() const noexcept
{
return isComponentIntroDemo (demoContent->getComponent()) && getCurrentTabIndex() == 0;
}
void DemoContentComponent::showHomeScreen()
{
demoContent->showHomeScreen();
#if ! (JUCE_ANDROID || JUCE_IOS)
codeContent->setDefaultCodeContent();
#endif
demoChangedCallback (false);
ensureDemoIsShowing();
resized();
currentDemoCategory = {};
currentDemoIndex = -1;
}
void DemoContentComponent::clearCurrentDemo()
{
demoContent->setComponent (nullptr);
demoChangedCallback (false);
}
void DemoContentComponent::updateLookAndFeel()
{
auto backgroundColour = findColour (ResizableWindow::backgroundColourId);
for (int i = 0; i < getNumTabs(); ++i)
setTabBackgroundColour (i, backgroundColour);
}
void DemoContentComponent::lookAndFeelChanged()
{
updateLookAndFeel();
}
String DemoContentComponent::trimPIP (const String& fileContents)
{
auto lines = StringArray::fromLines (fileContents);
auto metadataEndIndex = lines.indexOf (" END_JUCE_PIP_METADATA");
if (metadataEndIndex == -1)
return fileContents;
lines.removeRange (0, metadataEndIndex + 3); // account for newline and comment block end
return lines.joinIntoString ("\n");
}
void DemoContentComponent::ensureDemoIsShowing()
{
if (getCurrentTabIndex() == (getNumTabs() - 1))
setCurrentTabIndex (0);
}
@@ -0,0 +1,69 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#pragma once
#include <JuceHeader.h>
#include "../Demos/JUCEDemos.h"
struct DemoContent;
struct CodeContent;
//==============================================================================
class DemoContentComponent final : public TabbedComponent
{
public:
DemoContentComponent (Component& mainComponent, std::function<void (bool)> demoChangedCallback);
~DemoContentComponent() override;
void resized() override;
void setDemo (const String& category, int selectedDemoIndex);
void clearCurrentDemo();
int getCurrentDemoIndex() const noexcept { return currentDemoIndex; }
bool isShowingHomeScreen() const noexcept;
void showHomeScreen();
void setTabBarIndent (int indent) noexcept { tabBarIndent = indent; }
private:
std::function<void (bool)> demoChangedCallback;
std::unique_ptr<DemoContent> demoContent;
#if ! (JUCE_ANDROID || JUCE_IOS)
std::unique_ptr<CodeContent> codeContent;
#endif
String currentDemoCategory;
int currentDemoIndex = -1;
int tabBarIndent = 0;
//==============================================================================
void updateLookAndFeel();
void lookAndFeelChanged() override;
String trimPIP (const String& fileContents);
void ensureDemoIsShowing();
};
@@ -0,0 +1,466 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#include "MainComponent.h"
//==============================================================================
struct SidePanelHeader final : public Component
{
SidePanelHeader (MainComponent& o)
: owner (o)
{
setOpaque (true);
static const unsigned char homeIconPathData[]
= { 110,109,0,0,64,65,0,0,64,64,98,0,0,64,65,0,0,64,64,74,12,186,64,164,112,5,65,24,217,22,64,70,182,
51,65,98,35,219,9,64,240,167,54,65,0,0,0,64,170,241,58,65,0,0,0,64,0,0,64,65,98,0,0,0,64,22,217,
72,65,166,155,28,64,0,0,80,65,0,0,64,64,0,0,80,65,108,0,0,160,64,0,0,80,65,108,0,0,160,64,0,0,
160,65,98,0,0,160,64,139,108,164,65,211,77,174,64,0,0,168,65,0,0,192,64,0,0,168,65,108,0,0,16,65,
0,0,168,65,98,22,217,24,65,0,0,168,65,0,0,32,65,127,106,164,65,0,0,32,65,0,0,160,65,108,0,0,32,65,0,0,128,
65,108,0,0,96,65,0,0,128,65,108,0,0,96,65,0,0,160,65,98,0,0,96,65,127,106,164,65,233,38,103,65,0,0,168,
65,0,0,112,65,0,0,168,65,108,0,0,144,65,0,0,168,65,98,139,108,148,65,0,0,168,65,0,0,152,65,139,108,164,
65,0,0,152,65,0,0,160,65,108,0,0,152,65,0,0,80,65,108,0,0,168,65,0,0,80,65,98,139,108,172,65,0,0,80,65,0,
0,176,65,23,217,72,65,0,0,176,65,0,0,64,65,98,0,0,176,65,170,241,58,65,156,196,174,65,240,167,54,65,158,239,
172,65,70,182,51,65,98,213,120,145,65,164,112,5,65,0,0,64,65,0,0,64,64,0,0,64,65,0,0,64,64,99,
101,0,0 };
static const unsigned char settingsIconPathData[]
= { 110,109,202,111,210,64,243,226,61,64,108,0,0,224,64,0,0,0,0,108,0,0,48,65,0,0,0,0,108,27,200,54,65,243,
226,61,64,98,91,248,63,65,174,170,76,64,95,130,72,65,231,138,96,64,46,46,80,65,180,163,120,64,108,42,
181,124,65,20,38,49,64,108,149,90,142,65,246,108,199,64,108,68,249,118,65,2,85,1,65,98,112,166,119,65,
201,31,6,65,0,0,120,65,111,5,11,65,0,0,120,65,0,0,16,65,98,0,0,120,65,145,250,20,65,108,166,119,65,55,
224,25,65,72,249,118,65,254,170,30,65,108,151,90,142,65,133,73,60,65,108,46,181,124,65,123,182,115,65,
108,50,46,80,65,18,215,97,65,98,99,130,72,65,70,221,103,65,96,248,63,65,83,213,108,65,32,200,54,65,66,
135,112,65,108,0,0,48,65,0,0,144,65,108,0,0,224,64,0,0,144,65,108,202,111,210,64,67,135,112,65,98,74,
15,192,64,84,213,108,65,65,251,174,64,70,221,103,65,164,163,159,64,19,215,97,65,108,92,43,13,64,123,182,
115,65,108,187,181,82,62,133,73,60,65,108,244,26,36,64,254,170,30,65,98,64,102,33,64,55,224,25,5,0,0,32,
64,145,250,20,65,0,0,32,64,0,0,16,65,98,0,0,32,64,111,5,11,65,64,102,33,64,201,31,6,65,244,26,36,64,2,85,
1,65,108,187,181,82,62,246,108,199,64,108,92,43,13,64,20,38,49,64,108,164,163,159,64,180,163,120,64,98,65,
251,174,64,231,138,96,64,74,15,192,64,175,170,76,64,202,111,210,64,243,226,61,64,99,109,0,0,16,65,0,0,64,
65,98,121,130,42,65,0,0,64,65,0,0,64,65,121,130,42,65,0,0,64,65,0,0,16,65,98,0,0,64,65,13,251,234,64,121,
130,42,65,0,0,192,64,0,0,16,65,0,0,192,64,98,13,251,234,64,0,0,192,64,0,0,192,64,13,251,234,64,0,0,192,64,
0,0,16,65,98,0,0,192,64,121,130,42,65,13,251,234,64,0,0,64,65,0,0,16,65,0,0,64,65,99,101,0,0 };
Path p;
p.loadPathFromData (homeIconPathData, sizeof (homeIconPathData));
homeButton.setShape (p, true, true, false);
p.clear();
p.loadPathFromData (settingsIconPathData, sizeof (settingsIconPathData));
settingsButton.setShape (p, true, true, false);
titleLabel.setText (owner.getSidePanel().getTitleText(), NotificationType::dontSendNotification);
addAndMakeVisible (titleLabel);
homeButton.onClick = [this] { owner.homeButtonClicked(); };
addAndMakeVisible (homeButton);
addAndMakeVisible (settingsButton);
settingsButton.onClick = [this] { owner.settingsButtonClicked(); };
updateLookAndFeel();
}
void paint (Graphics& g) override
{
g.fillAll (owner.getSidePanel().findColour (SidePanel::backgroundColour));
}
void resized() override
{
auto bounds = getLocalBounds();
auto buttonWidth = owner.getSidePanel().getTitleBarHeight();
bounds.removeFromLeft (10);
homeButton.setBounds (bounds.removeFromLeft (buttonWidth).reduced (7));
settingsButton.setBounds (bounds.removeFromLeft (buttonWidth).reduced (7));
bounds.removeFromLeft (10);
bounds.removeFromRight (10);
titleLabel.setBounds (bounds);
}
void updateLookAndFeel()
{
auto& sidePanel = owner.getSidePanel();
auto& lf = sidePanel.getLookAndFeel();
titleLabel.setFont (lf.getSidePanelTitleFont (sidePanel));
titleLabel.setJustificationType (lf.getSidePanelTitleJustification (sidePanel));
titleLabel.setColour (Label::textColourId, owner.findColour (SidePanel::titleTextColour));
auto normal = sidePanel.findColour (SidePanel::dismissButtonNormalColour);
auto over = sidePanel.findColour (SidePanel::dismissButtonOverColour);
auto down = sidePanel.findColour (SidePanel::dismissButtonDownColour);
homeButton.setColours (normal, over, down);
settingsButton.setColours (normal, over, down);
}
void lookAndFeelChanged() override
{
updateLookAndFeel();
}
MainComponent& owner;
Label titleLabel;
ShapeButton homeButton { "Home", Colours::transparentBlack, Colours::transparentBlack, Colours::transparentBlack },
settingsButton { "Settings", Colours::transparentBlack, Colours::transparentBlack, Colours::transparentBlack };
};
//==============================================================================
class DemoList final : public Component,
public ListBoxModel
{
public:
DemoList (DemoContentComponent& holder)
: demoHolder (holder)
{
addAndMakeVisible (demos);
demos.setModel (this);
demos.setRowHeight (40);
}
void resized() override
{
demos.setBounds (getLocalBounds());
}
//==============================================================================
void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) override
{
Rectangle<int> bounds (0, 0, width, height);
auto textColour = findColour (Label::textColourId);
g.setColour (textColour.withAlpha (0.4f));
if (rowNumber == 0)
g.fillRect (bounds.removeFromTop (2).reduced (7, 0));
g.fillRect (bounds.removeFromBottom (2).reduced (7, 0));
if (rowIsSelected)
{
g.setColour (findColour (TextEditor::highlightColourId).withAlpha (0.4f));
g.fillRect (bounds);
textColour = findColour (TextEditor::highlightedTextColourId);
}
g.setColour (textColour);
g.drawFittedText (getNameForRow (rowNumber), bounds, Justification::centred, 1);
}
int getNumRows() override
{
return (int) (selectedCategory.isEmpty() ? JUCEDemos::getCategories().size()
: JUCEDemos::getCategory (selectedCategory).demos.size());
}
String getNameForRow (int rowNumber) override
{
if (selectedCategory.isEmpty())
{
if (isPositiveAndBelow (rowNumber, JUCEDemos::getCategories().size()))
return JUCEDemos::getCategories()[(size_t) rowNumber].name;
}
else
{
auto& category = JUCEDemos::getCategory (selectedCategory);
if (isPositiveAndBelow (rowNumber, category.demos.size()))
return category.demos[(size_t) rowNumber].demoFile.getFileName();
}
return {};
}
void returnKeyPressed (int row) override { selectRow (row); }
void listBoxItemClicked (int row, const MouseEvent&) override { selectRow (row); }
//==============================================================================
void showCategory (const String& categoryName) noexcept
{
selectedCategory = categoryName;
demos.deselectAllRows();
demos.setHeaderComponent (categoryName.isEmpty() ? nullptr
: std::make_unique<CategoryListHeaderComponent> (*this));
demos.updateContent();
}
private:
//==============================================================================
class CategoryListHeaderComponent final : public Button
{
public:
explicit CategoryListHeaderComponent (DemoList& o)
: Button ({}),
owner (o)
{
setTitle ("Previous");
setSize (0, 30);
}
void paintButton (Graphics& g, bool, bool) override
{
g.setColour (findColour (Label::textColourId));
g.drawFittedText ("<", getLocalBounds().reduced (20, 0), Justification::centredLeft, 1);
}
void clicked() override
{
owner.showCategory ({});
}
using Button::clicked;
private:
DemoList& owner;
};
//==============================================================================
void selectRow (int row)
{
if (row < 0)
return;
if (selectedCategory.isEmpty())
showCategory (JUCEDemos::getCategories()[(size_t) row].name);
else
demoHolder.setDemo (selectedCategory, row);
if (demos.isShowing())
selectFirstRow();
}
void selectFirstRow()
{
if (auto* handler = demos.getAccessibilityHandler())
{
for (auto* child : handler->getChildren())
{
if (child->getRole() == AccessibilityRole::listItem)
{
child->grabFocus();
break;
}
}
}
}
//==============================================================================
String selectedCategory;
DemoContentComponent& demoHolder;
ListBox demos;
};
//==============================================================================
MainComponent::MainComponent()
{
contentComponent.reset (new DemoContentComponent (*this, [this] (bool isHeavyweight)
{
demosPanel.showOrHide (false);
if (isHeavyweight)
{
#if JUCE_MAC && USE_COREGRAPHICS_RENDERING
setRenderingEngine (1);
#elif ! JUCE_WINDOWS
setRenderingEngine (0);
#endif
}
isShowingHeavyweightDemo = isHeavyweight;
resized();
}));
demosPanel.setContent (new DemoList (*contentComponent));
demosPanel.setTitleBarComponent (new SidePanelHeader (*this), true);
addAndMakeVisible (contentComponent.get());
addAndMakeVisible (showDemosButton);
addAndMakeVisible (demosPanel);
demosPanel.setTitle ("Demos");
demosPanel.setFocusContainerType (FocusContainerType::focusContainer);
showDemosButton.onClick = [this] { demosPanel.showOrHide (true); };
demosPanel.onPanelMove = [this]
{
sidePanelWidth = jmax (0, demosPanel.getRight());
if (isShowingHeavyweightDemo)
resized();
};
demosPanel.onPanelShowHide = [this] (bool isShowing)
{
if (isShowing)
{
sidePanelWidth = jmax (0, demosPanel.getWidth());
if (isShowingHeavyweightDemo)
resized();
if (auto* handler = demosPanel.getAccessibilityHandler())
handler->grabFocus();
}
else
{
sidePanelWidth = 0;
if (isShowingHeavyweightDemo)
Timer::callAfterDelay (250, [this] { resized(); });
}
};
contentComponent->showHomeScreen();
setOpaque (true);
setSize (800, 800);
}
MainComponent::~MainComponent()
{
contentComponent->clearCurrentDemo();
}
//==============================================================================
void MainComponent::paint (Graphics& g)
{
g.fillAll (findColour (ResizableWindow::backgroundColourId));
}
void MainComponent::resized()
{
auto safeBounds = [this]
{
auto bounds = getLocalBounds();
#if JUCE_IOS || JUCE_ANDROID
if (auto* display = Desktop::getInstance().getDisplays().getDisplayForRect (getScreenBounds()))
return display->safeAreaInsets.subtractedFrom (display->keyboardInsets.subtractedFrom (bounds));
#endif
return bounds;
}();
showDemosButton.setBounds (safeBounds.getX(), safeBounds.getY(), 150, contentComponent->getTabBarDepth());
if (isShowingHeavyweightDemo)
{
safeBounds.removeFromLeft (sidePanelWidth);
contentComponent->setTabBarIndent (jmax (0, 150 - sidePanelWidth));
}
else
{
contentComponent->setTabBarIndent (150);
}
contentComponent->setBounds (safeBounds);
}
void MainComponent::homeButtonClicked()
{
if (auto* list = dynamic_cast<DemoList*> (demosPanel.getContent()))
list->showCategory ({});
if (contentComponent != nullptr)
{
if (contentComponent->isShowingHomeScreen())
return;
contentComponent->showHomeScreen();
if (isShowingHeavyweightDemo)
{
isShowingHeavyweightDemo = false;
resized();
}
}
}
void MainComponent::settingsButtonClicked()
{
if (contentComponent != nullptr)
contentComponent->setCurrentTabIndex (2);
}
void MainComponent::setRenderingEngine (int renderingEngineIndex)
{
if (renderingEngineIndex != currentRenderingEngineIdx)
updateRenderingEngine (renderingEngineIndex);
}
void MainComponent::parentHierarchyChanged()
{
auto* newPeer = getPeer();
if (peer != newPeer)
{
peer = newPeer;
auto previousRenderingEngine = renderingEngines[currentRenderingEngineIdx];
renderingEngines.clear();
if (peer != nullptr)
renderingEngines = peer->getAvailableRenderingEngines();
renderingEngines.add ("OpenGL Renderer");
currentRenderingEngineIdx = renderingEngines.indexOf (previousRenderingEngine);
if (currentRenderingEngineIdx < 0)
{
#if JUCE_ANDROID
currentRenderingEngineIdx = (renderingEngines.size() - 1);
#else
currentRenderingEngineIdx = peer->getCurrentRenderingEngine();
#endif
}
updateRenderingEngine (currentRenderingEngineIdx);
}
}
void MainComponent::updateRenderingEngine (int renderingEngineIndex)
{
if (renderingEngineIndex == (renderingEngines.size() - 1))
{
if (isShowingHeavyweightDemo)
return;
openGLContext.attachTo (*getTopLevelComponent());
}
else
{
openGLContext.detach();
peer->setCurrentRenderingEngine (renderingEngineIndex);
}
currentRenderingEngineIdx = renderingEngineIndex;
}
@@ -0,0 +1,72 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#pragma once
#include <JuceHeader.h>
#include "DemoContentComponent.h"
//==============================================================================
class MainComponent final : public Component
{
public:
//==============================================================================
MainComponent();
~MainComponent() override;
//==============================================================================
void paint (Graphics&) override;
void resized() override;
//==============================================================================
SidePanel& getSidePanel() { return demosPanel; }
//==============================================================================
void homeButtonClicked();
void settingsButtonClicked();
//==============================================================================
StringArray getRenderingEngines() { return renderingEngines; }
int getCurrentRenderingEngine() { return currentRenderingEngineIdx; }
void setRenderingEngine (int index);
private:
void parentHierarchyChanged() override;
void updateRenderingEngine (int index);
//==============================================================================
std::unique_ptr<DemoContentComponent> contentComponent;
SidePanel demosPanel { "Demos", 250, true };
OpenGLContext openGLContext;
ComponentPeer* peer = nullptr;
StringArray renderingEngines;
int currentRenderingEngineIdx = -1;
TextButton showDemosButton { "Browse Demos" };
bool isShowingHeavyweightDemo = false;
int sidePanelWidth = 0;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};
@@ -0,0 +1,249 @@
/*
==============================================================================
This file is part of the JUCE framework examples.
Copyright (c) Raw Material Software Limited
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
to use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
==============================================================================
*/
#pragma once
#include "MainComponent.h"
//==============================================================================
class SettingsContent final : public Component
{
public:
SettingsContent (MainComponent& topLevelComponent)
: innerContent (topLevelComponent)
{
settingsViewport.setViewedComponent (&innerContent, false);
addAndMakeVisible (settingsViewport);
setFocusContainerType (FocusContainerType::focusContainer);
setTitle ("DemoRunner Settings");
setOpaque (true);
}
void paint (Graphics& g) override
{
g.fillAll (findColour (ResizableWindow::backgroundColourId));
}
void resized() override
{
constexpr int minimumWidth = 350;
constexpr int minimumHeight = 550;
auto r = getLocalBounds();
const auto scrollBarWidth = getLookAndFeel().getDefaultScrollbarWidth();
innerContent.setSize (jmax (r.getWidth() - scrollBarWidth, minimumWidth),
jmax (r.getHeight(), minimumHeight));
settingsViewport.setBounds (r);
}
private:
static constexpr float titleLabelFontHeight = 18.0f;
static constexpr int itemHeight = 30;
static constexpr int itemSpacing = 7;
class GraphicsSettingsGroup final : public Component,
private ComponentMovementWatcher
{
public:
GraphicsSettingsGroup (MainComponent& comp)
: ComponentMovementWatcher (&comp),
mainComponent (comp)
{
addAndMakeVisible (titleLabel);
titleLabel.setFont (FontOptions { titleLabelFontHeight });
addLookAndFeels();
addAndMakeVisible (lookAndFeelSelector);
for (int i = 0; i < lookAndFeelNames.size(); ++i)
lookAndFeelSelector.addItem (lookAndFeelNames.getReference (i), i + 1);
lookAndFeelSelector.setSelectedItemIndex (lookAndFeelNames.indexOf ("LookAndFeel_V4 (Dark)"));
lookAndFeelSelector.onChange = [this]
{
auto* lf = lookAndFeels.getUnchecked (lookAndFeelSelector.getSelectedItemIndex());
Desktop::getInstance().setDefaultLookAndFeel (lf);
};
addAndMakeVisible (lookAndFeelLabel);
lookAndFeelLabel.setJustificationType (Justification::centredRight);
lookAndFeelLabel.attachToComponent (&lookAndFeelSelector, true);
addAndMakeVisible (rendererSelector);
rendererSelector.onChange = [this] { mainComponent.setRenderingEngine (rendererSelector.getSelectedItemIndex()); };
addAndMakeVisible (rendererLabel);
rendererLabel.setJustificationType (Justification::centredRight);
rendererLabel.attachToComponent (&rendererSelector, true);
setFocusContainerType (FocusContainerType::focusContainer);
setTitle ("Graphics Settings");
}
void resized() override
{
auto bounds = getLocalBounds();
titleLabel.setBounds (bounds.removeFromTop (itemHeight));
bounds.removeFromTop (itemSpacing);
const auto xPos = roundToInt ((float) bounds.getX() + ((float) bounds.getWidth() * 0.35f));
const auto width = roundToInt ((float) bounds.getWidth() * 0.6f);
lookAndFeelSelector.setBounds (bounds.removeFromTop (itemHeight).withWidth (width).withX (xPos));
bounds.removeFromTop (itemSpacing);
rendererSelector.setBounds (bounds.removeFromTop (itemHeight).withWidth (width).withX (xPos));
}
private:
void componentMovedOrResized (bool, bool) override {}
using ComponentListener::componentMovedOrResized;
void componentVisibilityChanged() override {}
using ComponentListener::componentVisibilityChanged;
void componentPeerChanged() override
{
auto* newPeer = mainComponent.getPeer();
if (peer != newPeer)
{
peer = newPeer;
if (peer != nullptr)
refreshRenderingEngineSelector();
}
}
void refreshRenderingEngineSelector()
{
rendererSelector.clear (NotificationType::dontSendNotification);
rendererSelector.addItemList (mainComponent.getRenderingEngines(), 1);
rendererSelector.setSelectedItemIndex (mainComponent.getCurrentRenderingEngine());
}
void addLookAndFeels()
{
lookAndFeelNames.addArray ({ "LookAndFeel_V1", "LookAndFeel_V2", "LookAndFeel_V3",
"LookAndFeel_V4 (Dark)", "LookAndFeel_V4 (Midnight)",
"LookAndFeel_V4 (Grey)", "LookAndFeel_V4 (Light)" });
lookAndFeels.add (new LookAndFeel_V1());
lookAndFeels.add (new LookAndFeel_V2());
lookAndFeels.add (new LookAndFeel_V3());
lookAndFeels.add (new LookAndFeel_V4 (LookAndFeel_V4::getDarkColourScheme()));
lookAndFeels.add (new LookAndFeel_V4 (LookAndFeel_V4::getMidnightColourScheme()));
lookAndFeels.add (new LookAndFeel_V4 (LookAndFeel_V4::getGreyColourScheme()));
lookAndFeels.add (new LookAndFeel_V4 (LookAndFeel_V4::getLightColourScheme()));
}
MainComponent& mainComponent;
ComponentPeer* peer = nullptr;
Label titleLabel { {}, "Graphics" },
lookAndFeelLabel { {}, "LookAndFeel:" },
rendererLabel { {}, "Renderer:" };
ComboBox lookAndFeelSelector, rendererSelector;
StringArray lookAndFeelNames;
OwnedArray<LookAndFeel> lookAndFeels;
};
class AudioSettingsGroup final : public Component
{
public:
AudioSettingsGroup()
: deviceSelectorComp (getSharedAudioDeviceManager(), 0, 256, 0, 256, true, true, true, false)
{
addAndMakeVisible (titleLabel);
titleLabel.setFont (FontOptions { titleLabelFontHeight });
addAndMakeVisible (deviceSelectorComp);
deviceSelectorComp.setItemHeight (itemHeight);
setFocusContainerType (FocusContainerType::focusContainer);
setTitle ("Audio Settings");
}
void resized() override
{
auto bounds = getLocalBounds();
titleLabel.setBounds (bounds.removeFromTop (itemHeight));
bounds.removeFromTop (itemSpacing);
deviceSelectorComp.setBounds (bounds);
}
private:
Label titleLabel { {}, "Audio" };
AudioDeviceSelectorComponent deviceSelectorComp;
};
//==============================================================================
class InnerContent final : public Component
{
public:
InnerContent (MainComponent& mainComponent)
: graphicsSettings (mainComponent)
{
addAndMakeVisible (graphicsSettings);
addAndMakeVisible (audioSettings);
setOpaque (true);
}
void paint (Graphics& g) override
{
g.fillAll (findColour (ResizableWindow::backgroundColourId).contrasting (0.2f));
}
void resized() override
{
auto bounds = getLocalBounds();
graphicsSettings.setBounds (bounds.removeFromTop (150));
audioSettings.setBounds (bounds);
}
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
{
return createIgnoredAccessibilityHandler (*this);
}
private:
GraphicsSettingsGroup graphicsSettings;
AudioSettingsGroup audioSettings;
};
Viewport settingsViewport;
InnerContent innerContent;
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB