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:
103
deps/juce/extras/Projucer/Source/Application/Windows/jucer_AboutWindowComponent.h
vendored
Normal file
103
deps/juce/extras/Projucer/Source/Application/Windows/jucer_AboutWindowComponent.h
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class AboutWindowComponent : public Component
|
||||
{
|
||||
public:
|
||||
AboutWindowComponent()
|
||||
{
|
||||
addAndMakeVisible (titleLabel);
|
||||
titleLabel.setJustificationType (Justification::centred);
|
||||
titleLabel.setFont (Font (35.0f, Font::FontStyleFlags::bold));
|
||||
|
||||
auto buildDate = Time::getCompilationDate();
|
||||
addAndMakeVisible (versionLabel);
|
||||
versionLabel.setText ("JUCE v" + ProjucerApplication::getApp().getApplicationVersion()
|
||||
+ "\nBuild date: " + String (buildDate.getDayOfMonth())
|
||||
+ " " + Time::getMonthName (buildDate.getMonth(), true)
|
||||
+ " " + String (buildDate.getYear()),
|
||||
dontSendNotification);
|
||||
|
||||
versionLabel.setJustificationType (Justification::centred);
|
||||
addAndMakeVisible (copyrightLabel);
|
||||
copyrightLabel.setJustificationType (Justification::centred);
|
||||
|
||||
addAndMakeVisible (aboutButton);
|
||||
aboutButton.setTooltip ( {} );
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto bounds = getLocalBounds();
|
||||
bounds.removeFromBottom (20);
|
||||
|
||||
auto leftSlice = bounds.removeFromLeft (150);
|
||||
auto centreSlice = bounds.withTrimmedRight (150);
|
||||
|
||||
juceLogoBounds = leftSlice.removeFromTop (150).toFloat();
|
||||
juceLogoBounds.setWidth (juceLogoBounds.getWidth() + 100);
|
||||
juceLogoBounds.setHeight (juceLogoBounds.getHeight() + 100);
|
||||
|
||||
auto titleHeight = 40;
|
||||
|
||||
centreSlice.removeFromTop ((centreSlice.getHeight() / 2) - (titleHeight / 2));
|
||||
|
||||
titleLabel.setBounds (centreSlice.removeFromTop (titleHeight));
|
||||
|
||||
centreSlice.removeFromTop (10);
|
||||
versionLabel.setBounds (centreSlice.removeFromTop (40));
|
||||
|
||||
centreSlice.removeFromTop (10);
|
||||
aboutButton.setBounds (centreSlice.removeFromTop (20));
|
||||
|
||||
copyrightLabel.setBounds (getLocalBounds().removeFromBottom (50));
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillAll (findColour (backgroundColourId));
|
||||
|
||||
if (juceLogo != nullptr)
|
||||
juceLogo->drawWithin (g, juceLogoBounds.translated (-75, -75), RectanglePlacement::centred, 1.0);
|
||||
}
|
||||
|
||||
private:
|
||||
Label titleLabel { "title", "PROJUCER" },
|
||||
versionLabel { "version" },
|
||||
copyrightLabel { "copyright", String (CharPointer_UTF8 ("\xc2\xa9")) + String (" 2020 Raw Material Software Limited") };
|
||||
|
||||
HyperlinkButton aboutButton { "About Us", URL ("https://juce.com") };
|
||||
|
||||
Rectangle<float> juceLogoBounds;
|
||||
|
||||
std::unique_ptr<Drawable> juceLogo { Drawable::createFromImageData (BinaryData::juce_icon_png,
|
||||
BinaryData::juce_icon_pngSize) };
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AboutWindowComponent)
|
||||
};
|
347
deps/juce/extras/Projucer/Source/Application/Windows/jucer_EditorColourSchemeWindowComponent.h
vendored
Normal file
347
deps/juce/extras/Projucer/Source/Application/Windows/jucer_EditorColourSchemeWindowComponent.h
vendored
Normal file
@ -0,0 +1,347 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../Utility/UI/PropertyComponents/jucer_ColourPropertyComponent.h"
|
||||
|
||||
//==============================================================================
|
||||
class EditorColourSchemeWindowComponent : public Component
|
||||
{
|
||||
public:
|
||||
EditorColourSchemeWindowComponent()
|
||||
{
|
||||
if (getAppSettings().monospacedFontNames.size() == 0)
|
||||
changeContent (new AppearanceEditor::FontScanPanel());
|
||||
else
|
||||
changeContent (new AppearanceEditor::EditorPanel());
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillAll (findColour (backgroundColourId));
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
content->setBounds (getLocalBounds());
|
||||
}
|
||||
|
||||
void changeContent (Component* newContent)
|
||||
{
|
||||
content.reset (newContent);
|
||||
addAndMakeVisible (newContent);
|
||||
content->setBounds (getLocalBounds().reduced (10));
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Component> content;
|
||||
|
||||
//==============================================================================
|
||||
struct AppearanceEditor
|
||||
{
|
||||
struct FontScanPanel : public Component,
|
||||
private Timer
|
||||
{
|
||||
FontScanPanel()
|
||||
{
|
||||
fontsToScan = Font::findAllTypefaceNames();
|
||||
startTimer (1);
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillAll (findColour (backgroundColourId));
|
||||
|
||||
g.setFont (14.0f);
|
||||
g.setColour (findColour (defaultTextColourId));
|
||||
g.drawFittedText ("Scanning for fonts..", getLocalBounds(), Justification::centred, 2);
|
||||
|
||||
const auto size = 30;
|
||||
getLookAndFeel().drawSpinningWaitAnimation (g, Colours::white, (getWidth() - size) / 2, getHeight() / 2 - 50, size, size);
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
repaint();
|
||||
|
||||
if (fontsToScan.size() == 0)
|
||||
{
|
||||
getAppSettings().monospacedFontNames = fontsFound;
|
||||
|
||||
if (auto* owner = findParentComponentOfClass<EditorColourSchemeWindowComponent>())
|
||||
owner->changeContent (new EditorPanel());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isMonospacedTypeface (fontsToScan[0]))
|
||||
fontsFound.add (fontsToScan[0]);
|
||||
|
||||
fontsToScan.remove (0);
|
||||
}
|
||||
}
|
||||
|
||||
// A rather hacky trick to select only the fixed-pitch fonts..
|
||||
// This is unfortunately a bit slow, but will work on all platforms.
|
||||
static bool isMonospacedTypeface (const String& name)
|
||||
{
|
||||
const Font font (name, 20.0f, Font::plain);
|
||||
|
||||
const auto width = font.getStringWidth ("....");
|
||||
|
||||
return width == font.getStringWidth ("WWWW")
|
||||
&& width == font.getStringWidth ("0000")
|
||||
&& width == font.getStringWidth ("1111")
|
||||
&& width == font.getStringWidth ("iiii");
|
||||
}
|
||||
|
||||
StringArray fontsToScan, fontsFound;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct EditorPanel : public Component
|
||||
{
|
||||
EditorPanel()
|
||||
: loadButton ("Load Scheme..."),
|
||||
saveButton ("Save Scheme...")
|
||||
{
|
||||
rebuildProperties();
|
||||
addAndMakeVisible (panel);
|
||||
|
||||
addAndMakeVisible (loadButton);
|
||||
addAndMakeVisible (saveButton);
|
||||
|
||||
loadButton.onClick = [this] { loadScheme(); };
|
||||
saveButton.onClick = [this] { saveScheme (false); };
|
||||
|
||||
lookAndFeelChanged();
|
||||
|
||||
saveSchemeState();
|
||||
}
|
||||
|
||||
~EditorPanel() override
|
||||
{
|
||||
if (hasSchemeBeenModifiedSinceSave())
|
||||
saveScheme (true);
|
||||
}
|
||||
|
||||
void rebuildProperties()
|
||||
{
|
||||
auto& scheme = getAppSettings().appearance;
|
||||
|
||||
Array<PropertyComponent*> props;
|
||||
auto fontValue = scheme.getCodeFontValue();
|
||||
props.add (FontNameValueSource::createProperty ("Code Editor Font", fontValue));
|
||||
props.add (FontSizeValueSource::createProperty ("Font Size", fontValue));
|
||||
|
||||
const auto colourNames = scheme.getColourNames();
|
||||
|
||||
for (int i = 0; i < colourNames.size(); ++i)
|
||||
props.add (new ColourPropertyComponent (nullptr, colourNames[i],
|
||||
scheme.getColourValue (colourNames[i]),
|
||||
Colours::white, false));
|
||||
|
||||
panel.clear();
|
||||
panel.addProperties (props);
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto r = getLocalBounds();
|
||||
panel.setBounds (r.removeFromTop (getHeight() - 28).reduced (10, 2));
|
||||
loadButton.setBounds (r.removeFromLeft (getWidth() / 2).reduced (10, 1));
|
||||
saveButton.setBounds (r.reduced (10, 1));
|
||||
}
|
||||
|
||||
private:
|
||||
PropertyPanel panel;
|
||||
TextButton loadButton, saveButton;
|
||||
|
||||
Font codeFont;
|
||||
Array<var> colourValues;
|
||||
|
||||
void saveScheme (bool isExit)
|
||||
{
|
||||
chooser = std::make_unique<FileChooser> ("Select a file in which to save this colour-scheme...",
|
||||
getAppSettings().appearance.getSchemesFolder()
|
||||
.getNonexistentChildFile ("Scheme", AppearanceSettings::getSchemeFileSuffix()),
|
||||
AppearanceSettings::getSchemeFileWildCard());
|
||||
auto chooserFlags = FileBrowserComponent::saveMode
|
||||
| FileBrowserComponent::canSelectFiles
|
||||
| FileBrowserComponent::warnAboutOverwriting;
|
||||
|
||||
chooser->launchAsync (chooserFlags, [this, isExit] (const FileChooser& fc)
|
||||
{
|
||||
if (fc.getResult() == File{})
|
||||
{
|
||||
if (isExit)
|
||||
restorePreviousScheme();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
File file (fc.getResult().withFileExtension (AppearanceSettings::getSchemeFileSuffix()));
|
||||
getAppSettings().appearance.writeToFile (file);
|
||||
getAppSettings().appearance.refreshPresetSchemeList();
|
||||
|
||||
saveSchemeState();
|
||||
ProjucerApplication::getApp().selectEditorColourSchemeWithName (file.getFileNameWithoutExtension());
|
||||
});
|
||||
}
|
||||
|
||||
void loadScheme()
|
||||
{
|
||||
chooser = std::make_unique<FileChooser> ("Please select a colour-scheme file to load...",
|
||||
getAppSettings().appearance.getSchemesFolder(),
|
||||
AppearanceSettings::getSchemeFileWildCard());
|
||||
auto chooserFlags = FileBrowserComponent::openMode
|
||||
| FileBrowserComponent::canSelectFiles;
|
||||
|
||||
chooser->launchAsync (chooserFlags, [this] (const FileChooser& fc)
|
||||
{
|
||||
if (fc.getResult() == File{})
|
||||
return;
|
||||
|
||||
if (getAppSettings().appearance.readFromFile (fc.getResult()))
|
||||
{
|
||||
rebuildProperties();
|
||||
saveSchemeState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void lookAndFeelChanged() override
|
||||
{
|
||||
loadButton.setColour (TextButton::buttonColourId,
|
||||
findColour (secondaryButtonBackgroundColourId));
|
||||
}
|
||||
|
||||
void saveSchemeState()
|
||||
{
|
||||
auto& appearance = getAppSettings().appearance;
|
||||
const auto colourNames = appearance.getColourNames();
|
||||
|
||||
codeFont = appearance.getCodeFont();
|
||||
|
||||
colourValues.clear();
|
||||
for (int i = 0; i < colourNames.size(); ++i)
|
||||
colourValues.add (appearance.getColourValue (colourNames[i]).getValue());
|
||||
}
|
||||
|
||||
bool hasSchemeBeenModifiedSinceSave()
|
||||
{
|
||||
auto& appearance = getAppSettings().appearance;
|
||||
const auto colourNames = appearance.getColourNames();
|
||||
|
||||
if (codeFont != appearance.getCodeFont())
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < colourNames.size(); ++i)
|
||||
if (colourValues[i] != appearance.getColourValue (colourNames[i]).getValue())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void restorePreviousScheme()
|
||||
{
|
||||
auto& appearance = getAppSettings().appearance;
|
||||
const auto colourNames = appearance.getColourNames();
|
||||
|
||||
appearance.getCodeFontValue().setValue (codeFont.toString());
|
||||
|
||||
for (int i = 0; i < colourNames.size(); ++i)
|
||||
appearance.getColourValue (colourNames[i]).setValue (colourValues[i]);
|
||||
}
|
||||
|
||||
std::unique_ptr<FileChooser> chooser;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (EditorPanel)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct FontNameValueSource : public ValueSourceFilter
|
||||
{
|
||||
FontNameValueSource (const Value& source) : ValueSourceFilter (source) {}
|
||||
|
||||
var getValue() const override
|
||||
{
|
||||
return Font::fromString (sourceValue.toString()).getTypefaceName();
|
||||
}
|
||||
|
||||
void setValue (const var& newValue) override
|
||||
{
|
||||
auto font = Font::fromString (sourceValue.toString());
|
||||
font.setTypefaceName (newValue.toString().isEmpty() ? Font::getDefaultMonospacedFontName()
|
||||
: newValue.toString());
|
||||
sourceValue = font.toString();
|
||||
}
|
||||
|
||||
static ChoicePropertyComponent* createProperty (const String& title, const Value& value)
|
||||
{
|
||||
auto fontNames = getAppSettings().monospacedFontNames;
|
||||
|
||||
Array<var> values;
|
||||
values.add (Font::getDefaultMonospacedFontName());
|
||||
values.add (var());
|
||||
|
||||
for (int i = 0; i < fontNames.size(); ++i)
|
||||
values.add (fontNames[i]);
|
||||
|
||||
StringArray names;
|
||||
names.add ("<Default Monospaced>");
|
||||
names.add (String());
|
||||
names.addArray (getAppSettings().monospacedFontNames);
|
||||
|
||||
return new ChoicePropertyComponent (Value (new FontNameValueSource (value)),
|
||||
title, names, values);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct FontSizeValueSource : public ValueSourceFilter
|
||||
{
|
||||
FontSizeValueSource (const Value& source) : ValueSourceFilter (source) {}
|
||||
|
||||
var getValue() const override
|
||||
{
|
||||
return Font::fromString (sourceValue.toString()).getHeight();
|
||||
}
|
||||
|
||||
void setValue (const var& newValue) override
|
||||
{
|
||||
sourceValue = Font::fromString (sourceValue.toString()).withHeight (newValue).toString();
|
||||
}
|
||||
|
||||
static PropertyComponent* createProperty (const String& title, const Value& value)
|
||||
{
|
||||
return new SliderPropertyComponent (Value (new FontSizeValueSource (value)),
|
||||
title, 5.0, 40.0, 0.1, 0.5);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EditorColourSchemeWindowComponent)
|
||||
};
|
89
deps/juce/extras/Projucer/Source/Application/Windows/jucer_FloatingToolWindow.h
vendored
Normal file
89
deps/juce/extras/Projucer/Source/Application/Windows/jucer_FloatingToolWindow.h
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//==============================================================================
|
||||
struct FloatingToolWindow : public DialogWindow
|
||||
{
|
||||
FloatingToolWindow (const String& title,
|
||||
const String& windowPosPropertyName,
|
||||
Component* content,
|
||||
std::unique_ptr<Component>& ownerPointer,
|
||||
bool shouldBeResizable,
|
||||
int defaultW, int defaultH,
|
||||
int minW, int minH,
|
||||
int maxW, int maxH)
|
||||
: DialogWindow (title, content->findColour (secondaryBackgroundColourId), true, true),
|
||||
windowPosProperty (windowPosPropertyName),
|
||||
owner (ownerPointer)
|
||||
{
|
||||
setUsingNativeTitleBar (true);
|
||||
setResizable (shouldBeResizable, shouldBeResizable);
|
||||
setResizeLimits (minW, minH, maxW, maxH);
|
||||
setContentOwned (content, false);
|
||||
|
||||
String windowState;
|
||||
if (windowPosProperty.isNotEmpty())
|
||||
windowState = getGlobalProperties().getValue (windowPosProperty);
|
||||
|
||||
if (windowState.isNotEmpty())
|
||||
restoreWindowStateFromString (windowState);
|
||||
else
|
||||
centreAroundComponent (Component::getCurrentlyFocusedComponent(), defaultW, defaultH);
|
||||
|
||||
setVisible (true);
|
||||
owner.reset (this);
|
||||
}
|
||||
|
||||
~FloatingToolWindow() override
|
||||
{
|
||||
if (windowPosProperty.isNotEmpty())
|
||||
getGlobalProperties().setValue (windowPosProperty, getWindowStateAsString());
|
||||
}
|
||||
|
||||
void closeButtonPressed() override
|
||||
{
|
||||
owner.reset();
|
||||
}
|
||||
|
||||
bool escapeKeyPressed() override
|
||||
{
|
||||
closeButtonPressed();
|
||||
return true;
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillAll (findColour (secondaryBackgroundColourId));
|
||||
}
|
||||
|
||||
private:
|
||||
String windowPosProperty;
|
||||
std::unique_ptr<Component>& owner;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FloatingToolWindow)
|
||||
};
|
318
deps/juce/extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h
vendored
Normal file
318
deps/juce/extras/Projucer/Source/Application/Windows/jucer_GlobalPathsWindowComponent.h
vendored
Normal file
@ -0,0 +1,318 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../Utility/UI/PropertyComponents/jucer_LabelPropertyComponent.h"
|
||||
|
||||
//==============================================================================
|
||||
class GlobalPathsWindowComponent : public Component,
|
||||
private Timer,
|
||||
private Value::Listener,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
GlobalPathsWindowComponent()
|
||||
{
|
||||
addChildComponent (rescanJUCEPathButton);
|
||||
rescanJUCEPathButton.onClick = [this]
|
||||
{
|
||||
ProjucerApplication::getApp().rescanJUCEPathModules();
|
||||
lastJUCEModulePath = getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get();
|
||||
};
|
||||
|
||||
addChildComponent (rescanUserPathButton);
|
||||
rescanUserPathButton.onClick = [this]
|
||||
{
|
||||
ProjucerApplication::getApp().rescanUserPathModules();
|
||||
lastUserModulePath = getAppSettings().getStoredPath (Ids::defaultUserModulePath, TargetOS::getThisOS()).get();
|
||||
};
|
||||
|
||||
addChildComponent (warnAboutJUCEPathButton);
|
||||
warnAboutJUCEPathButton.setToggleState (ProjucerApplication::getApp().shouldPromptUserAboutIncorrectJUCEPath(),
|
||||
dontSendNotification);
|
||||
warnAboutJUCEPathButton.onClick = [this]
|
||||
{
|
||||
ProjucerApplication::getApp().setShouldPromptUserAboutIncorrectJUCEPath (warnAboutJUCEPathButton.getToggleState());
|
||||
};
|
||||
|
||||
getGlobalProperties().addChangeListener (this);
|
||||
|
||||
addAndMakeVisible (resetToDefaultsButton);
|
||||
resetToDefaultsButton.onClick = [this] { resetCurrentOSPathsToDefaults(); };
|
||||
|
||||
addAndMakeVisible (propertyViewport);
|
||||
propertyViewport.setViewedComponent (&propertyGroup, false);
|
||||
|
||||
auto os = TargetOS::getThisOS();
|
||||
|
||||
if (os == TargetOS::osx) selectedOSValue = "osx";
|
||||
else if (os == TargetOS::windows) selectedOSValue = "windows";
|
||||
else if (os == TargetOS::linux) selectedOSValue = "linux";
|
||||
|
||||
selectedOSValue.addListener (this);
|
||||
|
||||
buildProps();
|
||||
|
||||
lastJUCEModulePath = getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS()).get();
|
||||
lastUserModulePath = getAppSettings().getStoredPath (Ids::defaultUserModulePath, TargetOS::getThisOS()).get();
|
||||
}
|
||||
|
||||
~GlobalPathsWindowComponent() override
|
||||
{
|
||||
getGlobalProperties().removeChangeListener (this);
|
||||
|
||||
auto juceValue = getAppSettings().getStoredPath (Ids::defaultJuceModulePath, TargetOS::getThisOS());
|
||||
auto userValue = getAppSettings().getStoredPath (Ids::defaultUserModulePath, TargetOS::getThisOS());
|
||||
|
||||
if (juceValue.get() != lastJUCEModulePath) ProjucerApplication::getApp().rescanJUCEPathModules();
|
||||
if (userValue.get() != lastUserModulePath) ProjucerApplication::getApp().rescanUserPathModules();
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillAll (findColour (backgroundColourId));
|
||||
}
|
||||
|
||||
void paintOverChildren (Graphics& g) override
|
||||
{
|
||||
g.setColour (findColour (defaultHighlightColourId).withAlpha (flashAlpha));
|
||||
g.fillRect (boundsToHighlight);
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto b = getLocalBounds().reduced (10);
|
||||
|
||||
auto bottomBounds = b.removeFromBottom (80);
|
||||
auto buttonBounds = bottomBounds.removeFromBottom (50);
|
||||
|
||||
rescanJUCEPathButton.setBounds (buttonBounds.removeFromLeft (150).reduced (5, 10));
|
||||
rescanUserPathButton.setBounds (buttonBounds.removeFromLeft (150).reduced (5, 10));
|
||||
|
||||
resetToDefaultsButton.setBounds (buttonBounds.removeFromRight (150).reduced (5, 10));
|
||||
warnAboutJUCEPathButton.setBounds (bottomBounds.reduced (0, 5));
|
||||
warnAboutJUCEPathButton.changeWidthToFitText();
|
||||
|
||||
propertyGroup.updateSize (0, 0, getWidth() - 20 - propertyViewport.getScrollBarThickness());
|
||||
propertyViewport.setBounds (b);
|
||||
}
|
||||
|
||||
void highlightJUCEPath()
|
||||
{
|
||||
if (isTimerRunning() || ! isSelectedOSThisOS())
|
||||
return;
|
||||
|
||||
const auto findJucePathPropertyComponent = [this]() -> PropertyComponent*
|
||||
{
|
||||
for (const auto& prop : propertyGroup.getProperties())
|
||||
if (prop->getName() == "Path to JUCE")
|
||||
return prop.get();
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
if (auto* propComponent = findJucePathPropertyComponent())
|
||||
{
|
||||
boundsToHighlight = getLocalArea (nullptr, propComponent->getScreenBounds());
|
||||
flashAlpha = 0.0f;
|
||||
hasFlashed = false;
|
||||
|
||||
startTimer (25);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void timerCallback() override
|
||||
{
|
||||
flashAlpha += (hasFlashed ? -0.05f : 0.05f);
|
||||
|
||||
if (flashAlpha > 0.75f)
|
||||
{
|
||||
hasFlashed = true;
|
||||
}
|
||||
else if (flashAlpha < 0.0f)
|
||||
{
|
||||
flashAlpha = 0.0f;
|
||||
boundsToHighlight = {};
|
||||
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
void valueChanged (Value&) override
|
||||
{
|
||||
buildProps();
|
||||
resized();
|
||||
}
|
||||
|
||||
void changeListenerCallback (ChangeBroadcaster*) override
|
||||
{
|
||||
warnAboutJUCEPathButton.setToggleState (ProjucerApplication::getApp().shouldPromptUserAboutIncorrectJUCEPath(),
|
||||
dontSendNotification);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool isSelectedOSThisOS() { return TargetOS::getThisOS() == getSelectedOS(); }
|
||||
|
||||
TargetOS::OS getSelectedOS() const
|
||||
{
|
||||
auto val = selectedOSValue.getValue();
|
||||
|
||||
if (val == "osx") return TargetOS::osx;
|
||||
else if (val == "windows") return TargetOS::windows;
|
||||
else if (val == "linux") return TargetOS::linux;
|
||||
|
||||
jassertfalse;
|
||||
return TargetOS::unknown;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void buildProps()
|
||||
{
|
||||
updateValues();
|
||||
|
||||
PropertyListBuilder builder;
|
||||
auto isThisOS = isSelectedOSThisOS();
|
||||
|
||||
builder.add (new ChoicePropertyComponent (selectedOSValue, "OS", { "OSX", "Windows", "Linux" }, { "osx", "windows", "linux" }),
|
||||
"Use this dropdown to set the global paths for different OSes. "
|
||||
"\nN.B. These paths are stored locally and will only be used when "
|
||||
"saving a project on this machine. Other machines will have their own "
|
||||
"locally stored paths.");
|
||||
|
||||
builder.add (new LabelPropertyComponent ("JUCE"), {});
|
||||
|
||||
builder.add (new FilePathPropertyComponent (jucePathValue, "Path to JUCE", true, isThisOS),
|
||||
"This should be the path to the top-level directory of your JUCE folder. "
|
||||
"This path will be used when searching for the JUCE examples and DemoRunner application.");
|
||||
|
||||
builder.add (new FilePathPropertyComponent (juceModulePathValue, "JUCE Modules", true, isThisOS),
|
||||
String ("This should be the path to the folder containing the JUCE modules that you wish to use, typically the \"modules\" directory of your JUCE folder.")
|
||||
+ (isThisOS ? " Use the button below to re-scan a new path." : ""));
|
||||
builder.add (new FilePathPropertyComponent (userModulePathValue, "User Modules", true, isThisOS),
|
||||
String ("A path to a folder containing any custom modules that you wish to use.")
|
||||
+ (isThisOS ? " Use the button below to re-scan new paths." : ""));
|
||||
|
||||
builder.add (new LabelPropertyComponent ("SDKs"), {});
|
||||
|
||||
builder.add (new FilePathPropertyComponent (vstPathValue, "VST (Legacy) SDK", true, isThisOS),
|
||||
"If you are building a legacy VST plug-in then this path should point to a VST2 SDK. "
|
||||
"The VST2 SDK can be obtained from the vstsdk3610_11_06_2018_build_37 (or older) VST3 SDK or JUCE version 5.3.2. "
|
||||
"You also need a VST2 license from Steinberg to distribute VST2 plug-ins.");
|
||||
|
||||
if (getSelectedOS() != TargetOS::linux)
|
||||
{
|
||||
builder.add (new FilePathPropertyComponent (aaxPathValue, "AAX SDK", true, isThisOS),
|
||||
"If you are building AAX plug-ins, this should be the path to the AAX SDK folder.");
|
||||
builder.add (new FilePathPropertyComponent (rtasPathValue, "RTAS SDK (deprecated)", true, isThisOS),
|
||||
"If you are building RTAS plug-ins, this should be the path to the RTAS SDK folder.");
|
||||
}
|
||||
|
||||
builder.add (new FilePathPropertyComponent (androidSDKPathValue, "Android SDK", true, isThisOS),
|
||||
"This path will be used when writing the local.properties file of an Android project and should point to the Android SDK folder.");
|
||||
|
||||
if (isThisOS)
|
||||
{
|
||||
builder.add (new LabelPropertyComponent ("Other"), {});
|
||||
|
||||
#if JUCE_MAC
|
||||
String exeLabel ("app");
|
||||
#elif JUCE_WINDOWS
|
||||
String exeLabel ("executable");
|
||||
#else
|
||||
String exeLabel ("startup script");
|
||||
#endif
|
||||
|
||||
builder.add (new FilePathPropertyComponent (clionExePathValue, "CLion " + exeLabel, false, isThisOS),
|
||||
"This path will be used for the \"Save Project and Open in IDE...\" option of the CLion exporter.");
|
||||
builder.add (new FilePathPropertyComponent (androidStudioExePathValue, "Android Studio " + exeLabel, false, isThisOS),
|
||||
"This path will be used for the \"Save Project and Open in IDE...\" option of the Android Studio exporter.");
|
||||
}
|
||||
|
||||
rescanJUCEPathButton.setVisible (isThisOS);
|
||||
rescanUserPathButton.setVisible (isThisOS);
|
||||
warnAboutJUCEPathButton.setVisible (isThisOS);
|
||||
|
||||
propertyGroup.setProperties (builder);
|
||||
}
|
||||
|
||||
void updateValues()
|
||||
{
|
||||
auto& settings = getAppSettings();
|
||||
auto os = getSelectedOS();
|
||||
|
||||
jucePathValue = settings.getStoredPath (Ids::jucePath, os);
|
||||
juceModulePathValue = settings.getStoredPath (Ids::defaultJuceModulePath, os);
|
||||
userModulePathValue = settings.getStoredPath (Ids::defaultUserModulePath, os);
|
||||
vstPathValue = settings.getStoredPath (Ids::vstLegacyPath, os);
|
||||
rtasPathValue = settings.getStoredPath (Ids::rtasPath, os);
|
||||
aaxPathValue = settings.getStoredPath (Ids::aaxPath, os);
|
||||
androidSDKPathValue = settings.getStoredPath (Ids::androidSDKPath, os);
|
||||
clionExePathValue = settings.getStoredPath (Ids::clionExePath, os);
|
||||
androidStudioExePathValue = settings.getStoredPath (Ids::androidStudioExePath, os);
|
||||
}
|
||||
|
||||
void resetCurrentOSPathsToDefaults()
|
||||
{
|
||||
jucePathValue .resetToDefault();
|
||||
juceModulePathValue .resetToDefault();
|
||||
userModulePathValue .resetToDefault();
|
||||
vstPathValue .resetToDefault();
|
||||
rtasPathValue .resetToDefault();
|
||||
aaxPathValue .resetToDefault();
|
||||
androidSDKPathValue .resetToDefault();
|
||||
clionExePathValue .resetToDefault();
|
||||
androidStudioExePathValue.resetToDefault();
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Value selectedOSValue;
|
||||
|
||||
ValueWithDefault jucePathValue, juceModulePathValue, userModulePathValue,
|
||||
vstPathValue, rtasPathValue, aaxPathValue, androidSDKPathValue, clionExePathValue, androidStudioExePathValue;
|
||||
|
||||
Viewport propertyViewport;
|
||||
PropertyGroupComponent propertyGroup { "Global Paths", { getIcons().openFolder, Colours::transparentBlack } };
|
||||
|
||||
ToggleButton warnAboutJUCEPathButton { "Warn about incorrect JUCE path" };
|
||||
TextButton rescanJUCEPathButton { "Re-scan JUCE Modules" },
|
||||
rescanUserPathButton { "Re-scan User Modules" },
|
||||
resetToDefaultsButton { "Reset to Defaults" };
|
||||
|
||||
Rectangle<int> boundsToHighlight;
|
||||
float flashAlpha = 0.0f;
|
||||
bool hasFlashed = false;
|
||||
|
||||
var lastJUCEModulePath, lastUserModulePath;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlobalPathsWindowComponent)
|
||||
};
|
347
deps/juce/extras/Projucer/Source/Application/Windows/jucer_PIPCreatorWindowComponent.h
vendored
Normal file
347
deps/juce/extras/Projucer/Source/Application/Windows/jucer_PIPCreatorWindowComponent.h
vendored
Normal file
@ -0,0 +1,347 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//==============================================================================
|
||||
static String getWidthLimitedStringFromVarArray (const var& varArray) noexcept
|
||||
{
|
||||
if (! varArray.isArray())
|
||||
return {};
|
||||
|
||||
int numLines = 1;
|
||||
const int lineWidth = 100;
|
||||
const String indent (" ");
|
||||
|
||||
String str;
|
||||
if (auto* arr = varArray.getArray())
|
||||
{
|
||||
for (auto& v : *arr)
|
||||
{
|
||||
if ((str.length() + v.toString().length()) > (lineWidth * numLines))
|
||||
{
|
||||
str += newLine;
|
||||
str += indent;
|
||||
|
||||
++numLines;
|
||||
}
|
||||
|
||||
str += v.toString() + (arr->indexOf (v) != arr->size() - 1 ? ", " : "");
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class PIPCreatorWindowComponent : public Component,
|
||||
private ValueTree::Listener
|
||||
{
|
||||
public:
|
||||
PIPCreatorWindowComponent()
|
||||
{
|
||||
lf.reset (new PIPCreatorLookAndFeel());
|
||||
setLookAndFeel (lf.get());
|
||||
|
||||
addAndMakeVisible (propertyViewport);
|
||||
propertyViewport.setViewedComponent (&propertyGroup, false);
|
||||
buildProps();
|
||||
|
||||
addAndMakeVisible (createButton);
|
||||
createButton.onClick = [this]
|
||||
{
|
||||
chooser = std::make_unique<FileChooser> ("Save PIP File",
|
||||
File::getSpecialLocation (File::SpecialLocationType::userDesktopDirectory)
|
||||
.getChildFile (nameValue.get().toString() + ".h"));
|
||||
auto browserFlags = FileBrowserComponent::saveMode
|
||||
| FileBrowserComponent::canSelectFiles
|
||||
| FileBrowserComponent::warnAboutOverwriting;
|
||||
|
||||
chooser->launchAsync (browserFlags, [this] (const FileChooser& fc)
|
||||
{
|
||||
const auto result = fc.getResult();
|
||||
|
||||
if (result != File{})
|
||||
createPIPFile (result);
|
||||
});
|
||||
};
|
||||
|
||||
pipTree.addListener (this);
|
||||
}
|
||||
|
||||
~PIPCreatorWindowComponent() override
|
||||
{
|
||||
setLookAndFeel (nullptr);
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto bounds = getLocalBounds();
|
||||
|
||||
createButton.setBounds (bounds.removeFromBottom (50).reduced (100, 10));
|
||||
|
||||
propertyGroup.updateSize (0, 0, getWidth() - propertyViewport.getScrollBarThickness());
|
||||
propertyViewport.setBounds (bounds);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
struct PIPCreatorLookAndFeel : public ProjucerLookAndFeel
|
||||
{
|
||||
PIPCreatorLookAndFeel() {}
|
||||
|
||||
Rectangle<int> getPropertyComponentContentPosition (PropertyComponent& component)
|
||||
{
|
||||
auto textW = jmin (200, component.getWidth() / 3);
|
||||
return { textW, 0, component.getWidth() - textW, component.getHeight() - 1 };
|
||||
}
|
||||
};
|
||||
|
||||
void lookAndFeelChanged() override
|
||||
{
|
||||
lf->setColourScheme (ProjucerApplication::getApp().lookAndFeel.getCurrentColourScheme());
|
||||
lf->setupColours();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void buildProps()
|
||||
{
|
||||
PropertyListBuilder builder;
|
||||
|
||||
builder.add (new TextPropertyComponent (nameValue, "Name", 256, false),
|
||||
"The name of your JUCE project.");
|
||||
builder.add (new TextPropertyComponent (versionValue, "Version", 16, false),
|
||||
"This will be used for the \"Project Version\" field in the Projucer.");
|
||||
builder.add (new TextPropertyComponent (vendorValue, "Vendor", 2048, false),
|
||||
"This will be used for the \"Company Name\" field in the Projucer.");
|
||||
builder.add (new TextPropertyComponent (websiteValue, "Website", 2048, false),
|
||||
"This will be used for the \"Company Website\" field in the Projucer");
|
||||
builder.add (new TextPropertyComponent (descriptionValue, "Description", 2048, true),
|
||||
"A short description of your JUCE project.");
|
||||
|
||||
{
|
||||
Array<var> moduleVars;
|
||||
for (auto& m : getJUCEModules())
|
||||
moduleVars.add (m);
|
||||
|
||||
builder.add (new MultiChoicePropertyComponent (dependenciesValue, "Dependencies",
|
||||
getJUCEModules(), moduleVars),
|
||||
"The JUCE modules that should be added to your project.");
|
||||
}
|
||||
|
||||
{
|
||||
Array<var> exporterVars;
|
||||
StringArray exporterNames;
|
||||
|
||||
for (auto& exporterTypeInfo : ProjectExporter::getExporterTypeInfos())
|
||||
{
|
||||
exporterVars.add (exporterTypeInfo.identifier.toString());
|
||||
exporterNames.add (exporterTypeInfo.displayName);
|
||||
}
|
||||
|
||||
builder.add (new MultiChoicePropertyComponent (exportersValue, "Exporters", exporterNames, exporterVars),
|
||||
"The exporters that should be added to your project.");
|
||||
}
|
||||
|
||||
builder.add (new TextPropertyComponent (moduleFlagsValue, "Module Flags", 2048, true),
|
||||
"Use this to set one, or many, of the JUCE module flags");
|
||||
builder.add (new TextPropertyComponent (definesValue, "Defines", 2048, true),
|
||||
"This sets some global preprocessor definitions for your project. Used to populate the \"Preprocessor Definitions\" field in the Projucer.");
|
||||
builder.add (new ChoicePropertyComponent (typeValue, "Type",
|
||||
{ "Component", "Plugin", "Console Application" },
|
||||
{ "Component", "AudioProcessor", "Console" }),
|
||||
"The project type.");
|
||||
|
||||
builder.add (new TextPropertyComponent (mainClassValue, "Main Class", 2048, false),
|
||||
"The name of the main class that should be instantiated. "
|
||||
"There can only be one main class and it must have a default constructor. "
|
||||
"Depending on the type, this may need to inherit from a specific JUCE class");
|
||||
|
||||
builder.add (new ChoicePropertyComponent (useLocalCopyValue, "Use Local Copy"),
|
||||
"Enable this to specify that the PIP file should be copied to the generated project directory instead of just referred to.");
|
||||
|
||||
propertyGroup.setProperties (builder);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void valueTreePropertyChanged (ValueTree&, const Identifier& identifier) override
|
||||
{
|
||||
if (identifier == Ids::type)
|
||||
{
|
||||
auto type = typeValue.get().toString();
|
||||
|
||||
if (type == "Component")
|
||||
{
|
||||
nameValue.setDefault ("MyComponentPIP");
|
||||
dependenciesValue.setDefault (getModulesRequiredForComponent());
|
||||
mainClassValue.setDefault ("MyComponent");
|
||||
}
|
||||
else if (type == "AudioProcessor")
|
||||
{
|
||||
nameValue.setDefault ("MyPluginPIP");
|
||||
dependenciesValue.setDefault (getModulesRequiredForAudioProcessor());
|
||||
mainClassValue.setDefault ("MyPlugin");
|
||||
}
|
||||
else if (type == "Console")
|
||||
{
|
||||
nameValue.setDefault ("MyConsolePIP");
|
||||
dependenciesValue.setDefault (getModulesRequiredForConsole());
|
||||
mainClassValue.setDefault ({});
|
||||
}
|
||||
|
||||
MessageManager::callAsync ([this]
|
||||
{
|
||||
buildProps();
|
||||
resized();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
String getFormattedMetadataString() const noexcept
|
||||
{
|
||||
StringArray metadata;
|
||||
|
||||
{
|
||||
StringArray section;
|
||||
|
||||
if (nameValue.get().toString().isNotEmpty()) section.add (" name: " + nameValue.get().toString());
|
||||
if (versionValue.get().toString().isNotEmpty()) section.add (" version: " + versionValue.get().toString());
|
||||
if (vendorValue.get().toString().isNotEmpty()) section.add (" vendor: " + vendorValue.get().toString());
|
||||
if (websiteValue.get().toString().isNotEmpty()) section.add (" website: " + websiteValue.get().toString());
|
||||
if (descriptionValue.get().toString().isNotEmpty()) section.add (" description: " + descriptionValue.get().toString());
|
||||
|
||||
if (! section.isEmpty())
|
||||
metadata.add (section.joinIntoString (getPreferredLineFeed()));
|
||||
}
|
||||
|
||||
{
|
||||
StringArray section;
|
||||
|
||||
auto dependenciesString = getWidthLimitedStringFromVarArray (dependenciesValue.get());
|
||||
if (dependenciesString.isNotEmpty()) section.add (" dependencies: " + dependenciesString);
|
||||
|
||||
auto exportersString = getWidthLimitedStringFromVarArray (exportersValue.get());
|
||||
if (exportersString.isNotEmpty()) section.add (" exporters: " + exportersString);
|
||||
|
||||
if (! section.isEmpty())
|
||||
metadata.add (section.joinIntoString (getPreferredLineFeed()));
|
||||
}
|
||||
|
||||
{
|
||||
StringArray section;
|
||||
|
||||
if (moduleFlagsValue.get().toString().isNotEmpty()) section.add (" moduleFlags: " + moduleFlagsValue.get().toString());
|
||||
if (definesValue.get().toString().isNotEmpty()) section.add (" defines: " + definesValue.get().toString());
|
||||
|
||||
if (! section.isEmpty())
|
||||
metadata.add (section.joinIntoString (getPreferredLineFeed()));
|
||||
}
|
||||
|
||||
{
|
||||
StringArray section;
|
||||
|
||||
if (typeValue.get().toString().isNotEmpty()) section.add (" type: " + typeValue.get().toString());
|
||||
if (mainClassValue.get().toString().isNotEmpty()) section.add (" mainClass: " + mainClassValue.get().toString());
|
||||
|
||||
if (! section.isEmpty())
|
||||
metadata.add (section.joinIntoString (getPreferredLineFeed()));
|
||||
}
|
||||
|
||||
{
|
||||
StringArray section;
|
||||
|
||||
if (useLocalCopyValue.get()) section.add (" useLocalCopy: " + useLocalCopyValue.get().toString());
|
||||
|
||||
if (! section.isEmpty())
|
||||
metadata.add (section.joinIntoString (getPreferredLineFeed()));
|
||||
}
|
||||
|
||||
return metadata.joinIntoString (String (getPreferredLineFeed()) + getPreferredLineFeed());
|
||||
}
|
||||
|
||||
void createPIPFile (File fileToSave)
|
||||
{
|
||||
String fileTemplate (BinaryData::jucer_PIPTemplate_h);
|
||||
fileTemplate = fileTemplate.replace ("%%pip_metadata%%", getFormattedMetadataString());
|
||||
|
||||
auto type = typeValue.get().toString();
|
||||
|
||||
if (type == "Component")
|
||||
{
|
||||
String componentCode (BinaryData::jucer_ContentCompSimpleTemplate_h);
|
||||
componentCode = componentCode.substring (componentCode.indexOf ("class %%content_component_class%%"))
|
||||
.replace ("%%content_component_class%%", mainClassValue.get().toString());
|
||||
|
||||
fileTemplate = fileTemplate.replace ("%%pip_code%%", componentCode);
|
||||
}
|
||||
else if (type == "AudioProcessor")
|
||||
{
|
||||
String audioProcessorCode (BinaryData::jucer_PIPAudioProcessorTemplate_h);
|
||||
audioProcessorCode = audioProcessorCode.replace ("%%class_name%%", mainClassValue.get().toString())
|
||||
.replace ("%%name%%", nameValue.get().toString());
|
||||
|
||||
fileTemplate = fileTemplate.replace ("%%pip_code%%", audioProcessorCode);
|
||||
}
|
||||
else if (type == "Console")
|
||||
{
|
||||
String consoleCode (BinaryData::jucer_MainConsoleAppTemplate_cpp);
|
||||
consoleCode = consoleCode.substring (consoleCode.indexOf ("int main (int argc, char* argv[])"));
|
||||
|
||||
fileTemplate = fileTemplate.replace ("%%pip_code%%", consoleCode);
|
||||
}
|
||||
|
||||
if (fileToSave.create())
|
||||
fileToSave.replaceWithText (fileTemplate);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
ValueTree pipTree { "PIPSettings" };
|
||||
ValueWithDefault nameValue { pipTree, Ids::name, nullptr, "MyComponentPIP" },
|
||||
versionValue { pipTree, Ids::version, nullptr },
|
||||
vendorValue { pipTree, Ids::vendor, nullptr },
|
||||
websiteValue { pipTree, Ids::website, nullptr },
|
||||
descriptionValue { pipTree, Ids::description, nullptr },
|
||||
dependenciesValue { pipTree, Ids::dependencies_, nullptr, getModulesRequiredForComponent(), "," },
|
||||
exportersValue { pipTree, Ids::exporters, nullptr, StringArray (ProjectExporter::getCurrentPlatformExporterTypeInfo().identifier.toString()), "," },
|
||||
moduleFlagsValue { pipTree, Ids::moduleFlags, nullptr, "JUCE_STRICT_REFCOUNTEDPOINTER=1" },
|
||||
definesValue { pipTree, Ids::defines, nullptr },
|
||||
typeValue { pipTree, Ids::type, nullptr, "Component" },
|
||||
mainClassValue { pipTree, Ids::mainClass, nullptr, "MyComponent" },
|
||||
useLocalCopyValue { pipTree, Ids::useLocalCopy, nullptr, false };
|
||||
|
||||
std::unique_ptr<PIPCreatorLookAndFeel> lf;
|
||||
|
||||
Viewport propertyViewport;
|
||||
PropertyGroupComponent propertyGroup { "PIP Creator", {} };
|
||||
|
||||
TextButton createButton { "Create PIP" };
|
||||
|
||||
std::unique_ptr<FileChooser> chooser;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PIPCreatorWindowComponent)
|
||||
};
|
218
deps/juce/extras/Projucer/Source/Application/Windows/jucer_SVGPathDataWindowComponent.h
vendored
Normal file
218
deps/juce/extras/Projucer/Source/Application/Windows/jucer_SVGPathDataWindowComponent.h
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class SVGPathDataComponent : public Component,
|
||||
public FileDragAndDropTarget
|
||||
|
||||
{
|
||||
public:
|
||||
SVGPathDataComponent()
|
||||
{
|
||||
desc.setJustificationType (Justification::centred);
|
||||
addAndMakeVisible (desc);
|
||||
|
||||
userText.setFont (getAppSettings().appearance.getCodeFont().withHeight (13.0f));
|
||||
userText.setMultiLine (true, true);
|
||||
userText.setReturnKeyStartsNewLine (true);
|
||||
addAndMakeVisible (userText);
|
||||
userText.onTextChange = [this] { update(); };
|
||||
userText.onEscapeKey = [this] { getTopLevelComponent()->exitModalState (0); };
|
||||
|
||||
resultText.setFont (getAppSettings().appearance.getCodeFont().withHeight (13.0f));
|
||||
resultText.setMultiLine (true, true);
|
||||
resultText.setReadOnly (true);
|
||||
resultText.setSelectAllWhenFocused (true);
|
||||
addAndMakeVisible (resultText);
|
||||
|
||||
userText.setText (getLastText());
|
||||
|
||||
addAndMakeVisible (copyButton);
|
||||
copyButton.onClick = [this] { SystemClipboard::copyTextToClipboard (resultText.getText()); };
|
||||
|
||||
addAndMakeVisible (closeSubPathButton);
|
||||
closeSubPathButton.onClick = [this] { update(); };
|
||||
closeSubPathButton.setToggleState (true, NotificationType::dontSendNotification);
|
||||
|
||||
addAndMakeVisible (fillPathButton);
|
||||
fillPathButton.onClick = [this] { update(); };
|
||||
fillPathButton.setToggleState (true, NotificationType::dontSendNotification);
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
getLastText() = userText.getText();
|
||||
auto text = getLastText().trim().unquoted().trim();
|
||||
|
||||
path = Drawable::parseSVGPath (text);
|
||||
|
||||
if (path.isEmpty())
|
||||
path = pathFromPoints (text);
|
||||
|
||||
String result = "No path generated.. Not a valid SVG path string?";
|
||||
|
||||
if (! path.isEmpty())
|
||||
{
|
||||
MemoryOutputStream data;
|
||||
path.writePathToStream (data);
|
||||
|
||||
MemoryOutputStream out;
|
||||
|
||||
out << "static const unsigned char pathData[] = ";
|
||||
build_tools::writeDataAsCppLiteral (data.getMemoryBlock(), out, false, true);
|
||||
out << newLine
|
||||
<< newLine
|
||||
<< "Path path;" << newLine
|
||||
<< "path.loadPathFromData (pathData, sizeof (pathData));" << newLine;
|
||||
|
||||
result = out.toString();
|
||||
}
|
||||
|
||||
resultText.setText (result, false);
|
||||
repaint (previewPathArea);
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto r = getLocalBounds().reduced (8);
|
||||
|
||||
auto bottomSection = r.removeFromBottom (30);
|
||||
copyButton.setBounds (bottomSection.removeFromLeft (50));
|
||||
bottomSection.removeFromLeft (25);
|
||||
fillPathButton.setBounds (bottomSection.removeFromLeft (bottomSection.getWidth() / 2));
|
||||
closeSubPathButton.setBounds (bottomSection);
|
||||
|
||||
r.removeFromBottom (5);
|
||||
desc.setBounds (r.removeFromTop (44));
|
||||
r.removeFromTop (8);
|
||||
userText.setBounds (r.removeFromTop (r.getHeight() / 2));
|
||||
r.removeFromTop (8);
|
||||
previewPathArea = r.removeFromRight (r.getHeight());
|
||||
resultText.setBounds (r);
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
if (dragOver)
|
||||
{
|
||||
g.setColour (findColour (secondaryBackgroundColourId).brighter());
|
||||
g.fillAll();
|
||||
}
|
||||
|
||||
g.setColour (findColour (defaultTextColourId));
|
||||
path.applyTransform (path.getTransformToScaleToFit (previewPathArea.reduced (4).toFloat(), true));
|
||||
|
||||
if (fillPathButton.getToggleState())
|
||||
g.fillPath (path);
|
||||
else
|
||||
g.strokePath (path, PathStrokeType (2.0f));
|
||||
}
|
||||
|
||||
void lookAndFeelChanged() override
|
||||
{
|
||||
userText.applyFontToAllText (userText.getFont());
|
||||
resultText.applyFontToAllText (resultText.getFont());
|
||||
}
|
||||
|
||||
bool isInterestedInFileDrag (const StringArray& files) override
|
||||
{
|
||||
return files.size() == 1
|
||||
&& File (files[0]).hasFileExtension ("svg");
|
||||
}
|
||||
|
||||
void fileDragEnter (const StringArray&, int, int) override
|
||||
{
|
||||
dragOver = true;
|
||||
repaint();
|
||||
}
|
||||
|
||||
void fileDragExit (const StringArray&) override
|
||||
{
|
||||
dragOver = false;
|
||||
repaint();
|
||||
}
|
||||
|
||||
void filesDropped (const StringArray& files, int, int) override
|
||||
{
|
||||
dragOver = false;
|
||||
repaint();
|
||||
|
||||
if (auto element = parseXML (File (files[0])))
|
||||
{
|
||||
if (auto* ePath = element->getChildByName ("path"))
|
||||
userText.setText (ePath->getStringAttribute ("d"), true);
|
||||
else if (auto* ePolygon = element->getChildByName ("polygon"))
|
||||
userText.setText (ePolygon->getStringAttribute ("points"), true);
|
||||
}
|
||||
}
|
||||
|
||||
Path pathFromPoints (String pointsText)
|
||||
{
|
||||
auto points = StringArray::fromTokens (pointsText, " ,", "");
|
||||
points.removeEmptyStrings();
|
||||
|
||||
jassert (points.size() % 2 == 0);
|
||||
|
||||
Path p;
|
||||
|
||||
for (int i = 0; i < points.size() / 2; i++)
|
||||
{
|
||||
auto x = points[i * 2].getFloatValue();
|
||||
auto y = points[i * 2 + 1].getFloatValue();
|
||||
|
||||
if (i == 0)
|
||||
p.startNewSubPath ({ x, y });
|
||||
else
|
||||
p.lineTo ({ x, y });
|
||||
}
|
||||
|
||||
if (closeSubPathButton.getToggleState())
|
||||
p.closeSubPath();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
Label desc { {}, "Paste an SVG path string into the top box, and it'll be converted to some C++ "
|
||||
"code that will load it as a Path object.." };
|
||||
TextButton copyButton { "Copy" };
|
||||
TextEditor userText, resultText;
|
||||
|
||||
ToggleButton closeSubPathButton { "Close sub-path" };
|
||||
ToggleButton fillPathButton { "Fill path" };
|
||||
|
||||
Rectangle<int> previewPathArea;
|
||||
Path path;
|
||||
bool dragOver = false;
|
||||
|
||||
String& getLastText()
|
||||
{
|
||||
static String t;
|
||||
return t;
|
||||
}
|
||||
};
|
198
deps/juce/extras/Projucer/Source/Application/Windows/jucer_TranslationToolWindowComponent.h
vendored
Normal file
198
deps/juce/extras/Projucer/Source/Application/Windows/jucer_TranslationToolWindowComponent.h
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../Utility/Helpers/jucer_TranslationHelpers.h"
|
||||
|
||||
//==============================================================================
|
||||
class TranslationToolComponent : public Component
|
||||
{
|
||||
public:
|
||||
TranslationToolComponent()
|
||||
: editorOriginal (documentOriginal, nullptr),
|
||||
editorPre (documentPre, nullptr),
|
||||
editorPost (documentPost, nullptr),
|
||||
editorResult (documentResult, nullptr)
|
||||
{
|
||||
instructionsLabel.setText (
|
||||
"This utility converts translation files to/from a format that can be passed to automatic translation tools."
|
||||
"\n\n"
|
||||
"First, choose whether to scan the current project for all TRANS() macros, or "
|
||||
"pick an existing translation file to load:", dontSendNotification);
|
||||
addAndMakeVisible (instructionsLabel);
|
||||
|
||||
label1.setText ("..then copy-and-paste this annotated text into Google Translate or some other translator:", dontSendNotification);
|
||||
addAndMakeVisible (label1);
|
||||
|
||||
label2.setText ("...then, take the translated result and paste it into the box below:", dontSendNotification);
|
||||
addAndMakeVisible (label2);
|
||||
|
||||
label3.setText ("Finally, click the 'Generate' button, and a translation file will be created below. "
|
||||
"Remember to update its language code at the top!", dontSendNotification);
|
||||
addAndMakeVisible (label3);
|
||||
|
||||
label4.setText ("If you load an existing file the already translated strings will be removed. Ensure this box is empty to create a fresh translation", dontSendNotification);
|
||||
addAndMakeVisible (label4);
|
||||
|
||||
addAndMakeVisible (editorOriginal);
|
||||
addAndMakeVisible (editorPre);
|
||||
addAndMakeVisible (editorPost);
|
||||
addAndMakeVisible (editorResult);
|
||||
|
||||
addAndMakeVisible (generateButton);
|
||||
generateButton.onClick = [this] { generate(); };
|
||||
|
||||
addAndMakeVisible (scanProjectButton);
|
||||
scanProjectButton.onClick = [this] { scanProject(); };
|
||||
|
||||
addAndMakeVisible (scanFolderButton);
|
||||
scanFolderButton.onClick = [this] { scanFolder(); };
|
||||
|
||||
addAndMakeVisible (loadTranslationButton);
|
||||
loadTranslationButton.onClick = [this] { loadFile(); };
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillAll (findColour (backgroundColourId));
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
const int m = 6;
|
||||
const int textH = 44;
|
||||
const int extraH = (7 * textH);
|
||||
const int editorH = (getHeight() - extraH) / 4;
|
||||
const int numButtons = 3;
|
||||
|
||||
Rectangle<int> r (getLocalBounds().withTrimmedBottom (m));
|
||||
const int buttonWidth = r.getWidth() / numButtons;
|
||||
|
||||
instructionsLabel.setBounds (r.removeFromTop (textH * 2).reduced (m));
|
||||
r.removeFromTop (m);
|
||||
Rectangle<int> r2 (r.removeFromTop (textH - (2 * m)));
|
||||
scanProjectButton .setBounds (r2.removeFromLeft (buttonWidth).reduced (m, 0));
|
||||
scanFolderButton .setBounds (r2.removeFromLeft (buttonWidth).reduced (m, 0));
|
||||
loadTranslationButton.setBounds (r2.reduced (m, 0));
|
||||
|
||||
label1 .setBounds (r.removeFromTop (textH) .reduced (m));
|
||||
editorPre.setBounds (r.removeFromTop (editorH).reduced (m, 0));
|
||||
|
||||
label2 .setBounds (r.removeFromTop (textH) .reduced (m));
|
||||
editorPost.setBounds (r.removeFromTop (editorH).reduced (m, 0));
|
||||
|
||||
r2 = r.removeFromTop (textH);
|
||||
generateButton.setBounds (r2.removeFromRight (152).reduced (m));
|
||||
label3 .setBounds (r2.reduced (m));
|
||||
editorResult .setBounds (r.removeFromTop (editorH).reduced (m, 0));
|
||||
|
||||
label4 .setBounds (r.removeFromTop (textH).reduced (m));
|
||||
editorOriginal.setBounds (r.reduced (m, 0));
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void generate()
|
||||
{
|
||||
StringArray preStrings (TranslationHelpers::breakApart (documentPre.getAllContent()));
|
||||
StringArray postStrings (TranslationHelpers::breakApart (documentPost.getAllContent()));
|
||||
|
||||
if (postStrings.size() != preStrings.size())
|
||||
{
|
||||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon,
|
||||
TRANS("Error"),
|
||||
TRANS("The pre- and post-translation text doesn't match!\n\n"
|
||||
"Perhaps it got mangled by the translator?"));
|
||||
return;
|
||||
}
|
||||
|
||||
const LocalisedStrings originalTranslation (documentOriginal.getAllContent(), false);
|
||||
documentResult.replaceAllContent (TranslationHelpers::createFinishedTranslationFile (preStrings, postStrings, originalTranslation));
|
||||
}
|
||||
|
||||
void scanProject()
|
||||
{
|
||||
if (Project* project = ProjucerApplication::getApp().mainWindowList.getFrontmostProject())
|
||||
setPreTranslationText (TranslationHelpers::getPreTranslationText (*project));
|
||||
else
|
||||
AlertWindow::showMessageBoxAsync (MessageBoxIconType::WarningIcon, "Translation Tool",
|
||||
"This will only work when you have a project open!");
|
||||
}
|
||||
|
||||
void scanFolder()
|
||||
{
|
||||
chooser = std::make_unique<FileChooser> ("Choose the root folder to search for the TRANS macros",
|
||||
File(), "*");
|
||||
auto chooserFlags = FileBrowserComponent::openMode | FileBrowserComponent::canSelectDirectories;
|
||||
|
||||
chooser->launchAsync (chooserFlags, [this] (const FileChooser& fc)
|
||||
{
|
||||
if (fc.getResult() == File{})
|
||||
return;
|
||||
|
||||
StringArray strings;
|
||||
TranslationHelpers::scanFolderForTranslations (strings, fc.getResult());
|
||||
setPreTranslationText (TranslationHelpers::mungeStrings(strings));
|
||||
});
|
||||
}
|
||||
|
||||
void loadFile()
|
||||
{
|
||||
chooser = std::make_unique<FileChooser> ("Choose a translation file to load", File(), "*");
|
||||
auto chooserFlags = FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles;
|
||||
|
||||
chooser->launchAsync (chooserFlags, [this] (const FileChooser& fc)
|
||||
{
|
||||
if (fc.getResult() == File{})
|
||||
return;
|
||||
|
||||
const LocalisedStrings loadedStrings (fc.getResult(), false);
|
||||
documentOriginal.replaceAllContent (fc.getResult().loadFileAsString().trim());
|
||||
setPreTranslationText (TranslationHelpers::getPreTranslationText (loadedStrings));
|
||||
});
|
||||
}
|
||||
|
||||
void setPreTranslationText (const String& text)
|
||||
{
|
||||
documentPre.replaceAllContent (text);
|
||||
editorPre.grabKeyboardFocus();
|
||||
editorPre.selectAll();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
CodeDocument documentOriginal, documentPre, documentPost, documentResult;
|
||||
CodeEditorComponent editorOriginal, editorPre, editorPost, editorResult;
|
||||
|
||||
Label label1, label2, label3, label4;
|
||||
Label instructionsLabel;
|
||||
|
||||
TextButton generateButton { TRANS("Generate") },
|
||||
scanProjectButton { "Scan project for TRANS macros" },
|
||||
scanFolderButton { "Scan folder for TRANS macros" },
|
||||
loadTranslationButton { "Load existing translation file..."};
|
||||
|
||||
std::unique_ptr<FileChooser> chooser;
|
||||
};
|
87
deps/juce/extras/Projucer/Source/Application/Windows/jucer_UTF8WindowComponent.h
vendored
Normal file
87
deps/juce/extras/Projucer/Source/Application/Windows/jucer_UTF8WindowComponent.h
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class UTF8Component : public Component
|
||||
{
|
||||
public:
|
||||
UTF8Component()
|
||||
: desc (String(),
|
||||
"Type any string into the box, and it'll be shown below as a portable UTF-8 literal, "
|
||||
"ready to cut-and-paste into your source-code...")
|
||||
{
|
||||
desc.setJustificationType (Justification::centred);
|
||||
addAndMakeVisible (desc);
|
||||
|
||||
userText.setMultiLine (true, true);
|
||||
userText.setReturnKeyStartsNewLine (true);
|
||||
addAndMakeVisible (userText);
|
||||
userText.onTextChange = [this] { update(); };
|
||||
userText.onEscapeKey = [this] { getTopLevelComponent()->exitModalState (0); };
|
||||
|
||||
resultText.setFont (getAppSettings().appearance.getCodeFont().withHeight (13.0f));
|
||||
resultText.setMultiLine (true, true);
|
||||
resultText.setReadOnly (true);
|
||||
resultText.setSelectAllWhenFocused (true);
|
||||
addAndMakeVisible (resultText);
|
||||
|
||||
userText.setText (getLastText());
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
getLastText() = userText.getText();
|
||||
resultText.setText (CodeHelpers::stringLiteral (getLastText(), 100), false);
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto r = getLocalBounds().reduced (8);
|
||||
desc.setBounds (r.removeFromTop (44));
|
||||
r.removeFromTop (8);
|
||||
userText.setBounds (r.removeFromTop (r.getHeight() / 2));
|
||||
r.removeFromTop (8);
|
||||
resultText.setBounds (r);
|
||||
}
|
||||
|
||||
void lookAndFeelChanged() override
|
||||
{
|
||||
userText.applyFontToAllText (userText.getFont());
|
||||
resultText.applyFontToAllText (resultText.getFont());
|
||||
}
|
||||
|
||||
private:
|
||||
Label desc;
|
||||
TextEditor userText, resultText;
|
||||
|
||||
String& getLastText()
|
||||
{
|
||||
static String t;
|
||||
return t;
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user