@@ -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 | |||
{ | |||
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) | |||
+ (offset * (((y0 + 2.0f * y2) - (halfY3 + 2.5f * y1)) | |||
@@ -48,8 +48,8 @@ void CatmullRomInterpolator::reset() noexcept | |||
{ | |||
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 | |||
@@ -49,97 +49,67 @@ namespace | |||
} | |||
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)); | |||
pushInterpolationSamples (lastInputSamples, in, 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; | |||
return (int) (in - originalIn); | |||
return numUsed; | |||
} | |||
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); | |||
pushInterpolationSamples (lastInputSamples, in, 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; | |||
return (int) (in - originalIn); | |||
return numUsed; | |||
} | |||
} | |||
@@ -186,8 +156,8 @@ void LagrangeInterpolator::reset() noexcept | |||
{ | |||
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 | |||
@@ -44,24 +44,24 @@ bool MidiKeyboardState::isNoteOn (const int midiChannel, const int n) const noex | |||
{ | |||
jassert (midiChannel >= 0 && midiChannel <= 16); | |||
return isPositiveAndBelow (n, (int) 128) | |||
return isPositiveAndBelow (n, 128) | |||
&& (noteStates[n] & (1 << (midiChannel - 1))) != 0; | |||
} | |||
bool MidiKeyboardState::isNoteOnForChannels (const int midiChannelMask, const int n) const noexcept | |||
{ | |||
return isPositiveAndBelow (n, (int) 128) | |||
return isPositiveAndBelow (n, 128) | |||
&& (noteStates[n] & midiChannelMask) != 0; | |||
} | |||
void MidiKeyboardState::noteOn (const int midiChannel, const int midiNoteNumber, const float velocity) | |||
{ | |||
jassert (midiChannel >= 0 && midiChannel <= 16); | |||
jassert (isPositiveAndBelow (midiNoteNumber, (int) 128)); | |||
jassert (isPositiveAndBelow (midiNoteNumber, 128)); | |||
const ScopedLock sl (lock); | |||
if (isPositiveAndBelow (midiNoteNumber, (int) 128)) | |||
if (isPositiveAndBelow (midiNoteNumber, 128)) | |||
{ | |||
const int timeNow = (int) Time::getMillisecondCounter(); | |||
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) | |||
{ | |||
if (isPositiveAndBelow (midiNoteNumber, (int) 128)) | |||
if (isPositiveAndBelow (midiNoteNumber, 128)) | |||
{ | |||
noteStates [midiNoteNumber] |= (1 << (midiChannel - 1)); | |||
@@ -452,8 +452,8 @@ MidiMessage MidiMessage::aftertouchChange (const int channel, | |||
const int aftertouchValue) noexcept | |||
{ | |||
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), | |||
noteNum & 0x7f, | |||
@@ -474,7 +474,7 @@ int MidiMessage::getChannelPressureValue() const noexcept | |||
MidiMessage MidiMessage::channelPressureChange (const int channel, const int pressure) noexcept | |||
{ | |||
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); | |||
} | |||
@@ -522,7 +522,7 @@ int MidiMessage::getPitchWheelValue() const noexcept | |||
MidiMessage MidiMessage::pitchWheel (const int channel, const int position) noexcept | |||
{ | |||
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), | |||
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 | |||
{ | |||
jassert (channel > 0 && channel <= 16); | |||
jassert (isPositiveAndBelow (noteNumber, (int) 128)); | |||
jassert (isPositiveAndBelow (noteNumber, 128)); | |||
return MidiMessage (MidiHelpers::initialByte (0x90, channel), | |||
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 | |||
{ | |||
jassert (channel > 0 && channel <= 16); | |||
jassert (isPositiveAndBelow (noteNumber, (int) 128)); | |||
jassert (isPositiveAndBelow (noteNumber, 128)); | |||
return MidiMessage (MidiHelpers::initialByte (0x80, channel), | |||
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 | |||
{ | |||
jassert (channel > 0 && channel <= 16); | |||
jassert (isPositiveAndBelow (noteNumber, (int) 128)); | |||
jassert (isPositiveAndBelow (noteNumber, 128)); | |||
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 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] | |||
: flatNoteNames [note % 12]); | |||
@@ -731,6 +731,9 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat | |||
const double msTaken = Time::getMillisecondCounterHiRes() - callbackStartTime; | |||
const double filterAmount = 0.2; | |||
cpuUsageMs += filterAmount * (msTaken - cpuUsageMs); | |||
if (msTaken > msPerBlock) | |||
xruns++; | |||
} | |||
else | |||
{ | |||
@@ -756,13 +759,14 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat | |||
void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device) | |||
{ | |||
cpuUsageMs = 0; | |||
xruns = 0; | |||
const double sampleRate = device->getCurrentSampleRate(); | |||
const int blockSize = device->getCurrentBufferSizeSamples(); | |||
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; | |||
} | |||
@@ -779,6 +783,7 @@ void AudioDeviceManager::audioDeviceStoppedInt() | |||
{ | |||
cpuUsageMs = 0; | |||
timeToCpuScale = 0; | |||
xruns = 0; | |||
sendChangeMessage(); | |||
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::getCurrentOutputLevel() const noexcept { return outputLevelMeter.getCurrentLevel(); } | |||
@@ -436,6 +436,15 @@ public: | |||
*/ | |||
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: | |||
//============================================================================== | |||
OwnedArray<AudioIODeviceType> availableDeviceTypes; | |||
@@ -468,7 +477,8 @@ private: | |||
ScopedPointer<AudioSampleBuffer> testSound; | |||
int testSoundPosition; | |||
double cpuUsageMs, timeToCpuScale; | |||
double cpuUsageMs, timeToCpuScale, msPerBlock; | |||
int xruns; | |||
struct LevelMeter | |||
{ | |||
@@ -347,7 +347,7 @@ MidiOutput* MidiOutput::openDevice (int index) | |||
{ | |||
MidiOutput* mo = nullptr; | |||
if (isPositiveAndBelow (index, (int) MIDIGetNumberOfDestinations())) | |||
if (isPositiveAndBelow (index, MIDIGetNumberOfDestinations())) | |||
{ | |||
MIDIEndpointRef endPoint = MIDIGetDestination ((ItemCount) index); | |||
@@ -465,7 +465,7 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) | |||
using namespace CoreMidiHelpers; | |||
MidiInput* newInput = nullptr; | |||
if (isPositiveAndBelow (index, (int) MIDIGetNumberOfSources())) | |||
if (isPositiveAndBelow (index, MIDIGetNumberOfSources())) | |||
{ | |||
if (MIDIEndpointRef endPoint = MIDIGetSource ((ItemCount) index)) | |||
{ | |||
@@ -1444,16 +1444,7 @@ struct ASIOAudioIODevice::ASIOCallbackFunctions <sizeof(currentASIODev) / sizeof | |||
class ASIOAudioIODeviceType : public AudioIODeviceType | |||
{ | |||
public: | |||
ASIOAudioIODeviceType() | |||
: AudioIODeviceType ("ASIO"), | |||
hasScanned (false) | |||
{ | |||
} | |||
~ASIOAudioIODeviceType() | |||
{ | |||
masterReference.clear(); | |||
} | |||
ASIOAudioIODeviceType() : AudioIODeviceType ("ASIO") {} | |||
//============================================================================== | |||
void scanForDevices() | |||
@@ -1549,13 +1540,13 @@ public: | |||
callDeviceChangeListeners(); | |||
} | |||
WeakReference<ASIOAudioIODeviceType>::Master masterReference; | |||
JUCE_DECLARE_WEAK_REFERENCEABLE (ASIOAudioIODeviceType) | |||
private: | |||
StringArray deviceNames; | |||
Array<CLSID> classIds; | |||
bool hasScanned; | |||
bool hasScanned = false; | |||
//============================================================================== | |||
static bool checkClassIsOk (const String& classId) | |||
@@ -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 | |||
} | |||
@@ -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" | |||
@@ -1704,7 +1704,7 @@ private: | |||
for (MidiBuffer::Iterator i (midiEvents); i.getNextEvent (midiEventData, midiEventSize, midiEventPosition);) | |||
{ | |||
jassert (isPositiveAndBelow (midiEventPosition, (int) nFrames)); | |||
jassert (isPositiveAndBelow (midiEventPosition, nFrames)); | |||
ignoreUnused (nFrames); | |||
dataSize += (size_t) midiEventSize; | |||
@@ -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() {} | |||
@@ -943,7 +940,7 @@ struct VSTPluginInstance : public AudioPluginInstance, | |||
float getParameter (int index) override | |||
{ | |||
if (vstEffect != nullptr && isPositiveAndBelow (index, (int) vstEffect->numParameters)) | |||
if (vstEffect != nullptr && isPositiveAndBelow (index, vstEffect->numParameters)) | |||
{ | |||
const ScopedLock sl (lock); | |||
return vstEffect->getParameterValueFunction (vstEffect, index); | |||
@@ -954,7 +951,7 @@ struct VSTPluginInstance : public AudioPluginInstance, | |||
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); | |||
@@ -52,11 +52,15 @@ public: | |||
@param exitCallback A callback which will be called when the modal | |||
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. | |||
@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 | |||
platform. | |||
@@ -391,7 +391,9 @@ private: | |||
class BluetoothMidiSelectorOverlay : public Component | |||
{ | |||
public: | |||
BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse) | |||
BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse, | |||
const Rectangle<int>& boundsToUse) | |||
: bounds (boundsToUse) | |||
{ | |||
ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackToUse); | |||
@@ -400,8 +402,14 @@ public: | |||
setAlwaysOnTop (true); | |||
setVisible (true); | |||
addToDesktop (ComponentPeer::windowHasDropShadow); | |||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
if (bounds.isEmpty()) | |||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
else | |||
setBounds (bounds); | |||
toFront (true); | |||
setOpaque (! bounds.isEmpty()); | |||
addAndMakeVisible (bluetoothDevicesList); | |||
enterModalState (true, exitCallback.release(), true); | |||
@@ -414,7 +422,7 @@ public: | |||
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)); | |||
Rectangle<int> overlayBounds = getOverlayBounds(); | |||
@@ -441,19 +449,30 @@ public: | |||
void parentSizeChanged() override { update(); } | |||
private: | |||
Rectangle<int> bounds; | |||
void update() | |||
{ | |||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
if (bounds.isEmpty()) | |||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
else | |||
setBounds (bounds); | |||
bluetoothDevicesList.setBounds (getOverlayBounds().withTrimmedTop (40)); | |||
} | |||
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; | |||
@@ -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); | |||
auto boundsToUse = (btBounds != nullptr ? *btBounds : Rectangle<int> {}); | |||
if (! RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi)) | |||
{ | |||
@@ -475,7 +496,7 @@ bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* | |||
return false; | |||
} | |||
new BluetoothMidiSelectorOverlay (exitCallback.release()); | |||
new BluetoothMidiSelectorOverlay (exitCallback.release(), boundsToUse); | |||
return true; | |||
} | |||
@@ -40,15 +40,23 @@ namespace juce | |||
class BluetoothMidiSelectorOverlay : public Component | |||
{ | |||
public: | |||
BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse) | |||
BluetoothMidiSelectorOverlay (ModalComponentManager::Callback* exitCallbackToUse, | |||
const Rectangle<int>& boundsToUse) | |||
: bounds (boundsToUse) | |||
{ | |||
ScopedPointer<ModalComponentManager::Callback> exitCallback (exitCallbackToUse); | |||
setAlwaysOnTop (true); | |||
setVisible (true); | |||
addToDesktop (ComponentPeer::windowHasDropShadow); | |||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
if (bounds.isEmpty()) | |||
setBounds (0, 0, getParentWidth(), getParentHeight()); | |||
else | |||
setBounds (bounds); | |||
toFront (true); | |||
setOpaque (! bounds.isEmpty()); | |||
controller = [[CABTMIDICentralViewController alloc] init]; | |||
nativeSelectorComponent.setView ([controller view]); | |||
@@ -66,7 +74,7 @@ public: | |||
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(); } | |||
@@ -78,12 +86,19 @@ public: | |||
private: | |||
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() | |||
@@ -94,17 +109,20 @@ private: | |||
CABTMIDICentralViewController* controller; | |||
UIViewComponent nativeSelectorComponent; | |||
Rectangle<int> bounds; | |||
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); | |||
auto boundsToUse = (btBounds != nullptr ? *btBounds : Rectangle<int> {}); | |||
if (isAvailable()) | |||
{ | |||
new BluetoothMidiSelectorOverlay (cb.release()); | |||
new BluetoothMidiSelectorOverlay (cb.release(), boundsToUse); | |||
return true; | |||
} | |||
@@ -123,7 +141,8 @@ bool BluetoothMidiDevicePairingDialogue::isAvailable() | |||
namespace juce | |||
{ | |||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||
Rectangle<int>*) | |||
{ | |||
ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | |||
return false; | |||
@@ -27,7 +27,8 @@ | |||
namespace juce | |||
{ | |||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||
Rectangle<int>*) | |||
{ | |||
ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | |||
// not implemented on Linux yet! | |||
@@ -27,7 +27,8 @@ | |||
namespace juce | |||
{ | |||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||
Rectangle<int>*) | |||
{ | |||
ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | |||
// Do not call this on OSX. Instead, you should pair Bluetooth MIDI devices | |||
@@ -27,7 +27,8 @@ | |||
namespace juce | |||
{ | |||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback) | |||
bool BluetoothMidiDevicePairingDialogue::open (ModalComponentManager::Callback* exitCallback, | |||
Rectangle<int>*) | |||
{ | |||
ScopedPointer<ModalComponentManager::Callback> cb (exitCallback); | |||
// not implemented on Windows yet! | |||
@@ -337,10 +337,4 @@ private: | |||
/** Writes a BigInteger to an OutputStream as a UTF8 decimal string. */ | |||
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 |
@@ -212,9 +212,9 @@ void findMinAndMax (const Type* values, int numValues, Type& lowest, Type& highe | |||
@see jmin, jmax, jmap | |||
*/ | |||
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.. | |||
@@ -228,15 +228,15 @@ Type jlimit (const Type lowerLimit, | |||
@code valueToTest >= 0 && valueToTest < upperLimit | |||
@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.. | |||
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 | |||
@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.. | |||
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. */ | |||
template <typename Type1> | |||
void ignoreUnused (const Type1&) noexcept {} | |||
@@ -59,6 +59,8 @@ namespace juce | |||
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.. | |||
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 |
@@ -566,6 +566,9 @@ public class JuceAppActivity extends Activity | |||
@Override | |||
public void onDraw (Canvas canvas) | |||
{ | |||
if (host == 0) | |||
return; | |||
handlePaint (host, canvas, paint); | |||
} | |||
@@ -657,6 +660,9 @@ public class JuceAppActivity extends Activity | |||
@Override | |||
public boolean onKeyDown (int keyCode, KeyEvent event) | |||
{ | |||
if (host == 0) | |||
return false; | |||
switch (keyCode) | |||
{ | |||
case KeyEvent.KEYCODE_VOLUME_UP: | |||
@@ -679,6 +685,9 @@ public class JuceAppActivity extends Activity | |||
@Override | |||
public boolean onKeyUp (int keyCode, KeyEvent event) | |||
{ | |||
if (host == 0) | |||
return false; | |||
handleKeyUp (host, keyCode, event.getUnicodeChar()); | |||
return true; | |||
} | |||
@@ -686,6 +695,9 @@ public class JuceAppActivity extends Activity | |||
@Override | |||
public boolean onKeyMultiple (int keyCode, int count, KeyEvent event) | |||
{ | |||
if (host == 0) | |||
return false; | |||
if (keyCode != KeyEvent.KEYCODE_UNKNOWN || event.getAction() != KeyEvent.ACTION_MULTIPLE) | |||
return super.onKeyMultiple (keyCode, count, event); | |||
@@ -718,6 +730,9 @@ public class JuceAppActivity extends Activity | |||
@Override | |||
protected void onSizeChanged (int w, int h, int oldw, int oldh) | |||
{ | |||
if (host == 0) | |||
return; | |||
super.onSizeChanged (w, h, oldw, oldh); | |||
viewSizeChanged (host); | |||
} | |||
@@ -734,6 +749,9 @@ public class JuceAppActivity extends Activity | |||
@Override | |||
public void onFocusChange (View v, boolean hasFocus) | |||
{ | |||
if (host == 0) | |||
return; | |||
if (v == this) | |||
focusChanged (host, hasFocus); | |||
} | |||
@@ -407,7 +407,7 @@ int SystemStats::getMemorySizeInMegabytes() | |||
struct sysinfo sysi; | |||
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 | |||
return 0; | |||
@@ -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: | |||
{ | |||
@@ -202,6 +202,77 @@ private: | |||
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 | |||
template <typename ReturnT, class Class, typename... Params> | |||
@@ -1205,6 +1205,8 @@ public: | |||
close (pipeHandles[1]); // close the write handle | |||
} | |||
} | |||
ignoreUnused (streamFlags); | |||
} | |||
~ActiveProcess() | |||
@@ -130,7 +130,7 @@ URL::DownloadTask* URL::DownloadTask::createFallbackDownloader (const URL& urlTo | |||
return nullptr; | |||
} | |||
URL::DownloadTask::DownloadTask() : contentLength (-1), downloaded (0), finished (false), error (false), httpCode (-1) {} | |||
URL::DownloadTask::DownloadTask() {} | |||
URL::DownloadTask::~DownloadTask() {} | |||
//============================================================================== | |||
@@ -250,6 +250,7 @@ namespace URLHelpers | |||
static int findStartOfNetLocation (const String& url) | |||
{ | |||
int start = findEndOfScheme (url); | |||
while (url[start] == '/') | |||
++start; | |||
@@ -305,8 +306,8 @@ String URL::getDomain() const | |||
const int end2 = url.indexOfChar (start, ':'); | |||
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); | |||
} | |||
@@ -325,7 +326,7 @@ String URL::getScheme() 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; | |||
} | |||
@@ -366,7 +367,7 @@ void URL::createHeadersAndPostData (String& headers, MemoryBlock& postDataToWrit | |||
// (this doesn't currently support mixing custom post-data with uploads..) | |||
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"; | |||
@@ -379,22 +380,20 @@ void URL::createHeadersAndPostData (String& headers, MemoryBlock& postDataToWrit | |||
<< "\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"; | |||
if (f.data != nullptr) | |||
data << *f.data; | |||
if (f->data != nullptr) | |||
data << *f->data; | |||
else | |||
data << f.file; | |||
data << f->file; | |||
data << "\r\n--" << boundary; | |||
} | |||
@@ -419,8 +418,8 @@ bool URL::isProbablyAWebsiteURL (const String& possibleURL) | |||
{ | |||
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; | |||
if (possibleURL.containsChar ('@') | |||
@@ -435,7 +434,7 @@ bool URL::isProbablyAWebsiteURL (const String& possibleURL) | |||
bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress) | |||
{ | |||
const int atSign = possibleEmailAddress.indexOfChar ('@'); | |||
auto atSign = possibleEmailAddress.indexOfChar ('@'); | |||
return atSign > 0 | |||
&& 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)); | |||
@@ -518,7 +516,7 @@ bool URL::readEntireBinaryStream (MemoryBlock& destData, | |||
return false; | |||
} | |||
String URL::readEntireTextStream (const bool usePostCommand) const | |||
String URL::readEntireTextStream (bool usePostCommand) const | |||
{ | |||
const ScopedPointer<InputStream> in (createInputStream (usePostCommand)); | |||
@@ -528,7 +526,7 @@ String URL::readEntireTextStream (const bool usePostCommand) const | |||
return {}; | |||
} | |||
XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const | |||
XmlElement* URL::readEntireXmlStream (bool usePostCommand) const | |||
{ | |||
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 result (s.replaceCharacter ('+', ' ')); | |||
auto result = s.replaceCharacter ('+', ' '); | |||
if (! result.containsChar ('%')) | |||
return result; | |||
@@ -628,9 +626,9 @@ String URL::removeEscapeChars (const String& s) | |||
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) | |||
@@ -640,7 +638,7 @@ String URL::addEscapeChars (const String& s, const bool isParameter, bool roundB | |||
for (int i = 0; i < utf8.size(); ++i) | |||
{ | |||
const char c = utf8.getUnchecked(i); | |||
auto c = utf8.getUnchecked(i); | |||
if (! (CharacterFunctions::isLetterOrDigit (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 | |||
{ | |||
String u (toString (true)); | |||
auto u = toString (true); | |||
if (u.containsChar ('@') && ! u.containsChar (':')) | |||
u = "mailto:" + u; | |||
return Process::openDocument (u, String()); | |||
return Process::openDocument (u, {}); | |||
} | |||
} // namespace juce |
@@ -47,13 +47,13 @@ public: | |||
URL (const String& url); | |||
/** Creates a copy of another URL. */ | |||
URL (const URL& other); | |||
URL (const URL&); | |||
/** Destructor. */ | |||
~URL(); | |||
/** Copies this URL from another one. */ | |||
URL& operator= (const URL& other); | |||
URL& operator= (const URL&); | |||
/** Compares two URLs. | |||
All aspects of the URLs must be identical for them to match, including any parameters, | |||
@@ -78,19 +78,16 @@ public: | |||
bool isWellFormed() const; | |||
/** Returns just the domain part of the URL. | |||
E.g. for "http://www.xyz.com/foobar", this will return "www.xyz.com". | |||
*/ | |||
String getDomain() const; | |||
/** Returns the path part of the URL. | |||
E.g. for "http://www.xyz.com/foo/bar?x=1", this will return "foo/bar". | |||
*/ | |||
String getSubPath() const; | |||
/** Returns the scheme of the URL. | |||
E.g. for "http://www.xyz.com/foobar", this will return "http". (It won't | |||
include the colon). | |||
*/ | |||
@@ -102,7 +99,6 @@ public: | |||
int getPort() const; | |||
/** 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 | |||
"abc.com/zzz", it'll return "http://abc.com/zzz?x=1". | |||
@see withNewSubPath | |||
@@ -110,7 +106,6 @@ public: | |||
URL withNewDomainAndPath (const String& newFullPath) const; | |||
/** 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 | |||
"bar", it'll return "http://www.xyz.com/bar?x=1". | |||
@see withNewDomainAndPath | |||
@@ -118,7 +113,6 @@ public: | |||
URL withNewSubPath (const String& newPath) const; | |||
/** 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 | |||
"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 | |||
@@ -134,7 +128,6 @@ public: | |||
/** 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. | |||
e.g. calling "withParameter ("amount", "some fish") for the url "www.fish.com" | |||
would produce a new url whose toString(true) method would return | |||
"www.fish.com?amount=some+fish". | |||
@@ -241,20 +234,17 @@ public: | |||
//============================================================================== | |||
/** Tries to launch the system's default browser to open the URL. | |||
Returns true if this seems to have worked. | |||
*/ | |||
bool launchInDefaultBrowser() const; | |||
//============================================================================== | |||
/** Takes a guess as to whether a string might be a valid website address. | |||
This isn't foolproof! | |||
*/ | |||
static bool isProbablyAWebsiteURL (const String& possibleURL); | |||
/** Takes a guess as to whether a string might be a valid email address. | |||
This isn't foolproof! | |||
*/ | |||
static bool isProbablyAnEmailAddress (const String& possibleEmailAddress); | |||
@@ -319,7 +309,6 @@ public: | |||
//============================================================================== | |||
/** Represents a download task. | |||
Returned by downloadToFile to allow querying and controling the download task. | |||
*/ | |||
class DownloadTask | |||
@@ -346,34 +335,32 @@ public: | |||
/** Returns the total length of the download task. This may return -1 if the length | |||
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. */ | |||
inline int64 getLengthDownloaded() const { return downloaded; } | |||
int64 getLengthDownloaded() const { return downloaded; } | |||
/** 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 | |||
*/ | |||
inline int statusCode() const { return httpCode; } | |||
int statusCode() const { return httpCode; } | |||
/** Returns true if there was an error. */ | |||
inline bool hadError() const { return error; } | |||
protected: | |||
int64 contentLength, downloaded; | |||
bool finished, error; | |||
int httpCode; | |||
int64 contentLength = -1, downloaded = 0; | |||
bool finished = false, error = false; | |||
int httpCode = -1; | |||
DownloadTask(); | |||
private: | |||
friend class URL; | |||
static DownloadTask* createFallbackDownloader (const URL&, const File&, const String&, Listener*, bool); | |||
public: | |||
@@ -381,6 +368,7 @@ public: | |||
/** internal **/ | |||
static void juce_iosURLSessionNotify (const String&); | |||
#endif | |||
private: | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DownloadTask) | |||
}; | |||
@@ -114,11 +114,6 @@ | |||
#include "../misc/juce_StdFunctionCompat.h" | |||
#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 | |||
#if JUCE_ATOMIC_AVAILABLE | |||
#include <atomic> | |||
@@ -241,12 +241,13 @@ public: | |||
STRING_DOUBLE_PAIR_COMBOS (2087.3087e+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.23456789012345678901234567890e-111) | |||
// Limits. DBL_MAX may not exist on Linux. | |||
#if ! JUCE_LINUX | |||
// Limits | |||
, STRING_DOUBLE_PAIR (DBL_MAX), | |||
STRING_DOUBLE_PAIR (-DBL_MAX), | |||
STRING_DOUBLE_PAIR (DBL_MIN) | |||
@@ -61,7 +61,7 @@ namespace juce | |||
#endif | |||
//============================================================================== | |||
/** GNU libstdc++ does not have std::make_unsigned */ | |||
// GNU libstdc++ does not have std::make_unsigned | |||
namespace internal | |||
{ | |||
template <typename Type> struct make_unsigned { typedef Type type; }; | |||
@@ -140,20 +140,29 @@ public: | |||
template <typename CharPointerType> | |||
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* currentCharacter = &(buffer[0]); | |||
int numSigFigs = 0; | |||
bool decimalPointFound = false; | |||
#endif | |||
text = text.findEndOfWhitespace(); | |||
auto c = *text; | |||
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) | |||
@@ -171,11 +180,121 @@ public: | |||
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 (;;) | |||
{ | |||
if (text.isDigit()) | |||
{ | |||
int digit = (int) text.getAndAdvance() - '0'; | |||
auto digit = (int) text.getAndAdvance() - '0'; | |||
if (numSigFigs >= maxSignificantDigits | |||
|| ((numSigFigs == 0 && (! decimalPointFound)) && digit == 0)) | |||
@@ -231,22 +350,19 @@ public: | |||
*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 | |||
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 // JUCE_MINGW | |||
} | |||
/** Parses a character string, to read a floating-point value. */ | |||
@@ -241,7 +241,7 @@ namespace XmlOutputFunctions | |||
outputStream << (char) character; | |||
break; | |||
} | |||
// Note: deliberate fall-through here! | |||
// fall-through | |||
default: | |||
outputStream << "&#" << ((int) character) << ';'; | |||
break; | |||
@@ -92,7 +92,7 @@ private: | |||
{ | |||
case Z_STREAM_END: | |||
finished = true; | |||
// Deliberate fall-through.. | |||
// fall-through.. | |||
case Z_OK: | |||
{ | |||
data += dataSize - stream.avail_in; | |||
@@ -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; | |||
@@ -59,8 +59,6 @@ ActionBroadcaster::~ActionBroadcaster() | |||
{ | |||
// all event-based objects must be deleted BEFORE juce is shut down! | |||
jassert (MessageManager::getInstanceWithoutCreating() != nullptr); | |||
masterReference.clear(); | |||
} | |||
void ActionBroadcaster::addActionListener (ActionListener* const listener) | |||
@@ -64,15 +64,13 @@ public: | |||
private: | |||
//============================================================================== | |||
friend class WeakReference<ActionBroadcaster>; | |||
WeakReference<ActionBroadcaster>::Master masterReference; | |||
class ActionMessage; | |||
friend class ActionMessage; | |||
SortedSet<ActionListener*> actionListeners; | |||
CriticalSection actionListenerLock; | |||
JUCE_DECLARE_WEAK_REFERENCEABLE (ActionBroadcaster) | |||
JUCE_DECLARE_NON_COPYABLE (ActionBroadcaster) | |||
}; | |||
@@ -26,22 +26,16 @@ namespace juce | |||
struct InterprocessConnection::ConnectionThread : public Thread | |||
{ | |||
ConnectionThread (InterprocessConnection& c) : Thread ("JUCE IPC"), owner (c) {} | |||
void run() override { owner.runThread(); } | |||
private: | |||
InterprocessConnection& owner; | |||
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); | |||
} | |||
@@ -207,7 +201,7 @@ struct ConnectionStateMessage : public MessageManager::MessageBase | |||
void messageCallback() override | |||
{ | |||
if (InterprocessConnection* const ipc = owner) | |||
if (auto* ipc = owner.get()) | |||
{ | |||
if (connectionMade) | |||
ipc->connectionMade(); | |||
@@ -256,7 +250,7 @@ struct DataDeliveryMessage : public Message | |||
void messageCallback() override | |||
{ | |||
if (InterprocessConnection* const ipc = owner) | |||
if (auto* ipc = owner.get()) | |||
ipc->messageReceived (data); | |||
} | |||
@@ -331,7 +325,7 @@ void InterprocessConnection::runThread() | |||
{ | |||
if (socket != nullptr) | |||
{ | |||
const int ready = socket->waitUntilReady (true, 0); | |||
auto ready = socket->waitUntilReady (true, 0); | |||
if (ready < 0) | |||
{ | |||
@@ -176,15 +176,13 @@ public: | |||
private: | |||
//============================================================================== | |||
WeakReference<InterprocessConnection>::Master masterReference; | |||
friend class WeakReference<InterprocessConnection>; | |||
CriticalSection pipeAndSocketLock; | |||
ScopedPointer<StreamingSocket> socket; | |||
ScopedPointer<NamedPipe> pipe; | |||
bool callbackConnectionState; | |||
bool callbackConnectionState = false; | |||
const bool useMessageThread; | |||
const uint32 magicMessageHeader; | |||
int pipeReceiveMessageTimeout; | |||
int pipeReceiveMessageTimeout = -1; | |||
friend class InterprocessConnectionServer; | |||
void initialiseWithSocket (StreamingSocket*); | |||
@@ -202,6 +200,7 @@ private: | |||
void runThread(); | |||
int writeData (void*, int); | |||
JUCE_DECLARE_WEAK_REFERENCEABLE (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.. | |||
jassert (findGlyph (character, false) == nullptr); | |||
if (isPositiveAndBelow ((int) character, (int) numElementsInArray (lookupTable))) | |||
if (isPositiveAndBelow ((int) character, numElementsInArray (lookupTable))) | |||
lookupTable [character] = (short) glyphs.size(); | |||
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 | |||
{ | |||
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]]; | |||
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 | |||
{ | |||
return Range<float> (lineOrigin.y - ascent, | |||
lineOrigin.y + descent); | |||
return { lineOrigin.y - ascent, | |||
lineOrigin.y + descent }; | |||
} | |||
Rectangle<float> TextLayout::Line::getLineBounds() const noexcept | |||
@@ -223,7 +223,8 @@ void TextLayout::draw (Graphics& g, Rectangle<float> area) const | |||
: 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, | |||
runExtent.getLength(), lineThickness }); | |||
} | |||
@@ -256,8 +257,8 @@ void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& te | |||
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; | |||
while (maxWidth > minimumWidth) | |||
@@ -267,12 +268,13 @@ void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& te | |||
if (getNumLines() < 2) | |||
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; | |||
if (prop > bestLineProportion) | |||
@@ -308,8 +310,7 @@ namespace TextLayoutHelpers | |||
float lineHeight; | |||
const bool isWhitespace, isNewLine; | |||
private: | |||
Token& operator= (const Token&); | |||
Token& operator= (const Token&) = delete; | |||
}; | |||
struct TokenList | |||
@@ -346,7 +347,7 @@ namespace TextLayoutHelpers | |||
if (newGlyphs.size() > 0) | |||
{ | |||
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) | |||
{ | |||
@@ -354,11 +355,11 @@ namespace TextLayoutHelpers | |||
currentLine->lineOrigin = tokenOrigin; | |||
} | |||
const Point<float> glyphOffset (tokenOrigin - currentLine->lineOrigin); | |||
auto glyphOffset = tokenOrigin - currentLine->lineOrigin; | |||
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), | |||
glyphOffset.translated (x, 0), | |||
xOffsets.getUnchecked (j + 1) - x)); | |||
@@ -370,7 +371,7 @@ namespace TextLayoutHelpers | |||
if (t.isWhitespace || t.isNewLine) | |||
++charPosition; | |||
if (auto* nextToken = tokens [i + 1]) | |||
if (auto* nextToken = tokens[i + 1]) | |||
{ | |||
if (t.font != nextToken->font || t.colour != nextToken->colour) | |||
{ | |||
@@ -408,12 +409,12 @@ namespace TextLayoutHelpers | |||
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) | |||
{ | |||
float dx = totalW - layout.getLine(i).getLineBoundsX().getLength(); | |||
auto dx = totalW - layout.getLine(i).getLineBoundsX().getLength(); | |||
if (isCentred) | |||
dx /= 2.0f; | |||
@@ -451,11 +452,12 @@ namespace TextLayoutHelpers | |||
for (;;) | |||
{ | |||
const juce_wchar c = t.getAndAdvance(); | |||
auto c = t.getAndAdvance(); | |||
if (c == 0) | |||
break; | |||
const int charType = getCharacterType (c); | |||
auto charType = getCharacterType (c); | |||
if (charType == 0 || charType != lastCharType) | |||
{ | |||
@@ -529,7 +531,7 @@ namespace TextLayoutHelpers | |||
void addTextRuns (const AttributedString& text) | |||
{ | |||
const int numAttributes = text.getNumAttributes(); | |||
auto numAttributes = text.getNumAttributes(); | |||
tokens.ensureStorageAllocated (jmax (64, numAttributes)); | |||
for (int i = 0; i < numAttributes; ++i) | |||
@@ -572,7 +572,7 @@ void EdgeTable::intersectWithEdgeTableLine (const int y, const int* const otherL | |||
lastX = nextX; | |||
const int nextLevel = (level1 * (level2 + 1)) >> 8; | |||
jassert (isPositiveAndBelow (nextLevel, (int) 256)); | |||
jassert (isPositiveAndBelow (nextLevel, 256)); | |||
if (nextLevel != lastLevel) | |||
{ | |||
@@ -129,7 +129,7 @@ public: | |||
while (--numPoints >= 0) | |||
{ | |||
const int level = *++line; | |||
jassert (isPositiveAndBelow (level, (int) 256)); | |||
jassert (isPositiveAndBelow (level, 256)); | |||
const int endX = *++line; | |||
jassert (endX >= x); | |||
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) | |||
@@ -231,14 +231,12 @@ public: | |||
private: | |||
//============================================================================== | |||
WeakReference<ApplicationCommandTarget>::Master masterReference; | |||
friend class WeakReference<ApplicationCommandTarget>; | |||
class CommandMessage; | |||
friend class CommandMessage; | |||
bool tryToInvoke (const InvocationInfo&, bool async); | |||
JUCE_DECLARE_WEAK_REFERENCEABLE (ApplicationCommandTarget) | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ApplicationCommandTarget) | |||
}; | |||
@@ -32,11 +32,6 @@ class ComponentAnimator::AnimationTask | |||
public: | |||
AnimationTask (Component* c) noexcept : component (c) {} | |||
~AnimationTask() | |||
{ | |||
masterReference.clear(); | |||
} | |||
void reset (const Rectangle<int>& finalBounds, | |||
float finalAlpha, | |||
int millisecondsToSpendMoving, | |||
@@ -186,9 +181,6 @@ public: | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProxyComponent) | |||
}; | |||
WeakReference<AnimationTask>::Master masterReference; | |||
friend class WeakReference<AnimationTask>; | |||
WeakReference<Component> component; | |||
ScopedPointer<Component> proxy; | |||
@@ -208,6 +200,7 @@ private: | |||
+ (time - 0.5) * (midSpeed + (time - 0.5) * (endSpeed - midSpeed)); | |||
} | |||
JUCE_DECLARE_WEAK_REFERENCEABLE (AnimationTask) | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnimationTask) | |||
}; | |||
@@ -37,7 +37,6 @@ extern GetTypefaceForFont juce_getTypefaceForFont; | |||
//============================================================================== | |||
LookAndFeel::LookAndFeel() | |||
: useNativeAlertWindows (false) | |||
{ | |||
/* 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 | |||
@@ -51,7 +50,6 @@ LookAndFeel::LookAndFeel() | |||
LookAndFeel::~LookAndFeel() | |||
{ | |||
masterReference.clear(); | |||
} | |||
//============================================================================== | |||
@@ -212,9 +212,6 @@ public: | |||
private: | |||
//============================================================================== | |||
friend class WeakReference<LookAndFeel>; | |||
WeakReference<LookAndFeel>::Master masterReference; | |||
struct ColourSetting | |||
{ | |||
int colourID; | |||
@@ -226,8 +223,9 @@ private: | |||
SortedSet<ColourSetting> colours; | |||
String defaultSans, defaultSerif, defaultFixed; | |||
bool useNativeAlertWindows; | |||
bool useNativeAlertWindows = false; | |||
JUCE_DECLARE_WEAK_REFERENCEABLE (LookAndFeel) | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel) | |||
}; | |||
@@ -200,6 +200,8 @@ void LookAndFeel_V4::positionDocumentWindowButtons (DocumentWindow&, | |||
Button* closeButton, | |||
bool positionTitleBarButtonsOnLeft) | |||
{ | |||
titleBarH = jmin (titleBarH, titleBarH - titleBarY); | |||
const int buttonW = (int) (titleBarH * 1.2); | |||
int x = positionTitleBarButtonsOnLeft ? titleBarX | |||
@@ -1621,7 +1621,7 @@ struct PopupMenuCompletionCallback : public ModalComponentManager::Callback | |||
if (prevTopLevel != nullptr) | |||
prevTopLevel->toFront (true); | |||
if (prevFocused != nullptr) | |||
if (prevFocused != nullptr && prevFocused->isShowing()) | |||
prevFocused->grabKeyboardFocus(); | |||
} | |||
} | |||
@@ -27,6 +27,41 @@ | |||
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, | |||
private DeletedAtShutdown | |||
{ | |||
@@ -95,7 +130,10 @@ public: | |||
[menu setAutoenablesItems: false]; | |||
[menu update]; | |||
removeItemRecursive ([parentItem submenu]); | |||
[parentItem setSubmenu: menu]; | |||
[menu release]; | |||
} | |||
@@ -104,7 +142,9 @@ public: | |||
NSMenu* superMenu = [menu supermenu]; | |||
auto menuNames = currentModel->getMenuBarNames(); | |||
auto indexOfMenu = (int) [superMenu indexOfItemWithSubmenu: menu] - 1; | |||
[menu removeAllItems]; | |||
removeItemRecursive (menu); | |||
auto updatedPopup = currentModel->getMenuForIndex (indexOfMenu, menuNames[indexOfMenu]); | |||
for (PopupMenu::MenuItemIterator iter (updatedPopup); iter.next();) | |||
@@ -113,7 +153,7 @@ public: | |||
[menu update]; | |||
} | |||
void menuBarItemsChanged (MenuBarModel*) | |||
void menuBarItemsChanged (MenuBarModel*) override | |||
{ | |||
if (isOpen) | |||
{ | |||
@@ -127,10 +167,10 @@ public: | |||
if (currentModel != nullptr) | |||
menuNames = currentModel->getMenuBarNames(); | |||
NSMenu* menuBar = [[NSApp mainMenu] retain]; | |||
auto* menuBar = getMainMenuBar(); | |||
while ([menuBar numberOfItems] > 1 + menuNames.size()) | |||
[menuBar removeItemAtIndex: [menuBar numberOfItems] - 1]; | |||
removeItemRecursive (menuBar, static_cast<int> ([menuBar numberOfItems] - 1)); | |||
int menuId = 1; | |||
@@ -143,34 +183,36 @@ public: | |||
else | |||
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 | |||
&& info.invocationMethod != ApplicationCommandTarget::InvocationInfo::fromKeyPress) | |||
if (auto* item = findMenuItemWithTag ([NSApp mainMenu], info.commandID)) | |||
if (auto* item = findMenuItemWithCommandID (getMainMenuBar(), info.commandID)) | |||
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 (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; | |||
commandManager->invoke (info, true); | |||
item.commandManager->invoke (info, true); | |||
} | |||
MessageManager::callAsync ([=]() | |||
{ | |||
if (instance != nullptr) | |||
instance->invokeDirectly (commandId, topLevelIndex); | |||
instance->invokeDirectly (item.itemID, topLevelIndex); | |||
}); | |||
} | |||
} | |||
@@ -232,18 +274,19 @@ public: | |||
} | |||
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 setState: i.isTicked ? NSOnState : NSOffState]; | |||
[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) | |||
{ | |||
@@ -264,6 +307,9 @@ public: | |||
break; | |||
} | |||
} | |||
[menuToAddTo addItem: item]; | |||
[item release]; | |||
} | |||
} | |||
@@ -357,16 +403,17 @@ private: | |||
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;) | |||
{ | |||
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 (NSMenuItem* found = findMenuItemWithTag (sub, tag)) | |||
if (NSMenuItem* found = findMenuItemWithCommandID (sub, commandID)) | |||
return found; | |||
} | |||
@@ -422,6 +469,39 @@ private: | |||
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> | |||
{ | |||
@@ -449,7 +529,7 @@ private: | |||
{ | |||
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 | |||
// 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); | |||
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. | |||
dummyModalComponent.enterModalState (false); | |||
@@ -615,23 +693,16 @@ namespace MainMenuHelpers | |||
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]; | |||
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; | |||
if (! SystemStats::isRunningInAppExtensionSandbox()) | |||
@@ -1184,8 +1184,8 @@ public: | |||
{ | |||
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; | |||
POINT p = { localPos.x + r.left + windowBorder.getLeft(), | |||
@@ -43,8 +43,7 @@ AlertWindow::AlertWindow (const String& title, | |||
Component* comp) | |||
: TopLevelWindow (title, true), | |||
alertIconType (iconType), | |||
associatedComponent (comp), | |||
escapeKeyCancels (true) | |||
associatedComponent (comp) | |||
{ | |||
setAlwaysOnTop (juce_areThereAnyAlwaysOnTopWindows()); | |||
@@ -71,7 +70,7 @@ void AlertWindow::userTriedToCloseWindow() | |||
//============================================================================== | |||
void AlertWindow::setMessage (const String& message) | |||
{ | |||
const String newMessage (message.substring (0, 2048)); | |||
auto newMessage = message.substring (0, 2048); | |||
if (text != newMessage) | |||
{ | |||
@@ -84,7 +83,7 @@ void AlertWindow::setMessage (const String& message) | |||
//============================================================================== | |||
void AlertWindow::buttonClicked (Button* button) | |||
{ | |||
if (Component* parent = button->getParentComponent()) | |||
if (auto* parent = button->getParentComponent()) | |||
parent->exitModalState (button->getCommandID()); | |||
} | |||
@@ -94,7 +93,7 @@ void AlertWindow::addButton (const String& name, | |||
const KeyPress& shortcutKey1, | |||
const KeyPress& shortcutKey2) | |||
{ | |||
TextButton* const b = new TextButton (name, String()); | |||
auto* b = new TextButton (name, {}); | |||
buttons.add (b); | |||
b->setWantsKeyboardFocus (true); | |||
@@ -105,19 +104,18 @@ void AlertWindow::addButton (const String& name, | |||
b->addListener (this); | |||
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()); | |||
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); | |||
updateLayout (false); | |||
} | |||
@@ -128,10 +126,8 @@ int AlertWindow::getNumButtons() const | |||
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()) | |||
{ | |||
b->triggerClick(); | |||
@@ -151,7 +147,7 @@ void AlertWindow::addTextEditor (const String& name, | |||
const String& onScreenLabel, | |||
const bool isPasswordBox) | |||
{ | |||
TextEditor* ed = new TextEditor (name, isPasswordBox ? getDefaultPasswordChar() : 0); | |||
auto* ed = new TextEditor (name, isPasswordBox ? getDefaultPasswordChar() : 0); | |||
ed->setSelectAllWhenFocused (true); | |||
ed->setEscapeAndReturnKeysConsumed (false); | |||
textBoxes.add (ed); | |||
@@ -169,9 +165,9 @@ void AlertWindow::addTextEditor (const String& name, | |||
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; | |||
} | |||
@@ -190,7 +186,7 @@ void AlertWindow::addComboBox (const String& name, | |||
const StringArray& items, | |||
const String& onScreenLabel) | |||
{ | |||
ComboBox* const cb = new ComboBox (name); | |||
auto* cb = new ComboBox (name); | |||
comboBoxes.add (cb); | |||
allComps.add (cb); | |||
@@ -205,9 +201,9 @@ void AlertWindow::addComboBox (const String& name, | |||
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; | |||
} | |||
@@ -231,15 +227,12 @@ public: | |||
setScrollbarsShown (true); | |||
lookAndFeelChanged(); | |||
setWantsKeyboardFocus (false); | |||
setFont (font); | |||
setText (message, false); | |||
bestWidth = 2 * (int) std::sqrt (font.getHeight() * font.getStringWidth (message)); | |||
} | |||
int getPreferredWidth() const noexcept { return bestWidth; } | |||
void updateLayout (const int width) | |||
{ | |||
AttributedString s; | |||
@@ -251,7 +244,6 @@ public: | |||
setSize (width, jmin (width, (int) (text.getHeight() + getFont().getHeight()))); | |||
} | |||
private: | |||
int bestWidth; | |||
JUCE_DECLARE_NON_COPYABLE (AlertTextComp) | |||
@@ -259,10 +251,9 @@ private: | |||
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); | |||
allComps.add (c); | |||
addAndMakeVisible (c); | |||
updateLayout (false); | |||
@@ -271,10 +262,9 @@ void AlertWindow::addTextBlock (const String& textBlock) | |||
//============================================================================== | |||
void AlertWindow::addProgressBarComponent (double& progressValue) | |||
{ | |||
ProgressBar* const pb = new ProgressBar (progressValue); | |||
auto* pb = new ProgressBar (progressValue); | |||
progressBars.add (pb); | |||
allComps.add (pb); | |||
addAndMakeVisible (pb); | |||
updateLayout (false); | |||
@@ -285,25 +275,17 @@ void AlertWindow::addCustomComponent (Component* const component) | |||
{ | |||
customComps.add (component); | |||
allComps.add (component); | |||
addAndMakeVisible (component); | |||
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* const c = getCustomComponent (index); | |||
auto* c = getCustomComponent (index); | |||
if (c != nullptr) | |||
{ | |||
@@ -320,14 +302,15 @@ Component* AlertWindow::removeCustomComponent (const int index) | |||
//============================================================================== | |||
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.setFont (getLookAndFeel().getAlertWindowFont()); | |||
g.setFont (lf.getAlertWindowFont()); | |||
for (int i = textBoxes.size(); --i >= 0;) | |||
{ | |||
const TextEditor* const te = textBoxes.getUnchecked(i); | |||
auto* te = textBoxes.getUnchecked(i); | |||
g.drawFittedText (textboxNames[i], | |||
te->getX(), te->getY() - 14, | |||
@@ -337,7 +320,7 @@ void AlertWindow::paint (Graphics& g) | |||
for (int i = comboBoxNames.size(); --i >= 0;) | |||
{ | |||
const ComboBox* const cb = comboBoxes.getUnchecked(i); | |||
auto* cb = comboBoxes.getUnchecked(i); | |||
g.drawFittedText (comboBoxNames[i], | |||
cb->getX(), cb->getY() - 14, | |||
@@ -345,15 +328,11 @@ void AlertWindow::paint (Graphics& g) | |||
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(), | |||
c->getX(), c->getY() - 14, | |||
c->getWidth(), 14, | |||
Justification::centredLeft, 1); | |||
} | |||
} | |||
void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
@@ -361,15 +340,14 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
const int titleH = 24; | |||
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 labelHeight = 18; | |||
int iconSpace = 0; | |||
@@ -397,24 +375,24 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
w = jmax (350, (int) textLayout.getWidth() + iconSpace + edgeGap * 4); | |||
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 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); | |||
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); | |||
h += 10 + c->getHeight(); | |||
@@ -422,17 +400,14 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
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)); | |||
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)); | |||
h += ac->getHeight() + 10; | |||
} | |||
@@ -455,15 +430,14 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
const int spacer = 16; | |||
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(); | |||
c->setTopLeftPosition (x, ny); | |||
if (ny < y) | |||
@@ -476,9 +450,8 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) | |||
y = textBottom; | |||
for (int i = 0; i < allComps.size(); ++i) | |||
for (auto* c : allComps) | |||
{ | |||
Component* const c = allComps.getUnchecked(i); | |||
h = 22; | |||
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) | |||
{ | |||
for (int i = buttons.size(); --i >= 0;) | |||
for (auto* b : buttons) | |||
{ | |||
TextButton* const b = buttons.getUnchecked(i); | |||
if (b->isRegisteredForShortcut (key)) | |||
{ | |||
b->triggerClick(); | |||
@@ -579,8 +550,7 @@ public: | |||
AlertWindow::AlertIconType icon, int numButts, | |||
ModalComponentManager::Callback* cb, bool runModally) | |||
: 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: | |||
AlertWindow::AlertIconType iconType; | |||
int numButtons, returnValue; | |||
int numButtons, returnValue = 0; | |||
WeakReference<Component> associatedComponent; | |||
ModalComponentManager::Callback* callback; | |||
bool modal; | |||
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, | |||
iconType, numButtons, associatedComponent)); | |||
@@ -479,8 +479,8 @@ private: | |||
OwnedArray<Component> textBlocks; | |||
Array<Component*> allComps; | |||
StringArray textboxNames, comboBoxNames; | |||
Component* associatedComponent; | |||
bool escapeKeyCancels; | |||
Component* const associatedComponent; | |||
bool escapeKeyCancels = true; | |||
void updateLayout (bool onlyIncreaseSize); | |||
@@ -27,8 +27,8 @@ | |||
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); | |||
@@ -84,7 +84,7 @@ public: | |||
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! | |||
@@ -110,7 +110,7 @@ void CallOutBox::paint (Graphics& g) | |||
void CallOutBox::resized() | |||
{ | |||
const int borderSpace = getBorderSize(); | |||
auto borderSpace = getBorderSize(); | |||
content.setTopLeftPosition (borderSpace, borderSpace); | |||
refreshPath(); | |||
} | |||
@@ -143,7 +143,8 @@ void CallOutBox::inputAttemptWhenModal() | |||
// as Windows still sends touch events before the CallOutBox had a chance | |||
// to really open. | |||
RelativeTime elapsed = Time::getCurrentTime() - creationTime; | |||
auto elapsed = Time::getCurrentTime() - creationTime; | |||
if (elapsed.inMilliseconds() > 200) | |||
dismiss(); | |||
} | |||
@@ -193,29 +194,29 @@ void CallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo, const R | |||
targetArea = newAreaToPointTo; | |||
availableArea = newAreaToFitIn; | |||
const int borderSpace = getBorderSize(); | |||
auto borderSpace = getBorderSize(); | |||
Rectangle<int> newBounds (content.getWidth() + 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; | |||
@@ -224,8 +225,8 @@ void CallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo, const R | |||
Line<float> constrainedLine (centrePointArea.getConstrainedPoint (lines[i].getStart()), | |||
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])) | |||
distanceFromCentre += 1000.0f; | |||
@@ -233,8 +234,8 @@ void CallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo, const R | |||
if (distanceFromCentre < nearest) | |||
{ | |||
nearest = distanceFromCentre; | |||
targetPoint = targets[i]; | |||
newBounds.setPosition ((int) (centre.x - hw), | |||
(int) (centre.y - hh)); | |||
} | |||
@@ -246,7 +247,7 @@ void CallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo, const R | |||
void CallOutBox::refreshPath() | |||
{ | |||
repaint(); | |||
background = Image(); | |||
background = {}; | |||
outline.clear(); | |||
const float gap = 4.5f; | |||
@@ -73,7 +73,7 @@ public: | |||
If this is a nullptr, the call-out will be added to the desktop. | |||
*/ | |||
CallOutBox (Component& contentComponent, | |||
const Rectangle<int>& areaToPointTo, | |||
Rectangle<int> areaToPointTo, | |||
Component* parentComponent); | |||
/** Destructor. */ | |||
@@ -117,7 +117,7 @@ public: | |||
If this is a nullptr, the call-out will be added to the desktop. | |||
*/ | |||
static CallOutBox& launchAsynchronously (Component* contentComponent, | |||
const Rectangle<int>& areaToPointTo, | |||
Rectangle<int> areaToPointTo, | |||
Component* parentComponent); | |||
/** Posts a message which will dismiss the callout box asynchronously. | |||
@@ -167,13 +167,13 @@ public: | |||
private: | |||
//============================================================================== | |||
float arrowSize; | |||
Component& content; | |||
Path outline; | |||
Point<float> targetPoint; | |||
Rectangle<int> availableArea, targetArea; | |||
Image background; | |||
bool dismissalMouseClicksAreAlwaysConsumed; | |||
float arrowSize = 16.0f; | |||
bool dismissalMouseClicksAreAlwaysConsumed = false; | |||
Time creationTime; | |||
@@ -63,7 +63,7 @@ void DialogWindow::resized() | |||
if (escapeKeyTriggersCloseButton) | |||
{ | |||
if (Button* const close = getCloseButton()) | |||
if (auto* close = getCloseButton()) | |||
{ | |||
const KeyPress esc (KeyPress::escapeKey, 0, 0); | |||
@@ -102,15 +102,7 @@ private: | |||
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() | |||
{ | |||
@@ -121,7 +113,7 @@ DialogWindow* DialogWindow::LaunchOptions::create() | |||
DialogWindow* DialogWindow::LaunchOptions::launchAsync() | |||
{ | |||
DialogWindow* const d = create(); | |||
auto* d = create(); | |||
d->enterModalState (true, nullptr, true); | |||
return d; | |||
} | |||
@@ -87,7 +87,7 @@ public: | |||
String dialogTitle; | |||
/** 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! | |||
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 | |||
more info about this parameter. | |||
*/ | |||
Component* componentToCentreAround; | |||
Component* componentToCentreAround = nullptr; | |||
/** 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() */ | |||
bool useNativeTitleBar; | |||
bool useNativeTitleBar = true; | |||
/** 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() */ | |||
bool useBottomRightCornerResizer; | |||
bool useBottomRightCornerResizer = false; | |||
/** Launches a new modal dialog window. | |||
This will create a dialog based on the settings in this structure, | |||
@@ -51,16 +51,12 @@ DocumentWindow::DocumentWindow (const String& title, | |||
int requiredButtons_, | |||
bool addToDesktop_) | |||
: ResizableWindow (title, backgroundColour, addToDesktop_), | |||
titleBarHeight (26), | |||
menuBarHeight (24), | |||
requiredButtons (requiredButtons_), | |||
#if JUCE_MAC | |||
positionTitleBarButtonsOnLeft (true), | |||
positionTitleBarButtonsOnLeft (true) | |||
#else | |||
positionTitleBarButtonsOnLeft (false), | |||
positionTitleBarButtonsOnLeft (false) | |||
#endif | |||
drawTitleTextCentred (true), | |||
menuBarModel (nullptr) | |||
{ | |||
setResizeLimits (128, 128, 32768, 32768); | |||
@@ -77,8 +73,8 @@ DocumentWindow::~DocumentWindow() | |||
jassert (titleBarButtons[1] == nullptr || getIndexOfChildComponent (titleBarButtons[1]) >= 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; | |||
} | |||
@@ -193,16 +189,16 @@ void DocumentWindow::paint (Graphics& g) | |||
{ | |||
ResizableWindow::paint (g); | |||
const Rectangle<int> titleBarArea (getTitleBarArea()); | |||
auto titleBarArea = getTitleBarArea(); | |||
g.reduceClipRegion (titleBarArea); | |||
g.setOrigin (titleBarArea.getPosition()); | |||
int titleSpaceX1 = 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) | |||
titleSpaceX1 = jmax (titleSpaceX1, b->getRight() + (getWidth() - b->getRight()) / 8); | |||
@@ -224,10 +220,10 @@ void DocumentWindow::resized() | |||
{ | |||
ResizableWindow::resized(); | |||
if (Button* const b = getMaximiseButton()) | |||
if (auto* b = getMaximiseButton()) | |||
b->setToggleState (isFullScreen(), dontSendNotification); | |||
const Rectangle<int> titleBarArea (getTitleBarArea()); | |||
auto titleBarArea = getTitleBarArea(); | |||
getLookAndFeel() | |||
.positionDocumentWindowButtons (*this, | |||
@@ -250,7 +246,7 @@ BorderSize<int> DocumentWindow::getBorderThickness() | |||
BorderSize<int> DocumentWindow::getContentComponentBorder() | |||
{ | |||
BorderSize<int> border (getBorderThickness()); | |||
auto border = getBorderThickness(); | |||
if (! isKioskMode()) | |||
border.setTop (border.getTop() | |||
@@ -267,13 +263,11 @@ int DocumentWindow::getTitleBarHeight() const | |||
Rectangle<int> DocumentWindow::getTitleBarArea() | |||
{ | |||
const BorderSize<int> border (getBorderThickness()); | |||
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]; } | |||
@@ -282,7 +276,7 @@ Button* DocumentWindow::getMaximiseButton() const noexcept { return titleBarBut | |||
int DocumentWindow::getDesktopWindowStyleFlags() const | |||
{ | |||
int styleFlags = ResizableWindow::getDesktopWindowStyleFlags(); | |||
auto styleFlags = ResizableWindow::getDesktopWindowStyleFlags(); | |||
if ((requiredButtons & minimiseButton) != 0) styleFlags |= ComponentPeer::windowHasMinimiseButton; | |||
if ((requiredButtons & maximiseButton) != 0) styleFlags |= ComponentPeer::windowHasMaximiseButton; | |||
@@ -293,8 +287,8 @@ int DocumentWindow::getDesktopWindowStyleFlags() const | |||
void DocumentWindow::lookAndFeelChanged() | |||
{ | |||
for (int i = numElementsInArray (titleBarButtons); --i >= 0;) | |||
titleBarButtons[i] = nullptr; | |||
for (auto& b : titleBarButtons) | |||
b = nullptr; | |||
if (! isUsingNativeTitleBar()) | |||
{ | |||
@@ -304,9 +298,9 @@ void DocumentWindow::lookAndFeelChanged() | |||
if ((requiredButtons & maximiseButton) != 0) titleBarButtons[1] = lf.createDocumentWindowButton (maximiseButton); | |||
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) | |||
buttonListener = new ButtonListenerProxy (*this); | |||
@@ -319,7 +313,7 @@ void DocumentWindow::lookAndFeelChanged() | |||
} | |||
} | |||
if (Button* const b = getCloseButton()) | |||
if (auto* b = getCloseButton()) | |||
{ | |||
#if JUCE_MAC | |||
b->addShortcut (KeyPress ('w', ModifierKeys::commandModifier, 0)); | |||
@@ -342,21 +336,21 @@ void DocumentWindow::parentHierarchyChanged() | |||
void DocumentWindow::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) | |||
menuBar->setEnabled (isActiveWindow()); | |||
menuBar->setEnabled (isActive); | |||
} | |||
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() | |||
@@ -276,12 +276,12 @@ public: | |||
private: | |||
//============================================================================== | |||
int titleBarHeight, menuBarHeight, requiredButtons; | |||
bool positionTitleBarButtonsOnLeft, drawTitleTextCentred; | |||
int titleBarHeight = 26, menuBarHeight = 24, requiredButtons; | |||
bool positionTitleBarButtonsOnLeft, drawTitleTextCentred = true; | |||
ScopedPointer<Button> titleBarButtons [3]; | |||
Image titleBarIcon; | |||
ScopedPointer<Component> menuBar; | |||
MenuBarModel* menuBarModel; | |||
MenuBarModel* menuBarModel = nullptr; | |||
class ButtonListenerProxy; | |||
friend struct ContainerDeletePolicy<ButtonListenerProxy>; | |||
@@ -37,7 +37,6 @@ ResizableWindow::ResizableWindow (const String& name, Colour bkgnd, bool shouldA | |||
: TopLevelWindow (name, shouldAddToDesktop) | |||
{ | |||
setBackgroundColour (bkgnd); | |||
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.. | |||
const BorderSize<int> border (getContentComponentBorder()); | |||
auto border = getContentComponentBorder(); | |||
setSize (width + border.getLeftAndRight(), | |||
height + border.getTopAndBottom()); | |||
@@ -156,7 +155,7 @@ void ResizableWindow::setContentComponentSize (int width, int height) | |||
BorderSize<int> ResizableWindow::getBorderThickness() | |||
{ | |||
if (isUsingNativeTitleBar() || isKioskMode()) | |||
return BorderSize<int>(); | |||
return {}; | |||
return BorderSize<int> ((resizableBorder != nullptr && ! isFullScreen()) ? 4 : 1); | |||
} | |||
@@ -174,7 +173,6 @@ void ResizableWindow::moved() | |||
void ResizableWindow::visibilityChanged() | |||
{ | |||
TopLevelWindow::visibilityChanged(); | |||
updateLastPosIfShowing(); | |||
} | |||
@@ -235,9 +233,9 @@ void ResizableWindow::childBoundsChanged (Component* child) | |||
//============================================================================== | |||
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.removeFromLeft (border.getLeft())); | |||
repaint (area.removeFromRight (border.getRight())); | |||
@@ -287,10 +285,10 @@ bool ResizableWindow::isResizable() const noexcept | |||
|| 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.. | |||
jassert (constrainer == &defaultConstrainer || constrainer == nullptr); | |||
@@ -315,8 +313,8 @@ void ResizableWindow::setConstrainer (ComponentBoundsConstrainer* 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; | |||
resizableBorder = nullptr; | |||
@@ -337,7 +335,7 @@ void ResizableWindow::setBoundsConstrained (const Rectangle<int>& newBounds) | |||
//============================================================================== | |||
void ResizableWindow::paint (Graphics& g) | |||
{ | |||
LookAndFeel& lf = getLookAndFeel(); | |||
auto& lf = getLookAndFeel(); | |||
lf.fillResizableWindowBackground (g, getWidth(), getHeight(), | |||
getBorderThickness(), *this); | |||
@@ -380,13 +378,12 @@ Colour ResizableWindow::getBackgroundColour() const noexcept | |||
void ResizableWindow::setBackgroundColour (Colour newColour) | |||
{ | |||
Colour backgroundColour (newColour); | |||
auto backgroundColour = newColour; | |||
if (! Desktop::canUseSemiTransparentWindows()) | |||
backgroundColour = newColour.withAlpha (1.0f); | |||
setColour (backgroundColourId, backgroundColour); | |||
setOpaque (backgroundColour.isOpaque()); | |||
repaint(); | |||
} | |||
@@ -396,7 +393,7 @@ bool ResizableWindow::isFullScreen() const | |||
{ | |||
if (isOnDesktop()) | |||
{ | |||
ComponentPeer* const peer = getPeer(); | |||
auto* peer = getPeer(); | |||
return peer != nullptr && peer->isFullScreen(); | |||
} | |||
@@ -412,10 +409,10 @@ void ResizableWindow::setFullScreen (const bool shouldBeFullScreen) | |||
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 | |||
const Rectangle<int> lastPos (lastNonFullScreenPos); | |||
auto lastPos = lastNonFullScreenPos; | |||
peer->setFullScreen (shouldBeFullScreen); | |||
@@ -441,7 +438,7 @@ void ResizableWindow::setFullScreen (const bool shouldBeFullScreen) | |||
bool ResizableWindow::isMinimised() const | |||
{ | |||
if (ComponentPeer* const peer = getPeer()) | |||
if (auto* peer = getPeer()) | |||
return peer->isMinimised(); | |||
return false; | |||
@@ -451,7 +448,7 @@ void ResizableWindow::setMinimised (const bool shouldMinimise) | |||
{ | |||
if (shouldMinimise != isMinimised()) | |||
{ | |||
if (ComponentPeer* const peer = getPeer()) | |||
if (auto* peer = getPeer()) | |||
{ | |||
updateLastPosIfShowing(); | |||
peer->setMinimised (shouldMinimise); | |||
@@ -466,7 +463,7 @@ void ResizableWindow::setMinimised (const bool shouldMinimise) | |||
bool ResizableWindow::isKioskMode() const | |||
{ | |||
if (isOnDesktop()) | |||
if (ComponentPeer* peer = getPeer()) | |||
if (auto* peer = getPeer()) | |||
return peer->isKioskMode(); | |||
return Desktop::getInstance().getKioskModeComponent() == this; | |||
@@ -490,7 +487,7 @@ void ResizableWindow::updateLastPosIfNotFullScreen() | |||
void ResizableWindow::updatePeerConstrainer() | |||
{ | |||
if (isOnDesktop()) | |||
if (ComponentPeer* const peer = getPeer()) | |||
if (auto* peer = getPeer()) | |||
peer->setConstrainer (constrainer); | |||
} | |||
@@ -528,19 +525,20 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s) | |||
if (newPos.isEmpty()) | |||
return false; | |||
ComponentPeer* const peer = isOnDesktop() ? getPeer() : nullptr; | |||
auto* peer = isOnDesktop() ? getPeer() : nullptr; | |||
if (peer != nullptr) | |||
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); | |||
const Rectangle<int> onScreenArea (allMonitors.getBounds()); | |||
auto onScreenArea = allMonitors.getBounds(); | |||
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()), | |||
jmin (newPos.getHeight(), screen.getHeight())); | |||
@@ -32,14 +32,8 @@ class TopLevelWindowManager : private Timer, | |||
private DeletedAtShutdown | |||
{ | |||
public: | |||
TopLevelWindowManager() : currentActive (nullptr) | |||
{ | |||
} | |||
~TopLevelWindowManager() | |||
{ | |||
clearSingletonInstance(); | |||
} | |||
TopLevelWindowManager() {} | |||
~TopLevelWindowManager() { clearSingletonInstance(); } | |||
juce_DeclareSingleton_SingleThreaded_Minimal (TopLevelWindowManager) | |||
@@ -52,14 +46,14 @@ public: | |||
{ | |||
startTimer (jmin (1731, getTimerInterval() * 2)); | |||
TopLevelWindow* newActive = findCurrentlyActiveWindow(); | |||
auto* newActive = findCurrentlyActiveWindow(); | |||
if (newActive != currentActive) | |||
{ | |||
currentActive = newActive; | |||
for (int i = windows.size(); --i >= 0;) | |||
if (TopLevelWindow* tlw = windows[i]) | |||
if (auto* tlw = windows[i]) | |||
tlw->setWindowActive (isWindowActive (tlw)); | |||
Desktop::getInstance().triggerFocusCallback(); | |||
@@ -83,14 +77,14 @@ public: | |||
windows.removeFirstMatchingValue (w); | |||
if (windows.size() == 0) | |||
if (windows.isEmpty()) | |||
deleteInstance(); | |||
} | |||
Array<TopLevelWindow*> windows; | |||
private: | |||
TopLevelWindow* currentActive; | |||
TopLevelWindow* currentActive = nullptr; | |||
void timerCallback() override | |||
{ | |||
@@ -109,8 +103,8 @@ private: | |||
{ | |||
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) | |||
w = focusedComp->findParentComponentOfClass<TopLevelWindow>(); | |||
@@ -133,16 +127,13 @@ juce_ImplementSingleton_SingleThreaded (TopLevelWindowManager) | |||
void juce_checkCurrentlyFocusedTopLevelWindow(); | |||
void juce_checkCurrentlyFocusedTopLevelWindow() | |||
{ | |||
if (TopLevelWindowManager* const wm = TopLevelWindowManager::getInstanceWithoutCreating()) | |||
if (auto* wm = TopLevelWindowManager::getInstanceWithoutCreating()) | |||
wm->checkFocusAsync(); | |||
} | |||
//============================================================================== | |||
TopLevelWindow::TopLevelWindow (const String& name, const bool shouldAddToDesktop) | |||
: Component (name), | |||
useDropShadow (true), | |||
useNativeTitleBar (false), | |||
isCurrentlyActive (false) | |||
: Component (name) | |||
{ | |||
setOpaque (true); | |||
@@ -165,7 +156,7 @@ TopLevelWindow::~TopLevelWindow() | |||
//============================================================================== | |||
void TopLevelWindow::focusOfChildComponentChanged (FocusChangeType) | |||
{ | |||
TopLevelWindowManager* const wm = TopLevelWindowManager::getInstance(); | |||
auto* wm = TopLevelWindowManager::getInstance(); | |||
if (hasKeyboardFocus (true)) | |||
wm->checkFocus(); | |||
@@ -194,7 +185,7 @@ bool TopLevelWindow::isUsingNativeTitleBar() const noexcept | |||
void TopLevelWindow::visibilityChanged() | |||
{ | |||
if (isShowing()) | |||
if (ComponentPeer* p = getPeer()) | |||
if (auto* p = getPeer()) | |||
if ((p->getStyleFlags() & (ComponentPeer::windowIsTemporary | |||
| ComponentPeer::windowIgnoresKeyPresses)) == 0) | |||
toFront (true); | |||
@@ -302,10 +293,10 @@ void TopLevelWindow::centreAroundComponent (Component* c, const int width, const | |||
} | |||
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); | |||
parentArea = parent->getLocalBounds(); | |||
@@ -336,13 +327,13 @@ TopLevelWindow* TopLevelWindow::getActiveTopLevelWindow() noexcept | |||
for (int i = TopLevelWindow::getNumTopLevelWindows(); --i >= 0;) | |||
{ | |||
TopLevelWindow* const tlw = TopLevelWindow::getTopLevelWindow (i); | |||
auto* tlw = TopLevelWindow::getTopLevelWindow (i); | |||
if (tlw->isActiveWindow()) | |||
{ | |||
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) | |||
++numTWLParents; | |||
@@ -153,7 +153,7 @@ protected: | |||
private: | |||
friend class TopLevelWindowManager; | |||
friend class ResizableWindow; | |||
bool useDropShadow, useNativeTitleBar, isCurrentlyActive; | |||
bool useDropShadow = true, useNativeTitleBar = false, isCurrentlyActive = false; | |||
ScopedPointer<DropShadower> shadower; | |||
void setWindowActive (bool); | |||
@@ -61,8 +61,8 @@ CodeEditorComponent::ColourScheme CPlusPlusCodeTokeniser::getDefaultColourScheme | |||
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; | |||
} | |||
@@ -84,7 +84,7 @@ struct LuaTokeniserFunctions | |||
while (CppTokeniserFunctions::isIdentifierBody (source.peekNextChar())) | |||
{ | |||
const juce_wchar c = source.nextChar(); | |||
auto c = source.nextChar(); | |||
if (tokenLength < 20) | |||
possible.write (c); | |||
@@ -108,7 +108,7 @@ struct LuaTokeniserFunctions | |||
{ | |||
source.skipWhitespace(); | |||
const juce_wchar firstChar = source.peekNextChar(); | |||
auto firstChar = source.peekNextChar(); | |||
switch (firstChar) | |||
{ | |||
@@ -119,7 +119,7 @@ struct LuaTokeniserFunctions | |||
case '5': case '6': case '7': case '8': case '9': | |||
case '.': | |||
{ | |||
int result = CppTokeniserFunctions::parseNumber (source); | |||
auto result = CppTokeniserFunctions::parseNumber (source); | |||
if (result == LuaTokeniser::tokenType_error) | |||
{ | |||
@@ -157,7 +157,7 @@ struct LuaTokeniserFunctions | |||
case '-': | |||
{ | |||
source.skip(); | |||
int result = CppTokeniserFunctions::parseNumber (source); | |||
auto result = CppTokeniserFunctions::parseNumber (source); | |||
if (source.peekNextChar() == '-') | |||
{ | |||
@@ -231,8 +231,8 @@ CodeEditorComponent::ColourScheme LuaTokeniser::getDefaultColourScheme() | |||
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; | |||
} | |||
@@ -53,8 +53,8 @@ CodeEditorComponent::ColourScheme XmlTokeniser::getDefaultColourScheme() | |||
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; | |||
} | |||
@@ -66,7 +66,7 @@ static void skipToEndOfXmlDTD (Iterator& source) noexcept | |||
for (;;) | |||
{ | |||
const juce_wchar c = source.nextChar(); | |||
auto c = source.nextChar(); | |||
if (c == 0 || (c == '>' && lastWasQuestionMark)) | |||
break; | |||
@@ -78,11 +78,11 @@ static void skipToEndOfXmlDTD (Iterator& source) noexcept | |||
template <typename Iterator> | |||
static void skipToEndOfXmlComment (Iterator& source) noexcept | |||
{ | |||
juce_wchar last[2] = { 0 }; | |||
juce_wchar last[2] = {}; | |||
for (;;) | |||
{ | |||
const juce_wchar c = source.nextChar(); | |||
auto c = source.nextChar(); | |||
if (c == 0 || (c == '>' && last[0] == '-' && last[1] == '-')) | |||
break; | |||
@@ -95,7 +95,7 @@ static void skipToEndOfXmlComment (Iterator& source) noexcept | |||
int XmlTokeniser::readNextToken (CodeDocument::Iterator& source) | |||
{ | |||
source.skipWhitespace(); | |||
const juce_wchar firstChar = source.peekNextChar(); | |||
auto firstChar = source.peekNextChar(); | |||
switch (firstChar) | |||
{ | |||
@@ -110,7 +110,7 @@ int XmlTokeniser::readNextToken (CodeDocument::Iterator& source) | |||
{ | |||
source.skip(); | |||
source.skipWhitespace(); | |||
const juce_wchar nextChar = source.peekNextChar(); | |||
auto nextChar = source.peekNextChar(); | |||
if (nextChar == '?') | |||
{ | |||