@@ -0,0 +1,13 @@ | |||||
diff --git a/modules/juce_audio_plugin_client/utility/juce_IncludeModuleHeaders.h b/modules/juce_audio_plugin_client/utility/juce_IncludeModuleHeaders.h | |||||
index 701c4df..0e8a324 100644 | |||||
--- a/modules/juce_audio_plugin_client/utility/juce_IncludeModuleHeaders.h | |||||
+++ b/modules/juce_audio_plugin_client/utility/juce_IncludeModuleHeaders.h | |||||
@@ -24,6 +24,8 @@ | |||||
============================================================================== | |||||
*/ | |||||
+#pragma once | |||||
+ | |||||
#include "../juce_audio_plugin_client.h" | |||||
namespace juce |
@@ -0,0 +1,14 @@ | |||||
diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp | |||||
index 172e348..2a33c4f 100644 | |||||
--- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp | |||||
+++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp | |||||
@@ -56,9 +56,6 @@ using namespace Vst2; | |||||
#ifndef WM_APPCOMMAND | |||||
#define WM_APPCOMMAND 0x0319 | |||||
#endif | |||||
- | |||||
- extern "C" void _fpreset(); | |||||
- extern "C" void _clearfp(); | |||||
#elif ! JUCE_WINDOWS | |||||
static void _fpreset() {} | |||||
static void _clearfp() {} |
@@ -0,0 +1,132 @@ | |||||
diff --git a/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp b/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp | |||||
index 05c3c44..2f03506 100644 | |||||
--- a/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp | |||||
+++ b/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp | |||||
@@ -117,6 +117,9 @@ namespace FlacNamespace | |||||
#pragma clang diagnostic ignored "-Wconversion" | |||||
#pragma clang diagnostic ignored "-Wshadow" | |||||
#pragma clang diagnostic ignored "-Wdeprecated-register" | |||||
+ #elif JUCE_GCC && (__GNUC__ >= 7) | |||||
+ #pragma GCC diagnostic push | |||||
+ #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" | |||||
#endif | |||||
#if JUCE_INTEL | |||||
@@ -157,6 +160,8 @@ namespace FlacNamespace | |||||
#if JUCE_CLANG | |||||
#pragma clang diagnostic pop | |||||
+ #elif JUCE_GCC && (__GNUC__ >= 7) | |||||
+ #pragma GCC diagnostic pop | |||||
#endif | |||||
} | |||||
diff --git a/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp b/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp | |||||
index 0a2737b..e2ebd13 100644 | |||||
--- a/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp | |||||
+++ b/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp | |||||
@@ -47,6 +47,12 @@ namespace OggVorbisNamespace | |||||
#elif JUCE_GCC | |||||
#pragma GCC diagnostic push | |||||
#pragma GCC diagnostic ignored "-Wshadow" | |||||
+ #if (__GNUC__ >= 6) | |||||
+ #pragma GCC diagnostic ignored "-Wmisleading-indentation" | |||||
+ #if (__GNUC__ >= 7) | |||||
+ #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" | |||||
+ #endif | |||||
+ #endif | |||||
#endif | |||||
#include "oggvorbis/vorbisenc.h" | |||||
diff --git a/modules/juce_core/native/juce_linux_Files.cpp b/modules/juce_core/native/juce_linux_Files.cpp | |||||
index d022175..1edbfe8 100644 | |||||
--- a/modules/juce_core/native/juce_linux_Files.cpp | |||||
+++ b/modules/juce_core/native/juce_linux_Files.cpp | |||||
@@ -136,14 +136,14 @@ File File::getSpecialLocation (const SpecialLocationType type) | |||||
case invokedExecutableFile: | |||||
if (juce_argv != nullptr && juce_argc > 0) | |||||
return File (CharPointer_UTF8 (juce_argv[0])); | |||||
- // deliberate fall-through... | |||||
+ // fall-through | |||||
case currentExecutableFile: | |||||
case currentApplicationFile: | |||||
#if ! JUCE_STANDALONE_APPLICATION | |||||
return juce_getExecutableFile(); | |||||
#endif | |||||
- // deliberate fall-through if this is not a shared-library | |||||
+ // fall-through | |||||
case hostApplicationPath: | |||||
{ | |||||
diff --git a/modules/juce_core/native/juce_posix_SharedCode.h b/modules/juce_core/native/juce_posix_SharedCode.h | |||||
index 67c884a..100d41a 100644 | |||||
--- a/modules/juce_core/native/juce_posix_SharedCode.h | |||||
+++ b/modules/juce_core/native/juce_posix_SharedCode.h | |||||
@@ -1205,6 +1205,8 @@ public: | |||||
close (pipeHandles[1]); // close the write handle | |||||
} | |||||
} | |||||
+ | |||||
+ ignoreUnused (streamFlags); | |||||
} | |||||
~ActiveProcess() | |||||
diff --git a/modules/juce_core/xml/juce_XmlElement.cpp b/modules/juce_core/xml/juce_XmlElement.cpp | |||||
index b04e307..5c86674 100644 | |||||
--- a/modules/juce_core/xml/juce_XmlElement.cpp | |||||
+++ b/modules/juce_core/xml/juce_XmlElement.cpp | |||||
@@ -241,7 +241,7 @@ namespace XmlOutputFunctions | |||||
outputStream << (char) character; | |||||
break; | |||||
} | |||||
- // Note: deliberate fall-through here! | |||||
+ // fall-through | |||||
default: | |||||
outputStream << "&#" << ((int) character) << ';'; | |||||
break; | |||||
diff --git a/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp b/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp | |||||
index df64f23..45087c6 100644 | |||||
--- a/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp | |||||
+++ b/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp | |||||
@@ -92,7 +92,7 @@ private: | |||||
{ | |||||
case Z_STREAM_END: | |||||
finished = true; | |||||
- // Deliberate fall-through.. | |||||
+ // fall-through.. | |||||
case Z_OK: | |||||
{ | |||||
data += dataSize - stream.avail_in; | |||||
diff --git a/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp b/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp | |||||
index 0bae4d3..bd33e93 100644 | |||||
--- a/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp | |||||
+++ b/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp | |||||
@@ -39,6 +39,9 @@ namespace zlibNamespace | |||||
#if __has_warning("-Wcomma") | |||||
#pragma clang diagnostic ignored "-Wcomma" | |||||
#endif | |||||
+ #elif JUCE_GCC && (__GNUC__ >= 7) | |||||
+ #pragma GCC diagnostic push | |||||
+ #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" | |||||
#endif | |||||
#undef OS_CODE | |||||
@@ -74,6 +77,8 @@ namespace zlibNamespace | |||||
#if JUCE_CLANG | |||||
#pragma clang diagnostic pop | |||||
+ #elif JUCE_GCC && (__GNUC__ >= 7) | |||||
+ #pragma GCC diagnostic pop | |||||
#endif | |||||
#else | |||||
#include JUCE_ZLIB_INCLUDE_PATH | |||||
@@ -136,7 +141,7 @@ public: | |||||
{ | |||||
case Z_STREAM_END: | |||||
finished = true; | |||||
- // deliberate fall-through | |||||
+ // fall-through | |||||
case Z_OK: | |||||
data += dataSize - stream.avail_in; | |||||
dataSize = (z_uInt) stream.avail_in; |
@@ -27,13 +27,13 @@ struct CatmullRomAlgorithm | |||||
{ | { | ||||
static forcedinline float valueAtOffset (const float* const inputs, const float offset) noexcept | static forcedinline float valueAtOffset (const float* const inputs, const float offset) noexcept | ||||
{ | { | ||||
const float y0 = inputs[3]; | |||||
const float y1 = inputs[2]; | |||||
const float y2 = inputs[1]; | |||||
const float y3 = inputs[0]; | |||||
auto y0 = inputs[3]; | |||||
auto y1 = inputs[2]; | |||||
auto y2 = inputs[1]; | |||||
auto y3 = inputs[0]; | |||||
const float halfY0 = 0.5f * y0; | |||||
const float halfY3 = 0.5f * y3; | |||||
auto halfY0 = 0.5f * y0; | |||||
auto halfY3 = 0.5f * y3; | |||||
return y1 + offset * ((0.5f * y2 - halfY0) | return y1 + offset * ((0.5f * y2 - halfY0) | ||||
+ (offset * (((y0 + 2.0f * y2) - (halfY3 + 2.5f * y1)) | + (offset * (((y0 + 2.0f * y2) - (halfY3 + 2.5f * y1)) | ||||
@@ -48,8 +48,8 @@ void CatmullRomInterpolator::reset() noexcept | |||||
{ | { | ||||
subSamplePos = 1.0; | subSamplePos = 1.0; | ||||
for (int i = 0; i < numElementsInArray (lastInputSamples); ++i) | |||||
lastInputSamples[i] = 0; | |||||
for (auto& s : lastInputSamples) | |||||
s = 0; | |||||
} | } | ||||
int CatmullRomInterpolator::process (double actualRatio, const float* in, float* out, int numOut) noexcept | int CatmullRomInterpolator::process (double actualRatio, const float* in, float* out, int numOut) noexcept | ||||
@@ -49,97 +49,67 @@ namespace | |||||
} | } | ||||
template <typename InterpolatorType> | template <typename InterpolatorType> | ||||
static int interpolate (float* lastInputSamples, double& subSamplePos, const double actualRatio, | |||||
const float* in, float* out, const int numOut) noexcept | |||||
static int interpolate (float* lastInputSamples, double& subSamplePos, double actualRatio, | |||||
const float* in, float* out, int numOut) noexcept | |||||
{ | { | ||||
if (actualRatio == 1.0) | |||||
auto pos = subSamplePos; | |||||
if (actualRatio == 1.0 && pos == 1.0) | |||||
{ | { | ||||
memcpy (out, in, (size_t) numOut * sizeof (float)); | memcpy (out, in, (size_t) numOut * sizeof (float)); | ||||
pushInterpolationSamples (lastInputSamples, in, numOut); | pushInterpolationSamples (lastInputSamples, in, numOut); | ||||
return numOut; | return numOut; | ||||
} | } | ||||
const float* const originalIn = in; | |||||
double pos = subSamplePos; | |||||
int numUsed = 0; | |||||
if (actualRatio < 1.0) | |||||
while (numOut > 0) | |||||
{ | { | ||||
for (int i = numOut; --i >= 0;) | |||||
while (pos >= 1.0) | |||||
{ | { | ||||
if (pos >= 1.0) | |||||
{ | |||||
pushInterpolationSample (lastInputSamples, *in++); | |||||
pos -= 1.0; | |||||
} | |||||
*out++ = InterpolatorType::valueAtOffset (lastInputSamples, (float) pos); | |||||
pos += actualRatio; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
for (int i = numOut; --i >= 0;) | |||||
{ | |||||
while (pos < actualRatio) | |||||
{ | |||||
pushInterpolationSample (lastInputSamples, *in++); | |||||
pos += 1.0; | |||||
} | |||||
pos -= actualRatio; | |||||
*out++ = InterpolatorType::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos)); | |||||
pushInterpolationSample (lastInputSamples, in[numUsed++]); | |||||
pos -= 1.0; | |||||
} | } | ||||
*out++ = InterpolatorType::valueAtOffset (lastInputSamples, (float) pos); | |||||
pos += actualRatio; | |||||
--numOut; | |||||
} | } | ||||
subSamplePos = pos; | subSamplePos = pos; | ||||
return (int) (in - originalIn); | |||||
return numUsed; | |||||
} | } | ||||
template <typename InterpolatorType> | template <typename InterpolatorType> | ||||
static int interpolateAdding (float* lastInputSamples, double& subSamplePos, const double actualRatio, | |||||
const float* in, float* out, const int numOut, const float gain) noexcept | |||||
static int interpolateAdding (float* lastInputSamples, double& subSamplePos, double actualRatio, | |||||
const float* in, float* out, int numOut, const float gain) noexcept | |||||
{ | { | ||||
if (actualRatio == 1.0) | |||||
auto pos = subSamplePos; | |||||
if (actualRatio == 1.0 && pos == 1.0) | |||||
{ | { | ||||
FloatVectorOperations::addWithMultiply (out, in, gain, numOut); | FloatVectorOperations::addWithMultiply (out, in, gain, numOut); | ||||
pushInterpolationSamples (lastInputSamples, in, numOut); | pushInterpolationSamples (lastInputSamples, in, numOut); | ||||
return numOut; | return numOut; | ||||
} | } | ||||
const float* const originalIn = in; | |||||
double pos = subSamplePos; | |||||
int numUsed = 0; | |||||
if (actualRatio < 1.0) | |||||
while (numOut > 0) | |||||
{ | { | ||||
for (int i = numOut; --i >= 0;) | |||||
while (pos >= 1.0) | |||||
{ | { | ||||
if (pos >= 1.0) | |||||
{ | |||||
pushInterpolationSample (lastInputSamples, *in++); | |||||
pos -= 1.0; | |||||
} | |||||
*out++ += gain * InterpolatorType::valueAtOffset (lastInputSamples, (float) pos); | |||||
pos += actualRatio; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
for (int i = numOut; --i >= 0;) | |||||
{ | |||||
while (pos < actualRatio) | |||||
{ | |||||
pushInterpolationSample (lastInputSamples, *in++); | |||||
pos += 1.0; | |||||
} | |||||
pos -= actualRatio; | |||||
*out++ += gain * InterpolatorType::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos)); | |||||
pushInterpolationSample (lastInputSamples, in[numUsed++]); | |||||
pos -= 1.0; | |||||
} | } | ||||
*out++ += gain * InterpolatorType::valueAtOffset (lastInputSamples, (float) pos); | |||||
pos += actualRatio; | |||||
--numOut; | |||||
} | } | ||||
subSamplePos = pos; | subSamplePos = pos; | ||||
return (int) (in - originalIn); | |||||
return numUsed; | |||||
} | } | ||||
} | } | ||||
@@ -186,8 +156,8 @@ void LagrangeInterpolator::reset() noexcept | |||||
{ | { | ||||
subSamplePos = 1.0; | subSamplePos = 1.0; | ||||
for (int i = 0; i < numElementsInArray (lastInputSamples); ++i) | |||||
lastInputSamples[i] = 0; | |||||
for (auto& s : lastInputSamples) | |||||
s = 0; | |||||
} | } | ||||
int LagrangeInterpolator::process (double actualRatio, const float* in, float* out, int numOut) noexcept | int LagrangeInterpolator::process (double actualRatio, const float* in, float* out, int numOut) noexcept | ||||
@@ -44,24 +44,24 @@ bool MidiKeyboardState::isNoteOn (const int midiChannel, const int n) const noex | |||||
{ | { | ||||
jassert (midiChannel >= 0 && midiChannel <= 16); | jassert (midiChannel >= 0 && midiChannel <= 16); | ||||
return isPositiveAndBelow (n, (int) 128) | |||||
return isPositiveAndBelow (n, 128) | |||||
&& (noteStates[n] & (1 << (midiChannel - 1))) != 0; | && (noteStates[n] & (1 << (midiChannel - 1))) != 0; | ||||
} | } | ||||
bool MidiKeyboardState::isNoteOnForChannels (const int midiChannelMask, const int n) const noexcept | bool MidiKeyboardState::isNoteOnForChannels (const int midiChannelMask, const int n) const noexcept | ||||
{ | { | ||||
return isPositiveAndBelow (n, (int) 128) | |||||
return isPositiveAndBelow (n, 128) | |||||
&& (noteStates[n] & midiChannelMask) != 0; | && (noteStates[n] & midiChannelMask) != 0; | ||||
} | } | ||||
void MidiKeyboardState::noteOn (const int midiChannel, const int midiNoteNumber, const float velocity) | void MidiKeyboardState::noteOn (const int midiChannel, const int midiNoteNumber, const float velocity) | ||||
{ | { | ||||
jassert (midiChannel >= 0 && midiChannel <= 16); | jassert (midiChannel >= 0 && midiChannel <= 16); | ||||
jassert (isPositiveAndBelow (midiNoteNumber, (int) 128)); | |||||
jassert (isPositiveAndBelow (midiNoteNumber, 128)); | |||||
const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
if (isPositiveAndBelow (midiNoteNumber, (int) 128)) | |||||
if (isPositiveAndBelow (midiNoteNumber, 128)) | |||||
{ | { | ||||
const int timeNow = (int) Time::getMillisecondCounter(); | const int timeNow = (int) Time::getMillisecondCounter(); | ||||
eventsToAdd.addEvent (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity), timeNow); | eventsToAdd.addEvent (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity), timeNow); | ||||
@@ -73,7 +73,7 @@ void MidiKeyboardState::noteOn (const int midiChannel, const int midiNoteNumber, | |||||
void MidiKeyboardState::noteOnInternal (const int midiChannel, const int midiNoteNumber, const float velocity) | void MidiKeyboardState::noteOnInternal (const int midiChannel, const int midiNoteNumber, const float velocity) | ||||
{ | { | ||||
if (isPositiveAndBelow (midiNoteNumber, (int) 128)) | |||||
if (isPositiveAndBelow (midiNoteNumber, 128)) | |||||
{ | { | ||||
noteStates [midiNoteNumber] |= (1 << (midiChannel - 1)); | noteStates [midiNoteNumber] |= (1 << (midiChannel - 1)); | ||||
@@ -452,8 +452,8 @@ MidiMessage MidiMessage::aftertouchChange (const int channel, | |||||
const int aftertouchValue) noexcept | const int aftertouchValue) noexcept | ||||
{ | { | ||||
jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 | jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 | ||||
jassert (isPositiveAndBelow (noteNum, (int) 128)); | |||||
jassert (isPositiveAndBelow (aftertouchValue, (int) 128)); | |||||
jassert (isPositiveAndBelow (noteNum, 128)); | |||||
jassert (isPositiveAndBelow (aftertouchValue, 128)); | |||||
return MidiMessage (MidiHelpers::initialByte (0xa0, channel), | return MidiMessage (MidiHelpers::initialByte (0xa0, channel), | ||||
noteNum & 0x7f, | noteNum & 0x7f, | ||||
@@ -474,7 +474,7 @@ int MidiMessage::getChannelPressureValue() const noexcept | |||||
MidiMessage MidiMessage::channelPressureChange (const int channel, const int pressure) noexcept | MidiMessage MidiMessage::channelPressureChange (const int channel, const int pressure) noexcept | ||||
{ | { | ||||
jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 | jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 | ||||
jassert (isPositiveAndBelow (pressure, (int) 128)); | |||||
jassert (isPositiveAndBelow (pressure, 128)); | |||||
return MidiMessage (MidiHelpers::initialByte (0xd0, channel), pressure & 0x7f); | return MidiMessage (MidiHelpers::initialByte (0xd0, channel), pressure & 0x7f); | ||||
} | } | ||||
@@ -522,7 +522,7 @@ int MidiMessage::getPitchWheelValue() const noexcept | |||||
MidiMessage MidiMessage::pitchWheel (const int channel, const int position) noexcept | MidiMessage MidiMessage::pitchWheel (const int channel, const int position) noexcept | ||||
{ | { | ||||
jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 | jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 | ||||
jassert (isPositiveAndBelow (position, (int) 0x4000)); | |||||
jassert (isPositiveAndBelow (position, 0x4000)); | |||||
return MidiMessage (MidiHelpers::initialByte (0xe0, channel), | return MidiMessage (MidiHelpers::initialByte (0xe0, channel), | ||||
position & 127, (position >> 7) & 127); | position & 127, (position >> 7) & 127); | ||||
@@ -563,7 +563,7 @@ MidiMessage MidiMessage::controllerEvent (const int channel, const int controlle | |||||
MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const uint8 velocity) noexcept | MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const uint8 velocity) noexcept | ||||
{ | { | ||||
jassert (channel > 0 && channel <= 16); | jassert (channel > 0 && channel <= 16); | ||||
jassert (isPositiveAndBelow (noteNumber, (int) 128)); | |||||
jassert (isPositiveAndBelow (noteNumber, 128)); | |||||
return MidiMessage (MidiHelpers::initialByte (0x90, channel), | return MidiMessage (MidiHelpers::initialByte (0x90, channel), | ||||
noteNumber & 127, MidiHelpers::validVelocity (velocity)); | noteNumber & 127, MidiHelpers::validVelocity (velocity)); | ||||
@@ -577,7 +577,7 @@ MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const | |||||
MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, uint8 velocity) noexcept | MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, uint8 velocity) noexcept | ||||
{ | { | ||||
jassert (channel > 0 && channel <= 16); | jassert (channel > 0 && channel <= 16); | ||||
jassert (isPositiveAndBelow (noteNumber, (int) 128)); | |||||
jassert (isPositiveAndBelow (noteNumber, 128)); | |||||
return MidiMessage (MidiHelpers::initialByte (0x80, channel), | return MidiMessage (MidiHelpers::initialByte (0x80, channel), | ||||
noteNumber & 127, MidiHelpers::validVelocity (velocity)); | noteNumber & 127, MidiHelpers::validVelocity (velocity)); | ||||
@@ -591,7 +591,7 @@ MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, float | |||||
MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber) noexcept | MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber) noexcept | ||||
{ | { | ||||
jassert (channel > 0 && channel <= 16); | jassert (channel > 0 && channel <= 16); | ||||
jassert (isPositiveAndBelow (noteNumber, (int) 128)); | |||||
jassert (isPositiveAndBelow (noteNumber, 128)); | |||||
return MidiMessage (MidiHelpers::initialByte (0x80, channel), noteNumber & 127, 0); | return MidiMessage (MidiHelpers::initialByte (0x80, channel), noteNumber & 127, 0); | ||||
} | } | ||||
@@ -983,7 +983,7 @@ String MidiMessage::getMidiNoteName (int note, bool useSharps, bool includeOctav | |||||
static const char* const sharpNoteNames[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; | static const char* const sharpNoteNames[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; | ||||
static const char* const flatNoteNames[] = { "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B" }; | static const char* const flatNoteNames[] = { "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B" }; | ||||
if (isPositiveAndBelow (note, (int) 128)) | |||||
if (isPositiveAndBelow (note, 128)) | |||||
{ | { | ||||
String s (useSharps ? sharpNoteNames [note % 12] | String s (useSharps ? sharpNoteNames [note % 12] | ||||
: flatNoteNames [note % 12]); | : flatNoteNames [note % 12]); | ||||
@@ -731,6 +731,9 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat | |||||
const double msTaken = Time::getMillisecondCounterHiRes() - callbackStartTime; | const double msTaken = Time::getMillisecondCounterHiRes() - callbackStartTime; | ||||
const double filterAmount = 0.2; | const double filterAmount = 0.2; | ||||
cpuUsageMs += filterAmount * (msTaken - cpuUsageMs); | cpuUsageMs += filterAmount * (msTaken - cpuUsageMs); | ||||
if (msTaken > msPerBlock) | |||||
xruns++; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -756,13 +759,14 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat | |||||
void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device) | void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device) | ||||
{ | { | ||||
cpuUsageMs = 0; | cpuUsageMs = 0; | ||||
xruns = 0; | |||||
const double sampleRate = device->getCurrentSampleRate(); | const double sampleRate = device->getCurrentSampleRate(); | ||||
const int blockSize = device->getCurrentBufferSizeSamples(); | const int blockSize = device->getCurrentBufferSizeSamples(); | ||||
if (sampleRate > 0.0 && blockSize > 0) | if (sampleRate > 0.0 && blockSize > 0) | ||||
{ | { | ||||
const double msPerBlock = 1000.0 * blockSize / sampleRate; | |||||
msPerBlock = 1000.0 * blockSize / sampleRate; | |||||
timeToCpuScale = (msPerBlock > 0.0) ? (1.0 / msPerBlock) : 0.0; | timeToCpuScale = (msPerBlock > 0.0) ? (1.0 / msPerBlock) : 0.0; | ||||
} | } | ||||
@@ -779,6 +783,7 @@ void AudioDeviceManager::audioDeviceStoppedInt() | |||||
{ | { | ||||
cpuUsageMs = 0; | cpuUsageMs = 0; | ||||
timeToCpuScale = 0; | timeToCpuScale = 0; | ||||
xruns = 0; | |||||
sendChangeMessage(); | sendChangeMessage(); | ||||
const ScopedLock sl (audioCallbackLock); | const ScopedLock sl (audioCallbackLock); | ||||
@@ -998,6 +1003,12 @@ void AudioDeviceManager::playTestSound() | |||||
} | } | ||||
} | } | ||||
int AudioDeviceManager::getXRunCount() const noexcept | |||||
{ | |||||
auto deviceXRuns = (currentAudioDevice != nullptr ? currentAudioDevice->getXRunCount() : -1); | |||||
return (deviceXRuns >= 0 ? deviceXRuns : xruns); | |||||
} | |||||
double AudioDeviceManager::getCurrentInputLevel() const noexcept { return inputLevelMeter.getCurrentLevel(); } | double AudioDeviceManager::getCurrentInputLevel() const noexcept { return inputLevelMeter.getCurrentLevel(); } | ||||
double AudioDeviceManager::getCurrentOutputLevel() const noexcept { return outputLevelMeter.getCurrentLevel(); } | double AudioDeviceManager::getCurrentOutputLevel() const noexcept { return outputLevelMeter.getCurrentLevel(); } | ||||
@@ -436,6 +436,15 @@ public: | |||||
*/ | */ | ||||
CriticalSection& getMidiCallbackLock() noexcept { return midiCallbackLock; } | CriticalSection& getMidiCallbackLock() noexcept { return midiCallbackLock; } | ||||
//============================================================================== | |||||
/** Returns the number of under- or over runs reported. | |||||
This method will use the underlying device's native getXRunCount if it supports | |||||
it. Otherwise it will estimate the number of under-/overruns by measuring the | |||||
time it spent in the audio callback. | |||||
*/ | |||||
int getXRunCount() const noexcept; | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
OwnedArray<AudioIODeviceType> availableDeviceTypes; | OwnedArray<AudioIODeviceType> availableDeviceTypes; | ||||
@@ -468,7 +477,8 @@ private: | |||||
ScopedPointer<AudioSampleBuffer> testSound; | ScopedPointer<AudioSampleBuffer> testSound; | ||||
int testSoundPosition; | int testSoundPosition; | ||||
double cpuUsageMs, timeToCpuScale; | |||||
double cpuUsageMs, timeToCpuScale, msPerBlock; | |||||
int xruns; | |||||
struct LevelMeter | struct LevelMeter | ||||
{ | { | ||||
@@ -347,7 +347,7 @@ MidiOutput* MidiOutput::openDevice (int index) | |||||
{ | { | ||||
MidiOutput* mo = nullptr; | MidiOutput* mo = nullptr; | ||||
if (isPositiveAndBelow (index, (int) MIDIGetNumberOfDestinations())) | |||||
if (isPositiveAndBelow (index, MIDIGetNumberOfDestinations())) | |||||
{ | { | ||||
MIDIEndpointRef endPoint = MIDIGetDestination ((ItemCount) index); | MIDIEndpointRef endPoint = MIDIGetDestination ((ItemCount) index); | ||||
@@ -465,7 +465,7 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) | |||||
using namespace CoreMidiHelpers; | using namespace CoreMidiHelpers; | ||||
MidiInput* newInput = nullptr; | MidiInput* newInput = nullptr; | ||||
if (isPositiveAndBelow (index, (int) MIDIGetNumberOfSources())) | |||||
if (isPositiveAndBelow (index, MIDIGetNumberOfSources())) | |||||
{ | { | ||||
if (MIDIEndpointRef endPoint = MIDIGetSource ((ItemCount) index)) | if (MIDIEndpointRef endPoint = MIDIGetSource ((ItemCount) index)) | ||||
{ | { | ||||
@@ -1444,16 +1444,7 @@ struct ASIOAudioIODevice::ASIOCallbackFunctions <sizeof(currentASIODev) / sizeof | |||||
class ASIOAudioIODeviceType : public AudioIODeviceType | class ASIOAudioIODeviceType : public AudioIODeviceType | ||||
{ | { | ||||
public: | public: | ||||
ASIOAudioIODeviceType() | |||||
: AudioIODeviceType ("ASIO"), | |||||
hasScanned (false) | |||||
{ | |||||
} | |||||
~ASIOAudioIODeviceType() | |||||
{ | |||||
masterReference.clear(); | |||||
} | |||||
ASIOAudioIODeviceType() : AudioIODeviceType ("ASIO") {} | |||||
//============================================================================== | //============================================================================== | ||||
void scanForDevices() | void scanForDevices() | ||||
@@ -1549,13 +1540,13 @@ public: | |||||
callDeviceChangeListeners(); | callDeviceChangeListeners(); | ||||
} | } | ||||
WeakReference<ASIOAudioIODeviceType>::Master masterReference; | |||||
JUCE_DECLARE_WEAK_REFERENCEABLE (ASIOAudioIODeviceType) | |||||
private: | private: | ||||
StringArray deviceNames; | StringArray deviceNames; | ||||
Array<CLSID> classIds; | Array<CLSID> classIds; | ||||
bool hasScanned; | |||||
bool hasScanned = false; | |||||
//============================================================================== | //============================================================================== | ||||
static bool checkClassIsOk (const String& classId) | static bool checkClassIsOk (const String& classId) | ||||
@@ -117,6 +117,9 @@ namespace FlacNamespace | |||||
#pragma clang diagnostic ignored "-Wconversion" | #pragma clang diagnostic ignored "-Wconversion" | ||||
#pragma clang diagnostic ignored "-Wshadow" | #pragma clang diagnostic ignored "-Wshadow" | ||||
#pragma clang diagnostic ignored "-Wdeprecated-register" | #pragma clang diagnostic ignored "-Wdeprecated-register" | ||||
#elif JUCE_GCC && (__GNUC__ >= 7) | |||||
#pragma GCC diagnostic push | |||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" | |||||
#endif | #endif | ||||
#if JUCE_INTEL | #if JUCE_INTEL | ||||
@@ -157,6 +160,8 @@ namespace FlacNamespace | |||||
#if JUCE_CLANG | #if JUCE_CLANG | ||||
#pragma clang diagnostic pop | #pragma clang diagnostic pop | ||||
#elif JUCE_GCC && (__GNUC__ >= 7) | |||||
#pragma GCC diagnostic pop | |||||
#endif | #endif | ||||
} | } | ||||
@@ -47,6 +47,12 @@ namespace OggVorbisNamespace | |||||
#elif JUCE_GCC | #elif JUCE_GCC | ||||
#pragma GCC diagnostic push | #pragma GCC diagnostic push | ||||
#pragma GCC diagnostic ignored "-Wshadow" | #pragma GCC diagnostic ignored "-Wshadow" | ||||
#if (__GNUC__ >= 6) | |||||
#pragma GCC diagnostic ignored "-Wmisleading-indentation" | |||||
#if (__GNUC__ >= 7) | |||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" | |||||
#endif | |||||
#endif | |||||
#endif | #endif | ||||
#include "oggvorbis/vorbisenc.h" | #include "oggvorbis/vorbisenc.h" | ||||
@@ -1704,7 +1704,7 @@ private: | |||||
for (MidiBuffer::Iterator i (midiEvents); i.getNextEvent (midiEventData, midiEventSize, midiEventPosition);) | for (MidiBuffer::Iterator i (midiEvents); i.getNextEvent (midiEventData, midiEventSize, midiEventPosition);) | ||||
{ | { | ||||
jassert (isPositiveAndBelow (midiEventPosition, (int) nFrames)); | |||||
jassert (isPositiveAndBelow (midiEventPosition, nFrames)); | |||||
ignoreUnused (nFrames); | ignoreUnused (nFrames); | ||||
dataSize += (size_t) midiEventSize; | dataSize += (size_t) midiEventSize; | ||||
@@ -56,9 +56,6 @@ using namespace Vst2; | |||||
#ifndef WM_APPCOMMAND | #ifndef WM_APPCOMMAND | ||||
#define WM_APPCOMMAND 0x0319 | #define WM_APPCOMMAND 0x0319 | ||||
#endif | #endif | ||||
extern "C" void _fpreset(); | |||||
extern "C" void _clearfp(); | |||||
#elif ! JUCE_WINDOWS | #elif ! JUCE_WINDOWS | ||||
static void _fpreset() {} | static void _fpreset() {} | ||||
static void _clearfp() {} | static void _clearfp() {} | ||||
@@ -943,7 +940,7 @@ struct VSTPluginInstance : public AudioPluginInstance, | |||||
float getParameter (int index) override | float getParameter (int index) override | ||||
{ | { | ||||
if (vstEffect != nullptr && isPositiveAndBelow (index, (int) vstEffect->numParameters)) | |||||
if (vstEffect != nullptr && isPositiveAndBelow (index, vstEffect->numParameters)) | |||||
{ | { | ||||
const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
return vstEffect->getParameterValueFunction (vstEffect, index); | return vstEffect->getParameterValueFunction (vstEffect, index); | ||||
@@ -954,7 +951,7 @@ struct VSTPluginInstance : public AudioPluginInstance, | |||||
void setParameter (int index, float newValue) override | void setParameter (int index, float newValue) override | ||||
{ | { | ||||
if (vstEffect != nullptr && isPositiveAndBelow (index, (int) vstEffect->numParameters)) | |||||
if (vstEffect != nullptr && isPositiveAndBelow (index, vstEffect->numParameters)) | |||||
{ | { | ||||
const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
@@ -52,11 +52,15 @@ public: | |||||
@param exitCallback A callback which will be called when the modal | @param exitCallback A callback which will be called when the modal | ||||
bluetooth dialog is closed. | bluetooth dialog is closed. | ||||
@param btWindowBounds The bounds of the bluetooth window that will | |||||
be opened. The dialog itself is opened by the OS so cannot | |||||
be customised by JUCE. | |||||
@return true if the dialogue was opened, false on error. | @return true if the dialogue was opened, false on error. | ||||
@see ModalComponentManager::Callback | @see ModalComponentManager::Callback | ||||
*/ | */ | ||||
static bool open (ModalComponentManager::Callback* exitCallback = nullptr); | |||||
static bool open (ModalComponentManager::Callback* exitCallback = nullptr, | |||||
Rectangle<int>* btWindowBounds = nullptr); | |||||
/** Checks if a Bluetooth MIDI pairing dialogue is available on this | /** Checks if a Bluetooth MIDI pairing dialogue is available on this | ||||
platform. | platform. | ||||
@@ -391,7 +391,9 @@ private: | |||||
class BluetoothMidiSelectorOverlay : public Component | class BluetoothMidiSelectorOverlay : public Component | ||||
{ | { | ||||
public: | public: | ||||
BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse) | |||||
BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse, | |||||
const Rectangle<int>& boundsToUse) | |||||
: bounds (boundsToUse) | |||||
{ | { | ||||
ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackToUse); | ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackToUse); | ||||
@@ -400,8 +402,14 @@ public: | |||||
setAlwaysOnTop (true); | setAlwaysOnTop (true); | ||||
setVisible (true); | setVisible (true); | ||||
addToDesktop (ComponentPeer::windowHasDropShadow); | addToDesktop (ComponentPeer::windowHasDropShadow); | ||||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||||
if (bounds.isEmpty()) | |||||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||||
else | |||||
setBounds (bounds); | |||||
toFront (true); | toFront (true); | ||||
setOpaque (! bounds.isEmpty()); | |||||
addAndMakeVisible (bluetoothDevicesList); | addAndMakeVisible (bluetoothDevicesList); | ||||
enterModalState (true, exitCallback.release(), true); | enterModalState (true, exitCallback.release(), true); | ||||
@@ -414,7 +422,7 @@ public: | |||||
void paint (Graphics& g) override | void paint (Graphics& g) override | ||||
{ | { | ||||
g.fillAll (Colours::black.withAlpha (0.6f)); | |||||
g.fillAll (bounds.isEmpty() ? Colours::black.withAlpha (0.6f) : Colours::black); | |||||
g.setColour (Colour (0xffdfdfdf)); | g.setColour (Colour (0xffdfdfdf)); | ||||
Rectangle<int> overlayBounds = getOverlayBounds(); | Rectangle<int> overlayBounds = getOverlayBounds(); | ||||
@@ -441,19 +449,30 @@ public: | |||||
void parentSizeChanged() override { update(); } | void parentSizeChanged() override { update(); } | ||||
private: | private: | ||||
Rectangle<int> bounds; | |||||
void update() | void update() | ||||
{ | { | ||||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||||
if (bounds.isEmpty()) | |||||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||||
else | |||||
setBounds (bounds); | |||||
bluetoothDevicesList.setBounds (getOverlayBounds().withTrimmedTop (40)); | bluetoothDevicesList.setBounds (getOverlayBounds().withTrimmedTop (40)); | ||||
} | } | ||||
Rectangle<int> getOverlayBounds() const noexcept | Rectangle<int> getOverlayBounds() const noexcept | ||||
{ | { | ||||
const int pw = getParentWidth(); | |||||
const int ph = getParentHeight(); | |||||
if (bounds.isEmpty()) | |||||
{ | |||||
const int pw = getParentWidth(); | |||||
const int ph = getParentHeight(); | |||||
return Rectangle<int> (pw, ph).withSizeKeepingCentre (jmin (400, pw - 14), | |||||
jmin (300, ph - 40)); | |||||
} | |||||
return Rectangle<int> (pw, ph).withSizeKeepingCentre (jmin (400, pw - 14), | |||||
jmin (300, ph - 40)); | |||||
return bounds.withZeroOrigin(); | |||||
} | } | ||||
AndroidBluetoothMidiDevicesListBox bluetoothDevicesList; | AndroidBluetoothMidiDevicesListBox bluetoothDevicesList; | ||||
@@ -462,9 +481,11 @@ private: | |||||
}; | }; | ||||
//============================================================================== | //============================================================================== | ||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallbackPtr) | |||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallbackPtr, | |||||
Rectangle<int>* btBounds) | |||||
{ | { | ||||
ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackPtr); | ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackPtr); | ||||
auto boundsToUse = (btBounds != nullptr ? *btBounds : Rectangle<int> {}); | |||||
if (! RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi)) | if (! RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi)) | ||||
{ | { | ||||
@@ -475,7 +496,7 @@ bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* | |||||
return false; | return false; | ||||
} | } | ||||
new BluetoothMidiSelectorOverlay (exitCallback.release()); | |||||
new BluetoothMidiSelectorOverlay (exitCallback.release(), boundsToUse); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -40,15 +40,23 @@ namespace juce | |||||
class BluetoothMidiSelectorOverlay : public Component | class BluetoothMidiSelectorOverlay : public Component | ||||
{ | { | ||||
public: | public: | ||||
BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse) | |||||
BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse, | |||||
const Rectangle<int>& boundsToUse) | |||||
: bounds (boundsToUse) | |||||
{ | { | ||||
ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackToUse); | ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackToUse); | ||||
setAlwaysOnTop (true); | setAlwaysOnTop (true); | ||||
setVisible (true); | setVisible (true); | ||||
addToDesktop (ComponentPeer::windowHasDropShadow); | addToDesktop (ComponentPeer::windowHasDropShadow); | ||||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||||
if (bounds.isEmpty()) | |||||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||||
else | |||||
setBounds (bounds); | |||||
toFront (true); | toFront (true); | ||||
setOpaque (! bounds.isEmpty()); | |||||
controller = [[CABTMIDICentralViewController alloc] init]; | controller = [[CABTMIDICentralViewController alloc] init]; | ||||
nativeSelectorComponent.setView ([controller view]); | nativeSelectorComponent.setView ([controller view]); | ||||
@@ -66,7 +74,7 @@ public: | |||||
void paint (Graphics& g) override | void paint (Graphics& g) override | ||||
{ | { | ||||
g.fillAll (Colours::black.withAlpha (0.5f)); | |||||
g.fillAll (bounds.isEmpty() ? Colours::black.withAlpha (0.5f) : Colours::black); | |||||
} | } | ||||
void inputAttemptWhenModal() override { close(); } | void inputAttemptWhenModal() override { close(); } | ||||
@@ -78,12 +86,19 @@ public: | |||||
private: | private: | ||||
void update() | void update() | ||||
{ | { | ||||
const int pw = getParentWidth(); | |||||
const int ph = getParentHeight(); | |||||
nativeSelectorComponent.setBounds (Rectangle<int> (pw, ph) | |||||
.withSizeKeepingCentre (jmin (400, pw), | |||||
jmin (450, ph - 40))); | |||||
if (bounds.isEmpty()) | |||||
{ | |||||
const int pw = getParentWidth(); | |||||
const int ph = getParentHeight(); | |||||
nativeSelectorComponent.setBounds (Rectangle<int> (pw, ph) | |||||
.withSizeKeepingCentre (jmin (400, pw), | |||||
jmin (450, ph - 40))); | |||||
} | |||||
else | |||||
{ | |||||
nativeSelectorComponent.setBounds (bounds.withZeroOrigin()); | |||||
} | |||||
} | } | ||||
void close() | void close() | ||||
@@ -94,17 +109,20 @@ private: | |||||
CABTMIDICentralViewController* controller; | CABTMIDICentralViewController* controller; | ||||
UIViewComponent nativeSelectorComponent; | UIViewComponent nativeSelectorComponent; | ||||
Rectangle<int> bounds; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BluetoothMidiSelectorOverlay) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BluetoothMidiSelectorOverlay) | ||||
}; | }; | ||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||||
Rectangle<int>* btBounds) | |||||
{ | { | ||||
ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | ||||
auto boundsToUse = (btBounds != nullptr ? *btBounds : Rectangle<int> {}); | |||||
if (isAvailable()) | if (isAvailable()) | ||||
{ | { | ||||
new BluetoothMidiSelectorOverlay (cb.release()); | |||||
new BluetoothMidiSelectorOverlay (cb.release(), boundsToUse); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -123,7 +141,8 @@ bool BluetoothMidiDevicePairingDialogue::isAvailable() | |||||
namespace juce | namespace juce | ||||
{ | { | ||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||||
Rectangle<int>*) | |||||
{ | { | ||||
ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | ||||
return false; | return false; | ||||
@@ -27,7 +27,8 @@ | |||||
namespace juce | namespace juce | ||||
{ | { | ||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||||
Rectangle<int>*) | |||||
{ | { | ||||
ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | ||||
// not implemented on Linux yet! | // not implemented on Linux yet! | ||||
@@ -27,7 +27,8 @@ | |||||
namespace juce | namespace juce | ||||
{ | { | ||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||||
Rectangle<int>*) | |||||
{ | { | ||||
ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | ||||
// Do not call this on OSX. Instead, you should pair Bluetooth MIDI devices | // Do not call this on OSX. Instead, you should pair Bluetooth MIDI devices | ||||
@@ -27,7 +27,8 @@ | |||||
namespace juce | namespace juce | ||||
{ | { | ||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||||
Rectangle<int>*) | |||||
{ | { | ||||
ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | ||||
// not implemented on Windows yet! | // not implemented on Windows yet! | ||||
@@ -337,10 +337,4 @@ private: | |||||
/** Writes a BigInteger to an OutputStream as a UTF8 decimal string. */ | /** Writes a BigInteger to an OutputStream as a UTF8 decimal string. */ | ||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const BigInteger& value); | OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const BigInteger& value); | ||||
//============================================================================== | |||||
#ifndef DOXYGEN | |||||
// For backwards compatibility, BitArray is defined as an alias for BigInteger. | |||||
typedef BigInteger BitArray; | |||||
#endif | |||||
} // namespace juce | } // namespace juce |
@@ -212,9 +212,9 @@ void findMinAndMax (const Type* values, int numValues, Type& lowest, Type& highe | |||||
@see jmin, jmax, jmap | @see jmin, jmax, jmap | ||||
*/ | */ | ||||
template <typename Type> | template <typename Type> | ||||
Type jlimit (const Type lowerLimit, | |||||
const Type upperLimit, | |||||
const Type valueToConstrain) noexcept | |||||
Type jlimit (Type lowerLimit, | |||||
Type upperLimit, | |||||
Type valueToConstrain) noexcept | |||||
{ | { | ||||
jassert (lowerLimit <= upperLimit); // if these are in the wrong order, results are unpredictable.. | jassert (lowerLimit <= upperLimit); // if these are in the wrong order, results are unpredictable.. | ||||
@@ -228,15 +228,15 @@ Type jlimit (const Type lowerLimit, | |||||
@code valueToTest >= 0 && valueToTest < upperLimit | @code valueToTest >= 0 && valueToTest < upperLimit | ||||
@endcode | @endcode | ||||
*/ | */ | ||||
template <typename Type> | |||||
bool isPositiveAndBelow (Type valueToTest, Type upperLimit) noexcept | |||||
template <typename Type1, typename Type2> | |||||
bool isPositiveAndBelow (Type1 valueToTest, Type2 upperLimit) noexcept | |||||
{ | { | ||||
jassert (Type() <= upperLimit); // makes no sense to call this if the upper limit is itself below zero.. | |||||
return Type() <= valueToTest && valueToTest < upperLimit; | |||||
jassert (Type1() <= static_cast<Type1> (upperLimit)); // makes no sense to call this if the upper limit is itself below zero.. | |||||
return Type1() <= valueToTest && valueToTest < static_cast<Type1> (upperLimit); | |||||
} | } | ||||
template <> | |||||
inline bool isPositiveAndBelow (const int valueToTest, const int upperLimit) noexcept | |||||
template <typename Type> | |||||
bool isPositiveAndBelow (int valueToTest, Type upperLimit) noexcept | |||||
{ | { | ||||
jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero.. | jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero.. | ||||
return static_cast<unsigned int> (valueToTest) < static_cast<unsigned int> (upperLimit); | return static_cast<unsigned int> (valueToTest) < static_cast<unsigned int> (upperLimit); | ||||
@@ -247,28 +247,21 @@ inline bool isPositiveAndBelow (const int valueToTest, const int upperLimit) noe | |||||
@code valueToTest >= 0 && valueToTest <= upperLimit | @code valueToTest >= 0 && valueToTest <= upperLimit | ||||
@endcode | @endcode | ||||
*/ | */ | ||||
template <typename Type> | |||||
bool isPositiveAndNotGreaterThan (Type valueToTest, Type upperLimit) noexcept | |||||
template <typename Type1, typename Type2> | |||||
bool isPositiveAndNotGreaterThan (Type1 valueToTest, Type2 upperLimit) noexcept | |||||
{ | { | ||||
jassert (Type() <= upperLimit); // makes no sense to call this if the upper limit is itself below zero.. | |||||
return Type() <= valueToTest && valueToTest <= upperLimit; | |||||
jassert (Type1() <= static_cast<Type1> (upperLimit)); // makes no sense to call this if the upper limit is itself below zero.. | |||||
return Type1() <= valueToTest && valueToTest <= static_cast<Type1> (upperLimit); | |||||
} | } | ||||
template <> | |||||
inline bool isPositiveAndNotGreaterThan (const int valueToTest, const int upperLimit) noexcept | |||||
template <typename Type> | |||||
bool isPositiveAndNotGreaterThan (int valueToTest, Type upperLimit) noexcept | |||||
{ | { | ||||
jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero.. | jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero.. | ||||
return static_cast<unsigned int> (valueToTest) <= static_cast<unsigned int> (upperLimit); | return static_cast<unsigned int> (valueToTest) <= static_cast<unsigned int> (upperLimit); | ||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
/** Handy function to swap two values. */ | |||||
template <typename Type> | |||||
void swapVariables (Type& variable1, Type& variable2) | |||||
{ | |||||
std::swap (variable1, variable2); | |||||
} | |||||
/** Handy function for avoiding unused variables warning. */ | /** Handy function for avoiding unused variables warning. */ | ||||
template <typename Type1> | template <typename Type1> | ||||
void ignoreUnused (const Type1&) noexcept {} | void ignoreUnused (const Type1&) noexcept {} | ||||
@@ -59,6 +59,8 @@ namespace juce | |||||
friend class WeakReference<MyObject>; | friend class WeakReference<MyObject>; | ||||
}; | }; | ||||
OR: just use the handy JUCE_DECLARE_WEAK_REFERENCEABLE macro to do all this for you. | |||||
// Here's an example of using a pointer.. | // Here's an example of using a pointer.. | ||||
MyObject* n = new MyObject(); | MyObject* n = new MyObject(); | ||||
@@ -202,4 +204,31 @@ private: | |||||
} | } | ||||
}; | }; | ||||
//============================================================================== | |||||
/** | |||||
Macro to easily allow a class to be made weak-referenceable. | |||||
This can be inserted in a class definition to add the requisite weak-ref boilerplate to that class. | |||||
e.g. | |||||
@code | |||||
class MyObject | |||||
{ | |||||
public: | |||||
MyObject(); | |||||
~MyObject(); | |||||
private: | |||||
JUCE_DECLARE_WEAK_REFERENCEABLE (MyObject) | |||||
}; | |||||
@endcode | |||||
@see WeakReference, WeakReference::Master | |||||
*/ | |||||
#define JUCE_DECLARE_WEAK_REFERENCEABLE(Class) \ | |||||
struct WeakRefMaster : public WeakReference<Class>::Master { ~WeakRefMaster() { this->clear(); } }; \ | |||||
WeakRefMaster masterReference; \ | |||||
friend class WeakReference<Class>; \ | |||||
} // namespace juce | } // namespace juce |
@@ -566,6 +566,9 @@ public class JuceAppActivity extends Activity | |||||
@Override | @Override | ||||
public void onDraw (Canvas canvas) | public void onDraw (Canvas canvas) | ||||
{ | { | ||||
if (host == 0) | |||||
return; | |||||
handlePaint (host, canvas, paint); | handlePaint (host, canvas, paint); | ||||
} | } | ||||
@@ -657,6 +660,9 @@ public class JuceAppActivity extends Activity | |||||
@Override | @Override | ||||
public boolean onKeyDown (int keyCode, KeyEvent event) | public boolean onKeyDown (int keyCode, KeyEvent event) | ||||
{ | { | ||||
if (host == 0) | |||||
return false; | |||||
switch (keyCode) | switch (keyCode) | ||||
{ | { | ||||
case KeyEvent.KEYCODE_VOLUME_UP: | case KeyEvent.KEYCODE_VOLUME_UP: | ||||
@@ -679,6 +685,9 @@ public class JuceAppActivity extends Activity | |||||
@Override | @Override | ||||
public boolean onKeyUp (int keyCode, KeyEvent event) | public boolean onKeyUp (int keyCode, KeyEvent event) | ||||
{ | { | ||||
if (host == 0) | |||||
return false; | |||||
handleKeyUp (host, keyCode, event.getUnicodeChar()); | handleKeyUp (host, keyCode, event.getUnicodeChar()); | ||||
return true; | return true; | ||||
} | } | ||||
@@ -686,6 +695,9 @@ public class JuceAppActivity extends Activity | |||||
@Override | @Override | ||||
public boolean onKeyMultiple (int keyCode, int count, KeyEvent event) | public boolean onKeyMultiple (int keyCode, int count, KeyEvent event) | ||||
{ | { | ||||
if (host == 0) | |||||
return false; | |||||
if (keyCode != KeyEvent.KEYCODE_UNKNOWN || event.getAction() != KeyEvent.ACTION_MULTIPLE) | if (keyCode != KeyEvent.KEYCODE_UNKNOWN || event.getAction() != KeyEvent.ACTION_MULTIPLE) | ||||
return super.onKeyMultiple (keyCode, count, event); | return super.onKeyMultiple (keyCode, count, event); | ||||
@@ -718,6 +730,9 @@ public class JuceAppActivity extends Activity | |||||
@Override | @Override | ||||
protected void onSizeChanged (int w, int h, int oldw, int oldh) | protected void onSizeChanged (int w, int h, int oldw, int oldh) | ||||
{ | { | ||||
if (host == 0) | |||||
return; | |||||
super.onSizeChanged (w, h, oldw, oldh); | super.onSizeChanged (w, h, oldw, oldh); | ||||
viewSizeChanged (host); | viewSizeChanged (host); | ||||
} | } | ||||
@@ -734,6 +749,9 @@ public class JuceAppActivity extends Activity | |||||
@Override | @Override | ||||
public void onFocusChange (View v, boolean hasFocus) | public void onFocusChange (View v, boolean hasFocus) | ||||
{ | { | ||||
if (host == 0) | |||||
return; | |||||
if (v == this) | if (v == this) | ||||
focusChanged (host, hasFocus); | focusChanged (host, hasFocus); | ||||
} | } | ||||
@@ -407,7 +407,7 @@ int SystemStats::getMemorySizeInMegabytes() | |||||
struct sysinfo sysi; | struct sysinfo sysi; | ||||
if (sysinfo (&sysi) == 0) | if (sysinfo (&sysi) == 0) | ||||
return (static_cast<int> (sysi.totalram * sysi.mem_unit) / (1024 * 1024)); | |||||
return static_cast<int> ((sysi.totalram * sysi.mem_unit) / (1024 * 1024)); | |||||
#endif | #endif | ||||
return 0; | return 0; | ||||
@@ -136,14 +136,14 @@ File File::getSpecialLocation (const SpecialLocationType type) | |||||
case invokedExecutableFile: | case invokedExecutableFile: | ||||
if (juce_argv != nullptr && juce_argc > 0) | if (juce_argv != nullptr && juce_argc > 0) | ||||
return File (CharPointer_UTF8 (juce_argv[0])); | return File (CharPointer_UTF8 (juce_argv[0])); | ||||
// deliberate fall-through... | |||||
// fall-through | |||||
case currentExecutableFile: | case currentExecutableFile: | ||||
case currentApplicationFile: | case currentApplicationFile: | ||||
#if ! JUCE_STANDALONE_APPLICATION | #if ! JUCE_STANDALONE_APPLICATION | ||||
return juce_getExecutableFile(); | return juce_getExecutableFile(); | ||||
#endif | #endif | ||||
// deliberate fall-through if this is not a shared-library | |||||
// fall-through | |||||
case hostApplicationPath: | case hostApplicationPath: | ||||
{ | { | ||||
@@ -202,6 +202,77 @@ private: | |||||
JUCE_DECLARE_NON_COPYABLE (ObjCClass) | JUCE_DECLARE_NON_COPYABLE (ObjCClass) | ||||
}; | }; | ||||
//============================================================================== | |||||
#ifndef DOXYGEN | |||||
template <class JuceClass> | |||||
struct ObjCLifetimeManagedClass : public ObjCClass<NSObject> | |||||
{ | |||||
ObjCLifetimeManagedClass() | |||||
: ObjCClass<NSObject> ("ObjCLifetimeManagedClass_") | |||||
{ | |||||
addIvar<JuceClass*> ("cppObject"); | |||||
#pragma clang diagnostic push | |||||
#pragma clang diagnostic ignored "-Wundeclared-selector" | |||||
addMethod (@selector (initWithJuceObject:), initWithJuceObject, "@@:@"); | |||||
#pragma clang diagnostic pop | |||||
addMethod (@selector (dealloc), dealloc, "v@:"); | |||||
registerClass(); | |||||
} | |||||
static id initWithJuceObject (id _self, SEL, JuceClass* obj) | |||||
{ | |||||
NSObject* self = _self; | |||||
objc_super s = { self, [NSObject class] }; | |||||
self = ObjCMsgSendSuper<NSObject*> (&s, @selector(init)); | |||||
object_setInstanceVariable (self, "cppObject", obj); | |||||
return self; | |||||
} | |||||
static void dealloc (id _self, SEL) | |||||
{ | |||||
if (auto* obj = getIvar<JuceClass*> (_self, "cppObject")) | |||||
{ | |||||
delete obj; | |||||
object_setInstanceVariable (_self, "cppObject", nullptr); | |||||
} | |||||
objc_super s = { _self, [NSObject class] }; | |||||
ObjCMsgSendSuper<void> (&s, @selector(dealloc)); | |||||
} | |||||
static ObjCLifetimeManagedClass objCLifetimeManagedClass; | |||||
}; | |||||
template <typename Class> | |||||
ObjCLifetimeManagedClass<Class> ObjCLifetimeManagedClass<Class>::objCLifetimeManagedClass; | |||||
#endif | |||||
// this will return an NSObject which takes ownership of the JUCE instance passed-in | |||||
// This is useful to tie the life-time of a juce instance to the life-time of an NSObject | |||||
template <typename Class> | |||||
NSObject* createNSObjectFromJuceClass (Class* obj) | |||||
{ | |||||
#pragma clang diagnostic push | |||||
#pragma clang diagnostic ignored "-Wobjc-method-access" | |||||
return [ObjCLifetimeManagedClass<Class>::objCLifetimeManagedClass.createInstance() initWithJuceObject:obj]; | |||||
#pragma clang diagnostic pop | |||||
} | |||||
// Get the JUCE class instance that was tied to the life-time of an NSObject with the | |||||
// function above | |||||
template <typename Class> | |||||
Class* getJuceClassFromNSObject (NSObject* obj) | |||||
{ | |||||
return obj != nullptr ? ObjCLifetimeManagedClass<Class>:: template getIvar<Class*> (obj, "cppObject") : nullptr; | |||||
} | |||||
#if JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES | #if JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES | ||||
template <typename ReturnT, class Class, typename... Params> | template <typename ReturnT, class Class, typename... Params> | ||||
@@ -1205,6 +1205,8 @@ public: | |||||
close (pipeHandles[1]); // close the write handle | close (pipeHandles[1]); // close the write handle | ||||
} | } | ||||
} | } | ||||
ignoreUnused (streamFlags); | |||||
} | } | ||||
~ActiveProcess() | ~ActiveProcess() | ||||
@@ -130,7 +130,7 @@ URL::DownloadTask* URL::DownloadTask::createFallbackDownloader (const URL& urlTo | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
URL::DownloadTask::DownloadTask() : contentLength (-1), downloaded (0), finished (false), error (false), httpCode (-1) {} | |||||
URL::DownloadTask::DownloadTask() {} | |||||
URL::DownloadTask::~DownloadTask() {} | URL::DownloadTask::~DownloadTask() {} | ||||
//============================================================================== | //============================================================================== | ||||
@@ -250,6 +250,7 @@ namespace URLHelpers | |||||
static int findStartOfNetLocation (const String& url) | static int findStartOfNetLocation (const String& url) | ||||
{ | { | ||||
int start = findEndOfScheme (url); | int start = findEndOfScheme (url); | ||||
while (url[start] == '/') | while (url[start] == '/') | ||||
++start; | ++start; | ||||
@@ -305,8 +306,8 @@ String URL::getDomain() const | |||||
const int end2 = url.indexOfChar (start, ':'); | const int end2 = url.indexOfChar (start, ':'); | ||||
const int end = (end1 < 0 && end2 < 0) ? std::numeric_limits<int>::max() | const int end = (end1 < 0 && end2 < 0) ? std::numeric_limits<int>::max() | ||||
: ((end1 < 0 || end2 < 0) ? jmax (end1, end2) | |||||
: jmin (end1, end2)); | |||||
: ((end1 < 0 || end2 < 0) ? jmax (end1, end2) | |||||
: jmin (end1, end2)); | |||||
return url.substring (start, end); | return url.substring (start, end); | ||||
} | } | ||||
@@ -325,7 +326,7 @@ String URL::getScheme() const | |||||
int URL::getPort() const | int URL::getPort() const | ||||
{ | { | ||||
const int colonPos = url.indexOfChar (URLHelpers::findStartOfNetLocation (url), ':'); | |||||
auto colonPos = url.indexOfChar (URLHelpers::findStartOfNetLocation (url), ':'); | |||||
return colonPos > 0 ? url.substring (colonPos + 1).getIntValue() : 0; | return colonPos > 0 ? url.substring (colonPos + 1).getIntValue() : 0; | ||||
} | } | ||||
@@ -366,7 +367,7 @@ void URL::createHeadersAndPostData (String& headers, MemoryBlock& postDataToWrit | |||||
// (this doesn't currently support mixing custom post-data with uploads..) | // (this doesn't currently support mixing custom post-data with uploads..) | ||||
jassert (postData.getSize() == 0); | jassert (postData.getSize() == 0); | ||||
const String boundary (String::toHexString (Random::getSystemRandom().nextInt64())); | |||||
auto boundary = String::toHexString (Random::getSystemRandom().nextInt64()); | |||||
headers << "Content-Type: multipart/form-data; boundary=" << boundary << "\r\n"; | headers << "Content-Type: multipart/form-data; boundary=" << boundary << "\r\n"; | ||||
@@ -379,22 +380,20 @@ void URL::createHeadersAndPostData (String& headers, MemoryBlock& postDataToWrit | |||||
<< "\r\n--" << boundary; | << "\r\n--" << boundary; | ||||
} | } | ||||
for (int i = 0; i < filesToUpload.size(); ++i) | |||||
for (auto* f : filesToUpload) | |||||
{ | { | ||||
const Upload& f = *filesToUpload.getObjectPointerUnchecked(i); | |||||
data << "\r\nContent-Disposition: form-data; name=\"" << f.parameterName | |||||
<< "\"; filename=\"" << f.filename << "\"\r\n"; | |||||
data << "\r\nContent-Disposition: form-data; name=\"" << f->parameterName | |||||
<< "\"; filename=\"" << f->filename << "\"\r\n"; | |||||
if (f.mimeType.isNotEmpty()) | |||||
data << "Content-Type: " << f.mimeType << "\r\n"; | |||||
if (f->mimeType.isNotEmpty()) | |||||
data << "Content-Type: " << f->mimeType << "\r\n"; | |||||
data << "Content-Transfer-Encoding: binary\r\n\r\n"; | data << "Content-Transfer-Encoding: binary\r\n\r\n"; | ||||
if (f.data != nullptr) | |||||
data << *f.data; | |||||
if (f->data != nullptr) | |||||
data << *f->data; | |||||
else | else | ||||
data << f.file; | |||||
data << f->file; | |||||
data << "\r\n--" << boundary; | data << "\r\n--" << boundary; | ||||
} | } | ||||
@@ -419,8 +418,8 @@ bool URL::isProbablyAWebsiteURL (const String& possibleURL) | |||||
{ | { | ||||
static const char* validProtocols[] = { "http:", "ftp:", "https:" }; | static const char* validProtocols[] = { "http:", "ftp:", "https:" }; | ||||
for (int i = 0; i < numElementsInArray (validProtocols); ++i) | |||||
if (possibleURL.startsWithIgnoreCase (validProtocols[i])) | |||||
for (auto* protocol : validProtocols) | |||||
if (possibleURL.startsWithIgnoreCase (protocol)) | |||||
return true; | return true; | ||||
if (possibleURL.containsChar ('@') | if (possibleURL.containsChar ('@') | ||||
@@ -435,7 +434,7 @@ bool URL::isProbablyAWebsiteURL (const String& possibleURL) | |||||
bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress) | bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress) | ||||
{ | { | ||||
const int atSign = possibleEmailAddress.indexOfChar ('@'); | |||||
auto atSign = possibleEmailAddress.indexOfChar ('@'); | |||||
return atSign > 0 | return atSign > 0 | ||||
&& possibleEmailAddress.lastIndexOfChar ('.') > (atSign + 1) | && possibleEmailAddress.lastIndexOfChar ('.') > (atSign + 1) | ||||
@@ -504,8 +503,7 @@ WebInputStream* URL::createInputStream (const bool usePostCommand, | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
bool URL::readEntireBinaryStream (MemoryBlock& destData, | |||||
const bool usePostCommand) const | |||||
bool URL::readEntireBinaryStream (MemoryBlock& destData, bool usePostCommand) const | |||||
{ | { | ||||
const ScopedPointer<InputStream> in (createInputStream (usePostCommand)); | const ScopedPointer<InputStream> in (createInputStream (usePostCommand)); | ||||
@@ -518,7 +516,7 @@ bool URL::readEntireBinaryStream (MemoryBlock& destData, | |||||
return false; | return false; | ||||
} | } | ||||
String URL::readEntireTextStream (const bool usePostCommand) const | |||||
String URL::readEntireTextStream (bool usePostCommand) const | |||||
{ | { | ||||
const ScopedPointer<InputStream> in (createInputStream (usePostCommand)); | const ScopedPointer<InputStream> in (createInputStream (usePostCommand)); | ||||
@@ -528,7 +526,7 @@ String URL::readEntireTextStream (const bool usePostCommand) const | |||||
return {}; | return {}; | ||||
} | } | ||||
XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const | |||||
XmlElement* URL::readEntireXmlStream (bool usePostCommand) const | |||||
{ | { | ||||
return XmlDocument::parse (readEntireTextStream (usePostCommand)); | return XmlDocument::parse (readEntireTextStream (usePostCommand)); | ||||
} | } | ||||
@@ -601,7 +599,7 @@ URL URL::withDataToUpload (const String& parameterName, const String& filename, | |||||
//============================================================================== | //============================================================================== | ||||
String URL::removeEscapeChars (const String& s) | String URL::removeEscapeChars (const String& s) | ||||
{ | { | ||||
String result (s.replaceCharacter ('+', ' ')); | |||||
auto result = s.replaceCharacter ('+', ' '); | |||||
if (! result.containsChar ('%')) | if (! result.containsChar ('%')) | ||||
return result; | return result; | ||||
@@ -628,9 +626,9 @@ String URL::removeEscapeChars (const String& s) | |||||
return String::fromUTF8 (utf8.getRawDataPointer(), utf8.size()); | return String::fromUTF8 (utf8.getRawDataPointer(), utf8.size()); | ||||
} | } | ||||
String URL::addEscapeChars (const String& s, const bool isParameter, bool roundBracketsAreLegal) | |||||
String URL::addEscapeChars (const String& s, bool isParameter, bool roundBracketsAreLegal) | |||||
{ | { | ||||
String legalChars (isParameter ? "_-.*!'" | |||||
String legalChars (isParameter ? "_-.~" | |||||
: ",$_-.*!'"); | : ",$_-.*!'"); | ||||
if (roundBracketsAreLegal) | if (roundBracketsAreLegal) | ||||
@@ -640,7 +638,7 @@ String URL::addEscapeChars (const String& s, const bool isParameter, bool roundB | |||||
for (int i = 0; i < utf8.size(); ++i) | for (int i = 0; i < utf8.size(); ++i) | ||||
{ | { | ||||
const char c = utf8.getUnchecked(i); | |||||
auto c = utf8.getUnchecked(i); | |||||
if (! (CharacterFunctions::isLetterOrDigit (c) | if (! (CharacterFunctions::isLetterOrDigit (c) | ||||
|| legalChars.containsChar ((juce_wchar) c))) | || legalChars.containsChar ((juce_wchar) c))) | ||||
@@ -657,12 +655,12 @@ String URL::addEscapeChars (const String& s, const bool isParameter, bool roundB | |||||
//============================================================================== | //============================================================================== | ||||
bool URL::launchInDefaultBrowser() const | bool URL::launchInDefaultBrowser() const | ||||
{ | { | ||||
String u (toString (true)); | |||||
auto u = toString (true); | |||||
if (u.containsChar ('@') && ! u.containsChar (':')) | if (u.containsChar ('@') && ! u.containsChar (':')) | ||||
u = "mailto:" + u; | u = "mailto:" + u; | ||||
return Process::openDocument (u, String()); | |||||
return Process::openDocument (u, {}); | |||||
} | } | ||||
} // namespace juce | } // namespace juce |
@@ -47,13 +47,13 @@ public: | |||||
URL (const String& url); | URL (const String& url); | ||||
/** Creates a copy of another URL. */ | /** Creates a copy of another URL. */ | ||||
URL (const URL& other); | |||||
URL (const URL&); | |||||
/** Destructor. */ | /** Destructor. */ | ||||
~URL(); | ~URL(); | ||||
/** Copies this URL from another one. */ | /** Copies this URL from another one. */ | ||||
URL& operator= (const URL& other); | |||||
URL& operator= (const URL&); | |||||
/** Compares two URLs. | /** Compares two URLs. | ||||
All aspects of the URLs must be identical for them to match, including any parameters, | All aspects of the URLs must be identical for them to match, including any parameters, | ||||
@@ -78,19 +78,16 @@ public: | |||||
bool isWellFormed() const; | bool isWellFormed() const; | ||||
/** Returns just the domain part of the URL. | /** Returns just the domain part of the URL. | ||||
E.g. for "http://www.xyz.com/foobar", this will return "www.xyz.com". | E.g. for "http://www.xyz.com/foobar", this will return "www.xyz.com". | ||||
*/ | */ | ||||
String getDomain() const; | String getDomain() const; | ||||
/** Returns the path part of the URL. | /** Returns the path part of the URL. | ||||
E.g. for "http://www.xyz.com/foo/bar?x=1", this will return "foo/bar". | E.g. for "http://www.xyz.com/foo/bar?x=1", this will return "foo/bar". | ||||
*/ | */ | ||||
String getSubPath() const; | String getSubPath() const; | ||||
/** Returns the scheme of the URL. | /** Returns the scheme of the URL. | ||||
E.g. for "http://www.xyz.com/foobar", this will return "http". (It won't | E.g. for "http://www.xyz.com/foobar", this will return "http". (It won't | ||||
include the colon). | include the colon). | ||||
*/ | */ | ||||
@@ -102,7 +99,6 @@ public: | |||||
int getPort() const; | int getPort() const; | ||||
/** Returns a new version of this URL with a different domain and path. | /** Returns a new version of this URL with a different domain and path. | ||||
E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with | E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with | ||||
"abc.com/zzz", it'll return "http://abc.com/zzz?x=1". | "abc.com/zzz", it'll return "http://abc.com/zzz?x=1". | ||||
@see withNewSubPath | @see withNewSubPath | ||||
@@ -110,7 +106,6 @@ public: | |||||
URL withNewDomainAndPath (const String& newFullPath) const; | URL withNewDomainAndPath (const String& newFullPath) const; | ||||
/** Returns a new version of this URL with a different sub-path. | /** Returns a new version of this URL with a different sub-path. | ||||
E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with | E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with | ||||
"bar", it'll return "http://www.xyz.com/bar?x=1". | "bar", it'll return "http://www.xyz.com/bar?x=1". | ||||
@see withNewDomainAndPath | @see withNewDomainAndPath | ||||
@@ -118,7 +113,6 @@ public: | |||||
URL withNewSubPath (const String& newPath) const; | URL withNewSubPath (const String& newPath) const; | ||||
/** Returns a new URL that refers to a sub-path relative to this one. | /** Returns a new URL that refers to a sub-path relative to this one. | ||||
E.g. if the URL is "http://www.xyz.com/foo" and you call this with | E.g. if the URL is "http://www.xyz.com/foo" and you call this with | ||||
"bar", it'll return "http://www.xyz.com/foo/bar". Note that there's no way for | "bar", it'll return "http://www.xyz.com/foo/bar". Note that there's no way for | ||||
this method to know whether the original URL is a file or directory, so it's | this method to know whether the original URL is a file or directory, so it's | ||||
@@ -134,7 +128,6 @@ public: | |||||
/** Returns a copy of this URL, with a GET or POST parameter added to the end. | /** Returns a copy of this URL, with a GET or POST parameter added to the end. | ||||
Any control characters in the value will be encoded. | Any control characters in the value will be encoded. | ||||
e.g. calling "withParameter ("amount", "some fish") for the url "www.fish.com" | e.g. calling "withParameter ("amount", "some fish") for the url "www.fish.com" | ||||
would produce a new url whose toString(true) method would return | would produce a new url whose toString(true) method would return | ||||
"www.fish.com?amount=some+fish". | "www.fish.com?amount=some+fish". | ||||
@@ -241,20 +234,17 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
/** Tries to launch the system's default browser to open the URL. | /** Tries to launch the system's default browser to open the URL. | ||||
Returns true if this seems to have worked. | Returns true if this seems to have worked. | ||||
*/ | */ | ||||
bool launchInDefaultBrowser() const; | bool launchInDefaultBrowser() const; | ||||
//============================================================================== | //============================================================================== | ||||
/** Takes a guess as to whether a string might be a valid website address. | /** Takes a guess as to whether a string might be a valid website address. | ||||
This isn't foolproof! | This isn't foolproof! | ||||
*/ | */ | ||||
static bool isProbablyAWebsiteURL (const String& possibleURL); | static bool isProbablyAWebsiteURL (const String& possibleURL); | ||||
/** Takes a guess as to whether a string might be a valid email address. | /** Takes a guess as to whether a string might be a valid email address. | ||||
This isn't foolproof! | This isn't foolproof! | ||||
*/ | */ | ||||
static bool isProbablyAnEmailAddress (const String& possibleEmailAddress); | static bool isProbablyAnEmailAddress (const String& possibleEmailAddress); | ||||
@@ -319,7 +309,6 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
/** Represents a download task. | /** Represents a download task. | ||||
Returned by downloadToFile to allow querying and controling the download task. | Returned by downloadToFile to allow querying and controling the download task. | ||||
*/ | */ | ||||
class DownloadTask | class DownloadTask | ||||
@@ -346,34 +335,32 @@ public: | |||||
/** Returns the total length of the download task. This may return -1 if the length | /** Returns the total length of the download task. This may return -1 if the length | ||||
was not returned by the server. */ | was not returned by the server. */ | ||||
inline int64 getTotalLength() const { return contentLength; } | |||||
int64 getTotalLength() const { return contentLength; } | |||||
/** Returns the number of bytes that have been downloaded so far. */ | /** Returns the number of bytes that have been downloaded so far. */ | ||||
inline int64 getLengthDownloaded() const { return downloaded; } | |||||
int64 getLengthDownloaded() const { return downloaded; } | |||||
/** Returns true if the download finished or there was an error. */ | /** Returns true if the download finished or there was an error. */ | ||||
inline bool isFinished() const { return finished; } | |||||
/** Returns the status code of the server's response. This will only be valid | |||||
after the download has finished. | |||||
bool isFinished() const { return finished; } | |||||
/** Returns the status code of the server's response. | |||||
This will only be valid after the download has finished. | |||||
@see isFinished | @see isFinished | ||||
*/ | */ | ||||
inline int statusCode() const { return httpCode; } | |||||
int statusCode() const { return httpCode; } | |||||
/** Returns true if there was an error. */ | /** Returns true if there was an error. */ | ||||
inline bool hadError() const { return error; } | inline bool hadError() const { return error; } | ||||
protected: | protected: | ||||
int64 contentLength, downloaded; | |||||
bool finished, error; | |||||
int httpCode; | |||||
int64 contentLength = -1, downloaded = 0; | |||||
bool finished = false, error = false; | |||||
int httpCode = -1; | |||||
DownloadTask(); | DownloadTask(); | ||||
private: | private: | ||||
friend class URL; | friend class URL; | ||||
static DownloadTask* createFallbackDownloader (const URL&, const File&, const String&, Listener*, bool); | static DownloadTask* createFallbackDownloader (const URL&, const File&, const String&, Listener*, bool); | ||||
public: | public: | ||||
@@ -381,6 +368,7 @@ public: | |||||
/** internal **/ | /** internal **/ | ||||
static void juce_iosURLSessionNotify (const String&); | static void juce_iosURLSessionNotify (const String&); | ||||
#endif | #endif | ||||
private: | private: | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DownloadTask) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DownloadTask) | ||||
}; | }; | ||||
@@ -114,11 +114,6 @@ | |||||
#include "../misc/juce_StdFunctionCompat.h" | #include "../misc/juce_StdFunctionCompat.h" | ||||
#endif | #endif | ||||
// The live build fails to compile std::stringstream | |||||
#if ! JUCE_PROJUCER_LIVE_BUILD | |||||
#include <sstream> | |||||
#endif | |||||
// Include std::atomic if it's supported by the compiler | // Include std::atomic if it's supported by the compiler | ||||
#if JUCE_ATOMIC_AVAILABLE | #if JUCE_ATOMIC_AVAILABLE | ||||
#include <atomic> | #include <atomic> | ||||
@@ -241,12 +241,13 @@ public: | |||||
STRING_DOUBLE_PAIR_COMBOS (2087.3087e+00006), | STRING_DOUBLE_PAIR_COMBOS (2087.3087e+00006), | ||||
STRING_DOUBLE_PAIR_COMBOS (6.0872e-00006), | STRING_DOUBLE_PAIR_COMBOS (6.0872e-00006), | ||||
// Too many sig figs | |||||
// Too many sig figs. The parsing routine on MinGW gets the last | |||||
// significant figure wrong. | |||||
STRING_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890), | STRING_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890), | ||||
STRING_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890e-111) | STRING_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890e-111) | ||||
// Limits. DBL_MAX may not exist on Linux. | |||||
#if ! JUCE_LINUX | #if ! JUCE_LINUX | ||||
// Limits | |||||
, STRING_DOUBLE_PAIR (DBL_MAX), | , STRING_DOUBLE_PAIR (DBL_MAX), | ||||
STRING_DOUBLE_PAIR (-DBL_MAX), | STRING_DOUBLE_PAIR (-DBL_MAX), | ||||
STRING_DOUBLE_PAIR (DBL_MIN) | STRING_DOUBLE_PAIR (DBL_MIN) | ||||
@@ -61,7 +61,7 @@ namespace juce | |||||
#endif | #endif | ||||
//============================================================================== | //============================================================================== | ||||
/** GNU libstdc++ does not have std::make_unsigned */ | |||||
// GNU libstdc++ does not have std::make_unsigned | |||||
namespace internal | namespace internal | ||||
{ | { | ||||
template <typename Type> struct make_unsigned { typedef Type type; }; | template <typename Type> struct make_unsigned { typedef Type type; }; | ||||
@@ -140,20 +140,29 @@ public: | |||||
template <typename CharPointerType> | template <typename CharPointerType> | ||||
static double readDoubleValue (CharPointerType& text) noexcept | static double readDoubleValue (CharPointerType& text) noexcept | ||||
{ | { | ||||
const int maxSignificantDigits = 17 + 1; // An additional digit for rounding | |||||
const int bufferSize = maxSignificantDigits + 7 + 1; // -.E-XXX and a trailing null-terminator | |||||
#if JUCE_MINGW | |||||
bool isNegative = false; | |||||
#else | |||||
JUCE_CONSTEXPR const int maxSignificantDigits = 17 + 1; // An additional digit for rounding | |||||
JUCE_CONSTEXPR const int bufferSize = maxSignificantDigits + 7 + 1; // -.E-XXX and a trailing null-terminator | |||||
char buffer[bufferSize] = {}; | char buffer[bufferSize] = {}; | ||||
char* currentCharacter = &(buffer[0]); | char* currentCharacter = &(buffer[0]); | ||||
int numSigFigs = 0; | |||||
bool decimalPointFound = false; | |||||
#endif | |||||
text = text.findEndOfWhitespace(); | text = text.findEndOfWhitespace(); | ||||
auto c = *text; | auto c = *text; | ||||
switch (c) | switch (c) | ||||
{ | { | ||||
case '-': *currentCharacter++ = '-'; // Fall-through.. | |||||
case '+': c = *++text; | |||||
case '-': | |||||
#if JUCE_MINGW | |||||
isNegative = true; | |||||
#else | |||||
*currentCharacter++ = '-'; | |||||
#endif | |||||
// Fall-through.. | |||||
case '+': | |||||
c = *++text; | |||||
} | } | ||||
switch (c) | switch (c) | ||||
@@ -171,11 +180,121 @@ public: | |||||
break; | break; | ||||
} | } | ||||
#if JUCE_MINGW | |||||
// MinGW does not have access to the locale functions required for strtold, so we parse the doubles | |||||
// ourselves. There are some edge cases where the least significant digit will be wrong! | |||||
double result[3] = { 0 }, accumulator[2] = { 0 }; | |||||
int exponentAdjustment[2] = { 0 }, exponentAccumulator[2] = { -1, -1 }; | |||||
int exponent = 0, decPointIndex = 0, digit = 0; | |||||
int lastDigit = 0, numSignificantDigits = 0; | |||||
bool digitsFound = false; | |||||
JUCE_CONSTEXPR const int maxSignificantDigits = 17 + 1; | |||||
for (;;) | |||||
{ | |||||
if (text.isDigit()) | |||||
{ | |||||
lastDigit = digit; | |||||
digit = (int) text.getAndAdvance() - '0'; | |||||
digitsFound = true; | |||||
if (decPointIndex != 0) | |||||
exponentAdjustment[1]++; | |||||
if (numSignificantDigits == 0 && digit == 0) | |||||
continue; | |||||
if (++numSignificantDigits > maxSignificantDigits) | |||||
{ | |||||
if (digit > 5) | |||||
++accumulator [decPointIndex]; | |||||
else if (digit == 5 && (lastDigit & 1) != 0) | |||||
++accumulator [decPointIndex]; | |||||
if (decPointIndex > 0) | |||||
exponentAdjustment[1]--; | |||||
else | |||||
exponentAdjustment[0]++; | |||||
while (text.isDigit()) | |||||
{ | |||||
++text; | |||||
if (decPointIndex == 0) | |||||
exponentAdjustment[0]++; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
const auto maxAccumulatorValue = (double) ((std::numeric_limits<unsigned int>::max() - 9) / 10); | |||||
if (accumulator [decPointIndex] > maxAccumulatorValue) | |||||
{ | |||||
result [decPointIndex] = mulexp10 (result [decPointIndex], exponentAccumulator [decPointIndex]) | |||||
+ accumulator [decPointIndex]; | |||||
accumulator [decPointIndex] = 0; | |||||
exponentAccumulator [decPointIndex] = 0; | |||||
} | |||||
accumulator [decPointIndex] = accumulator[decPointIndex] * 10 + digit; | |||||
exponentAccumulator [decPointIndex]++; | |||||
} | |||||
} | |||||
else if (decPointIndex == 0 && *text == '.') | |||||
{ | |||||
++text; | |||||
decPointIndex = 1; | |||||
if (numSignificantDigits > maxSignificantDigits) | |||||
{ | |||||
while (text.isDigit()) | |||||
++text; | |||||
break; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
break; | |||||
} | |||||
} | |||||
result[0] = mulexp10 (result[0], exponentAccumulator[0]) + accumulator[0]; | |||||
if (decPointIndex != 0) | |||||
result[1] = mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1]; | |||||
c = *text; | |||||
if ((c == 'e' || c == 'E') && digitsFound) | |||||
{ | |||||
auto negativeExponent = false; | |||||
switch (*++text) | |||||
{ | |||||
case '-': negativeExponent = true; // fall-through.. | |||||
case '+': ++text; | |||||
} | |||||
while (text.isDigit()) | |||||
exponent = (exponent * 10) + ((int) text.getAndAdvance() - '0'); | |||||
if (negativeExponent) | |||||
exponent = -exponent; | |||||
} | |||||
auto r = mulexp10 (result[0], exponent + exponentAdjustment[0]); | |||||
if (decPointIndex != 0) | |||||
r += mulexp10 (result[1], exponent - exponentAdjustment[1]); | |||||
return isNegative ? -r : r; | |||||
#else // ! JUCE_MINGW | |||||
int numSigFigs = 0; | |||||
bool decimalPointFound = false; | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
if (text.isDigit()) | if (text.isDigit()) | ||||
{ | { | ||||
int digit = (int) text.getAndAdvance() - '0'; | |||||
auto digit = (int) text.getAndAdvance() - '0'; | |||||
if (numSigFigs >= maxSignificantDigits | if (numSigFigs >= maxSignificantDigits | ||||
|| ((numSigFigs == 0 && (! decimalPointFound)) && digit == 0)) | || ((numSigFigs == 0 && (! decimalPointFound)) && digit == 0)) | ||||
@@ -231,22 +350,19 @@ public: | |||||
*currentCharacter++ = '0'; | *currentCharacter++ = '0'; | ||||
} | } | ||||
#if JUCE_PROJUCER_LIVE_BUILD | |||||
// This will change with locale! | |||||
return strtod (&buffer[0], nullptr); | |||||
#if JUCE_WINDOWS | |||||
static _locale_t locale = _create_locale (LC_ALL, "C"); | |||||
return _strtod_l (&buffer[0], nullptr, locale); | |||||
#else | #else | ||||
double result = 0; | |||||
const size_t stringSize = (size_t) (currentCharacter - &buffer[0]) + 1; | |||||
if (stringSize > 1) | |||||
{ | |||||
std::istringstream is (std::string (&buffer[0], stringSize)); | |||||
is.imbue (std::locale ("C")); | |||||
is >> result; | |||||
} | |||||
return result; | |||||
static locale_t locale = newlocale (LC_ALL_MASK, "C", nullptr); | |||||
#if JUCE_ANDROID | |||||
return (double) strtold_l (&buffer[0], nullptr, locale); | |||||
#else | |||||
return strtod_l (&buffer[0], nullptr, locale); | |||||
#endif | |||||
#endif | #endif | ||||
#endif // JUCE_MINGW | |||||
} | } | ||||
/** Parses a character string, to read a floating-point value. */ | /** Parses a character string, to read a floating-point value. */ | ||||
@@ -241,7 +241,7 @@ namespace XmlOutputFunctions | |||||
outputStream << (char) character; | outputStream << (char) character; | ||||
break; | break; | ||||
} | } | ||||
// Note: deliberate fall-through here! | |||||
// fall-through | |||||
default: | default: | ||||
outputStream << "&#" << ((int) character) << ';'; | outputStream << "&#" << ((int) character) << ';'; | ||||
break; | break; | ||||
@@ -92,7 +92,7 @@ private: | |||||
{ | { | ||||
case Z_STREAM_END: | case Z_STREAM_END: | ||||
finished = true; | finished = true; | ||||
// Deliberate fall-through.. | |||||
// fall-through.. | |||||
case Z_OK: | case Z_OK: | ||||
{ | { | ||||
data += dataSize - stream.avail_in; | data += dataSize - stream.avail_in; | ||||
@@ -39,6 +39,9 @@ namespace zlibNamespace | |||||
#if __has_warning("-Wcomma") | #if __has_warning("-Wcomma") | ||||
#pragma clang diagnostic ignored "-Wcomma" | #pragma clang diagnostic ignored "-Wcomma" | ||||
#endif | #endif | ||||
#elif JUCE_GCC && (__GNUC__ >= 7) | |||||
#pragma GCC diagnostic push | |||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" | |||||
#endif | #endif | ||||
#undef OS_CODE | #undef OS_CODE | ||||
@@ -74,6 +77,8 @@ namespace zlibNamespace | |||||
#if JUCE_CLANG | #if JUCE_CLANG | ||||
#pragma clang diagnostic pop | #pragma clang diagnostic pop | ||||
#elif JUCE_GCC && (__GNUC__ >= 7) | |||||
#pragma GCC diagnostic pop | |||||
#endif | #endif | ||||
#else | #else | ||||
#include JUCE_ZLIB_INCLUDE_PATH | #include JUCE_ZLIB_INCLUDE_PATH | ||||
@@ -136,7 +141,7 @@ public: | |||||
{ | { | ||||
case Z_STREAM_END: | case Z_STREAM_END: | ||||
finished = true; | finished = true; | ||||
// deliberate fall-through | |||||
// fall-through | |||||
case Z_OK: | case Z_OK: | ||||
data += dataSize - stream.avail_in; | data += dataSize - stream.avail_in; | ||||
dataSize = (z_uInt) stream.avail_in; | dataSize = (z_uInt) stream.avail_in; | ||||
@@ -59,8 +59,6 @@ ActionBroadcaster::~ActionBroadcaster() | |||||
{ | { | ||||
// all event-based objects must be deleted BEFORE juce is shut down! | // all event-based objects must be deleted BEFORE juce is shut down! | ||||
jassert (MessageManager::getInstanceWithoutCreating() != nullptr); | jassert (MessageManager::getInstanceWithoutCreating() != nullptr); | ||||
masterReference.clear(); | |||||
} | } | ||||
void ActionBroadcaster::addActionListener (ActionListener* const listener) | void ActionBroadcaster::addActionListener (ActionListener* const listener) | ||||
@@ -64,15 +64,13 @@ public: | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
friend class WeakReference<ActionBroadcaster>; | |||||
WeakReference<ActionBroadcaster>::Master masterReference; | |||||
class ActionMessage; | class ActionMessage; | ||||
friend class ActionMessage; | friend class ActionMessage; | ||||
SortedSet<ActionListener*> actionListeners; | SortedSet<ActionListener*> actionListeners; | ||||
CriticalSection actionListenerLock; | CriticalSection actionListenerLock; | ||||
JUCE_DECLARE_WEAK_REFERENCEABLE (ActionBroadcaster) | |||||
JUCE_DECLARE_NON_COPYABLE (ActionBroadcaster) | JUCE_DECLARE_NON_COPYABLE (ActionBroadcaster) | ||||
}; | }; | ||||
@@ -26,22 +26,16 @@ namespace juce | |||||
struct InterprocessConnection::ConnectionThread : public Thread | struct InterprocessConnection::ConnectionThread : public Thread | ||||
{ | { | ||||
ConnectionThread (InterprocessConnection& c) : Thread ("JUCE IPC"), owner (c) {} | ConnectionThread (InterprocessConnection& c) : Thread ("JUCE IPC"), owner (c) {} | ||||
void run() override { owner.runThread(); } | void run() override { owner.runThread(); } | ||||
private: | |||||
InterprocessConnection& owner; | InterprocessConnection& owner; | ||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectionThread) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectionThread) | ||||
}; | }; | ||||
//============================================================================== | //============================================================================== | ||||
InterprocessConnection::InterprocessConnection (const bool callbacksOnMessageThread, | |||||
const uint32 magicMessageHeaderNumber) | |||||
: callbackConnectionState (false), | |||||
useMessageThread (callbacksOnMessageThread), | |||||
magicMessageHeader (magicMessageHeaderNumber), | |||||
pipeReceiveMessageTimeout (-1) | |||||
InterprocessConnection::InterprocessConnection (bool callbacksOnMessageThread, uint32 magicMessageHeaderNumber) | |||||
: useMessageThread (callbacksOnMessageThread), | |||||
magicMessageHeader (magicMessageHeaderNumber) | |||||
{ | { | ||||
thread = new ConnectionThread (*this); | thread = new ConnectionThread (*this); | ||||
} | } | ||||
@@ -207,7 +201,7 @@ struct ConnectionStateMessage : public MessageManager::MessageBase | |||||
void messageCallback() override | void messageCallback() override | ||||
{ | { | ||||
if (InterprocessConnection* const ipc = owner) | |||||
if (auto* ipc = owner.get()) | |||||
{ | { | ||||
if (connectionMade) | if (connectionMade) | ||||
ipc->connectionMade(); | ipc->connectionMade(); | ||||
@@ -256,7 +250,7 @@ struct DataDeliveryMessage : public Message | |||||
void messageCallback() override | void messageCallback() override | ||||
{ | { | ||||
if (InterprocessConnection* const ipc = owner) | |||||
if (auto* ipc = owner.get()) | |||||
ipc->messageReceived (data); | ipc->messageReceived (data); | ||||
} | } | ||||
@@ -331,7 +325,7 @@ void InterprocessConnection::runThread() | |||||
{ | { | ||||
if (socket != nullptr) | if (socket != nullptr) | ||||
{ | { | ||||
const int ready = socket->waitUntilReady (true, 0); | |||||
auto ready = socket->waitUntilReady (true, 0); | |||||
if (ready < 0) | if (ready < 0) | ||||
{ | { | ||||
@@ -176,15 +176,13 @@ public: | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
WeakReference<InterprocessConnection>::Master masterReference; | |||||
friend class WeakReference<InterprocessConnection>; | |||||
CriticalSection pipeAndSocketLock; | CriticalSection pipeAndSocketLock; | ||||
ScopedPointer<StreamingSocket> socket; | ScopedPointer<StreamingSocket> socket; | ||||
ScopedPointer<NamedPipe> pipe; | ScopedPointer<NamedPipe> pipe; | ||||
bool callbackConnectionState; | |||||
bool callbackConnectionState = false; | |||||
const bool useMessageThread; | const bool useMessageThread; | ||||
const uint32 magicMessageHeader; | const uint32 magicMessageHeader; | ||||
int pipeReceiveMessageTimeout; | |||||
int pipeReceiveMessageTimeout = -1; | |||||
friend class InterprocessConnectionServer; | friend class InterprocessConnectionServer; | ||||
void initialiseWithSocket (StreamingSocket*); | void initialiseWithSocket (StreamingSocket*); | ||||
@@ -202,6 +200,7 @@ private: | |||||
void runThread(); | void runThread(); | ||||
int writeData (void*, int); | int writeData (void*, int); | ||||
JUCE_DECLARE_WEAK_REFERENCEABLE (InterprocessConnection) | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InterprocessConnection) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InterprocessConnection) | ||||
}; | }; | ||||
@@ -186,7 +186,7 @@ void CustomTypeface::addGlyph (const juce_wchar character, const Path& path, con | |||||
// Check that you're not trying to add the same character twice.. | // Check that you're not trying to add the same character twice.. | ||||
jassert (findGlyph (character, false) == nullptr); | jassert (findGlyph (character, false) == nullptr); | ||||
if (isPositiveAndBelow ((int) character, (int) numElementsInArray (lookupTable))) | |||||
if (isPositiveAndBelow ((int) character, numElementsInArray (lookupTable))) | |||||
lookupTable [character] = (short) glyphs.size(); | lookupTable [character] = (short) glyphs.size(); | ||||
glyphs.add (new GlyphInfo (character, path, width)); | glyphs.add (new GlyphInfo (character, path, width)); | ||||
@@ -205,7 +205,7 @@ void CustomTypeface::addKerningPair (const juce_wchar char1, const juce_wchar ch | |||||
CustomTypeface::GlyphInfo* CustomTypeface::findGlyph (const juce_wchar character, const bool loadIfNeeded) noexcept | CustomTypeface::GlyphInfo* CustomTypeface::findGlyph (const juce_wchar character, const bool loadIfNeeded) noexcept | ||||
{ | { | ||||
if (isPositiveAndBelow ((int) character, (int) numElementsInArray (lookupTable)) && lookupTable [character] > 0) | |||||
if (isPositiveAndBelow ((int) character, numElementsInArray (lookupTable)) && lookupTable [character] > 0) | |||||
return glyphs [(int) lookupTable [(int) character]]; | return glyphs [(int) lookupTable [(int) character]]; | ||||
for (int i = 0; i < glyphs.size(); ++i) | for (int i = 0; i < glyphs.size(); ++i) | ||||
@@ -122,8 +122,8 @@ Range<float> TextLayout::Line::getLineBoundsX() const noexcept | |||||
Range<float> TextLayout::Line::getLineBoundsY() const noexcept | Range<float> TextLayout::Line::getLineBoundsY() const noexcept | ||||
{ | { | ||||
return Range<float> (lineOrigin.y - ascent, | |||||
lineOrigin.y + descent); | |||||
return { lineOrigin.y - ascent, | |||||
lineOrigin.y + descent }; | |||||
} | } | ||||
Rectangle<float> TextLayout::Line::getLineBounds() const noexcept | Rectangle<float> TextLayout::Line::getLineBounds() const noexcept | ||||
@@ -223,7 +223,8 @@ void TextLayout::draw (Graphics& g, Rectangle<float> area) const | |||||
: runExtent.getUnionWith (glyphRange); | : runExtent.getUnionWith (glyphRange); | ||||
} | } | ||||
const float lineThickness = run->font.getDescent() * 0.3f; | |||||
auto lineThickness = run->font.getDescent() * 0.3f; | |||||
context.fillRect ({ runExtent.getStart() + lineOrigin.x, lineOrigin.y + lineThickness * 2.0f, | context.fillRect ({ runExtent.getStart() + lineOrigin.x, lineOrigin.y + lineThickness * 2.0f, | ||||
runExtent.getLength(), lineThickness }); | runExtent.getLength(), lineThickness }); | ||||
} | } | ||||
@@ -256,8 +257,8 @@ void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& te | |||||
void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& text, float maxWidth, float maxHeight) | void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& text, float maxWidth, float maxHeight) | ||||
{ | { | ||||
const float minimumWidth = maxWidth / 2.0f; | |||||
float bestWidth = maxWidth; | |||||
auto minimumWidth = maxWidth / 2.0f; | |||||
auto bestWidth = maxWidth; | |||||
float bestLineProportion = 0.0f; | float bestLineProportion = 0.0f; | ||||
while (maxWidth > minimumWidth) | while (maxWidth > minimumWidth) | ||||
@@ -267,12 +268,13 @@ void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& te | |||||
if (getNumLines() < 2) | if (getNumLines() < 2) | ||||
return; | return; | ||||
const float line1 = lines.getUnchecked (lines.size() - 1)->getLineBoundsX().getLength(); | |||||
const float line2 = lines.getUnchecked (lines.size() - 2)->getLineBoundsX().getLength(); | |||||
const float shortestLine = jmin (line1, line2); | |||||
const float prop = (shortestLine > 0) ? jmax (line1, line2) / shortestLine : 1.0f; | |||||
auto line1 = lines.getUnchecked (lines.size() - 1)->getLineBoundsX().getLength(); | |||||
auto line2 = lines.getUnchecked (lines.size() - 2)->getLineBoundsX().getLength(); | |||||
auto shortest = jmin (line1, line2); | |||||
auto longest = jmax (line1, line2); | |||||
auto prop = shortest > 0 ? longest / shortest : 1.0f; | |||||
if (prop > 0.9f) | |||||
if (prop > 0.9f && prop < 1.1f) | |||||
return; | return; | ||||
if (prop > bestLineProportion) | if (prop > bestLineProportion) | ||||
@@ -308,8 +310,7 @@ namespace TextLayoutHelpers | |||||
float lineHeight; | float lineHeight; | ||||
const bool isWhitespace, isNewLine; | const bool isWhitespace, isNewLine; | ||||
private: | |||||
Token& operator= (const Token&); | |||||
Token& operator= (const Token&) = delete; | |||||
}; | }; | ||||
struct TokenList | struct TokenList | ||||
@@ -346,7 +347,7 @@ namespace TextLayoutHelpers | |||||
if (newGlyphs.size() > 0) | if (newGlyphs.size() > 0) | ||||
{ | { | ||||
currentRun->glyphs.ensureStorageAllocated (currentRun->glyphs.size() + newGlyphs.size()); | currentRun->glyphs.ensureStorageAllocated (currentRun->glyphs.size() + newGlyphs.size()); | ||||
const Point<float> tokenOrigin (t.area.getPosition().translated (0, t.font.getAscent())); | |||||
auto tokenOrigin = t.area.getPosition().translated (0, t.font.getAscent()); | |||||
if (needToSetLineOrigin) | if (needToSetLineOrigin) | ||||
{ | { | ||||
@@ -354,11 +355,11 @@ namespace TextLayoutHelpers | |||||
currentLine->lineOrigin = tokenOrigin; | currentLine->lineOrigin = tokenOrigin; | ||||
} | } | ||||
const Point<float> glyphOffset (tokenOrigin - currentLine->lineOrigin); | |||||
auto glyphOffset = tokenOrigin - currentLine->lineOrigin; | |||||
for (int j = 0; j < newGlyphs.size(); ++j) | for (int j = 0; j < newGlyphs.size(); ++j) | ||||
{ | { | ||||
const float x = xOffsets.getUnchecked (j); | |||||
auto x = xOffsets.getUnchecked (j); | |||||
currentRun->glyphs.add (TextLayout::Glyph (newGlyphs.getUnchecked(j), | currentRun->glyphs.add (TextLayout::Glyph (newGlyphs.getUnchecked(j), | ||||
glyphOffset.translated (x, 0), | glyphOffset.translated (x, 0), | ||||
xOffsets.getUnchecked (j + 1) - x)); | xOffsets.getUnchecked (j + 1) - x)); | ||||
@@ -370,7 +371,7 @@ namespace TextLayoutHelpers | |||||
if (t.isWhitespace || t.isNewLine) | if (t.isWhitespace || t.isNewLine) | ||||
++charPosition; | ++charPosition; | ||||
if (auto* nextToken = tokens [i + 1]) | |||||
if (auto* nextToken = tokens[i + 1]) | |||||
{ | { | ||||
if (t.font != nextToken->font || t.colour != nextToken->colour) | if (t.font != nextToken->font || t.colour != nextToken->colour) | ||||
{ | { | ||||
@@ -408,12 +409,12 @@ namespace TextLayoutHelpers | |||||
if ((text.getJustification().getFlags() & (Justification::right | Justification::horizontallyCentred)) != 0) | if ((text.getJustification().getFlags() & (Justification::right | Justification::horizontallyCentred)) != 0) | ||||
{ | { | ||||
const float totalW = layout.getWidth(); | |||||
const bool isCentred = (text.getJustification().getFlags() & Justification::horizontallyCentred) != 0; | |||||
auto totalW = layout.getWidth(); | |||||
bool isCentred = (text.getJustification().getFlags() & Justification::horizontallyCentred) != 0; | |||||
for (int i = 0; i < layout.getNumLines(); ++i) | for (int i = 0; i < layout.getNumLines(); ++i) | ||||
{ | { | ||||
float dx = totalW - layout.getLine(i).getLineBoundsX().getLength(); | |||||
auto dx = totalW - layout.getLine(i).getLineBoundsX().getLength(); | |||||
if (isCentred) | if (isCentred) | ||||
dx /= 2.0f; | dx /= 2.0f; | ||||
@@ -451,11 +452,12 @@ namespace TextLayoutHelpers | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
const juce_wchar c = t.getAndAdvance(); | |||||
auto c = t.getAndAdvance(); | |||||
if (c == 0) | if (c == 0) | ||||
break; | break; | ||||
const int charType = getCharacterType (c); | |||||
auto charType = getCharacterType (c); | |||||
if (charType == 0 || charType != lastCharType) | if (charType == 0 || charType != lastCharType) | ||||
{ | { | ||||
@@ -529,7 +531,7 @@ namespace TextLayoutHelpers | |||||
void addTextRuns (const AttributedString& text) | void addTextRuns (const AttributedString& text) | ||||
{ | { | ||||
const int numAttributes = text.getNumAttributes(); | |||||
auto numAttributes = text.getNumAttributes(); | |||||
tokens.ensureStorageAllocated (jmax (64, numAttributes)); | tokens.ensureStorageAllocated (jmax (64, numAttributes)); | ||||
for (int i = 0; i < numAttributes; ++i) | for (int i = 0; i < numAttributes; ++i) | ||||
@@ -572,7 +572,7 @@ void EdgeTable::intersectWithEdgeTableLine (const int y, const int* const otherL | |||||
lastX = nextX; | lastX = nextX; | ||||
const int nextLevel = (level1 * (level2 + 1)) >> 8; | const int nextLevel = (level1 * (level2 + 1)) >> 8; | ||||
jassert (isPositiveAndBelow (nextLevel, (int) 256)); | |||||
jassert (isPositiveAndBelow (nextLevel, 256)); | |||||
if (nextLevel != lastLevel) | if (nextLevel != lastLevel) | ||||
{ | { | ||||
@@ -129,7 +129,7 @@ public: | |||||
while (--numPoints >= 0) | while (--numPoints >= 0) | ||||
{ | { | ||||
const int level = *++line; | const int level = *++line; | ||||
jassert (isPositiveAndBelow (level, (int) 256)); | |||||
jassert (isPositiveAndBelow (level, 256)); | |||||
const int endX = *++line; | const int endX = *++line; | ||||
jassert (endX >= x); | jassert (endX >= x); | ||||
const int endOfRun = (endX >> 8); | const int endOfRun = (endX >> 8); | ||||
@@ -49,14 +49,8 @@ private: | |||||
}; | }; | ||||
//============================================================================== | //============================================================================== | ||||
ApplicationCommandTarget::ApplicationCommandTarget() | |||||
{ | |||||
} | |||||
ApplicationCommandTarget::~ApplicationCommandTarget() | |||||
{ | |||||
masterReference.clear(); | |||||
} | |||||
ApplicationCommandTarget::ApplicationCommandTarget() {} | |||||
ApplicationCommandTarget::~ApplicationCommandTarget() {} | |||||
//============================================================================== | //============================================================================== | ||||
bool ApplicationCommandTarget::tryToInvoke (const InvocationInfo& info, const bool async) | bool ApplicationCommandTarget::tryToInvoke (const InvocationInfo& info, const bool async) | ||||
@@ -231,14 +231,12 @@ public: | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
WeakReference<ApplicationCommandTarget>::Master masterReference; | |||||
friend class WeakReference<ApplicationCommandTarget>; | |||||
class CommandMessage; | class CommandMessage; | ||||
friend class CommandMessage; | friend class CommandMessage; | ||||
bool tryToInvoke (const InvocationInfo&, bool async); | bool tryToInvoke (const InvocationInfo&, bool async); | ||||
JUCE_DECLARE_WEAK_REFERENCEABLE (ApplicationCommandTarget) | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ApplicationCommandTarget) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ApplicationCommandTarget) | ||||
}; | }; | ||||
@@ -32,11 +32,6 @@ class ComponentAnimator::AnimationTask | |||||
public: | public: | ||||
AnimationTask (Component* c) noexcept : component (c) {} | AnimationTask (Component* c) noexcept : component (c) {} | ||||
~AnimationTask() | |||||
{ | |||||
masterReference.clear(); | |||||
} | |||||
void reset (const Rectangle<int>& finalBounds, | void reset (const Rectangle<int>& finalBounds, | ||||
float finalAlpha, | float finalAlpha, | ||||
int millisecondsToSpendMoving, | int millisecondsToSpendMoving, | ||||
@@ -186,9 +181,6 @@ public: | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProxyComponent) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProxyComponent) | ||||
}; | }; | ||||
WeakReference<AnimationTask>::Master masterReference; | |||||
friend class WeakReference<AnimationTask>; | |||||
WeakReference<Component> component; | WeakReference<Component> component; | ||||
ScopedPointer<Component> proxy; | ScopedPointer<Component> proxy; | ||||
@@ -208,6 +200,7 @@ private: | |||||
+ (time - 0.5) * (midSpeed + (time - 0.5) * (endSpeed - midSpeed)); | + (time - 0.5) * (midSpeed + (time - 0.5) * (endSpeed - midSpeed)); | ||||
} | } | ||||
JUCE_DECLARE_WEAK_REFERENCEABLE (AnimationTask) | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnimationTask) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnimationTask) | ||||
}; | }; | ||||
@@ -37,7 +37,6 @@ extern GetTypefaceForFont juce_getTypefaceForFont; | |||||
//============================================================================== | //============================================================================== | ||||
LookAndFeel::LookAndFeel() | LookAndFeel::LookAndFeel() | ||||
: useNativeAlertWindows (false) | |||||
{ | { | ||||
/* if this fails it means you're trying to create a LookAndFeel object before | /* if this fails it means you're trying to create a LookAndFeel object before | ||||
the static Colours have been initialised. That ain't gonna work. It probably | the static Colours have been initialised. That ain't gonna work. It probably | ||||
@@ -51,7 +50,6 @@ LookAndFeel::LookAndFeel() | |||||
LookAndFeel::~LookAndFeel() | LookAndFeel::~LookAndFeel() | ||||
{ | { | ||||
masterReference.clear(); | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -212,9 +212,6 @@ public: | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
friend class WeakReference<LookAndFeel>; | |||||
WeakReference<LookAndFeel>::Master masterReference; | |||||
struct ColourSetting | struct ColourSetting | ||||
{ | { | ||||
int colourID; | int colourID; | ||||
@@ -226,8 +223,9 @@ private: | |||||
SortedSet<ColourSetting> colours; | SortedSet<ColourSetting> colours; | ||||
String defaultSans, defaultSerif, defaultFixed; | String defaultSans, defaultSerif, defaultFixed; | ||||
bool useNativeAlertWindows; | |||||
bool useNativeAlertWindows = false; | |||||
JUCE_DECLARE_WEAK_REFERENCEABLE (LookAndFeel) | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel) | ||||
}; | }; | ||||
@@ -200,6 +200,8 @@ void LookAndFeel_V4::positionDocumentWindowButtons (DocumentWindow&, | |||||
Button* closeButton, | Button* closeButton, | ||||
bool positionTitleBarButtonsOnLeft) | bool positionTitleBarButtonsOnLeft) | ||||
{ | { | ||||
titleBarH = jmin (titleBarH, titleBarH - titleBarY); | |||||
const int buttonW = (int) (titleBarH * 1.2); | const int buttonW = (int) (titleBarH * 1.2); | ||||
int x = positionTitleBarButtonsOnLeft ? titleBarX | int x = positionTitleBarButtonsOnLeft ? titleBarX | ||||
@@ -1621,7 +1621,7 @@ struct PopupMenuCompletionCallback : public ModalComponentManager::Callback | |||||
if (prevTopLevel != nullptr) | if (prevTopLevel != nullptr) | ||||
prevTopLevel->toFront (true); | prevTopLevel->toFront (true); | ||||
if (prevFocused != nullptr) | |||||
if (prevFocused != nullptr && prevFocused->isShowing()) | |||||
prevFocused->grabKeyboardFocus(); | prevFocused->grabKeyboardFocus(); | ||||
} | } | ||||
} | } | ||||
@@ -27,6 +27,41 @@ | |||||
namespace juce | namespace juce | ||||
{ | { | ||||
//============================================================================== | |||||
struct JuceMainMenuBarHolder : private DeletedAtShutdown | |||||
{ | |||||
JuceMainMenuBarHolder() | |||||
: mainMenuBar ([[NSMenu alloc] initWithTitle: nsStringLiteral ("MainMenu")]) | |||||
{ | |||||
auto* item = [mainMenuBar addItemWithTitle: nsStringLiteral ("Apple") | |||||
action: nil | |||||
keyEquivalent: nsEmptyString()]; | |||||
auto* appMenu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("Apple")]; | |||||
[NSApp performSelector: @selector (setAppleMenu:) withObject: appMenu]; | |||||
[mainMenuBar setSubmenu: appMenu forItem: item]; | |||||
[appMenu release]; | |||||
[NSApp setMainMenu: mainMenuBar]; | |||||
} | |||||
~JuceMainMenuBarHolder() | |||||
{ | |||||
clearSingletonInstance(); | |||||
[NSApp setMainMenu: nil]; | |||||
[mainMenuBar release]; | |||||
} | |||||
NSMenu* mainMenuBar = nil; | |||||
juce_DeclareSingleton_SingleThreaded (JuceMainMenuBarHolder, true) | |||||
}; | |||||
juce_ImplementSingleton_SingleThreaded (JuceMainMenuBarHolder) | |||||
//============================================================================== | |||||
class JuceMainMenuHandler : private MenuBarModel::Listener, | class JuceMainMenuHandler : private MenuBarModel::Listener, | ||||
private DeletedAtShutdown | private DeletedAtShutdown | ||||
{ | { | ||||
@@ -95,7 +130,10 @@ public: | |||||
[menu setAutoenablesItems: false]; | [menu setAutoenablesItems: false]; | ||||
[menu update]; | [menu update]; | ||||
removeItemRecursive ([parentItem submenu]); | |||||
[parentItem setSubmenu: menu]; | [parentItem setSubmenu: menu]; | ||||
[menu release]; | [menu release]; | ||||
} | } | ||||
@@ -104,7 +142,9 @@ public: | |||||
NSMenu* superMenu = [menu supermenu]; | NSMenu* superMenu = [menu supermenu]; | ||||
auto menuNames = currentModel->getMenuBarNames(); | auto menuNames = currentModel->getMenuBarNames(); | ||||
auto indexOfMenu = (int) [superMenu indexOfItemWithSubmenu: menu] - 1; | auto indexOfMenu = (int) [superMenu indexOfItemWithSubmenu: menu] - 1; | ||||
[menu removeAllItems]; | |||||
removeItemRecursive (menu); | |||||
auto updatedPopup = currentModel->getMenuForIndex (indexOfMenu, menuNames[indexOfMenu]); | auto updatedPopup = currentModel->getMenuForIndex (indexOfMenu, menuNames[indexOfMenu]); | ||||
for (PopupMenu::MenuItemIterator iter (updatedPopup); iter.next();) | for (PopupMenu::MenuItemIterator iter (updatedPopup); iter.next();) | ||||
@@ -113,7 +153,7 @@ public: | |||||
[menu update]; | [menu update]; | ||||
} | } | ||||
void menuBarItemsChanged (MenuBarModel*) | |||||
void menuBarItemsChanged (MenuBarModel*) override | |||||
{ | { | ||||
if (isOpen) | if (isOpen) | ||||
{ | { | ||||
@@ -127,10 +167,10 @@ public: | |||||
if (currentModel != nullptr) | if (currentModel != nullptr) | ||||
menuNames = currentModel->getMenuBarNames(); | menuNames = currentModel->getMenuBarNames(); | ||||
NSMenu* menuBar = [[NSApp mainMenu] retain]; | |||||
auto* menuBar = getMainMenuBar(); | |||||
while ([menuBar numberOfItems] > 1 + menuNames.size()) | while ([menuBar numberOfItems] > 1 + menuNames.size()) | ||||
[menuBar removeItemAtIndex: [menuBar numberOfItems] - 1]; | |||||
removeItemRecursive (menuBar, static_cast<int> ([menuBar numberOfItems] - 1)); | |||||
int menuId = 1; | int menuId = 1; | ||||
@@ -143,34 +183,36 @@ public: | |||||
else | else | ||||
updateTopLevelMenu ([menuBar itemAtIndex: 1 + i], menu, menuNames[i], menuId, i); | updateTopLevelMenu ([menuBar itemAtIndex: 1 + i], menu, menuNames[i], menuId, i); | ||||
} | } | ||||
[menuBar release]; | |||||
} | } | ||||
void menuCommandInvoked (MenuBarModel*, const ApplicationCommandTarget::InvocationInfo& info) | |||||
void menuCommandInvoked (MenuBarModel*, const ApplicationCommandTarget::InvocationInfo& info) override | |||||
{ | { | ||||
if ((info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) == 0 | if ((info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) == 0 | ||||
&& info.invocationMethod != ApplicationCommandTarget::InvocationInfo::fromKeyPress) | && info.invocationMethod != ApplicationCommandTarget::InvocationInfo::fromKeyPress) | ||||
if (auto* item = findMenuItemWithTag ([NSApp mainMenu], info.commandID)) | |||||
if (auto* item = findMenuItemWithCommandID (getMainMenuBar(), info.commandID)) | |||||
flashMenuBar ([item menu]); | flashMenuBar ([item menu]); | ||||
} | } | ||||
void invoke (int commandId, ApplicationCommandManager* commandManager, int topLevelIndex) const | |||||
void invoke (const PopupMenu::Item& item, int topLevelIndex) const | |||||
{ | { | ||||
if (currentModel != nullptr) | if (currentModel != nullptr) | ||||
{ | { | ||||
if (commandManager != nullptr) | |||||
if (item.customCallback != nullptr) | |||||
if (! item.customCallback->menuItemTriggered()) | |||||
return; | |||||
if (item.commandManager != nullptr) | |||||
{ | { | ||||
ApplicationCommandTarget::InvocationInfo info (commandId); | |||||
ApplicationCommandTarget::InvocationInfo info (item.itemID); | |||||
info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu; | info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu; | ||||
commandManager->invoke (info, true); | |||||
item.commandManager->invoke (info, true); | |||||
} | } | ||||
MessageManager::callAsync ([=]() | MessageManager::callAsync ([=]() | ||||
{ | { | ||||
if (instance != nullptr) | if (instance != nullptr) | ||||
instance->invokeDirectly (commandId, topLevelIndex); | |||||
instance->invokeDirectly (item.itemID, topLevelIndex); | |||||
}); | }); | ||||
} | } | ||||
} | } | ||||
@@ -232,18 +274,19 @@ public: | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
NSMenuItem* item = [menuToAddTo addItemWithTitle: text | |||||
action: @selector (menuItemInvoked:) | |||||
keyEquivalent: nsEmptyString()]; | |||||
auto* item = [[NSMenuItem alloc] initWithTitle: text | |||||
action: @selector (menuItemInvoked:) | |||||
keyEquivalent: nsEmptyString()]; | |||||
[item setTag: i.itemID]; | |||||
[item setTag: topLevelIndex]; | |||||
[item setEnabled: i.isEnabled]; | [item setEnabled: i.isEnabled]; | ||||
[item setState: i.isTicked ? NSOnState : NSOffState]; | [item setState: i.isTicked ? NSOnState : NSOffState]; | ||||
[item setTarget: (id) callback]; | [item setTarget: (id) callback]; | ||||
NSMutableArray* info = [NSMutableArray arrayWithObject: [NSNumber numberWithUnsignedLongLong: (pointer_sized_uint) (void*) i.commandManager]]; | |||||
[info addObject: [NSNumber numberWithInt: topLevelIndex]]; | |||||
[item setRepresentedObject: info]; | |||||
auto* juceItem = new PopupMenu::Item (i); | |||||
juceItem->customComponent = nullptr; | |||||
[item setRepresentedObject: [createNSObjectFromJuceClass (juceItem) autorelease]]; | |||||
if (i.commandManager != nullptr) | if (i.commandManager != nullptr) | ||||
{ | { | ||||
@@ -264,6 +307,9 @@ public: | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
[menuToAddTo addItem: item]; | |||||
[item release]; | |||||
} | } | ||||
} | } | ||||
@@ -357,16 +403,17 @@ private: | |||||
ScopedPointer<RecentFilesMenuItem> recent; | ScopedPointer<RecentFilesMenuItem> recent; | ||||
//============================================================================== | //============================================================================== | ||||
static NSMenuItem* findMenuItemWithTag (NSMenu* const menu, int tag) | |||||
static NSMenuItem* findMenuItemWithCommandID (NSMenu* const menu, int commandID) | |||||
{ | { | ||||
for (NSInteger i = [menu numberOfItems]; --i >= 0;) | for (NSInteger i = [menu numberOfItems]; --i >= 0;) | ||||
{ | { | ||||
NSMenuItem* m = [menu itemAtIndex: i]; | NSMenuItem* m = [menu itemAtIndex: i]; | ||||
if ([m tag] == tag) | |||||
return m; | |||||
if (auto* menuItem = getJuceClassFromNSObject<PopupMenu::Item> ([m representedObject])) | |||||
if (menuItem->itemID == commandID) | |||||
return m; | |||||
if (NSMenu* sub = [m submenu]) | if (NSMenu* sub = [m submenu]) | ||||
if (NSMenuItem* found = findMenuItemWithTag (sub, tag)) | |||||
if (NSMenuItem* found = findMenuItemWithCommandID (sub, commandID)) | |||||
return found; | return found; | ||||
} | } | ||||
@@ -422,6 +469,39 @@ private: | |||||
return m; | return m; | ||||
} | } | ||||
// Apple Bug: For some reason [NSMenu removeAllItems] seems to leak it's objects | |||||
// on shutdown, so we need this method to release the items one-by-one manually | |||||
static void removeItemRecursive (NSMenu* parentMenu, int menuItemIndex) | |||||
{ | |||||
if (isPositiveAndBelow (menuItemIndex, (int) [parentMenu numberOfItems])) | |||||
{ | |||||
auto* menuItem = [parentMenu itemAtIndex:menuItemIndex]; | |||||
if (auto* submenu = [menuItem submenu]) | |||||
removeItemRecursive (submenu); | |||||
[parentMenu removeItem:menuItem]; | |||||
} | |||||
else | |||||
jassertfalse; | |||||
} | |||||
static void removeItemRecursive (NSMenu* menu) | |||||
{ | |||||
if (menu != nullptr) | |||||
{ | |||||
auto n = static_cast<int> ([menu numberOfItems]); | |||||
for (auto i = n; --i >= 0;) | |||||
removeItemRecursive (menu, i); | |||||
} | |||||
} | |||||
static NSMenu* getMainMenuBar() | |||||
{ | |||||
return JuceMainMenuBarHolder::getInstance()->mainMenuBar; | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
struct JuceMenuCallbackClass : public ObjCClass<NSObject> | struct JuceMenuCallbackClass : public ObjCClass<NSObject> | ||||
{ | { | ||||
@@ -449,7 +529,7 @@ private: | |||||
{ | { | ||||
auto owner = getIvar<JuceMainMenuHandler*> (self, "owner"); | auto owner = getIvar<JuceMainMenuHandler*> (self, "owner"); | ||||
if ([[item representedObject] isKindOfClass: [NSArray class]]) | |||||
if (auto* juceItem = getJuceClassFromNSObject<PopupMenu::Item> ([item representedObject])) | |||||
{ | { | ||||
// If the menu is being triggered by a keypress, the OS will have picked it up before we had a chance to offer it to | // If the menu is being triggered by a keypress, the OS will have picked it up before we had a chance to offer it to | ||||
// our own components, which may have wanted to intercept it. So, rather than dispatching directly, we'll feed it back | // our own components, which may have wanted to intercept it. So, rather than dispatching directly, we'll feed it back | ||||
@@ -472,12 +552,7 @@ private: | |||||
} | } | ||||
} | } | ||||
NSArray* info = (NSArray*) [item representedObject]; | |||||
owner->invoke ((int) [item tag], | |||||
(ApplicationCommandManager*) (pointer_sized_int) | |||||
[((NSNumber*) [info objectAtIndex: 0]) unsignedLongLongValue], | |||||
(int) [((NSNumber*) [info objectAtIndex: 1]) intValue]); | |||||
owner->invoke (*juceItem, static_cast<int> ([item tag])); | |||||
} | } | ||||
} | } | ||||
@@ -505,28 +580,31 @@ public: | |||||
MenuBarModel::setMacMainMenu (nullptr); | MenuBarModel::setMacMainMenu (nullptr); | ||||
NSMenu* menu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("Edit")]; | |||||
NSMenuItem* item; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Cut"), nil) | |||||
action: @selector (cut:) keyEquivalent: nsStringLiteral ("x")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Copy"), nil) | |||||
action: @selector (copy:) keyEquivalent: nsStringLiteral ("c")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Paste"), nil) | |||||
action: @selector (paste:) keyEquivalent: nsStringLiteral ("v")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSApp mainMenu] addItemWithTitle: NSLocalizedString (nsStringLiteral ("Edit"), nil) | |||||
action: nil keyEquivalent: nsEmptyString()]; | |||||
[[NSApp mainMenu] setSubmenu: menu forItem: item]; | |||||
[menu release]; | |||||
if (auto* mainMenu = JuceMainMenuBarHolder::getInstance()->mainMenuBar) | |||||
{ | |||||
NSMenu* menu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("Edit")]; | |||||
NSMenuItem* item; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Cut"), nil) | |||||
action: @selector (cut:) keyEquivalent: nsStringLiteral ("x")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Copy"), nil) | |||||
action: @selector (copy:) keyEquivalent: nsStringLiteral ("c")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (nsStringLiteral ("Paste"), nil) | |||||
action: @selector (paste:) keyEquivalent: nsStringLiteral ("v")]; | |||||
[menu addItem: item]; | |||||
[item release]; | |||||
item = [mainMenu addItemWithTitle: NSLocalizedString (nsStringLiteral ("Edit"), nil) | |||||
action: nil keyEquivalent: nsEmptyString()]; | |||||
[mainMenu setSubmenu: menu forItem: item]; | |||||
[menu release]; | |||||
} | |||||
// use a dummy modal component so that apps can tell that something is currently modal. | // use a dummy modal component so that apps can tell that something is currently modal. | ||||
dummyModalComponent.enterModalState (false); | dummyModalComponent.enterModalState (false); | ||||
@@ -615,23 +693,16 @@ namespace MainMenuHelpers | |||||
if (auto* app = JUCEApplicationBase::getInstance()) | if (auto* app = JUCEApplicationBase::getInstance()) | ||||
{ | { | ||||
JUCE_AUTORELEASEPOOL | |||||
if (auto* mainMenu = JuceMainMenuBarHolder::getInstance()->mainMenuBar) | |||||
{ | { | ||||
NSMenu* mainMenu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("MainMenu")]; | |||||
NSMenuItem* item = [mainMenu addItemWithTitle: nsStringLiteral ("Apple") | |||||
action: nil | |||||
keyEquivalent: nsEmptyString()]; | |||||
NSMenu* appMenu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("Apple")]; | |||||
[NSApp performSelector: @selector (setAppleMenu:) withObject: appMenu]; | |||||
[mainMenu setSubmenu: appMenu forItem: item]; | |||||
[NSApp setMainMenu: mainMenu]; | |||||
MainMenuHelpers::createStandardAppMenu (appMenu, app->getApplicationName(), extraItems); | |||||
[appMenu release]; | |||||
[mainMenu release]; | |||||
if ([mainMenu numberOfItems] > 0) | |||||
{ | |||||
if (auto* appMenu = [[mainMenu itemAtIndex:0] submenu]) | |||||
{ | |||||
[appMenu removeAllItems]; | |||||
MainMenuHelpers::createStandardAppMenu (appMenu, app->getApplicationName(), extraItems); | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -392,8 +392,8 @@ public: | |||||
{ | { | ||||
NSRect viewFrame = [view frame]; | NSRect viewFrame = [view frame]; | ||||
if (! (isPositiveAndBelow (localPos.getX(), (int) viewFrame.size.width) | |||||
&& isPositiveAndBelow (localPos.getY(), (int) viewFrame.size.height))) | |||||
if (! (isPositiveAndBelow (localPos.getX(), viewFrame.size.width) | |||||
&& isPositiveAndBelow (localPos.getY(), viewFrame.size.height))) | |||||
return false; | return false; | ||||
if (! SystemStats::isRunningInAppExtensionSandbox()) | if (! SystemStats::isRunningInAppExtensionSandbox()) | ||||
@@ -1184,8 +1184,8 @@ public: | |||||
{ | { | ||||
auto r = getWindowRect (hwnd); | auto r = getWindowRect (hwnd); | ||||
if (! (isPositiveAndBelow (localPos.x, (int) (r.right - r.left)) | |||||
&& isPositiveAndBelow (localPos.y, (int) (r.bottom - r.top)))) | |||||
if (! (isPositiveAndBelow (localPos.x, r.right - r.left) | |||||
&& isPositiveAndBelow (localPos.y, r.bottom - r.top))) | |||||
return false; | return false; | ||||
POINT p = { localPos.x + r.left + windowBorder.getLeft(), | POINT p = { localPos.x + r.left + windowBorder.getLeft(), | ||||
@@ -43,8 +43,7 @@ AlertWindow::AlertWindow (const String& title, | |||||
Component* comp) | Component* comp) | ||||
: TopLevelWindow (title, true), | : TopLevelWindow (title, true), | ||||
alertIconType (iconType), | alertIconType (iconType), | ||||
associatedComponent (comp), | |||||
escapeKeyCancels (true) | |||||
associatedComponent (comp) | |||||
{ | { | ||||
setAlwaysOnTop (juce_areThereAnyAlwaysOnTopWindows()); | setAlwaysOnTop (juce_areThereAnyAlwaysOnTopWindows()); | ||||
@@ -71,7 +70,7 @@ void AlertWindow::userTriedToCloseWindow() | |||||
//============================================================================== | //============================================================================== | ||||
void AlertWindow::setMessage (const String& message) | void AlertWindow::setMessage (const String& message) | ||||
{ | { | ||||
const String newMessage (message.substring (0, 2048)); | |||||
auto newMessage = message.substring (0, 2048); | |||||
if (text != newMessage) | if (text != newMessage) | ||||
{ | { | ||||
@@ -84,7 +83,7 @@ void AlertWindow::setMessage (const String& message) | |||||
//============================================================================== | //============================================================================== | ||||
void AlertWindow::buttonClicked (Button* button) | void AlertWindow::buttonClicked (Button* button) | ||||
{ | { | ||||
if (Component* parent = button->getParentComponent()) | |||||
if (auto* parent = button->getParentComponent()) | |||||
parent->exitModalState (button->getCommandID()); | parent->exitModalState (button->getCommandID()); | ||||
} | } | ||||
@@ -94,7 +93,7 @@ void AlertWindow::addButton (const String& name, | |||||
const KeyPress& shortcutKey1, | const KeyPress& shortcutKey1, | ||||
const KeyPress& shortcutKey2) | const KeyPress& shortcutKey2) | ||||
{ | { | ||||
TextButton* const b = new TextButton (name, String()); | |||||
auto* b = new TextButton (name, {}); | |||||
buttons.add (b); | buttons.add (b); | ||||
b->setWantsKeyboardFocus (true); | b->setWantsKeyboardFocus (true); | ||||
@@ -105,19 +104,18 @@ void AlertWindow::addButton (const String& name, | |||||
b->addListener (this); | b->addListener (this); | ||||
Array<TextButton*> buttonsArray (buttons.begin(), buttons.size()); | Array<TextButton*> buttonsArray (buttons.begin(), buttons.size()); | ||||
auto& lf = getLookAndFeel(); | |||||
const int buttonHeight = getLookAndFeel().getAlertWindowButtonHeight(); | |||||
const Array<int> buttonWidths = getLookAndFeel().getWidthsForTextButtons (*this, buttonsArray); | |||||
auto buttonHeight = lf.getAlertWindowButtonHeight(); | |||||
auto buttonWidths = lf.getWidthsForTextButtons (*this, buttonsArray); | |||||
jassert (buttonWidths.size() == buttons.size()); | jassert (buttonWidths.size() == buttons.size()); | ||||
int i = 0; | |||||
const int n = buttonWidths.size(); | |||||
for (int i = 0; i < n; ++i) | |||||
buttons.getUnchecked (i)->setSize (buttonWidths.getReference (i), buttonHeight); | |||||
for (auto* button : buttons) | |||||
button->setSize (buttonWidths[i++], buttonHeight); | |||||
addAndMakeVisible (b, 0); | addAndMakeVisible (b, 0); | ||||
updateLayout (false); | updateLayout (false); | ||||
} | } | ||||
@@ -128,10 +126,8 @@ int AlertWindow::getNumButtons() const | |||||
void AlertWindow::triggerButtonClick (const String& buttonName) | void AlertWindow::triggerButtonClick (const String& buttonName) | ||||
{ | { | ||||
for (int i = buttons.size(); --i >= 0;) | |||||
for (auto* b : buttons) | |||||
{ | { | ||||
TextButton* const b = buttons.getUnchecked(i); | |||||
if (buttonName == b->getName()) | if (buttonName == b->getName()) | ||||
{ | { | ||||
b->triggerClick(); | b->triggerClick(); | ||||
@@ -151,7 +147,7 @@ void AlertWindow::addTextEditor (const String& name, | |||||
const String& onScreenLabel, | const String& onScreenLabel, | ||||
const bool isPasswordBox) | const bool isPasswordBox) | ||||
{ | { | ||||
TextEditor* ed = new TextEditor (name, isPasswordBox ? getDefaultPasswordChar() : 0); | |||||
auto* ed = new TextEditor (name, isPasswordBox ? getDefaultPasswordChar() : 0); | |||||
ed->setSelectAllWhenFocused (true); | ed->setSelectAllWhenFocused (true); | ||||
ed->setEscapeAndReturnKeysConsumed (false); | ed->setEscapeAndReturnKeysConsumed (false); | ||||
textBoxes.add (ed); | textBoxes.add (ed); | ||||
@@ -169,9 +165,9 @@ void AlertWindow::addTextEditor (const String& name, | |||||
TextEditor* AlertWindow::getTextEditor (const String& nameOfTextEditor) const | TextEditor* AlertWindow::getTextEditor (const String& nameOfTextEditor) const | ||||
{ | { | ||||
for (int i = textBoxes.size(); --i >= 0;) | |||||
if (textBoxes.getUnchecked(i)->getName() == nameOfTextEditor) | |||||
return textBoxes.getUnchecked(i); | |||||
for (auto* tb : textBoxes) | |||||
if (tb->getName() == nameOfTextEditor) | |||||
return tb; | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
@@ -190,7 +186,7 @@ void AlertWindow::addComboBox (const String& name, | |||||
const StringArray& items, | const StringArray& items, | ||||
const String& onScreenLabel) | const String& onScreenLabel) | ||||
{ | { | ||||
ComboBox* const cb = new ComboBox (name); | |||||
auto* cb = new ComboBox (name); | |||||
comboBoxes.add (cb); | comboBoxes.add (cb); | ||||
allComps.add (cb); | allComps.add (cb); | ||||
@@ -205,9 +201,9 @@ void AlertWindow::addComboBox (const String& name, | |||||
ComboBox* AlertWindow::getComboBoxComponent (const String& nameOfList) const | ComboBox* AlertWindow::getComboBoxComponent (const String& nameOfList) const | ||||
{ | { | ||||
for (int i = comboBoxes.size(); --i >= 0;) | |||||
if (comboBoxes.getUnchecked(i)->getName() == nameOfList) | |||||
return comboBoxes.getUnchecked(i); | |||||
for (auto* cb : comboBoxes) | |||||
if (cb->getName() == nameOfList) | |||||
return cb; | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
@@ -231,15 +227,12 @@ public: | |||||
setScrollbarsShown (true); | setScrollbarsShown (true); | ||||
lookAndFeelChanged(); | lookAndFeelChanged(); | ||||
setWantsKeyboardFocus (false); | setWantsKeyboardFocus (false); | ||||
setFont (font); | setFont (font); | ||||
setText (message, false); | setText (message, false); | ||||
bestWidth = 2 * (int) std::sqrt (font.getHeight() * font.getStringWidth (message)); | bestWidth = 2 * (int) std::sqrt (font.getHeight() * font.getStringWidth (message)); | ||||
} | } | ||||
int getPreferredWidth() const noexcept { return bestWidth; } | |||||
void updateLayout (const int width) | void updateLayout (const int width) | ||||
{ | { | ||||
AttributedString s; | AttributedString s; | ||||
@@ -251,7 +244,6 @@ public: | |||||
setSize (width, jmin (width, (int) (text.getHeight() + getFont().getHeight()))); | setSize (width, jmin (width, (int) (text.getHeight() + getFont().getHeight()))); | ||||
} | } | ||||
private: | |||||
int bestWidth; | int bestWidth; | ||||
JUCE_DECLARE_NON_COPYABLE (AlertTextComp) | JUCE_DECLARE_NON_COPYABLE (AlertTextComp) | ||||
@@ -259,10 +251,9 @@ private: | |||||
void AlertWindow::addTextBlock (const String& textBlock) | void AlertWindow::addTextBlock (const String& textBlock) | ||||
{ | { | ||||
AlertTextComp* const c = new AlertTextComp (*this, textBlock, getLookAndFeel().getAlertWindowMessageFont()); | |||||
auto* c = new AlertTextComp (*this, textBlock, getLookAndFeel().getAlertWindowMessageFont()); | |||||
textBlocks.add (c); | textBlocks.add (c); | ||||
allComps.add (c); | allComps.add (c); | ||||
addAndMakeVisible (c); | addAndMakeVisible (c); | ||||
updateLayout (false); | updateLayout (false); | ||||
@@ -271,10 +262,9 @@ void AlertWindow::addTextBlock (const String& textBlock) | |||||
//============================================================================== | //============================================================================== | ||||
void AlertWindow::addProgressBarComponent (double& progressValue) | void AlertWindow::addProgressBarComponent (double& progressValue) | ||||
{ | { | ||||
ProgressBar* const pb = new ProgressBar (progressValue); | |||||
auto* pb = new ProgressBar (progressValue); | |||||
progressBars.add (pb); | progressBars.add (pb); | ||||
allComps.add (pb); | allComps.add (pb); | ||||
addAndMakeVisible (pb); | addAndMakeVisible (pb); | ||||
updateLayout (false); | updateLayout (false); | ||||
@@ -285,25 +275,17 @@ void AlertWindow::addCustomComponent (Component* const component) | |||||
{ | { | ||||
customComps.add (component); | customComps.add (component); | ||||
allComps.add (component); | allComps.add (component); | ||||
addAndMakeVisible (component); | addAndMakeVisible (component); | ||||
updateLayout (false); | updateLayout (false); | ||||
} | } | ||||
int AlertWindow::getNumCustomComponents() const | |||||
{ | |||||
return customComps.size(); | |||||
} | |||||
Component* AlertWindow::getCustomComponent (const int index) const | |||||
{ | |||||
return customComps [index]; | |||||
} | |||||
int AlertWindow::getNumCustomComponents() const { return customComps.size(); } | |||||
Component* AlertWindow::getCustomComponent (int index) const { return customComps [index]; } | |||||
Component* AlertWindow::removeCustomComponent (const int index) | Component* AlertWindow::removeCustomComponent (const int index) | ||||
{ | { | ||||
Component* const c = getCustomComponent (index); | |||||
auto* c = getCustomComponent (index); | |||||
if (c != nullptr) | if (c != nullptr) | ||||
{ | { | ||||
@@ -320,14 +302,15 @@ Component* AlertWindow::removeCustomComponent (const int index) | |||||
//============================================================================== | //============================================================================== | ||||
void AlertWindow::paint (Graphics& g) | void AlertWindow::paint (Graphics& g) | ||||
{ | { | ||||
getLookAndFeel().drawAlertBox (g, *this, textArea, textLayout); | |||||
auto& lf = getLookAndFeel(); | |||||
lf.drawAlertBox (g, *this, textArea, textLayout); | |||||
g.setColour (findColour (textColourId)); | g.setColour (findColour (textColourId)); | ||||
g.setFont (getLookAndFeel().getAlertWindowFont()); | |||||
g.setFont (lf.getAlertWindowFont()); | |||||
for (int i = textBoxes.size(); --i >= 0;) | for (int i = textBoxes.size(); --i >= 0;) | ||||
{ | { | ||||
const TextEditor* const te = textBoxes.getUnchecked(i); | |||||
auto* te = textBoxes.getUnchecked(i); | |||||
g.drawFittedText (textboxNames[i], | g.drawFittedText (textboxNames[i], | ||||
te->getX(), te->getY() - 14, | te->getX(), te->getY() - 14, | ||||
@@ -337,7 +320,7 @@ void AlertWindow::paint (Graphics& g) | |||||
for (int i = comboBoxNames.size(); --i >= 0;) | for (int i = comboBoxNames.size(); --i >= 0;) | ||||
{ | { | ||||
const ComboBox* const cb = comboBoxes.getUnchecked(i); | |||||
auto* cb = comboBoxes.getUnchecked(i); | |||||
g.drawFittedText (comboBoxNames[i], | g.drawFittedText (comboBoxNames[i], | ||||
cb->getX(), cb->getY() - 14, | cb->getX(), cb->getY() - 14, | ||||
@@ -345,15 +328,11 @@ void AlertWindow::paint (Graphics& g) | |||||
Justification::centredLeft, 1); | Justification::centredLeft, 1); | ||||
} | } | ||||
for (int i = customComps.size(); --i >= 0;) | |||||
{ | |||||
const Component* const c = customComps.getUnchecked(i); | |||||
for (auto* c : customComps) | |||||
g.drawFittedText (c->getName(), | g.drawFittedText (c->getName(), | ||||
c->getX(), c->getY() - 14, | c->getX(), c->getY() - 14, | ||||
c->getWidth(), 14, | c->getWidth(), 14, | ||||
Justification::centredLeft, 1); | Justification::centredLeft, 1); | ||||
} | |||||
} | } | ||||
void AlertWindow::updateLayout (const bool onlyIncreaseSize) | void AlertWindow::updateLayout (const bool onlyIncreaseSize) | ||||
@@ -361,15 +340,14 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||||
const int titleH = 24; | const int titleH = 24; | ||||
const int iconWidth = 80; | const int iconWidth = 80; | ||||
LookAndFeel& lf = getLookAndFeel(); | |||||
auto& lf = getLookAndFeel(); | |||||
auto messageFont (lf.getAlertWindowMessageFont()); | |||||
const Font messageFont (lf.getAlertWindowMessageFont()); | |||||
auto wid = jmax (messageFont.getStringWidth (text), | |||||
messageFont.getStringWidth (getName())); | |||||
const int wid = jmax (messageFont.getStringWidth (text), | |||||
messageFont.getStringWidth (getName())); | |||||
const int sw = (int) std::sqrt (messageFont.getHeight() * wid); | |||||
int w = jmin (300 + sw * 2, (int) (getParentWidth() * 0.7f)); | |||||
auto sw = (int) std::sqrt (messageFont.getHeight() * wid); | |||||
auto w = jmin (300 + sw * 2, (int) (getParentWidth() * 0.7f)); | |||||
const int edgeGap = 10; | const int edgeGap = 10; | ||||
const int labelHeight = 18; | const int labelHeight = 18; | ||||
int iconSpace = 0; | int iconSpace = 0; | ||||
@@ -397,24 +375,24 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||||
w = jmax (350, (int) textLayout.getWidth() + iconSpace + edgeGap * 4); | w = jmax (350, (int) textLayout.getWidth() + iconSpace + edgeGap * 4); | ||||
w = jmin (w, (int) (getParentWidth() * 0.7f)); | w = jmin (w, (int) (getParentWidth() * 0.7f)); | ||||
const int textLayoutH = (int) textLayout.getHeight(); | |||||
const int textBottom = 16 + titleH + textLayoutH; | |||||
auto textLayoutH = (int) textLayout.getHeight(); | |||||
auto textBottom = 16 + titleH + textLayoutH; | |||||
int h = textBottom; | int h = textBottom; | ||||
int buttonW = 40; | int buttonW = 40; | ||||
for (int i = 0; i < buttons.size(); ++i) | |||||
buttonW += 16 + buttons.getUnchecked (i)->getWidth(); | |||||
for (auto* b : buttons) | |||||
buttonW += 16 + b->getWidth(); | |||||
w = jmax (buttonW, w); | w = jmax (buttonW, w); | ||||
h += (textBoxes.size() + comboBoxes.size() + progressBars.size()) * 50; | h += (textBoxes.size() + comboBoxes.size() + progressBars.size()) * 50; | ||||
if (buttons.size() > 0) | |||||
h += 20 + buttons.getUnchecked (0)->getHeight(); | |||||
if (auto* b = buttons[0]) | |||||
h += 20 + b->getHeight(); | |||||
for (int i = customComps.size(); --i >= 0;) | |||||
for (auto* c : customComps) | |||||
{ | { | ||||
Component* c = customComps.getUnchecked (i); | |||||
w = jmax (w, (c->getWidth() * 100) / 80); | w = jmax (w, (c->getWidth() * 100) / 80); | ||||
h += 10 + c->getHeight(); | h += 10 + c->getHeight(); | ||||
@@ -422,17 +400,14 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||||
h += labelHeight; | h += labelHeight; | ||||
} | } | ||||
for (int i = textBlocks.size(); --i >= 0;) | |||||
{ | |||||
const AlertTextComp* const ac = static_cast<const AlertTextComp*> (textBlocks.getUnchecked(i)); | |||||
w = jmax (w, ac->getPreferredWidth()); | |||||
} | |||||
for (auto* tb : textBlocks) | |||||
w = jmax (w, static_cast<const AlertTextComp*> (tb)->bestWidth); | |||||
w = jmin (w, (int) (getParentWidth() * 0.7f)); | w = jmin (w, (int) (getParentWidth() * 0.7f)); | ||||
for (int i = textBlocks.size(); --i >= 0;) | |||||
for (auto* tb : textBlocks) | |||||
{ | { | ||||
AlertTextComp* const ac = static_cast<AlertTextComp*> (textBlocks.getUnchecked(i)); | |||||
auto* ac = static_cast<AlertTextComp*> (tb); | |||||
ac->updateLayout ((int) (w * 0.8f)); | ac->updateLayout ((int) (w * 0.8f)); | ||||
h += ac->getHeight() + 10; | h += ac->getHeight() + 10; | ||||
} | } | ||||
@@ -455,15 +430,14 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||||
const int spacer = 16; | const int spacer = 16; | ||||
int totalWidth = -spacer; | int totalWidth = -spacer; | ||||
for (int i = buttons.size(); --i >= 0;) | |||||
totalWidth += buttons.getUnchecked(i)->getWidth() + spacer; | |||||
for (auto* b : buttons) | |||||
totalWidth += b->getWidth() + spacer; | |||||
int x = (w - totalWidth) / 2; | |||||
int y = (int) (getHeight() * 0.95f); | |||||
auto x = (w - totalWidth) / 2; | |||||
auto y = (int) (getHeight() * 0.95f); | |||||
for (int i = 0; i < buttons.size(); ++i) | |||||
for (auto* c : buttons) | |||||
{ | { | ||||
TextButton* const c = buttons.getUnchecked(i); | |||||
int ny = proportionOfHeight (0.95f) - c->getHeight(); | int ny = proportionOfHeight (0.95f) - c->getHeight(); | ||||
c->setTopLeftPosition (x, ny); | c->setTopLeftPosition (x, ny); | ||||
if (ny < y) | if (ny < y) | ||||
@@ -476,9 +450,8 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||||
y = textBottom; | y = textBottom; | ||||
for (int i = 0; i < allComps.size(); ++i) | |||||
for (auto* c : allComps) | |||||
{ | { | ||||
Component* const c = allComps.getUnchecked(i); | |||||
h = 22; | h = 22; | ||||
const int comboIndex = comboBoxes.indexOf (dynamic_cast<ComboBox*> (c)); | const int comboIndex = comboBoxes.indexOf (dynamic_cast<ComboBox*> (c)); | ||||
@@ -531,10 +504,8 @@ void AlertWindow::mouseDrag (const MouseEvent& e) | |||||
bool AlertWindow::keyPressed (const KeyPress& key) | bool AlertWindow::keyPressed (const KeyPress& key) | ||||
{ | { | ||||
for (int i = buttons.size(); --i >= 0;) | |||||
for (auto* b : buttons) | |||||
{ | { | ||||
TextButton* const b = buttons.getUnchecked(i); | |||||
if (b->isRegisteredForShortcut (key)) | if (b->isRegisteredForShortcut (key)) | ||||
{ | { | ||||
b->triggerClick(); | b->triggerClick(); | ||||
@@ -579,8 +550,7 @@ public: | |||||
AlertWindow::AlertIconType icon, int numButts, | AlertWindow::AlertIconType icon, int numButts, | ||||
ModalComponentManager::Callback* cb, bool runModally) | ModalComponentManager::Callback* cb, bool runModally) | ||||
: title (t), message (m), iconType (icon), numButtons (numButts), | : title (t), message (m), iconType (icon), numButtons (numButts), | ||||
returnValue (0), associatedComponent (component), | |||||
callback (cb), modal (runModally) | |||||
associatedComponent (component), callback (cb), modal (runModally) | |||||
{ | { | ||||
} | } | ||||
@@ -594,15 +564,15 @@ public: | |||||
private: | private: | ||||
AlertWindow::AlertIconType iconType; | AlertWindow::AlertIconType iconType; | ||||
int numButtons, returnValue; | |||||
int numButtons, returnValue = 0; | |||||
WeakReference<Component> associatedComponent; | WeakReference<Component> associatedComponent; | ||||
ModalComponentManager::Callback* callback; | ModalComponentManager::Callback* callback; | ||||
bool modal; | bool modal; | ||||
void show() | void show() | ||||
{ | { | ||||
LookAndFeel& lf = associatedComponent != nullptr ? associatedComponent->getLookAndFeel() | |||||
: LookAndFeel::getDefaultLookAndFeel(); | |||||
auto& lf = associatedComponent != nullptr ? associatedComponent->getLookAndFeel() | |||||
: LookAndFeel::getDefaultLookAndFeel(); | |||||
ScopedPointer<Component> alertBox (lf.createAlertWindow (title, message, button1, button2, button3, | ScopedPointer<Component> alertBox (lf.createAlertWindow (title, message, button1, button2, button3, | ||||
iconType, numButtons, associatedComponent)); | iconType, numButtons, associatedComponent)); | ||||
@@ -479,8 +479,8 @@ private: | |||||
OwnedArray<Component> textBlocks; | OwnedArray<Component> textBlocks; | ||||
Array<Component*> allComps; | Array<Component*> allComps; | ||||
StringArray textboxNames, comboBoxNames; | StringArray textboxNames, comboBoxNames; | ||||
Component* associatedComponent; | |||||
bool escapeKeyCancels; | |||||
Component* const associatedComponent; | |||||
bool escapeKeyCancels = true; | |||||
void updateLayout (bool onlyIncreaseSize); | void updateLayout (bool onlyIncreaseSize); | ||||
@@ -27,8 +27,8 @@ | |||||
namespace juce | namespace juce | ||||
{ | { | ||||
CallOutBox::CallOutBox (Component& c, const Rectangle<int>& area, Component* const parent) | |||||
: arrowSize (16.0f), content (c), dismissalMouseClicksAreAlwaysConsumed (false) | |||||
CallOutBox::CallOutBox (Component& c, Rectangle<int> area, Component* const parent) | |||||
: content (c) | |||||
{ | { | ||||
addAndMakeVisible (content); | addAndMakeVisible (content); | ||||
@@ -84,7 +84,7 @@ public: | |||||
JUCE_DECLARE_NON_COPYABLE (CallOutBoxCallback) | JUCE_DECLARE_NON_COPYABLE (CallOutBoxCallback) | ||||
}; | }; | ||||
CallOutBox& CallOutBox::launchAsynchronously (Component* content, const Rectangle<int>& area, Component* parent) | |||||
CallOutBox& CallOutBox::launchAsynchronously (Component* content, Rectangle<int> area, Component* parent) | |||||
{ | { | ||||
jassert (content != nullptr); // must be a valid content component! | jassert (content != nullptr); // must be a valid content component! | ||||
@@ -110,7 +110,7 @@ void CallOutBox::paint (Graphics& g) | |||||
void CallOutBox::resized() | void CallOutBox::resized() | ||||
{ | { | ||||
const int borderSpace = getBorderSize(); | |||||
auto borderSpace = getBorderSize(); | |||||
content.setTopLeftPosition (borderSpace, borderSpace); | content.setTopLeftPosition (borderSpace, borderSpace); | ||||
refreshPath(); | refreshPath(); | ||||
} | } | ||||
@@ -143,7 +143,8 @@ void CallOutBox::inputAttemptWhenModal() | |||||
// as Windows still sends touch events before the CallOutBox had a chance | // as Windows still sends touch events before the CallOutBox had a chance | ||||
// to really open. | // to really open. | ||||
RelativeTime elapsed = Time::getCurrentTime() - creationTime; | |||||
auto elapsed = Time::getCurrentTime() - creationTime; | |||||
if (elapsed.inMilliseconds() > 200) | if (elapsed.inMilliseconds() > 200) | ||||
dismiss(); | dismiss(); | ||||
} | } | ||||
@@ -193,29 +194,29 @@ void CallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo, const R | |||||
targetArea = newAreaToPointTo; | targetArea = newAreaToPointTo; | ||||
availableArea = newAreaToFitIn; | availableArea = newAreaToFitIn; | ||||
const int borderSpace = getBorderSize(); | |||||
auto borderSpace = getBorderSize(); | |||||
Rectangle<int> newBounds (content.getWidth() + borderSpace * 2, | Rectangle<int> newBounds (content.getWidth() + borderSpace * 2, | ||||
content.getHeight() + borderSpace * 2); | content.getHeight() + borderSpace * 2); | ||||
const int hw = newBounds.getWidth() / 2; | |||||
const int hh = newBounds.getHeight() / 2; | |||||
const float hwReduced = (float) (hw - borderSpace * 2); | |||||
const float hhReduced = (float) (hh - borderSpace * 2); | |||||
const float arrowIndent = borderSpace - arrowSize; | |||||
auto hw = newBounds.getWidth() / 2; | |||||
auto hh = newBounds.getHeight() / 2; | |||||
auto hwReduced = (float) (hw - borderSpace * 2); | |||||
auto hhReduced = (float) (hh - borderSpace * 2); | |||||
auto arrowIndent = borderSpace - arrowSize; | |||||
Point<float> targets[4] = { Point<float> ((float) targetArea.getCentreX(), (float) targetArea.getBottom()), | |||||
Point<float> ((float) targetArea.getRight(), (float) targetArea.getCentreY()), | |||||
Point<float> ((float) targetArea.getX(), (float) targetArea.getCentreY()), | |||||
Point<float> ((float) targetArea.getCentreX(), (float) targetArea.getY()) }; | |||||
Point<float> targets[4] = { { (float) targetArea.getCentreX(), (float) targetArea.getBottom() }, | |||||
{ (float) targetArea.getRight(), (float) targetArea.getCentreY() }, | |||||
{ (float) targetArea.getX(), (float) targetArea.getCentreY() }, | |||||
{ (float) targetArea.getCentreX(), (float) targetArea.getY() } }; | |||||
Line<float> lines[4] = { Line<float> (targets[0].translated (-hwReduced, hh - arrowIndent), targets[0].translated (hwReduced, hh - arrowIndent)), | |||||
Line<float> (targets[1].translated (hw - arrowIndent, -hhReduced), targets[1].translated (hw - arrowIndent, hhReduced)), | |||||
Line<float> (targets[2].translated (-(hw - arrowIndent), -hhReduced), targets[2].translated (-(hw - arrowIndent), hhReduced)), | |||||
Line<float> (targets[3].translated (-hwReduced, -(hh - arrowIndent)), targets[3].translated (hwReduced, -(hh - arrowIndent))) }; | |||||
Line<float> lines[4] = { { targets[0].translated (-hwReduced, hh - arrowIndent), targets[0].translated (hwReduced, hh - arrowIndent) }, | |||||
{ targets[1].translated (hw - arrowIndent, -hhReduced), targets[1].translated (hw - arrowIndent, hhReduced) }, | |||||
{ targets[2].translated (-(hw - arrowIndent), -hhReduced), targets[2].translated (-(hw - arrowIndent), hhReduced) }, | |||||
{ targets[3].translated (-hwReduced, -(hh - arrowIndent)), targets[3].translated (hwReduced, -(hh - arrowIndent)) } }; | |||||
const Rectangle<float> centrePointArea (newAreaToFitIn.reduced (hw, hh).toFloat()); | |||||
const Point<float> targetCentre (targetArea.getCentre().toFloat()); | |||||
auto centrePointArea = newAreaToFitIn.reduced (hw, hh).toFloat(); | |||||
auto targetCentre = targetArea.getCentre().toFloat(); | |||||
float nearest = 1.0e9f; | float nearest = 1.0e9f; | ||||
@@ -224,8 +225,8 @@ void CallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo, const R | |||||
Line<float> constrainedLine (centrePointArea.getConstrainedPoint (lines[i].getStart()), | Line<float> constrainedLine (centrePointArea.getConstrainedPoint (lines[i].getStart()), | ||||
centrePointArea.getConstrainedPoint (lines[i].getEnd())); | centrePointArea.getConstrainedPoint (lines[i].getEnd())); | ||||
const Point<float> centre (constrainedLine.findNearestPointTo (targetCentre)); | |||||
float distanceFromCentre = centre.getDistanceFrom (targets[i]); | |||||
auto centre = constrainedLine.findNearestPointTo (targetCentre); | |||||
auto distanceFromCentre = centre.getDistanceFrom (targets[i]); | |||||
if (! centrePointArea.intersects (lines[i])) | if (! centrePointArea.intersects (lines[i])) | ||||
distanceFromCentre += 1000.0f; | distanceFromCentre += 1000.0f; | ||||
@@ -233,8 +234,8 @@ void CallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo, const R | |||||
if (distanceFromCentre < nearest) | if (distanceFromCentre < nearest) | ||||
{ | { | ||||
nearest = distanceFromCentre; | nearest = distanceFromCentre; | ||||
targetPoint = targets[i]; | targetPoint = targets[i]; | ||||
newBounds.setPosition ((int) (centre.x - hw), | newBounds.setPosition ((int) (centre.x - hw), | ||||
(int) (centre.y - hh)); | (int) (centre.y - hh)); | ||||
} | } | ||||
@@ -246,7 +247,7 @@ void CallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo, const R | |||||
void CallOutBox::refreshPath() | void CallOutBox::refreshPath() | ||||
{ | { | ||||
repaint(); | repaint(); | ||||
background = Image(); | |||||
background = {}; | |||||
outline.clear(); | outline.clear(); | ||||
const float gap = 4.5f; | const float gap = 4.5f; | ||||
@@ -73,7 +73,7 @@ public: | |||||
If this is a nullptr, the call-out will be added to the desktop. | If this is a nullptr, the call-out will be added to the desktop. | ||||
*/ | */ | ||||
CallOutBox (Component& contentComponent, | CallOutBox (Component& contentComponent, | ||||
const Rectangle<int>& areaToPointTo, | |||||
Rectangle<int> areaToPointTo, | |||||
Component* parentComponent); | Component* parentComponent); | ||||
/** Destructor. */ | /** Destructor. */ | ||||
@@ -117,7 +117,7 @@ public: | |||||
If this is a nullptr, the call-out will be added to the desktop. | If this is a nullptr, the call-out will be added to the desktop. | ||||
*/ | */ | ||||
static CallOutBox& launchAsynchronously (Component* contentComponent, | static CallOutBox& launchAsynchronously (Component* contentComponent, | ||||
const Rectangle<int>& areaToPointTo, | |||||
Rectangle<int> areaToPointTo, | |||||
Component* parentComponent); | Component* parentComponent); | ||||
/** Posts a message which will dismiss the callout box asynchronously. | /** Posts a message which will dismiss the callout box asynchronously. | ||||
@@ -167,13 +167,13 @@ public: | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
float arrowSize; | |||||
Component& content; | Component& content; | ||||
Path outline; | Path outline; | ||||
Point<float> targetPoint; | Point<float> targetPoint; | ||||
Rectangle<int> availableArea, targetArea; | Rectangle<int> availableArea, targetArea; | ||||
Image background; | Image background; | ||||
bool dismissalMouseClicksAreAlwaysConsumed; | |||||
float arrowSize = 16.0f; | |||||
bool dismissalMouseClicksAreAlwaysConsumed = false; | |||||
Time creationTime; | Time creationTime; | ||||
@@ -63,7 +63,7 @@ void DialogWindow::resized() | |||||
if (escapeKeyTriggersCloseButton) | if (escapeKeyTriggersCloseButton) | ||||
{ | { | ||||
if (Button* const close = getCloseButton()) | |||||
if (auto* close = getCloseButton()) | |||||
{ | { | ||||
const KeyPress esc (KeyPress::escapeKey, 0, 0); | const KeyPress esc (KeyPress::escapeKey, 0, 0); | ||||
@@ -102,15 +102,7 @@ private: | |||||
JUCE_DECLARE_NON_COPYABLE (DefaultDialogWindow) | JUCE_DECLARE_NON_COPYABLE (DefaultDialogWindow) | ||||
}; | }; | ||||
DialogWindow::LaunchOptions::LaunchOptions() noexcept | |||||
: dialogBackgroundColour (Colours::lightgrey), | |||||
componentToCentreAround (nullptr), | |||||
escapeKeyTriggersCloseButton (true), | |||||
useNativeTitleBar (true), | |||||
resizable (true), | |||||
useBottomRightCornerResizer (false) | |||||
{ | |||||
} | |||||
DialogWindow::LaunchOptions::LaunchOptions() noexcept {} | |||||
DialogWindow* DialogWindow::LaunchOptions::create() | DialogWindow* DialogWindow::LaunchOptions::create() | ||||
{ | { | ||||
@@ -121,7 +113,7 @@ DialogWindow* DialogWindow::LaunchOptions::create() | |||||
DialogWindow* DialogWindow::LaunchOptions::launchAsync() | DialogWindow* DialogWindow::LaunchOptions::launchAsync() | ||||
{ | { | ||||
DialogWindow* const d = create(); | |||||
auto* d = create(); | |||||
d->enterModalState (true, nullptr, true); | d->enterModalState (true, nullptr, true); | ||||
return d; | return d; | ||||
} | } | ||||
@@ -87,7 +87,7 @@ public: | |||||
String dialogTitle; | String dialogTitle; | ||||
/** The background colour for the window. */ | /** The background colour for the window. */ | ||||
Colour dialogBackgroundColour; | |||||
Colour dialogBackgroundColour = Colours::lightgrey; | |||||
/** The content component to show in the window. This must not be null! | /** The content component to show in the window. This must not be null! | ||||
Using an OptionalScopedPointer to hold this pointer lets you indicate whether | Using an OptionalScopedPointer to hold this pointer lets you indicate whether | ||||
@@ -100,16 +100,16 @@ public: | |||||
dialog box in front of. See the DocumentWindow::centreAroundComponent() method for | dialog box in front of. See the DocumentWindow::centreAroundComponent() method for | ||||
more info about this parameter. | more info about this parameter. | ||||
*/ | */ | ||||
Component* componentToCentreAround; | |||||
Component* componentToCentreAround = nullptr; | |||||
/** If true, then the escape key will trigger the dialog's close button. */ | /** If true, then the escape key will trigger the dialog's close button. */ | ||||
bool escapeKeyTriggersCloseButton; | |||||
bool escapeKeyTriggersCloseButton = true; | |||||
/** If true, the dialog will use a native title bar. See TopLevelWindow::setUsingNativeTitleBar() */ | /** If true, the dialog will use a native title bar. See TopLevelWindow::setUsingNativeTitleBar() */ | ||||
bool useNativeTitleBar; | |||||
bool useNativeTitleBar = true; | |||||
/** If true, the window will be resizable. See ResizableWindow::setResizable() */ | /** If true, the window will be resizable. See ResizableWindow::setResizable() */ | ||||
bool resizable; | |||||
bool resizable = true; | |||||
/** Indicates whether to use a border or corner resizer component. See ResizableWindow::setResizable() */ | /** Indicates whether to use a border or corner resizer component. See ResizableWindow::setResizable() */ | ||||
bool useBottomRightCornerResizer; | |||||
bool useBottomRightCornerResizer = false; | |||||
/** Launches a new modal dialog window. | /** Launches a new modal dialog window. | ||||
This will create a dialog based on the settings in this structure, | This will create a dialog based on the settings in this structure, | ||||
@@ -51,16 +51,12 @@ DocumentWindow::DocumentWindow (const String& title, | |||||
int requiredButtons_, | int requiredButtons_, | ||||
bool addToDesktop_) | bool addToDesktop_) | ||||
: ResizableWindow (title, backgroundColour, addToDesktop_), | : ResizableWindow (title, backgroundColour, addToDesktop_), | ||||
titleBarHeight (26), | |||||
menuBarHeight (24), | |||||
requiredButtons (requiredButtons_), | requiredButtons (requiredButtons_), | ||||
#if JUCE_MAC | #if JUCE_MAC | ||||
positionTitleBarButtonsOnLeft (true), | |||||
positionTitleBarButtonsOnLeft (true) | |||||
#else | #else | ||||
positionTitleBarButtonsOnLeft (false), | |||||
positionTitleBarButtonsOnLeft (false) | |||||
#endif | #endif | ||||
drawTitleTextCentred (true), | |||||
menuBarModel (nullptr) | |||||
{ | { | ||||
setResizeLimits (128, 128, 32768, 32768); | setResizeLimits (128, 128, 32768, 32768); | ||||
@@ -77,8 +73,8 @@ DocumentWindow::~DocumentWindow() | |||||
jassert (titleBarButtons[1] == nullptr || getIndexOfChildComponent (titleBarButtons[1]) >= 0); | jassert (titleBarButtons[1] == nullptr || getIndexOfChildComponent (titleBarButtons[1]) >= 0); | ||||
jassert (titleBarButtons[2] == nullptr || getIndexOfChildComponent (titleBarButtons[2]) >= 0); | jassert (titleBarButtons[2] == nullptr || getIndexOfChildComponent (titleBarButtons[2]) >= 0); | ||||
for (int i = numElementsInArray (titleBarButtons); --i >= 0;) | |||||
titleBarButtons[i] = nullptr; | |||||
for (auto& b : titleBarButtons) | |||||
b = nullptr; | |||||
menuBar = nullptr; | menuBar = nullptr; | ||||
} | } | ||||
@@ -193,16 +189,16 @@ void DocumentWindow::paint (Graphics& g) | |||||
{ | { | ||||
ResizableWindow::paint (g); | ResizableWindow::paint (g); | ||||
const Rectangle<int> titleBarArea (getTitleBarArea()); | |||||
auto titleBarArea = getTitleBarArea(); | |||||
g.reduceClipRegion (titleBarArea); | g.reduceClipRegion (titleBarArea); | ||||
g.setOrigin (titleBarArea.getPosition()); | g.setOrigin (titleBarArea.getPosition()); | ||||
int titleSpaceX1 = 6; | int titleSpaceX1 = 6; | ||||
int titleSpaceX2 = titleBarArea.getWidth() - 6; | int titleSpaceX2 = titleBarArea.getWidth() - 6; | ||||
for (int i = 0; i < 3; ++i) | |||||
for (auto& b : titleBarButtons) | |||||
{ | { | ||||
if (Button* const b = titleBarButtons[i]) | |||||
if (b != nullptr) | |||||
{ | { | ||||
if (positionTitleBarButtonsOnLeft) | if (positionTitleBarButtonsOnLeft) | ||||
titleSpaceX1 = jmax (titleSpaceX1, b->getRight() + (getWidth() - b->getRight()) / 8); | titleSpaceX1 = jmax (titleSpaceX1, b->getRight() + (getWidth() - b->getRight()) / 8); | ||||
@@ -224,10 +220,10 @@ void DocumentWindow::resized() | |||||
{ | { | ||||
ResizableWindow::resized(); | ResizableWindow::resized(); | ||||
if (Button* const b = getMaximiseButton()) | |||||
if (auto* b = getMaximiseButton()) | |||||
b->setToggleState (isFullScreen(), dontSendNotification); | b->setToggleState (isFullScreen(), dontSendNotification); | ||||
const Rectangle<int> titleBarArea (getTitleBarArea()); | |||||
auto titleBarArea = getTitleBarArea(); | |||||
getLookAndFeel() | getLookAndFeel() | ||||
.positionDocumentWindowButtons (*this, | .positionDocumentWindowButtons (*this, | ||||
@@ -250,7 +246,7 @@ BorderSize<int> DocumentWindow::getBorderThickness() | |||||
BorderSize<int> DocumentWindow::getContentComponentBorder() | BorderSize<int> DocumentWindow::getContentComponentBorder() | ||||
{ | { | ||||
BorderSize<int> border (getBorderThickness()); | |||||
auto border = getBorderThickness(); | |||||
if (! isKioskMode()) | if (! isKioskMode()) | ||||
border.setTop (border.getTop() | border.setTop (border.getTop() | ||||
@@ -267,13 +263,11 @@ int DocumentWindow::getTitleBarHeight() const | |||||
Rectangle<int> DocumentWindow::getTitleBarArea() | Rectangle<int> DocumentWindow::getTitleBarArea() | ||||
{ | { | ||||
const BorderSize<int> border (getBorderThickness()); | |||||
if (isKioskMode()) | if (isKioskMode()) | ||||
return Rectangle<int>(); | |||||
return {}; | |||||
return Rectangle<int> (border.getLeft(), border.getTop(), | |||||
getWidth() - border.getLeftAndRight(), getTitleBarHeight()); | |||||
auto border = getBorderThickness(); | |||||
return { border.getLeft(), border.getTop(), getWidth() - border.getLeftAndRight(), getTitleBarHeight() }; | |||||
} | } | ||||
Button* DocumentWindow::getCloseButton() const noexcept { return titleBarButtons[2]; } | Button* DocumentWindow::getCloseButton() const noexcept { return titleBarButtons[2]; } | ||||
@@ -282,7 +276,7 @@ Button* DocumentWindow::getMaximiseButton() const noexcept { return titleBarBut | |||||
int DocumentWindow::getDesktopWindowStyleFlags() const | int DocumentWindow::getDesktopWindowStyleFlags() const | ||||
{ | { | ||||
int styleFlags = ResizableWindow::getDesktopWindowStyleFlags(); | |||||
auto styleFlags = ResizableWindow::getDesktopWindowStyleFlags(); | |||||
if ((requiredButtons & minimiseButton) != 0) styleFlags |= ComponentPeer::windowHasMinimiseButton; | if ((requiredButtons & minimiseButton) != 0) styleFlags |= ComponentPeer::windowHasMinimiseButton; | ||||
if ((requiredButtons & maximiseButton) != 0) styleFlags |= ComponentPeer::windowHasMaximiseButton; | if ((requiredButtons & maximiseButton) != 0) styleFlags |= ComponentPeer::windowHasMaximiseButton; | ||||
@@ -293,8 +287,8 @@ int DocumentWindow::getDesktopWindowStyleFlags() const | |||||
void DocumentWindow::lookAndFeelChanged() | void DocumentWindow::lookAndFeelChanged() | ||||
{ | { | ||||
for (int i = numElementsInArray (titleBarButtons); --i >= 0;) | |||||
titleBarButtons[i] = nullptr; | |||||
for (auto& b : titleBarButtons) | |||||
b = nullptr; | |||||
if (! isUsingNativeTitleBar()) | if (! isUsingNativeTitleBar()) | ||||
{ | { | ||||
@@ -304,9 +298,9 @@ void DocumentWindow::lookAndFeelChanged() | |||||
if ((requiredButtons & maximiseButton) != 0) titleBarButtons[1] = lf.createDocumentWindowButton (maximiseButton); | if ((requiredButtons & maximiseButton) != 0) titleBarButtons[1] = lf.createDocumentWindowButton (maximiseButton); | ||||
if ((requiredButtons & closeButton) != 0) titleBarButtons[2] = lf.createDocumentWindowButton (closeButton); | if ((requiredButtons & closeButton) != 0) titleBarButtons[2] = lf.createDocumentWindowButton (closeButton); | ||||
for (int i = 0; i < 3; ++i) | |||||
for (auto& b : titleBarButtons) | |||||
{ | { | ||||
if (Button* const b = titleBarButtons[i]) | |||||
if (b != nullptr) | |||||
{ | { | ||||
if (buttonListener == nullptr) | if (buttonListener == nullptr) | ||||
buttonListener = new ButtonListenerProxy (*this); | buttonListener = new ButtonListenerProxy (*this); | ||||
@@ -319,7 +313,7 @@ void DocumentWindow::lookAndFeelChanged() | |||||
} | } | ||||
} | } | ||||
if (Button* const b = getCloseButton()) | |||||
if (auto* b = getCloseButton()) | |||||
{ | { | ||||
#if JUCE_MAC | #if JUCE_MAC | ||||
b->addShortcut (KeyPress ('w', ModifierKeys::commandModifier, 0)); | b->addShortcut (KeyPress ('w', ModifierKeys::commandModifier, 0)); | ||||
@@ -342,21 +336,21 @@ void DocumentWindow::parentHierarchyChanged() | |||||
void DocumentWindow::activeWindowStatusChanged() | void DocumentWindow::activeWindowStatusChanged() | ||||
{ | { | ||||
ResizableWindow::activeWindowStatusChanged(); | ResizableWindow::activeWindowStatusChanged(); | ||||
bool isActive = isActiveWindow(); | |||||
for (int i = numElementsInArray (titleBarButtons); --i >= 0;) | |||||
if (Button* const b = titleBarButtons[i]) | |||||
b->setEnabled (isActiveWindow()); | |||||
for (auto& b : titleBarButtons) | |||||
if (b != nullptr) | |||||
b->setEnabled (isActive); | |||||
if (menuBar != nullptr) | if (menuBar != nullptr) | ||||
menuBar->setEnabled (isActiveWindow()); | |||||
menuBar->setEnabled (isActive); | |||||
} | } | ||||
void DocumentWindow::mouseDoubleClick (const MouseEvent& e) | void DocumentWindow::mouseDoubleClick (const MouseEvent& e) | ||||
{ | { | ||||
Button* const maximise = getMaximiseButton(); | |||||
if (maximise != nullptr && getTitleBarArea().contains (e.x, e.y)) | |||||
maximise->triggerClick(); | |||||
if (getTitleBarArea().contains (e.x, e.y)) | |||||
if (auto* maximise = getMaximiseButton()) | |||||
maximise->triggerClick(); | |||||
} | } | ||||
void DocumentWindow::userTriedToCloseWindow() | void DocumentWindow::userTriedToCloseWindow() | ||||
@@ -276,12 +276,12 @@ public: | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
int titleBarHeight, menuBarHeight, requiredButtons; | |||||
bool positionTitleBarButtonsOnLeft, drawTitleTextCentred; | |||||
int titleBarHeight = 26, menuBarHeight = 24, requiredButtons; | |||||
bool positionTitleBarButtonsOnLeft, drawTitleTextCentred = true; | |||||
ScopedPointer<Button> titleBarButtons [3]; | ScopedPointer<Button> titleBarButtons [3]; | ||||
Image titleBarIcon; | Image titleBarIcon; | ||||
ScopedPointer<Component> menuBar; | ScopedPointer<Component> menuBar; | ||||
MenuBarModel* menuBarModel; | |||||
MenuBarModel* menuBarModel = nullptr; | |||||
class ButtonListenerProxy; | class ButtonListenerProxy; | ||||
friend struct ContainerDeletePolicy<ButtonListenerProxy>; | friend struct ContainerDeletePolicy<ButtonListenerProxy>; | ||||
@@ -37,7 +37,6 @@ ResizableWindow::ResizableWindow (const String& name, Colour bkgnd, bool shouldA | |||||
: TopLevelWindow (name, shouldAddToDesktop) | : TopLevelWindow (name, shouldAddToDesktop) | ||||
{ | { | ||||
setBackgroundColour (bkgnd); | setBackgroundColour (bkgnd); | ||||
initialise (shouldAddToDesktop); | initialise (shouldAddToDesktop); | ||||
} | } | ||||
@@ -147,7 +146,7 @@ void ResizableWindow::setContentComponentSize (int width, int height) | |||||
{ | { | ||||
jassert (width > 0 && height > 0); // not a great idea to give it a zero size.. | jassert (width > 0 && height > 0); // not a great idea to give it a zero size.. | ||||
const BorderSize<int> border (getContentComponentBorder()); | |||||
auto border = getContentComponentBorder(); | |||||
setSize (width + border.getLeftAndRight(), | setSize (width + border.getLeftAndRight(), | ||||
height + border.getTopAndBottom()); | height + border.getTopAndBottom()); | ||||
@@ -156,7 +155,7 @@ void ResizableWindow::setContentComponentSize (int width, int height) | |||||
BorderSize<int> ResizableWindow::getBorderThickness() | BorderSize<int> ResizableWindow::getBorderThickness() | ||||
{ | { | ||||
if (isUsingNativeTitleBar() || isKioskMode()) | if (isUsingNativeTitleBar() || isKioskMode()) | ||||
return BorderSize<int>(); | |||||
return {}; | |||||
return BorderSize<int> ((resizableBorder != nullptr && ! isFullScreen()) ? 4 : 1); | return BorderSize<int> ((resizableBorder != nullptr && ! isFullScreen()) ? 4 : 1); | ||||
} | } | ||||
@@ -174,7 +173,6 @@ void ResizableWindow::moved() | |||||
void ResizableWindow::visibilityChanged() | void ResizableWindow::visibilityChanged() | ||||
{ | { | ||||
TopLevelWindow::visibilityChanged(); | TopLevelWindow::visibilityChanged(); | ||||
updateLastPosIfShowing(); | updateLastPosIfShowing(); | ||||
} | } | ||||
@@ -235,9 +233,9 @@ void ResizableWindow::childBoundsChanged (Component* child) | |||||
//============================================================================== | //============================================================================== | ||||
void ResizableWindow::activeWindowStatusChanged() | void ResizableWindow::activeWindowStatusChanged() | ||||
{ | { | ||||
const BorderSize<int> border (getContentComponentBorder()); | |||||
auto border = getContentComponentBorder(); | |||||
auto area = getLocalBounds(); | |||||
Rectangle<int> area (getLocalBounds()); | |||||
repaint (area.removeFromTop (border.getTop())); | repaint (area.removeFromTop (border.getTop())); | ||||
repaint (area.removeFromLeft (border.getLeft())); | repaint (area.removeFromLeft (border.getLeft())); | ||||
repaint (area.removeFromRight (border.getRight())); | repaint (area.removeFromRight (border.getRight())); | ||||
@@ -287,10 +285,10 @@ bool ResizableWindow::isResizable() const noexcept | |||||
|| resizableBorder != nullptr; | || resizableBorder != nullptr; | ||||
} | } | ||||
void ResizableWindow::setResizeLimits (const int newMinimumWidth, | |||||
const int newMinimumHeight, | |||||
const int newMaximumWidth, | |||||
const int newMaximumHeight) noexcept | |||||
void ResizableWindow::setResizeLimits (int newMinimumWidth, | |||||
int newMinimumHeight, | |||||
int newMaximumWidth, | |||||
int newMaximumHeight) noexcept | |||||
{ | { | ||||
// if you've set up a custom constrainer then these settings won't have any effect.. | // if you've set up a custom constrainer then these settings won't have any effect.. | ||||
jassert (constrainer == &defaultConstrainer || constrainer == nullptr); | jassert (constrainer == &defaultConstrainer || constrainer == nullptr); | ||||
@@ -315,8 +313,8 @@ void ResizableWindow::setConstrainer (ComponentBoundsConstrainer* newConstrainer | |||||
{ | { | ||||
constrainer = newConstrainer; | constrainer = newConstrainer; | ||||
const bool useBottomRightCornerResizer = resizableCorner != nullptr; | |||||
const bool shouldBeResizable = useBottomRightCornerResizer || resizableBorder != nullptr; | |||||
bool useBottomRightCornerResizer = resizableCorner != nullptr; | |||||
bool shouldBeResizable = useBottomRightCornerResizer || resizableBorder != nullptr; | |||||
resizableCorner = nullptr; | resizableCorner = nullptr; | ||||
resizableBorder = nullptr; | resizableBorder = nullptr; | ||||
@@ -337,7 +335,7 @@ void ResizableWindow::setBoundsConstrained (const Rectangle<int>& newBounds) | |||||
//============================================================================== | //============================================================================== | ||||
void ResizableWindow::paint (Graphics& g) | void ResizableWindow::paint (Graphics& g) | ||||
{ | { | ||||
LookAndFeel& lf = getLookAndFeel(); | |||||
auto& lf = getLookAndFeel(); | |||||
lf.fillResizableWindowBackground (g, getWidth(), getHeight(), | lf.fillResizableWindowBackground (g, getWidth(), getHeight(), | ||||
getBorderThickness(), *this); | getBorderThickness(), *this); | ||||
@@ -380,13 +378,12 @@ Colour ResizableWindow::getBackgroundColour() const noexcept | |||||
void ResizableWindow::setBackgroundColour (Colour newColour) | void ResizableWindow::setBackgroundColour (Colour newColour) | ||||
{ | { | ||||
Colour backgroundColour (newColour); | |||||
auto backgroundColour = newColour; | |||||
if (! Desktop::canUseSemiTransparentWindows()) | if (! Desktop::canUseSemiTransparentWindows()) | ||||
backgroundColour = newColour.withAlpha (1.0f); | backgroundColour = newColour.withAlpha (1.0f); | ||||
setColour (backgroundColourId, backgroundColour); | setColour (backgroundColourId, backgroundColour); | ||||
setOpaque (backgroundColour.isOpaque()); | setOpaque (backgroundColour.isOpaque()); | ||||
repaint(); | repaint(); | ||||
} | } | ||||
@@ -396,7 +393,7 @@ bool ResizableWindow::isFullScreen() const | |||||
{ | { | ||||
if (isOnDesktop()) | if (isOnDesktop()) | ||||
{ | { | ||||
ComponentPeer* const peer = getPeer(); | |||||
auto* peer = getPeer(); | |||||
return peer != nullptr && peer->isFullScreen(); | return peer != nullptr && peer->isFullScreen(); | ||||
} | } | ||||
@@ -412,10 +409,10 @@ void ResizableWindow::setFullScreen (const bool shouldBeFullScreen) | |||||
if (isOnDesktop()) | if (isOnDesktop()) | ||||
{ | { | ||||
if (ComponentPeer* const peer = getPeer()) | |||||
if (auto* peer = getPeer()) | |||||
{ | { | ||||
// keep a copy of this intact in case the real one gets messed-up while we're un-maximising | // keep a copy of this intact in case the real one gets messed-up while we're un-maximising | ||||
const Rectangle<int> lastPos (lastNonFullScreenPos); | |||||
auto lastPos = lastNonFullScreenPos; | |||||
peer->setFullScreen (shouldBeFullScreen); | peer->setFullScreen (shouldBeFullScreen); | ||||
@@ -441,7 +438,7 @@ void ResizableWindow::setFullScreen (const bool shouldBeFullScreen) | |||||
bool ResizableWindow::isMinimised() const | bool ResizableWindow::isMinimised() const | ||||
{ | { | ||||
if (ComponentPeer* const peer = getPeer()) | |||||
if (auto* peer = getPeer()) | |||||
return peer->isMinimised(); | return peer->isMinimised(); | ||||
return false; | return false; | ||||
@@ -451,7 +448,7 @@ void ResizableWindow::setMinimised (const bool shouldMinimise) | |||||
{ | { | ||||
if (shouldMinimise != isMinimised()) | if (shouldMinimise != isMinimised()) | ||||
{ | { | ||||
if (ComponentPeer* const peer = getPeer()) | |||||
if (auto* peer = getPeer()) | |||||
{ | { | ||||
updateLastPosIfShowing(); | updateLastPosIfShowing(); | ||||
peer->setMinimised (shouldMinimise); | peer->setMinimised (shouldMinimise); | ||||
@@ -466,7 +463,7 @@ void ResizableWindow::setMinimised (const bool shouldMinimise) | |||||
bool ResizableWindow::isKioskMode() const | bool ResizableWindow::isKioskMode() const | ||||
{ | { | ||||
if (isOnDesktop()) | if (isOnDesktop()) | ||||
if (ComponentPeer* peer = getPeer()) | |||||
if (auto* peer = getPeer()) | |||||
return peer->isKioskMode(); | return peer->isKioskMode(); | ||||
return Desktop::getInstance().getKioskModeComponent() == this; | return Desktop::getInstance().getKioskModeComponent() == this; | ||||
@@ -490,7 +487,7 @@ void ResizableWindow::updateLastPosIfNotFullScreen() | |||||
void ResizableWindow::updatePeerConstrainer() | void ResizableWindow::updatePeerConstrainer() | ||||
{ | { | ||||
if (isOnDesktop()) | if (isOnDesktop()) | ||||
if (ComponentPeer* const peer = getPeer()) | |||||
if (auto* peer = getPeer()) | |||||
peer->setConstrainer (constrainer); | peer->setConstrainer (constrainer); | ||||
} | } | ||||
@@ -528,19 +525,20 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s) | |||||
if (newPos.isEmpty()) | if (newPos.isEmpty()) | ||||
return false; | return false; | ||||
ComponentPeer* const peer = isOnDesktop() ? getPeer() : nullptr; | |||||
auto* peer = isOnDesktop() ? getPeer() : nullptr; | |||||
if (peer != nullptr) | if (peer != nullptr) | ||||
peer->getFrameSize().addTo (newPos); | peer->getFrameSize().addTo (newPos); | ||||
{ | { | ||||
Desktop& desktop = Desktop::getInstance(); | |||||
RectangleList<int> allMonitors (desktop.getDisplays().getRectangleList (true)); | |||||
auto& desktop = Desktop::getInstance(); | |||||
auto allMonitors = desktop.getDisplays().getRectangleList (true); | |||||
allMonitors.clipTo (newPos); | allMonitors.clipTo (newPos); | ||||
const Rectangle<int> onScreenArea (allMonitors.getBounds()); | |||||
auto onScreenArea = allMonitors.getBounds(); | |||||
if (onScreenArea.getWidth() * onScreenArea.getHeight() < 32 * 32) | if (onScreenArea.getWidth() * onScreenArea.getHeight() < 32 * 32) | ||||
{ | { | ||||
const Rectangle<int> screen (desktop.getDisplays().getDisplayContaining (newPos.getCentre()).userArea); | |||||
auto screen = desktop.getDisplays().getDisplayContaining (newPos.getCentre()).userArea; | |||||
newPos.setSize (jmin (newPos.getWidth(), screen.getWidth()), | newPos.setSize (jmin (newPos.getWidth(), screen.getWidth()), | ||||
jmin (newPos.getHeight(), screen.getHeight())); | jmin (newPos.getHeight(), screen.getHeight())); | ||||
@@ -32,14 +32,8 @@ class TopLevelWindowManager : private Timer, | |||||
private DeletedAtShutdown | private DeletedAtShutdown | ||||
{ | { | ||||
public: | public: | ||||
TopLevelWindowManager() : currentActive (nullptr) | |||||
{ | |||||
} | |||||
~TopLevelWindowManager() | |||||
{ | |||||
clearSingletonInstance(); | |||||
} | |||||
TopLevelWindowManager() {} | |||||
~TopLevelWindowManager() { clearSingletonInstance(); } | |||||
juce_DeclareSingleton_SingleThreaded_Minimal (TopLevelWindowManager) | juce_DeclareSingleton_SingleThreaded_Minimal (TopLevelWindowManager) | ||||
@@ -52,14 +46,14 @@ public: | |||||
{ | { | ||||
startTimer (jmin (1731, getTimerInterval() * 2)); | startTimer (jmin (1731, getTimerInterval() * 2)); | ||||
TopLevelWindow* newActive = findCurrentlyActiveWindow(); | |||||
auto* newActive = findCurrentlyActiveWindow(); | |||||
if (newActive != currentActive) | if (newActive != currentActive) | ||||
{ | { | ||||
currentActive = newActive; | currentActive = newActive; | ||||
for (int i = windows.size(); --i >= 0;) | for (int i = windows.size(); --i >= 0;) | ||||
if (TopLevelWindow* tlw = windows[i]) | |||||
if (auto* tlw = windows[i]) | |||||
tlw->setWindowActive (isWindowActive (tlw)); | tlw->setWindowActive (isWindowActive (tlw)); | ||||
Desktop::getInstance().triggerFocusCallback(); | Desktop::getInstance().triggerFocusCallback(); | ||||
@@ -83,14 +77,14 @@ public: | |||||
windows.removeFirstMatchingValue (w); | windows.removeFirstMatchingValue (w); | ||||
if (windows.size() == 0) | |||||
if (windows.isEmpty()) | |||||
deleteInstance(); | deleteInstance(); | ||||
} | } | ||||
Array<TopLevelWindow*> windows; | Array<TopLevelWindow*> windows; | ||||
private: | private: | ||||
TopLevelWindow* currentActive; | |||||
TopLevelWindow* currentActive = nullptr; | |||||
void timerCallback() override | void timerCallback() override | ||||
{ | { | ||||
@@ -109,8 +103,8 @@ private: | |||||
{ | { | ||||
if (Process::isForegroundProcess()) | if (Process::isForegroundProcess()) | ||||
{ | { | ||||
Component* const focusedComp = Component::getCurrentlyFocusedComponent(); | |||||
TopLevelWindow* w = dynamic_cast<TopLevelWindow*> (focusedComp); | |||||
auto* focusedComp = Component::getCurrentlyFocusedComponent(); | |||||
auto* w = dynamic_cast<TopLevelWindow*> (focusedComp); | |||||
if (w == nullptr && focusedComp != nullptr) | if (w == nullptr && focusedComp != nullptr) | ||||
w = focusedComp->findParentComponentOfClass<TopLevelWindow>(); | w = focusedComp->findParentComponentOfClass<TopLevelWindow>(); | ||||
@@ -133,16 +127,13 @@ juce_ImplementSingleton_SingleThreaded (TopLevelWindowManager) | |||||
void juce_checkCurrentlyFocusedTopLevelWindow(); | void juce_checkCurrentlyFocusedTopLevelWindow(); | ||||
void juce_checkCurrentlyFocusedTopLevelWindow() | void juce_checkCurrentlyFocusedTopLevelWindow() | ||||
{ | { | ||||
if (TopLevelWindowManager* const wm = TopLevelWindowManager::getInstanceWithoutCreating()) | |||||
if (auto* wm = TopLevelWindowManager::getInstanceWithoutCreating()) | |||||
wm->checkFocusAsync(); | wm->checkFocusAsync(); | ||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
TopLevelWindow::TopLevelWindow (const String& name, const bool shouldAddToDesktop) | TopLevelWindow::TopLevelWindow (const String& name, const bool shouldAddToDesktop) | ||||
: Component (name), | |||||
useDropShadow (true), | |||||
useNativeTitleBar (false), | |||||
isCurrentlyActive (false) | |||||
: Component (name) | |||||
{ | { | ||||
setOpaque (true); | setOpaque (true); | ||||
@@ -165,7 +156,7 @@ TopLevelWindow::~TopLevelWindow() | |||||
//============================================================================== | //============================================================================== | ||||
void TopLevelWindow::focusOfChildComponentChanged (FocusChangeType) | void TopLevelWindow::focusOfChildComponentChanged (FocusChangeType) | ||||
{ | { | ||||
TopLevelWindowManager* const wm = TopLevelWindowManager::getInstance(); | |||||
auto* wm = TopLevelWindowManager::getInstance(); | |||||
if (hasKeyboardFocus (true)) | if (hasKeyboardFocus (true)) | ||||
wm->checkFocus(); | wm->checkFocus(); | ||||
@@ -194,7 +185,7 @@ bool TopLevelWindow::isUsingNativeTitleBar() const noexcept | |||||
void TopLevelWindow::visibilityChanged() | void TopLevelWindow::visibilityChanged() | ||||
{ | { | ||||
if (isShowing()) | if (isShowing()) | ||||
if (ComponentPeer* p = getPeer()) | |||||
if (auto* p = getPeer()) | |||||
if ((p->getStyleFlags() & (ComponentPeer::windowIsTemporary | if ((p->getStyleFlags() & (ComponentPeer::windowIsTemporary | ||||
| ComponentPeer::windowIgnoresKeyPresses)) == 0) | | ComponentPeer::windowIgnoresKeyPresses)) == 0) | ||||
toFront (true); | toFront (true); | ||||
@@ -302,10 +293,10 @@ void TopLevelWindow::centreAroundComponent (Component* c, const int width, const | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
Point<int> targetCentre (c->localPointToGlobal (c->getLocalBounds().getCentre())); | |||||
Rectangle<int> parentArea (c->getParentMonitorArea()); | |||||
auto targetCentre = c->localPointToGlobal (c->getLocalBounds().getCentre()); | |||||
auto parentArea = c->getParentMonitorArea(); | |||||
if (Component* const parent = getParentComponent()) | |||||
if (auto* parent = getParentComponent()) | |||||
{ | { | ||||
targetCentre = parent->getLocalPoint (nullptr, targetCentre); | targetCentre = parent->getLocalPoint (nullptr, targetCentre); | ||||
parentArea = parent->getLocalBounds(); | parentArea = parent->getLocalBounds(); | ||||
@@ -336,13 +327,13 @@ TopLevelWindow* TopLevelWindow::getActiveTopLevelWindow() noexcept | |||||
for (int i = TopLevelWindow::getNumTopLevelWindows(); --i >= 0;) | for (int i = TopLevelWindow::getNumTopLevelWindows(); --i >= 0;) | ||||
{ | { | ||||
TopLevelWindow* const tlw = TopLevelWindow::getTopLevelWindow (i); | |||||
auto* tlw = TopLevelWindow::getTopLevelWindow (i); | |||||
if (tlw->isActiveWindow()) | if (tlw->isActiveWindow()) | ||||
{ | { | ||||
int numTWLParents = 0; | int numTWLParents = 0; | ||||
for (const Component* c = tlw->getParentComponent(); c != nullptr; c = c->getParentComponent()) | |||||
for (auto* c = tlw->getParentComponent(); c != nullptr; c = c->getParentComponent()) | |||||
if (dynamic_cast<const TopLevelWindow*> (c) != nullptr) | if (dynamic_cast<const TopLevelWindow*> (c) != nullptr) | ||||
++numTWLParents; | ++numTWLParents; | ||||
@@ -153,7 +153,7 @@ protected: | |||||
private: | private: | ||||
friend class TopLevelWindowManager; | friend class TopLevelWindowManager; | ||||
friend class ResizableWindow; | friend class ResizableWindow; | ||||
bool useDropShadow, useNativeTitleBar, isCurrentlyActive; | |||||
bool useDropShadow = true, useNativeTitleBar = false, isCurrentlyActive = false; | |||||
ScopedPointer<DropShadower> shadower; | ScopedPointer<DropShadower> shadower; | ||||
void setWindowActive (bool); | void setWindowActive (bool); | ||||
@@ -61,8 +61,8 @@ CodeEditorComponent::ColourScheme CPlusPlusCodeTokeniser::getDefaultColourScheme | |||||
CodeEditorComponent::ColourScheme cs; | CodeEditorComponent::ColourScheme cs; | ||||
for (unsigned int i = 0; i < sizeof (types) / sizeof (types[0]); ++i) // (NB: numElementsInArray doesn't work here in GCC4.2) | |||||
cs.set (types[i].name, Colour (types[i].colour)); | |||||
for (auto& t : types) | |||||
cs.set (t.name, Colour (t.colour)); | |||||
return cs; | return cs; | ||||
} | } | ||||
@@ -84,7 +84,7 @@ struct LuaTokeniserFunctions | |||||
while (CppTokeniserFunctions::isIdentifierBody (source.peekNextChar())) | while (CppTokeniserFunctions::isIdentifierBody (source.peekNextChar())) | ||||
{ | { | ||||
const juce_wchar c = source.nextChar(); | |||||
auto c = source.nextChar(); | |||||
if (tokenLength < 20) | if (tokenLength < 20) | ||||
possible.write (c); | possible.write (c); | ||||
@@ -108,7 +108,7 @@ struct LuaTokeniserFunctions | |||||
{ | { | ||||
source.skipWhitespace(); | source.skipWhitespace(); | ||||
const juce_wchar firstChar = source.peekNextChar(); | |||||
auto firstChar = source.peekNextChar(); | |||||
switch (firstChar) | switch (firstChar) | ||||
{ | { | ||||
@@ -119,7 +119,7 @@ struct LuaTokeniserFunctions | |||||
case '5': case '6': case '7': case '8': case '9': | case '5': case '6': case '7': case '8': case '9': | ||||
case '.': | case '.': | ||||
{ | { | ||||
int result = CppTokeniserFunctions::parseNumber (source); | |||||
auto result = CppTokeniserFunctions::parseNumber (source); | |||||
if (result == LuaTokeniser::tokenType_error) | if (result == LuaTokeniser::tokenType_error) | ||||
{ | { | ||||
@@ -157,7 +157,7 @@ struct LuaTokeniserFunctions | |||||
case '-': | case '-': | ||||
{ | { | ||||
source.skip(); | source.skip(); | ||||
int result = CppTokeniserFunctions::parseNumber (source); | |||||
auto result = CppTokeniserFunctions::parseNumber (source); | |||||
if (source.peekNextChar() == '-') | if (source.peekNextChar() == '-') | ||||
{ | { | ||||
@@ -231,8 +231,8 @@ CodeEditorComponent::ColourScheme LuaTokeniser::getDefaultColourScheme() | |||||
CodeEditorComponent::ColourScheme cs; | CodeEditorComponent::ColourScheme cs; | ||||
for (unsigned int i = 0; i < sizeof (types) / sizeof (types[0]); ++i) // (NB: numElementsInArray doesn't work here in GCC4.2) | |||||
cs.set (types[i].name, types[i].colour); | |||||
for (auto& t : types) | |||||
cs.set (t.name, Colour (t.colour)); | |||||
return cs; | return cs; | ||||
} | } | ||||
@@ -53,8 +53,8 @@ CodeEditorComponent::ColourScheme XmlTokeniser::getDefaultColourScheme() | |||||
CodeEditorComponent::ColourScheme cs; | CodeEditorComponent::ColourScheme cs; | ||||
for (unsigned int i = 0; i < sizeof (types) / sizeof (types[0]); ++i) // (NB: numElementsInArray doesn't work here in GCC4.2) | |||||
cs.set (types[i].name, Colour (types[i].colour)); | |||||
for (auto& t : types) | |||||
cs.set (t.name, Colour (t.colour)); | |||||
return cs; | return cs; | ||||
} | } | ||||
@@ -66,7 +66,7 @@ static void skipToEndOfXmlDTD (Iterator& source) noexcept | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
const juce_wchar c = source.nextChar(); | |||||
auto c = source.nextChar(); | |||||
if (c == 0 || (c == '>' && lastWasQuestionMark)) | if (c == 0 || (c == '>' && lastWasQuestionMark)) | ||||
break; | break; | ||||
@@ -78,11 +78,11 @@ static void skipToEndOfXmlDTD (Iterator& source) noexcept | |||||
template <typename Iterator> | template <typename Iterator> | ||||
static void skipToEndOfXmlComment (Iterator& source) noexcept | static void skipToEndOfXmlComment (Iterator& source) noexcept | ||||
{ | { | ||||
juce_wchar last[2] = { 0 }; | |||||
juce_wchar last[2] = {}; | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
const juce_wchar c = source.nextChar(); | |||||
auto c = source.nextChar(); | |||||
if (c == 0 || (c == '>' && last[0] == '-' && last[1] == '-')) | if (c == 0 || (c == '>' && last[0] == '-' && last[1] == '-')) | ||||
break; | break; | ||||
@@ -95,7 +95,7 @@ static void skipToEndOfXmlComment (Iterator& source) noexcept | |||||
int XmlTokeniser::readNextToken (CodeDocument::Iterator& source) | int XmlTokeniser::readNextToken (CodeDocument::Iterator& source) | ||||
{ | { | ||||
source.skipWhitespace(); | source.skipWhitespace(); | ||||
const juce_wchar firstChar = source.peekNextChar(); | |||||
auto firstChar = source.peekNextChar(); | |||||
switch (firstChar) | switch (firstChar) | ||||
{ | { | ||||
@@ -110,7 +110,7 @@ int XmlTokeniser::readNextToken (CodeDocument::Iterator& source) | |||||
{ | { | ||||
source.skip(); | source.skip(); | ||||
source.skipWhitespace(); | source.skipWhitespace(); | ||||
const juce_wchar nextChar = source.peekNextChar(); | |||||
auto nextChar = source.peekNextChar(); | |||||
if (nextChar == '?') | if (nextChar == '?') | ||||
{ | { | ||||