Browse Source

Update juce and fix wrong channel count

tags/2018-04-16
falkTX 9 years ago
parent
commit
ee7a5c6f19
69 changed files with 789 additions and 566 deletions
  1. +2
    -0
      libs/juce-plugin/JucePluginMain.cpp
  2. +16
    -5
      libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
  3. +2
    -2
      libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h
  4. +12
    -2
      libs/juce/source/modules/juce_audio_basics/effects/juce_LinearSmoothedValue.h
  5. +25
    -0
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
  6. +6
    -0
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.h
  7. +2
    -2
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEInstrument.cpp
  8. +2
    -2
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.cpp
  9. +1
    -2
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.h
  10. +1
    -0
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.cpp
  11. +3
    -2
      libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.h
  12. +1
    -1
      libs/juce/source/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h
  13. +4
    -0
      libs/juce/source/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp
  14. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp
  15. +19
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp
  16. +4
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp
  17. +11
    -3
      libs/juce/source/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h
  18. +1
    -1
      libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
  19. +9
    -4
      libs/juce/source/modules/juce_audio_plugin_client/utility/juce_PluginHostType.h
  20. +1
    -1
      libs/juce/source/modules/juce_audio_processors/format/juce_AudioPluginFormat.h
  21. +14
    -0
      libs/juce/source/modules/juce_audio_processors/processors/juce_AudioChannelSet.cpp
  22. +4
    -0
      libs/juce/source/modules/juce_audio_processors/processors/juce_AudioChannelSet.h
  23. +0
    -126
      libs/juce/source/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
  24. +9
    -0
      libs/juce/source/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp
  25. +6
    -0
      libs/juce/source/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h
  26. +3
    -0
      libs/juce/source/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h
  27. +1
    -1
      libs/juce/source/modules/juce_core/containers/juce_Array.h
  28. +6
    -0
      libs/juce/source/modules/juce_core/containers/juce_OwnedArray.h
  29. +6
    -0
      libs/juce/source/modules/juce_core/containers/juce_ReferenceCountedArray.h
  30. +6
    -0
      libs/juce/source/modules/juce_core/containers/juce_SortedSet.h
  31. +1
    -1
      libs/juce/source/modules/juce_core/javascript/juce_Javascript.cpp
  32. +0
    -2
      libs/juce/source/modules/juce_core/native/java/AndroidRuntimePermissions.java
  33. +2
    -0
      libs/juce/source/modules/juce_core/native/java/JuceAppActivity.java
  34. +3
    -1
      libs/juce/source/modules/juce_core/native/juce_win32_Files.cpp
  35. +1
    -0
      libs/juce/source/modules/juce_core/system/juce_StandardHeader.h
  36. +0
    -6
      libs/juce/source/modules/juce_core/text/juce_CharPointer_ASCII.h
  37. +13
    -0
      libs/juce/source/modules/juce_core/text/juce_CharacterFunctions.cpp
  38. +3
    -0
      libs/juce/source/modules/juce_core/text/juce_CharacterFunctions.h
  39. +4
    -0
      libs/juce/source/modules/juce_core/text/juce_String.cpp
  40. +4
    -1
      libs/juce/source/modules/juce_core/text/juce_StringArray.h
  41. +18
    -20
      libs/juce/source/modules/juce_core/time/juce_Time.cpp
  42. +1
    -1
      libs/juce/source/modules/juce_core/zip/juce_ZipFile.cpp
  43. +14
    -14
      libs/juce/source/modules/juce_events/native/juce_linux_Messaging.cpp
  44. +2
    -2
      libs/juce/source/modules/juce_graphics/colour/juce_FillType.cpp
  45. +2
    -2
      libs/juce/source/modules/juce_graphics/images/juce_ImageCache.cpp
  46. +10
    -0
      libs/juce/source/modules/juce_graphics/juce_graphics.cpp
  47. +1
    -1
      libs/juce/source/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm
  48. +3
    -3
      libs/juce/source/modules/juce_graphics/native/juce_mac_Fonts.mm
  49. +12
    -5
      libs/juce/source/modules/juce_gui_basics/components/juce_Component.cpp
  50. +1
    -1
      libs/juce/source/modules/juce_gui_basics/drawables/juce_DrawableShape.cpp
  51. +1
    -1
      libs/juce/source/modules/juce_gui_basics/drawables/juce_SVGParser.cpp
  52. +1
    -1
      libs/juce/source/modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp
  53. +1
    -1
      libs/juce/source/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.cpp
  54. +0
    -4
      libs/juce/source/modules/juce_gui_basics/juce_gui_basics.cpp
  55. +99
    -0
      libs/juce/source/modules/juce_gui_basics/layout/juce_Viewport.cpp
  56. +16
    -0
      libs/juce/source/modules/juce_gui_basics/layout/juce_Viewport.h
  57. +5
    -6
      libs/juce/source/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp
  58. +258
    -283
      libs/juce/source/modules/juce_gui_basics/menus/juce_PopupMenu.cpp
  59. +69
    -19
      libs/juce/source/modules/juce_gui_basics/menus/juce_PopupMenu.h
  60. +1
    -1
      libs/juce/source/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.h
  61. +1
    -1
      libs/juce/source/modules/juce_gui_basics/native/juce_ios_Windowing.mm
  62. +2
    -2
      libs/juce/source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp
  63. +16
    -15
      libs/juce/source/modules/juce_gui_basics/native/juce_mac_MainMenu.mm
  64. +32
    -4
      libs/juce/source/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm
  65. +2
    -2
      libs/juce/source/modules/juce_gui_basics/native/juce_win32_Windowing.cpp
  66. +1
    -1
      libs/juce/source/modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp
  67. +1
    -1
      libs/juce/source/modules/juce_gui_basics/windows/juce_CallOutBox.cpp
  68. +2
    -2
      libs/juce/source/modules/juce_gui_extra/misc/juce_ColourSelector.cpp
  69. +8
    -5
      libs/juce/source/modules/juce_gui_extra/misc/juce_KeyMappingEditorComponent.cpp

+ 2
- 0
libs/juce-plugin/JucePluginMain.cpp View File

@@ -37,3 +37,5 @@
#if ! JucePlugin_Build_Standalone
#include "modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp"
#endif

#include "modules/juce_audio_processors/processors/juce_AudioProcessor_export.cpp"

+ 16
- 5
libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp View File

@@ -481,6 +481,17 @@ namespace FloatVectorHelpers
#endif
}
//==============================================================================
namespace
{
#if JUCE_USE_VDSP_FRAMEWORK
// This casts away constness to account for slightly different vDSP function signatures
// in OSX 10.8 SDK and below. Can be safely removed once those SDKs are obsolete.
template <typename ValueType>
ValueType* osx108sdkCompatibilityCast (const ValueType* arg) noexcept { return const_cast<ValueType*> (arg); }
#endif
}
//==============================================================================
void JUCE_CALLTYPE FloatVectorOperations::clear (float* dest, int num) noexcept
{
@@ -568,10 +579,10 @@ void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double amount, int
const Mode::ParallelType amountToAdd = Mode::load1 (amount);)
}
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float* src, float amount, int num) noexcept
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, float amount, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsadd (src, 1, &amount, dest, 1, (vDSP_Length) num);
vDSP_vsadd (osx108sdkCompatibilityCast (src), 1, &amount, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount, Mode::add (am, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
@@ -579,10 +590,10 @@ void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float* src, float am
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double* src, double amount, int num) noexcept
void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src, double amount, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsaddD (src, 1, &amount, dest, 1, (vDSP_Length) num);
vDSP_vsaddD (osx108sdkCompatibilityCast (src), 1, &amount, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount, Mode::add (am, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
@@ -990,7 +1001,7 @@ void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnab
void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport() noexcept
{
#if JUCE_USE_SSE_INTRINSICS
const int mxcsr = _mm_getcsr();
const unsigned int mxcsr = _mm_getcsr();
_mm_setcsr (mxcsr | 0x8040); // add the DAZ and FZ bits
#endif
}


+ 2
- 2
libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h View File

@@ -66,10 +66,10 @@ public:
static void JUCE_CALLTYPE add (double* dest, double amountToAdd, int numValues) noexcept;
/** Adds a fixed value to each source value and stores it in the destination array. */
static void JUCE_CALLTYPE add (float* dest, float* src, float amount, int numValues) noexcept;
static void JUCE_CALLTYPE add (float* dest, const float* src, float amount, int numValues) noexcept;
/** Adds a fixed value to each source value and stores it in the destination array. */
static void JUCE_CALLTYPE add (double* dest, double* src, double amount, int numValues) noexcept;
static void JUCE_CALLTYPE add (double* dest, const double* src, double amount, int numValues) noexcept;
/** Adds the source values to the destination values. */
static void JUCE_CALLTYPE add (float* dest, const float* src, int numValues) noexcept;


+ 12
- 2
libs/juce/source/modules/juce_audio_basics/effects/juce_LinearSmoothedValue.h View File

@@ -59,7 +59,6 @@ public:
countdown = 0;
}
//==============================================================================
/** Set a new target value. */
void setValue (FloatType newValue) noexcept
{
@@ -75,7 +74,6 @@ public:
}
}
//==============================================================================
/** Compute the next value. */
FloatType getNextValue() noexcept
{
@@ -87,6 +85,18 @@ public:
return currentValue;
}
/** Returns true if the current value is currently being interpolated. */
bool isSmoothing() const noexcept
{
return countdown > 0;
}
/** Returns the target value towards which the smoothed value is currently moving. */
FloatType getTargetValue() const noexcept
{
return target;
}
private:
//==============================================================================
FloatType currentValue, target, step;


+ 25
- 0
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp View File

@@ -309,6 +309,31 @@ uint8* MidiMessage::allocateSpace (int bytes)
return preallocatedData.asBytes;
}
String MidiMessage::getDescription() const
{
if (isNoteOn()) return "Note on " + MidiMessage::getMidiNoteName (getNoteNumber(), true, true, 3) + " Velocity " + String (getVelocity()) + " Channel " + String (getChannel());
if (isNoteOff()) return "Note off " + MidiMessage::getMidiNoteName (getNoteNumber(), true, true, 3) + " Velocity " + String (getVelocity()) + " Channel " + String (getChannel());
if (isProgramChange()) return "Program change " + String (getProgramChangeNumber()) + " Channel " + String (getChannel());
if (isPitchWheel()) return "Pitch wheel " + String (getPitchWheelValue()) + " Channel " + String (getChannel());
if (isAftertouch()) return "Aftertouch " + MidiMessage::getMidiNoteName (getNoteNumber(), true, true, 3) + ": " + String (getAfterTouchValue()) + " Channel " + String (getChannel());
if (isChannelPressure()) return "Channel pressure " + String (getChannelPressureValue()) + " Channel " + String (getChannel());
if (isAllNotesOff()) return "All notes off Channel " + String (getChannel());
if (isAllSoundOff()) return "All sound off Channel " + String (getChannel());
if (isMetaEvent()) return "Meta event";
if (isController())
{
String name (MidiMessage::getControllerName (getControllerNumber()));
if (name.isEmpty())
name = String (getControllerNumber());
return "Controller " + name + ": " + String (getControllerValue()) + " Channel " + String (getChannel());
}
return String::toHexString (getRawData(), getRawDataSize());
}
int MidiMessage::getChannel() const noexcept
{
const uint8* const data = getRawData();


+ 6
- 0
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.h View File

@@ -125,6 +125,12 @@ public:
*/
int getRawDataSize() const noexcept { return size; }
//==============================================================================
/** Returns a human-readable description of the midi message as a string,
for example "Note On C#3 Velocity 120 Channel 1".
*/
String getDescription() const;
//==============================================================================
/** Returns the timestamp associated with this message.


+ 2
- 2
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEInstrument.cpp View File

@@ -324,7 +324,7 @@ void MPEInstrument::noteOff (int midiChannel,
int midiNoteNumber,
MPEValue midiNoteOffVelocity)
{
if (notes.empty() || ! isNoteChannel (midiChannel))
if (notes.isEmpty() || ! isNoteChannel (midiChannel))
return;
const ScopedLock sl (lock);
@@ -375,7 +375,7 @@ void MPEInstrument::updateDimension (int midiChannel, MPEDimension& dimension, M
{
dimension.lastValueReceivedOnChannel[midiChannel - 1] = value;
if (notes.empty())
if (notes.isEmpty())
return;
if (MPEZone* zone = zoneLayout.getZoneByMasterChannel (midiChannel))


+ 2
- 2
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.cpp View File

@@ -103,7 +103,7 @@ void MPESynthesiserBase::renderNextBlock (AudioBuffer<floatType>& outputAudio,
int midiEventPos;
MidiMessage m;
const ScopedLock sl (renderAudioLock);
const ScopedLock sl (noteStateLock);
while (numSamples > 0)
{
@@ -147,7 +147,7 @@ void MPESynthesiserBase::setCurrentPlaybackSampleRate (const double newRate)
{
if (sampleRate != newRate)
{
const ScopedLock sl (renderAudioLock);
const ScopedLock sl (noteStateLock);
instrument->releaseAllNotes();
sampleRate = newRate;
}


+ 1
- 2
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.h View File

@@ -179,11 +179,10 @@ protected:
//==============================================================================
/** @internal */
ScopedPointer<MPEInstrument> instrument;
/** @internal */
CriticalSection renderAudioLock;
private:
//==============================================================================
CriticalSection noteStateLock;
double sampleRate;
int minimumSubBlockSize;


+ 1
- 0
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.cpp View File

@@ -34,6 +34,7 @@ MPEZoneLayout::MPEZoneLayout (const MPEZoneLayout& other)
MPEZoneLayout& MPEZoneLayout::operator= (const MPEZoneLayout& other)
{
zones = other.zones;
listeners.call (&MPEZoneLayout::Listener::zoneLayoutChanged, *this);
return *this;
}


+ 3
- 2
libs/juce/source/modules/juce_audio_basics/mpe/juce_MPEZoneLayout.h View File

@@ -100,8 +100,9 @@ public:
/** Returns the current number of MPE zones. */
int getNumZones() const noexcept;
/** Returns a pointer to the MPE zone at the given index,
or nullptr if there is no such zone.
/** Returns a pointer to the MPE zone at the given index, or nullptr if there
is no such zone. Zones are sorted by insertion order (most recently added
zone last).
*/
MPEZone* getZoneByIndex (int index) const noexcept;


+ 1
- 1
libs/juce/source/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h View File

@@ -30,7 +30,7 @@
/**
A type of AudioSource that takes an input source and changes its sample rate.
@see AudioSource
@see AudioSource, LagrangeInterpolator, CatmullRomInterpolator
*/
class JUCE_API ResamplingAudioSource : public AudioSource
{


+ 4
- 0
libs/juce/source/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp View File

@@ -171,6 +171,10 @@ namespace CoreMidiHelpers
static StringArray findDevices (const bool forInput)
{
// It seems that OSX can be a bit picky about the thread that's first used to
// search for devices. It's safest to use the message thread for calling this.
jassert (MessageManager::getInstance()->isThisTheMessageThread());
const ItemCount num = forInput ? MIDIGetNumberOfSources()
: MIDIGetNumberOfDestinations();
StringArray s;


+ 1
- 1
libs/juce/source/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp View File

@@ -29,7 +29,7 @@ namespace FlacNamespace
#if JUCE_INCLUDE_FLAC_CODE || ! defined (JUCE_INCLUDE_FLAC_CODE)
#undef VERSION
#define VERSION "1.2.1"
#define VERSION "1.3.1"
#define FLAC__NO_DLL 1


+ 19
- 1
libs/juce/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp View File

@@ -646,6 +646,24 @@ namespace WavFileHelpers
return true;
}
static String getStringFromWindows1252Codepage (const uint8* data, size_t num)
{
HeapBlock<juce_wchar> unicode (num + 1);
for (size_t i = 0; i < num; ++i)
unicode[i] = CharacterFunctions::getUnicodeCharFromWindows1252Codepage (data[i]);
unicode[num] = 0;
return CharPointer_UTF32 (unicode);
}
static String getStringFromData (const MemoryBlock& mb)
{
return CharPointer_UTF8::isValidString ((const char*) mb.getData(), (int) mb.getSize())
? mb.toString()
: getStringFromWindows1252Codepage ((const uint8*) mb.getData(), mb.getSize());
}
static void addToMetadata (StringPairArray& values, InputStream& input, int64 chunkEnd)
{
while (input.getPosition() < chunkEnd)
@@ -664,7 +682,7 @@ namespace WavFileHelpers
{
MemoryBlock mb;
input.readIntoMemoryBlock (mb, (ssize_t) infoLength);
values.set (types[i], mb.toString());
values.set (types[i], getStringFromData (mb));
break;
}
}


+ 4
- 1
libs/juce/source/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp View File

@@ -166,6 +166,9 @@ public:
checkCoInitialiseCalled();
clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,
startSampleInFile, numSamples, lengthInSamples);
const int stride = numChannels * sizeof (int16);
while (numSamples > 0)
@@ -297,7 +300,7 @@ private:
sampleRate = inputFormat->nSamplesPerSec;
numChannels = inputFormat->nChannels;
bitsPerSample = inputFormat->wBitsPerSample;
bitsPerSample = inputFormat->wBitsPerSample != 0 ? inputFormat->wBitsPerSample : 16;
lengthInSamples = (lengthInNanoseconds * (int) sampleRate) / 10000000;
}
}


+ 11
- 3
libs/juce/source/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h View File

@@ -79,9 +79,17 @@ public:
jassert (processor != nullptr); // Your createPluginFilter() function must return a valid object!
AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Undefined);
processor->setPlayConfigDetails (JucePlugin_MaxNumInputChannels,
JucePlugin_MaxNumOutputChannels,
44100, 512);
// try to disable sidechain and aux buses
const int numInBuses = processor->busArrangement.inputBuses.size();
const int numOutBuses = processor->busArrangement.inputBuses.size();
for (int busIdx = 1; busIdx < numInBuses; ++busIdx)
processor->setPreferredBusArrangement (true, busIdx, AudioChannelSet::disabled());
for (int busIdx = 1; busIdx < numOutBuses; ++busIdx)
processor->setPreferredBusArrangement (false, busIdx, AudioChannelSet::disabled());
processor->setRateAndBufferSizeDetails(44100, 512);
}
virtual void deletePlugin()


+ 1
- 1
libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -258,7 +258,7 @@ public:
info.stepCount = 1;
info.defaultNormalizedValue = 0.0f;
info.unitId = Vst::kRootUnitId;
info.flags = Vst::ParameterInfo::kIsBypass;
info.flags = Vst::ParameterInfo::kIsBypass | Vst::ParameterInfo::kCanAutomate;
}
virtual ~BypassParam() {}


+ 9
- 4
libs/juce/source/modules/juce_audio_plugin_client/utility/juce_PluginHostType.h View File

@@ -45,6 +45,7 @@ public:
Ardour,
CakewalkSonar8,
CakewalkSonarGeneric,
DaVinciResolve,
DigidesignProTools,
DigitalPerformer,
FinalCut,
@@ -84,18 +85,21 @@ public:
bool isAbletonLive() const noexcept { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8 || type == AbletonLiveGeneric; }
bool isAdobeAudition() const noexcept { return type == AdobeAudition; }
bool isArdour() const noexcept { return type == Ardour; }
bool isDigitalPerformer() const noexcept { return type == DigitalPerformer; }
bool isCubase() const noexcept { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6 || type == SteinbergCubase7 || type == SteinbergCubase8 || type == SteinbergCubaseGeneric; }
bool isCubase7orLater() const noexcept { return isCubase() && ! (type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase6); }
bool isCubaseBridged() const noexcept { return type == SteinbergCubase5Bridged; }
bool isLogic() const noexcept { return type == AppleLogic; }
bool isDaVinciResolve() const noexcept { return type == DaVinciResolve; }
bool isDigitalPerformer() const noexcept { return type == DigitalPerformer; }
bool isFinalCut() const noexcept { return type == FinalCut; }
bool isFruityLoops() const noexcept { return type == FruityLoops; }
bool isLogic() const noexcept { return type == AppleLogic; }
bool isNuendo() const noexcept { return type == SteinbergNuendo3 || type == SteinbergNuendo4 || type == SteinbergNuendo5 || type == SteinbergNuendoGeneric; }
bool isPremiere() const noexcept { return type == AdobePremierePro; }
bool isProTools() const noexcept { return type == DigidesignProTools; }
bool isPyramix() const noexcept { return type == MergingPyramix; }
bool isReceptor() const noexcept { return type == MuseReceptorGeneric; }
bool isReaper() const noexcept { return type == Reaper; }
bool isRenoise() const noexcept { return type == Renoise; }
bool isSamplitude() const noexcept { return type == MagixSamplitude; }
bool isSonar() const noexcept { return type == CakewalkSonar8 || type == CakewalkSonarGeneric; }
bool isSteinbergTestHost() const noexcept { return type == SteinbergTestHost; }
@@ -106,8 +110,6 @@ public:
bool isWaveBurner() const noexcept { return type == WaveBurner; }
bool isWavelab() const noexcept { return isWavelabLegacy() || type == SteinbergWavelab7 || type == SteinbergWavelab8 || type == SteinbergWavelabGeneric; }
bool isWavelabLegacy() const noexcept { return type == SteinbergWavelab5 || type == SteinbergWavelab6; }
bool isRenoise() const noexcept { return type == Renoise; }
bool isProTools() const noexcept { return type == DigidesignProTools; }
//==============================================================================
const char* getHostDescription() const noexcept
@@ -123,6 +125,7 @@ public:
case AppleLogic: return "Apple Logic";
case CakewalkSonar8: return "Cakewalk Sonar 8";
case CakewalkSonarGeneric: return "Cakewalk Sonar";
case DaVinciResolve: return "DaVinci Resolve";
case DigidesignProTools: return "ProTools";
case DigitalPerformer: return "DigitalPerformer";
case FinalCut: return "Final Cut";
@@ -203,6 +206,7 @@ private:
if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3;
if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric;
if (hostFilename.containsIgnoreCase ("Renoise")) return Renoise;
if (hostFilename.containsIgnoreCase ("Resolve")) return DaVinciResolve;
#elif JUCE_WINDOWS
if (hostFilename.containsIgnoreCase ("Live 6.")) return AbletonLive6;
@@ -241,6 +245,7 @@ private:
if (hostPath.containsIgnoreCase ("Merging Technologies")) return MergingPyramix;
if (hostFilename.startsWithIgnoreCase ("Sam")) return MagixSamplitude;
if (hostFilename.containsIgnoreCase ("Renoise")) return Renoise;
if (hostFilename.containsIgnoreCase ("Resolve")) return DaVinciResolve;
#elif JUCE_LINUX
if (hostFilename.containsIgnoreCase ("Ardour")) return Ardour;


+ 1
- 1
libs/juce/source/modules/juce_audio_processors/format/juce_AudioPluginFormat.h View File

@@ -30,7 +30,7 @@
/**
The base class for a type of plugin format, such as VST, AudioUnit, LADSPA, etc.
@see AudioFormatManager
@see AudioPluginFormatManager
*/
class JUCE_API AudioPluginFormat
{


+ 14
- 0
libs/juce/source/modules/juce_audio_processors/processors/juce_AudioChannelSet.cpp View File

@@ -135,6 +135,20 @@ AudioChannelSet::ChannelType AudioChannelSet::getTypeOfChannel (int index) const
return static_cast<ChannelType> (bit);
}
int AudioChannelSet::getChannelIndexForType (AudioChannelSet::ChannelType type) const noexcept
{
int idx = 0;
for (int bit = channels.findNextSetBit (0); bit >= 0; bit = channels.findNextSetBit (bit + 1))
{
if (static_cast<ChannelType> (bit) == type)
return idx;
idx++;
}
return -1;
}
Array<AudioChannelSet::ChannelType> AudioChannelSet::getChannelTypes() const
{
Array<ChannelType> result;


+ 4
- 0
libs/juce/source/modules/juce_audio_processors/processors/juce_AudioChannelSet.h View File

@@ -166,6 +166,10 @@ public:
/** Returns the type of one of the channels in the set, by index. */
ChannelType getTypeOfChannel (int channelIndex) const noexcept;
/** Returns the index for a particular channel-type.
Will return -1 if the this set does not contain a channel of this type. */
int getChannelIndexForType (ChannelType type) const noexcept;
/** Returns a string containing a whitespace-separated list of speaker types
corresponding to each channel. For example in a 5.1 arrangement,
the string may be "L R C Lfe Ls Rs". If the speaker arrangement is unknown,


+ 0
- 126
libs/juce/source/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp View File

@@ -22,48 +22,6 @@
==============================================================================
*/
static ThreadLocalValue<AudioProcessor::WrapperType> wrapperTypeBeingCreated;
void JUCE_CALLTYPE AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::WrapperType type)
{
wrapperTypeBeingCreated = type;
}
AudioProcessor::AudioProcessor()
: wrapperType (wrapperTypeBeingCreated.get()),
playHead (nullptr),
currentSampleRate (0),
blockSize (0),
latencySamples (0),
#if JUCE_DEBUG
textRecursionCheck (false),
#endif
suspended (false),
nonRealtime (false),
processingPrecision (singlePrecision)
{
#ifdef JucePlugin_PreferredChannelConfigurations
const short channelConfigs[][2] = { JucePlugin_PreferredChannelConfigurations };
#else
const short channelConfigs[][2] = { {2, 2} };
#endif
#if ! JucePlugin_IsMidiEffect
#if ! JucePlugin_IsSynth
busArrangement.inputBuses.add (AudioProcessorBus ("Input", AudioChannelSet::canonicalChannelSet (channelConfigs[0][0])));
#endif
busArrangement.outputBuses.add (AudioProcessorBus ("Output", AudioChannelSet::canonicalChannelSet (channelConfigs[0][1])));
#ifdef JucePlugin_PreferredChannelConfigurations
#if ! JucePlugin_IsSynth
AudioProcessor::setPreferredBusArrangement (true, 0, AudioChannelSet::stereo());
#endif
AudioProcessor::setPreferredBusArrangement (false, 0, AudioChannelSet::stereo());
#endif
#endif
updateSpeakerFormatStrings();
}
AudioProcessor::~AudioProcessor()
{
#if ! JUCE_AUDIO_PROCESSOR_NO_GUI
@@ -425,90 +383,6 @@ bool AudioProcessor::isInputChannelStereoPair (int index) const { return isS
bool AudioProcessor::isOutputChannelStereoPair (int index) const { return isStereoPair (busArrangement.outputBuses, index); }
//==============================================================================
bool AudioProcessor::setPreferredBusArrangement (bool isInput, int busIndex, const AudioChannelSet& preferredSet)
{
const int oldNumInputs = getTotalNumInputChannels();
const int oldNumOutputs = getTotalNumOutputChannels();
Array<AudioProcessorBus>& buses = isInput ? busArrangement.inputBuses : busArrangement.outputBuses;
const int numBuses = buses.size();
if (! isPositiveAndBelow (busIndex, numBuses))
return false;
AudioProcessorBus& bus = buses.getReference (busIndex);
#ifdef JucePlugin_PreferredChannelConfigurations
// the user is using the deprecated way to specify channel configurations
if (numBuses > 0 && busIndex == 0)
{
const short channelConfigs[][2] = { JucePlugin_PreferredChannelConfigurations };
const int numChannelConfigs = sizeof (channelConfigs) / sizeof (*channelConfigs);
// we need the main bus in the opposite direction
Array<AudioProcessorBus>& oppositeBuses = isInput ? busArrangement.outputBuses : busArrangement.inputBuses;
AudioProcessorBus* oppositeBus = (busIndex < oppositeBuses.size()) ? &oppositeBuses.getReference (0) : nullptr;
// get the target number of channels
const int mainBusNumChannels = preferredSet.size();
const int mainBusOppositeChannels = (oppositeBus != nullptr) ? oppositeBus->channels.size() : 0;
const int dir = isInput ? 0 : 1;
// find a compatible channel configuration on the opposite bus which is the closest match
// to the current number of channels on that bus
int distance = std::numeric_limits<int>::max();
int bestConfiguration = -1;
for (int i = 0; i < numChannelConfigs; ++i)
{
// is the configuration compatible with the preferred set
if (channelConfigs[i][dir] == mainBusNumChannels)
{
const int configChannels = channelConfigs[i][dir^1];
const int channelDifference = std::abs (configChannels - mainBusOppositeChannels);
if (channelDifference < distance)
{
distance = channelDifference;
bestConfiguration = configChannels;
// we can exit if we found a perfect match
if (distance == 0)
break;
}
}
}
// unable to find a good configuration
if (bestConfiguration == -1)
return false;
// did the number of channels change on the opposite bus?
if (mainBusOppositeChannels != bestConfiguration && oppositeBus != nullptr)
{
// if the channels on the opposite bus are the same as the preferred set
// then also copy over the layout information. If not, then assume
// a cononical channel layout
if (bestConfiguration == mainBusNumChannels)
oppositeBus->channels = preferredSet;
else
oppositeBus->channels = AudioChannelSet::canonicalChannelSet (bestConfiguration);
}
}
#endif
bus.channels = preferredSet;
if (oldNumInputs != getTotalNumInputChannels() || oldNumOutputs != getTotalNumOutputChannels())
{
updateSpeakerFormatStrings();
numChannelsChanged();
}
return true;
}
void AudioProcessor::disableNonMainBuses (bool isInput)
{
const Array<AudioProcessorBus>& buses = (isInput ? busArrangement.inputBuses : busArrangement.outputBuses);


+ 9
- 0
libs/juce/source/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp View File

@@ -1126,6 +1126,15 @@ bool AudioProcessorGraph::removeNode (const uint32 nodeId)
return false;
}
bool AudioProcessorGraph::removeNode (Node* node)
{
if (node != nullptr)
return removeNode (node->nodeId);
jassertfalse;
return false;
}
//==============================================================================
const AudioProcessorGraph::Connection* AudioProcessorGraph::getConnectionBetween (const uint32 sourceNodeId,
const int sourceChannelIndex,


+ 6
- 0
libs/juce/source/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h View File

@@ -183,6 +183,12 @@ public:
*/
bool removeNode (uint32 nodeId);
/** Deletes a node within the graph which has the specified ID.
This will also delete any connections that are attached to this node.
*/
bool removeNode (Node* node);
//==============================================================================
/** Returns the number of connections in the graph. */
int getNumConnections() const { return connections.size(); }


+ 3
- 0
libs/juce/source/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h View File

@@ -149,6 +149,7 @@ public:
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
ScopedPointer<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderAttachment)
};
@@ -172,6 +173,7 @@ public:
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
ScopedPointer<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComboBoxAttachment)
};
@@ -195,6 +197,7 @@ public:
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
ScopedPointer<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonAttachment)
};


+ 1
- 1
libs/juce/source/modules/juce_core/containers/juce_Array.h View File

@@ -223,7 +223,7 @@ public:
}
/** Returns true if the array is empty, false otherwise. */
inline bool empty() const noexcept
inline bool isEmpty() const noexcept
{
return size() == 0;
}


+ 6
- 0
libs/juce/source/modules/juce_core/containers/juce_OwnedArray.h View File

@@ -126,6 +126,12 @@ public:
return numUsed;
}
/** Returns true if the array is empty, false otherwise. */
inline bool isEmpty() const noexcept
{
return size() == 0;
}
/** Returns a pointer to the object at this index in the array.
If the index is out-of-range, this will return a null pointer, (and


+ 6
- 0
libs/juce/source/modules/juce_core/containers/juce_ReferenceCountedArray.h View File

@@ -149,6 +149,12 @@ public:
return numUsed;
}
/** Returns true if the array is empty, false otherwise. */
inline bool isEmpty() const noexcept
{
return size() == 0;
}
/** Returns a pointer to the object at this index in the array.
If the index is out-of-range, this will return a null pointer, (and


+ 6
- 0
libs/juce/source/modules/juce_core/containers/juce_SortedSet.h View File

@@ -136,6 +136,12 @@ public:
return data.size();
}
/** Returns true if the set is empty, false otherwise. */
inline bool isEmpty() const noexcept
{
return size() == 0;
}
/** Returns one of the elements in the set.
If the index passed in is beyond the range of valid elements, this


+ 1
- 1
libs/juce/source/modules/juce_core/javascript/juce_Javascript.cpp View File

@@ -1362,7 +1362,7 @@ struct JavascriptEngine::RootObject : public DynamicObject
{
ScopedPointer<FunctionCall> f (new FunctionCall (location));
f->object = new UnqualifiedName (location, "typeof");
f->arguments.add (parseExpression());
f->arguments.add (parseUnary());
return f.release();
}


+ 0
- 2
libs/juce/source/modules/juce_core/native/java/AndroidRuntimePermissions.java View File

@@ -1,5 +1,3 @@
private native void androidRuntimePermissionsCallback (boolean permissionWasGranted, long ptrToCallback);
@Override
public void onRequestPermissionsResult (int permissionID, String permissions[], int[] grantResults)
{


+ 2
- 0
libs/juce/source/modules/juce_core/native/java/JuceAppActivity.java View File

@@ -136,6 +136,8 @@ public class JuceAppActivity extends Activity
}
}
private native void androidRuntimePermissionsCallback (boolean permissionWasGranted, long ptrToCallback);
$$JuceAndroidRuntimePermissionsCode$$ // If you get an error here, you need to re-save your project with the introjucer!
//==============================================================================


+ 3
- 1
libs/juce/source/modules/juce_core/native/juce_win32_Files.cpp View File

@@ -524,7 +524,9 @@ bool File::isOnHardDisk() const
if (fullPath.toLowerCase()[0] <= 'b' && fullPath[1] == ':')
return n != DRIVE_REMOVABLE;
return n != DRIVE_CDROM && n != DRIVE_REMOTE;
return n != DRIVE_CDROM
&& n != DRIVE_REMOTE
&& n != DRIVE_NO_ROOT_DIR;
}
bool File::isOnRemovableDrive() const


+ 1
- 0
libs/juce/source/modules/juce_core/system/juce_StandardHeader.h View File

@@ -50,6 +50,7 @@
//==============================================================================
#include <memory>
#include <vector> // included before platform defs to provide a definition of _LIBCPP_VERSION
#include "juce_CompilerSupport.h"


+ 0
- 6
libs/juce/source/modules/juce_core/text/juce_CharPointer_ASCII.h View File

@@ -215,12 +215,6 @@ public:
CharacterFunctions::copyAll (*this, src);
}
/** Copies a source string to this pointer, advancing this pointer as it goes. */
void writeAll (const CharPointer_ASCII src) noexcept
{
strcpy (data, src.data);
}
/** Copies a source string to this pointer, advancing this pointer as it goes.
The maxDestBytes parameter specifies the maximum number of bytes that can be written
to the destination buffer before stopping.


+ 13
- 0
libs/juce/source/modules/juce_core/text/juce_CharacterFunctions.cpp View File

@@ -162,3 +162,16 @@ double CharacterFunctions::mulexp10 (const double value, int exponent) noexcept
return negative ? (value / result) : (value * result);
}
juce_wchar CharacterFunctions::getUnicodeCharFromWindows1252Codepage (const uint8 c) noexcept
{
if (c < 0x80 || c >= 0xa0)
return (juce_wchar) c;
static const uint16 lookup[] = { 0x20AC, 0x0007, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0007, 0x017D, 0x0007,
0x0007, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0007, 0x017E, 0x0178 };
return (juce_wchar) lookup[c - 0x80];
}

+ 3
- 0
libs/juce/source/modules/juce_core/text/juce_CharacterFunctions.h View File

@@ -123,6 +123,9 @@ public:
/** Returns 0 to 16 for '0' to 'F", or -1 for characters that aren't a legal hex digit. */
static int getHexDigitValue (juce_wchar digit) noexcept;
/** Converts a byte of Windows 1252 codepage to unicode. */
static juce_wchar getUnicodeCharFromWindows1252Codepage (uint8 windows1252Char) noexcept;
//==============================================================================
/** Parses a character string to read a floating-point number.
Note that this will advance the pointer that is passed in, leaving it at


+ 4
- 0
libs/juce/source/modules/juce_core/text/juce_String.cpp View File

@@ -1387,6 +1387,10 @@ String String::replaceCharacter (const juce_wchar charToReplace, const juce_wcha
String String::replaceCharacters (StringRef charactersToReplace, StringRef charactersToInsertInstead) const
{
// Each character in the first string must have a matching one in the
// second, so the two strings must be the same length.
jassert (charactersToReplace.length() == charactersToInsertInstead.length());
StringCreationHelper builder (text);
for (;;)


+ 4
- 1
libs/juce/source/modules/juce_core/text/juce_StringArray.h View File

@@ -118,7 +118,10 @@ public:
//==============================================================================
/** Returns the number of strings in the array */
inline int size() const noexcept { return strings.size(); };
inline int size() const noexcept { return strings.size(); }
/** Returns true if the array is empty, false otherwise. */
inline bool isEmpty() const noexcept { return size() == 0; }
/** Returns one of the strings from the array.


+ 18
- 20
libs/juce/source/modules/juce_core/time/juce_Time.cpp View File

@@ -136,15 +136,16 @@ namespace TimeHelpers
static inline int daysFromJan1 (int year, int month) noexcept
{
const short dayOfYear[] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
const short dayOfYear[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
return dayOfYear [(isLeapYear (year) ? 12 : 0) + month];
}
static inline int64 daysFromYear0 (int year) noexcept
{
return 365 * (year - 1) + (year / 400) - (year / 100) + (year / 4);
--year;
return 365 * year + (year / 400) - (year / 100) + (year / 4);
}
static inline int64 daysFrom1970 (int year) noexcept
@@ -213,18 +214,9 @@ Time::Time (const int year,
t.tm_sec = seconds;
t.tm_isdst = -1;
const int64 time = useLocalTime ? (int64) mktime (&t)
: TimeHelpers::mktime_utc (t);
if (time >= 0)
{
millisSinceEpoch = 1000 * time + milliseconds;
}
else
{
jassertfalse; // trying to create a date that is beyond the range that mktime supports!
millisSinceEpoch = 0;
}
millisSinceEpoch = 1000 * (useLocalTime ? (int64) mktime (&t)
: TimeHelpers::mktime_utc (t))
+ milliseconds;
}
Time::~Time() noexcept
@@ -458,8 +450,8 @@ String Time::getUTCOffsetString (bool includeSemiColon) const
String Time::toISO8601 (bool includeDividerCharacters) const
{
return String::formatted (includeDividerCharacters ? "%04d-%02d-%02dT%02d:%02d:%02.03f"
: "%04d%02d%02dT%02d%02d%02.03f",
return String::formatted (includeDividerCharacters ? "%04d-%02d-%02dT%02d:%02d:%06.03f"
: "%04d%02d%02dT%02d%02d%06.03f",
getYear(),
getMonth() + 1,
getDayOfMonth(),
@@ -542,9 +534,7 @@ Time Time::fromISO8601 (StringRef iso) noexcept
return Time();
}
Time result (year, month - 1, day, hours, minutes, 0, 0, false);
result.millisSinceEpoch += milliseconds;
return result;
return Time (year, month - 1, day, hours, minutes, 0, milliseconds, false);
}
String Time::getMonthName (const bool threeLetterVersion) const
@@ -661,6 +651,14 @@ public:
expect (Time::fromISO8601 ("2016-02-16T15:03:57.999-02:30") == Time (2016, 1, 16, 17, 33, 57, 999, false));
expect (Time::fromISO8601 ("20160216T150357.999-0230") == Time (2016, 1, 16, 17, 33, 57, 999, false));
expect (Time (1970, 0, 1, 0, 0, 0, 0, false) == Time (0));
expect (Time (2106, 1, 7, 6, 28, 15, 0, false) == Time (4294967295000));
expect (Time (2007, 10, 7, 1, 7, 20, 0, false) == Time (1194397640000));
expect (Time (2038, 0, 19, 3, 14, 7, 0, false) == Time (2147483647000));
expect (Time (2016, 2, 7, 11, 20, 8, 0, false) == Time (1457349608000));
expect (Time (1969, 11, 31, 23, 59, 59, 0, false) == Time (-1000));
expect (Time (1901, 11, 13, 20, 45, 53, 0, false) == Time (-2147483647000));
expect (Time (1982, 1, 1, 12, 0, 0, 0, true) + RelativeTime::days (365) == Time (1983, 1, 1, 12, 0, 0, 0, true));
expect (Time (1970, 1, 1, 12, 0, 0, 0, true) + RelativeTime::days (365) == Time (1971, 1, 1, 12, 0, 0, 0, true));
expect (Time (2038, 1, 1, 12, 0, 0, 0, true) + RelativeTime::days (365) == Time (2039, 1, 1, 12, 0, 0, 0, true));


+ 1
- 1
libs/juce/source/modules/juce_core/zip/juce_ZipFile.cpp View File

@@ -60,7 +60,7 @@ private:
const int day = date & 31;
const int hours = time >> 11;
const int minutes = (time >> 5) & 63;
const int seconds = (time & 31) << 1;
const int seconds = (int) ((time & 31) << 1);
return Time (year, month, day, hours, minutes, seconds);
}


+ 14
- 14
libs/juce/source/modules/juce_events/native/juce_linux_Messaging.cpp View File

@@ -357,13 +357,13 @@ void MessageManager::doPlatformSpecificShutdown()
bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message)
{
if (LinuxErrorHandling::errorOccurred)
return false;
if (InternalMessageQueue* const queue = InternalMessageQueue::getInstanceWithoutCreating())
if (! LinuxErrorHandling::errorOccurred)
{
queue->postMessage (message);
return true;
if (InternalMessageQueue* queue = InternalMessageQueue::getInstanceWithoutCreating())
{
queue->postMessage (message);
return true;
}
}
return false;
@@ -389,16 +389,16 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMes
break;
}
InternalMessageQueue* const queue = InternalMessageQueue::getInstanceWithoutCreating();
jassert (queue != nullptr);
if (queue->dispatchNextEvent())
return true;
if (InternalMessageQueue* queue = InternalMessageQueue::getInstanceWithoutCreating())
{
if (queue->dispatchNextEvent())
return true;
if (returnIfNoPendingMessages)
break;
if (returnIfNoPendingMessages)
break;
queue->sleepUntilEvent (2000);
queue->sleepUntilEvent (2000);
}
}
return false;


+ 2
- 2
libs/juce/source/modules/juce_graphics/colour/juce_FillType.cpp View File

@@ -104,7 +104,7 @@ bool FillType::operator!= (const FillType& other) const
void FillType::setColour (Colour newColour) noexcept
{
gradient = nullptr;
image = Image::null;
image = Image();
colour = newColour;
}
@@ -116,7 +116,7 @@ void FillType::setGradient (const ColourGradient& newGradient)
}
else
{
image = Image::null;
image = Image();
gradient = new ColourGradient (newGradient);
colour = Colours::black;
}


+ 2
- 2
libs/juce/source/modules/juce_graphics/images/juce_ImageCache.cpp View File

@@ -47,7 +47,7 @@ public:
return item->image;
}
return Image::null;
return Image();
}
void addImageToCache (const Image& image, const int64 hashCode)
@@ -128,7 +128,7 @@ Image ImageCache::getFromHashCode (const int64 hashCode)
if (Pimpl::getInstanceWithoutCreating() != nullptr)
return Pimpl::getInstanceWithoutCreating()->getFromHashCode (hashCode);
return Image::null;
return Image();
}
void ImageCache::addImageToCache (const Image& image, const int64 hashCode)


+ 10
- 0
libs/juce/source/modules/juce_graphics/juce_graphics.cpp View File

@@ -44,6 +44,12 @@
#import <QuartzCore/QuartzCore.h>
#elif JUCE_WINDOWS
// get rid of some warnings in Window's own headers
#ifdef JUCE_MSVC
#pragma warning (push)
#pragma warning (disable : 4458)
#endif
#if JUCE_MINGW && JUCE_USE_DIRECTWRITE
#warning "DirectWrite not currently implemented with mingw..."
#undef JUCE_USE_DIRECTWRITE
@@ -62,6 +68,10 @@
#include <malloc.h>
#endif
#ifdef JUCE_MSVC
#pragma warning (pop)
#endif
#elif JUCE_IOS
#import <QuartzCore/QuartzCore.h>
#import <CoreText/CoreText.h>


+ 1
- 1
libs/juce/source/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm View File

@@ -863,7 +863,7 @@ Image juce_loadWithCoreImage (InputStream& input)
}
}
return Image::null;
return Image();
}
#endif


+ 3
- 3
libs/juce/source/modules/juce_graphics/native/juce_mac_Fonts.mm View File

@@ -245,9 +245,9 @@ namespace CoreTextTypeLayout
{
switch (text.getReadingDirection())
{
case AttributedString::ReadingDirection::rightToLeft: return kCTWritingDirectionRightToLeft;
case AttributedString::ReadingDirection::leftToRight: return kCTWritingDirectionLeftToRight;
default: return kCTWritingDirectionNatural;
case AttributedString::rightToLeft: return kCTWritingDirectionRightToLeft;
case AttributedString::leftToRight: return kCTWritingDirectionLeftToRight;
default: return kCTWritingDirectionNatural;
}
}


+ 12
- 5
libs/juce/source/modules/juce_gui_basics/components/juce_Component.cpp View File

@@ -438,6 +438,15 @@ struct Component::ComponentHelpers
return Desktop::getInstance().getDisplays().getMainDisplay().userArea;
}
static void releaseAllCachedImageResources (Component& c)
{
if (CachedComponentImage* cached = c.getCachedComponentImage())
cached->releaseResources();
for (int i = c.getNumChildComponents(); --i >= 0;)
releaseAllCachedImageResources (*c.getChildComponent (i));
}
};
//==============================================================================
@@ -528,8 +537,7 @@ void Component::setVisible (bool shouldBeVisible)
if (! shouldBeVisible)
{
if (cachedImage != nullptr)
cachedImage->releaseResources();
ComponentHelpers::releaseAllCachedImageResources (*this);
if (currentlyFocusedComponent == this || isParentOf (currentlyFocusedComponent))
{
@@ -813,7 +821,7 @@ public:
bool invalidateAll() override { validArea.clear(); return true; }
bool invalidate (const Rectangle<int>& area) override { validArea.subtract (area); return true; }
void releaseResources() override { image = Image::null; }
void releaseResources() override { image = Image(); }
private:
Image image;
@@ -1547,8 +1555,7 @@ Component* Component::removeChildComponent (const int index, bool sendParentEven
childComponentList.remove (index);
child->parentComponent = nullptr;
if (child->cachedImage != nullptr)
child->cachedImage->releaseResources();
ComponentHelpers::releaseAllCachedImageResources (*child);
// (NB: there are obscure situations where child->isShowing() = false, but it still has the focus)
if (currentlyFocusedComponent == child || child->isParentOf (currentlyFocusedComponent))


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/drawables/juce_DrawableShape.cpp View File

@@ -190,7 +190,7 @@ void DrawableShape::strokeChanged()
strokePath.clear();
const float extraAccuracy = 4.0f;
if (dashLengths.empty())
if (dashLengths.isEmpty())
strokeType.createStrokedPath (strokePath, path, AffineTransform(), extraAccuracy);
else
strokeType.createDashedStroke (strokePath, path, dashLengths.getRawDataPointer(),


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/drawables/juce_SVGParser.cpp View File

@@ -905,7 +905,7 @@ private:
}
};
GetFillTypeOp op = { this, &path, opacity };
GetFillTypeOp op = { this, &path, opacity, FillType() };
if (topLevelXml.applyOperationToChildWithID (urlID, op))
return op.fillType;


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp View File

@@ -153,7 +153,7 @@ public:
file = newFile;
fileSize = newFileSize;
modTime = newModTime;
icon = Image::null;
icon = Image();
isDirectory = fileInfo != nullptr && fileInfo->isDirectory;
repaint();


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.cpp View File

@@ -57,7 +57,7 @@ void ImagePreviewComponent::timerCallback()
{
stopTimer();
currentThumbnail = Image::null;
currentThumbnail = Image();
currentDetails.clear();
repaint();


+ 0
- 4
libs/juce/source/modules/juce_gui_basics/juce_gui_basics.cpp View File

@@ -48,11 +48,7 @@
#import <IOKit/pwr_mgt/IOPMLib.h>
#if JUCE_SUPPORT_CARBON
#define Point CarbonDummyPointName
#define Component CarbonDummyCompName
#import <Carbon/Carbon.h> // still needed for SetSystemUIMode()
#undef Point
#undef Component
#endif
//==============================================================================


+ 99
- 0
libs/juce/source/modules/juce_gui_basics/layout/juce_Viewport.cpp View File

@@ -54,6 +54,7 @@ Viewport::Viewport (const String& name)
Viewport::~Viewport()
{
setScrollOnDragEnabled (false);
deleteOrRemoveContentComp();
}
@@ -180,6 +181,104 @@ void Viewport::componentMovedOrResized (Component&, bool, bool)
updateVisibleArea();
}
//==============================================================================
typedef AnimatedPosition<AnimatedPositionBehaviours::ContinuousWithMomentum> ViewportDragPosition;
struct Viewport::DragToScrollListener : private MouseListener,
private ViewportDragPosition::Listener
{
DragToScrollListener (Viewport& v)
: viewport (v), numTouches (0), isDragging (false)
{
viewport.contentHolder.addMouseListener (this, true);
offsetX.addListener (this);
offsetY.addListener (this);
}
~DragToScrollListener()
{
viewport.contentHolder.removeMouseListener (this);
}
void positionChanged (ViewportDragPosition&, double) override
{
viewport.setViewPosition (originalViewPos - Point<int> ((int) offsetX.getPosition(),
(int) offsetY.getPosition()));
}
void mouseDown (const MouseEvent&) override
{
++numTouches;
}
void mouseDrag (const MouseEvent& e) override
{
if (numTouches == 1)
{
Point<float> totalOffset = e.getOffsetFromDragStart().toFloat();
if (! isDragging && totalOffset.getDistanceFromOrigin() > 8.0f)
{
isDragging = true;
originalViewPos = viewport.getViewPosition();
offsetX.setPosition (0.0);
offsetX.beginDrag();
offsetY.setPosition (0.0);
offsetY.beginDrag();
}
if (isDragging)
{
offsetX.drag (totalOffset.x);
offsetY.drag (totalOffset.y);
}
}
}
void mouseUp (const MouseEvent&) override
{
if (--numTouches == 0)
{
offsetX.endDrag();
offsetY.endDrag();
isDragging = false;
}
jassert (numTouches >= 0);
}
Viewport& viewport;
ViewportDragPosition offsetX, offsetY;
Point<int> originalViewPos;
int numTouches;
bool isDragging;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DragToScrollListener)
};
void Viewport::setScrollOnDragEnabled (bool shouldScrollOnDrag)
{
if (isScrollOnDragEnabled() != shouldScrollOnDrag)
{
if (shouldScrollOnDrag)
dragToScrollListener = new DragToScrollListener (*this);
else
dragToScrollListener = nullptr;
}
}
bool Viewport::isScrollOnDragEnabled() const noexcept
{
return dragToScrollListener != nullptr;
}
bool Viewport::isCurrentlyScrollingOnDrag() const noexcept
{
return dragToScrollListener != nullptr && dragToScrollListener->isDragging;
}
//==============================================================================
void Viewport::lookAndFeelChanged()
{
if (! customScrollBarThickness)


+ 16
- 0
libs/juce/source/modules/juce_gui_basics/layout/juce_Viewport.h View File

@@ -241,6 +241,17 @@ public:
ScrollBar* getHorizontalScrollBar() noexcept { return &horizontalScrollBar; }
/** Enables or disables drag-to-scroll functionality in the viewport. */
void setScrollOnDragEnabled (bool shouldScrollOnDrag);
/** Returns true if drag-to-scroll functionality is enabled. */
bool isScrollOnDragEnabled() const noexcept;
/** Returns true if the user is currently dragging-to-scroll.
@see setScrollOnDragEnabled
*/
bool isCurrentlyScrollingOnDrag() const noexcept;
//==============================================================================
/** @internal */
void resized() override;
@@ -271,6 +282,11 @@ private:
Component contentHolder;
ScrollBar verticalScrollBar, horizontalScrollBar;
struct DragToScrollListener;
friend struct DragToScrollListener;
friend struct ContainerDeletePolicy<DragToScrollListener>;
ScopedPointer<DragToScrollListener> dragToScrollListener;
Point<int> viewportPosToCompPos (Point<int>) const;
void updateVisibleArea();


+ 5
- 6
libs/juce/source/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp View File

@@ -265,13 +265,12 @@ void LookAndFeel_V2::drawButtonText (Graphics& g, TextButton& button, bool /*isM
const int fontHeight = roundToInt (font.getHeight() * 0.6f);
const int leftIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnLeft() ? 4 : 2));
const int rightIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnRight() ? 4 : 2));
const int textWidth = button.getWidth() - leftIndent - rightIndent;
g.drawFittedText (button.getButtonText(),
leftIndent,
yIndent,
button.getWidth() - leftIndent - rightIndent,
button.getHeight() - yIndent * 2,
Justification::centred, 2);
if (textWidth > 0)
g.drawFittedText (button.getButtonText(),
leftIndent, yIndent, textWidth, button.getHeight() - yIndent * 2,
Justification::centred, 2);
}
void LookAndFeel_V2::drawTickBox (Graphics& g, Component& component,


+ 258
- 283
libs/juce/source/modules/juce_gui_basics/menus/juce_PopupMenu.cpp View File

@@ -22,120 +22,68 @@
==============================================================================
*/
//==============================================================================
namespace PopupMenuSettings
{
const int scrollZone = 24;
const int borderSize = 2;
const int timerInterval = 50;
const int dismissCommandId = 0x6287345f;
const int sectionHeaderID = 0x4734a34f;
static bool menuWasHiddenBecauseOfAppChange = false;
}
class PopupMenu::Item
//==============================================================================
struct PopupMenu::HelperClasses
{
public:
Item() : itemID (0), isActive (true), isSeparator (true), isTicked (false),
usesColour (false), commandManager (nullptr)
{}
Item (const int itemId,
const String& name,
const bool active,
const bool ticked,
Drawable* drawable,
const Colour colour,
const bool useColour,
CustomComponent* const custom,
const PopupMenu* const sub,
ApplicationCommandManager* const manager)
: itemID (itemId), text (name), textColour (colour),
isActive (active), isSeparator (false), isTicked (ticked),
usesColour (useColour), iconDrawable (drawable),
customComp (custom), subMenu (createCopyIfNotNull (sub)), commandManager (manager)
{
if (commandManager != nullptr && itemID != 0)
{
String shortcutKey;
const Array<KeyPress> keyPresses (commandManager->getKeyMappings()
->getKeyPressesAssignedToCommand (itemID));
for (int i = 0; i < keyPresses.size(); ++i)
{
const String key (keyPresses.getReference(i).getTextDescriptionWithIcons());
if (shortcutKey.isNotEmpty())
shortcutKey << ", ";
if (key.length() == 1 && key[0] < 128)
shortcutKey << "shortcut: '" << key << '\'';
else
shortcutKey << key;
}
class MouseSourceState;
class MenuWindow;
shortcutKey = shortcutKey.trim();
static bool canBeTriggered (const PopupMenu::Item& item) noexcept { return item.isEnabled && item.itemID != 0 && ! item.isSectionHeader; }
static bool hasActiveSubMenu (const PopupMenu::Item& item) noexcept { return item.isEnabled && item.subMenu != nullptr && item.subMenu->items.size() > 0; }
static const Colour* getColour (const PopupMenu::Item& item) noexcept { return item.colour != Colour (0x00000000) ? &item.colour : nullptr; }
static bool hasSubMenu (const PopupMenu::Item& item) noexcept { return item.subMenu != nullptr && (item.itemID == 0 || item.subMenu->getNumItems() > 0); }
if (shortcutKey.isNotEmpty())
text << "<end>" << shortcutKey;
}
//==============================================================================
struct HeaderItemComponent : public PopupMenu::CustomComponent
{
HeaderItemComponent (const String& name) : PopupMenu::CustomComponent (false)
{
setName (name);
}
Item (const Item& other)
: itemID (other.itemID),
text (other.text),
textColour (other.textColour),
isActive (other.isActive),
isSeparator (other.isSeparator),
isTicked (other.isTicked),
usesColour (other.usesColour),
iconDrawable (other.iconDrawable != nullptr ? other.iconDrawable->createCopy() : nullptr),
customComp (other.customComp),
subMenu (createCopyIfNotNull (other.subMenu.get())),
commandManager (other.commandManager)
{}
bool canBeTriggered() const noexcept { return isActive && itemID != 0 && itemID != PopupMenuSettings::sectionHeaderID; }
bool hasActiveSubMenu() const noexcept { return isActive && subMenu != nullptr && subMenu->items.size() > 0; }
//==============================================================================
const int itemID;
String text;
const Colour textColour;
const bool isActive, isSeparator, isTicked, usesColour;
ScopedPointer<Drawable> iconDrawable;
ReferenceCountedObjectPtr<CustomComponent> customComp;
ScopedPointer<PopupMenu> subMenu;
ApplicationCommandManager* const commandManager;
void paint (Graphics& g) override
{
getLookAndFeel().drawPopupMenuSectionHeader (g, getLocalBounds(), getName());
}
private:
Item& operator= (const Item&);
void getIdealSize (int& idealWidth, int& idealHeight) override
{
getLookAndFeel().getIdealPopupMenuItemSize (getName(), false, -1, idealWidth, idealHeight);
idealHeight += idealHeight / 2;
idealWidth += idealWidth / 4;
}
JUCE_LEAK_DETECTOR (Item)
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HeaderItemComponent)
};
//==============================================================================
struct PopupMenu::HelperClasses
struct ItemComponent : public Component
{
class MouseSourceState;
class MenuWindow;
//==============================================================================
class ItemComponent : public Component
{
public:
ItemComponent (const PopupMenu::Item& info, int standardItemHeight, MenuWindow& parent)
: itemInfo (info),
ItemComponent (const PopupMenu::Item& i, int standardItemHeight, MenuWindow& parent)
: item (i),
customComp (i.customComponent),
isHighlighted (false)
{
addAndMakeVisible (itemInfo.customComp);
if (item.isSectionHeader)
customComp = new HeaderItemComponent (item.text);
addAndMakeVisible (customComp);
parent.addAndMakeVisible (this);
updateShortcutKeyDescription();
int itemW = 80;
int itemH = 16;
getIdealSize (itemW, itemH, standardItemHeight);
@@ -146,45 +94,33 @@ public:
~ItemComponent()
{
removeChildComponent (itemInfo.customComp);
removeChildComponent (customComp);
}
void getIdealSize (int& idealWidth, int& idealHeight, const int standardItemHeight)
{
if (itemInfo.customComp != nullptr)
itemInfo.customComp->getIdealSize (idealWidth, idealHeight);
if (customComp != nullptr)
customComp->getIdealSize (idealWidth, idealHeight);
else
getLookAndFeel().getIdealPopupMenuItemSize (itemInfo.text,
itemInfo.isSeparator,
getLookAndFeel().getIdealPopupMenuItemSize (getTextForMeasurement(),
item.isSeparator,
standardItemHeight,
idealWidth, idealHeight);
}
void paint (Graphics& g) override
{
if (itemInfo.customComp == nullptr)
{
String mainText (itemInfo.text);
String endText;
const int endIndex = mainText.indexOf ("<end>");
if (endIndex >= 0)
{
endText = mainText.substring (endIndex + 5).trim();
mainText = mainText.substring (0, endIndex);
}
getLookAndFeel()
.drawPopupMenuItem (g, getLocalBounds(),
itemInfo.isSeparator,
itemInfo.isActive,
isHighlighted,
itemInfo.isTicked,
itemInfo.subMenu != nullptr && (itemInfo.itemID == 0 || itemInfo.subMenu->getNumItems() > 0),
mainText, endText,
itemInfo.iconDrawable,
itemInfo.usesColour ? &(itemInfo.textColour) : nullptr);
}
if (customComp == nullptr)
getLookAndFeel().drawPopupMenuItem (g, getLocalBounds(),
item.isSeparator,
item.isEnabled,
isHighlighted,
item.isTicked,
hasSubMenu (item),
item.text,
item.shortcutKeyDescription,
item.image,
getColour (item));
}
void resized() override
@@ -195,24 +131,57 @@ public:
void setHighlighted (bool shouldBeHighlighted)
{
shouldBeHighlighted = shouldBeHighlighted && itemInfo.isActive;
shouldBeHighlighted = shouldBeHighlighted && item.isEnabled;
if (isHighlighted != shouldBeHighlighted)
{
isHighlighted = shouldBeHighlighted;
if (itemInfo.customComp != nullptr)
itemInfo.customComp->setHighlighted (shouldBeHighlighted);
if (customComp != nullptr)
customComp->setHighlighted (shouldBeHighlighted);
repaint();
}
}
PopupMenu::Item itemInfo;
PopupMenu::Item item;
private:
// NB: we use a copy of the one from the item info in case we're using our own section comp
ReferenceCountedObjectPtr<CustomComponent> customComp;
bool isHighlighted;
void updateShortcutKeyDescription()
{
if (item.commandManager != nullptr && item.itemID != 0)
{
String shortcutKey;
const Array<KeyPress> keyPresses (item.commandManager->getKeyMappings()
->getKeyPressesAssignedToCommand (item.itemID));
for (int i = 0; i < keyPresses.size(); ++i)
{
const String key (keyPresses.getReference(i).getTextDescriptionWithIcons());
if (shortcutKey.isNotEmpty())
shortcutKey << ", ";
if (key.length() == 1 && key[0] < 128)
shortcutKey << "shortcut: '" << key << '\'';
else
shortcutKey << key;
}
item.shortcutKeyDescription = shortcutKey.trim();
}
}
String getTextForMeasurement() const
{
return item.shortcutKeyDescription.isNotEmpty() ? item.text + " " + item.shortcutKeyDescription
: item.text;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ItemComponent)
};
@@ -744,43 +713,43 @@ public:
for (int i = items.size(); --i >= 0;)
{
ItemComponent* const m = items.getUnchecked(i);
if (m != nullptr
&& m->itemInfo.itemID == itemID
&& windowPos.getHeight() > PopupMenuSettings::scrollZone * 4)
if (ItemComponent* const m = items.getUnchecked(i))
{
const int currentY = m->getY();
if (wantedY > 0 || currentY < 0 || m->getBottom() > windowPos.getHeight())
if (m->item.itemID == itemID
&& windowPos.getHeight() > PopupMenuSettings::scrollZone * 4)
{
if (wantedY < 0)
wantedY = jlimit (PopupMenuSettings::scrollZone,
jmax (PopupMenuSettings::scrollZone,
windowPos.getHeight() - (PopupMenuSettings::scrollZone + m->getHeight())),
currentY);
const int currentY = m->getY();
const Rectangle<int> mon (Desktop::getInstance().getDisplays()
.getDisplayContaining (windowPos.getPosition()).userArea);
if (wantedY > 0 || currentY < 0 || m->getBottom() > windowPos.getHeight())
{
if (wantedY < 0)
wantedY = jlimit (PopupMenuSettings::scrollZone,
jmax (PopupMenuSettings::scrollZone,
windowPos.getHeight() - (PopupMenuSettings::scrollZone + m->getHeight())),
currentY);
int deltaY = wantedY - currentY;
const Rectangle<int> mon (Desktop::getInstance().getDisplays()
.getDisplayContaining (windowPos.getPosition()).userArea);
windowPos.setSize (jmin (windowPos.getWidth(), mon.getWidth()),
jmin (windowPos.getHeight(), mon.getHeight()));
int deltaY = wantedY - currentY;
const int newY = jlimit (mon.getY(),
mon.getBottom() - windowPos.getHeight(),
windowPos.getY() + deltaY);
windowPos.setSize (jmin (windowPos.getWidth(), mon.getWidth()),
jmin (windowPos.getHeight(), mon.getHeight()));
deltaY -= newY - windowPos.getY();
const int newY = jlimit (mon.getY(),
mon.getBottom() - windowPos.getHeight(),
windowPos.getY() + deltaY);
childYOffset -= deltaY;
windowPos.setPosition (windowPos.getX(), newY);
deltaY -= newY - windowPos.getY();
updateYPositions();
}
childYOffset -= deltaY;
windowPos.setPosition (windowPos.getX(), newY);
break;
updateYPositions();
}
break;
}
}
}
}
@@ -877,9 +846,9 @@ public:
activeSubMenu = nullptr;
if (childComp != nullptr
&& childComp->itemInfo.hasActiveSubMenu())
&& hasActiveSubMenu (childComp->item))
{
activeSubMenu = new HelperClasses::MenuWindow (*(childComp->itemInfo.subMenu), this,
activeSubMenu = new HelperClasses::MenuWindow (*(childComp->item.subMenu), this,
options.withTargetScreenArea (childComp->getScreenBounds())
.withMinimumWidth (0)
.withTargetComponent (nullptr),
@@ -897,11 +866,11 @@ public:
void triggerCurrentlyHighlightedItem()
{
if (currentChild != nullptr
&& currentChild->itemInfo.canBeTriggered()
&& (currentChild->itemInfo.customComp == nullptr
|| currentChild->itemInfo.customComp->isTriggeredAutomatically()))
&& canBeTriggered (currentChild->item)
&& (currentChild->item.customComponent == nullptr
|| currentChild->item.customComponent->isTriggeredAutomatically()))
{
dismissMenu (&currentChild->itemInfo);
dismissMenu (&currentChild->item);
}
}
@@ -917,7 +886,7 @@ public:
if (ItemComponent* mic = items.getUnchecked ((start + items.size()) % items.size()))
{
if (mic->itemInfo.canBeTriggered() || mic->itemInfo.hasActiveSubMenu())
if (canBeTriggered (mic->item) || hasActiveSubMenu (mic->item))
{
setCurrentlyHighlightedChild (mic);
break;
@@ -973,7 +942,7 @@ public:
if (! window.windowIsStillValid())
return;
startTimer (PopupMenuSettings::timerInterval);
startTimerHz (20);
handleMousePosition (e.getScreenPosition());
}
@@ -1175,9 +1144,8 @@ private:
};
//==============================================================================
class NormalComponentWrapper : public PopupMenu::CustomComponent
struct NormalComponentWrapper : public PopupMenu::CustomComponent
{
public:
NormalComponentWrapper (Component* const comp, const int w, const int h,
const bool triggerMenuItemAutomaticallyWhenClicked)
: PopupMenu::CustomComponent (triggerMenuItemAutomaticallyWhenClicked),
@@ -1198,38 +1166,11 @@ public:
child->setBounds (getLocalBounds());
}
private:
const int width, height;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NormalComponentWrapper)
};
//==============================================================================
class HeaderItemComponent : public PopupMenu::CustomComponent
{
public:
HeaderItemComponent (const String& name)
: PopupMenu::CustomComponent (false)
{
setName (name);
}
void paint (Graphics& g) override
{
getLookAndFeel().drawPopupMenuSectionHeader (g, getLocalBounds(), getName());
}
void getIdealSize (int& idealWidth, int& idealHeight) override
{
getLookAndFeel().getIdealPopupMenuItemSize (getName(), false, -1, idealWidth, idealHeight);
idealHeight += idealHeight / 2;
idealWidth += idealWidth / 4;
}
private:
JUCE_LEAK_DETECTOR (HeaderItemComponent)
};
};
//==============================================================================
@@ -1282,14 +1223,70 @@ void PopupMenu::clear()
items.clear();
}
void PopupMenu::addItem (int itemResultID, const String& itemText, bool isActive, bool isTicked)
//==============================================================================
PopupMenu::Item::Item() noexcept
: itemID (0),
commandManager (nullptr),
colour (0x00000000),
isEnabled (true),
isTicked (false),
isSeparator (false),
isSectionHeader (false)
{
jassert (itemResultID != 0); // 0 is used as a return value to indicate that the user
// didn't pick anything, so you shouldn't use it as the id
// for an item..
}
items.add (new Item (itemResultID, itemText, isActive, isTicked, nullptr,
Colours::black, false, nullptr, nullptr, nullptr));
PopupMenu::Item::Item (const Item& other)
: text (other.text),
itemID (other.itemID),
subMenu (createCopyIfNotNull (other.subMenu.get())),
image (other.image != nullptr ? other.image->createCopy() : nullptr),
customComponent (other.customComponent),
commandManager (other.commandManager),
shortcutKeyDescription (other.shortcutKeyDescription),
colour (other.colour),
isEnabled (other.isEnabled),
isTicked (other.isTicked),
isSeparator (other.isSeparator),
isSectionHeader (other.isSectionHeader)
{
}
PopupMenu::Item& PopupMenu::Item::operator= (const Item& other)
{
text = other.text;
itemID = other.itemID;
subMenu = createCopyIfNotNull (other.subMenu.get());
image = (other.image != nullptr ? other.image->createCopy() : nullptr);
customComponent = other.customComponent;
commandManager = other.commandManager;
shortcutKeyDescription = other.shortcutKeyDescription;
colour = other.colour;
isEnabled = other.isEnabled;
isTicked = other.isTicked;
isSeparator = other.isSeparator;
isSectionHeader = other.isSectionHeader;
return *this;
}
void PopupMenu::addItem (const Item& newItem)
{
// An ID of 0 is used as a return value to indicate that the user
// didn't pick anything, so you shouldn't use it as the ID for an item..
jassert (newItem.itemID != 0
|| newItem.isSeparator || newItem.isSectionHeader
|| newItem.subMenu != nullptr);
items.add (new Item (newItem));
}
void PopupMenu::addItem (int itemResultID, const String& itemText, bool isActive, bool isTicked)
{
Item i;
i.text = itemText;
i.itemID = itemResultID;
i.isEnabled = isActive;
i.isTicked = isTicked;
addItem (i);
}
static Drawable* createDrawableFromImage (const Image& im)
@@ -1306,23 +1303,18 @@ static Drawable* createDrawableFromImage (const Image& im)
void PopupMenu::addItem (int itemResultID, const String& itemText, bool isActive, bool isTicked, const Image& iconToUse)
{
jassert (itemResultID != 0); // 0 is used as a return value to indicate that the user
// didn't pick anything, so you shouldn't use it as the id
// for an item..
items.add (new Item (itemResultID, itemText, isActive, isTicked, createDrawableFromImage (iconToUse),
Colours::black, false, nullptr, nullptr, nullptr));
addItem (itemResultID, itemText, isActive, isTicked, createDrawableFromImage (iconToUse));
}
void PopupMenu::addItem (int itemResultID, const String& itemText, bool isActive, bool isTicked, Drawable* iconToUse)
{
jassert (itemResultID != 0); // 0 is used as a return value to indicate that the user
// didn't pick anything, so you shouldn't use it as the id
// for an item..
items.add (new Item (itemResultID, itemText, isActive, isTicked, iconToUse,
Colours::black, false, nullptr, nullptr, nullptr));
Item i;
i.text = itemText;
i.itemID = itemResultID;
i.isEnabled = isActive;
i.isTicked = isTicked;
i.image = iconToUse;
addItem (i);
}
void PopupMenu::addCommandItem (ApplicationCommandManager* commandManager,
@@ -1337,53 +1329,59 @@ void PopupMenu::addCommandItem (ApplicationCommandManager* commandManager,
ApplicationCommandInfo info (*registeredInfo);
ApplicationCommandTarget* const target = commandManager->getTargetForCommand (commandID, info);
items.add (new Item (commandID,
displayName.isNotEmpty() ? displayName
: info.shortName,
target != nullptr && (info.flags & ApplicationCommandInfo::isDisabled) == 0,
(info.flags & ApplicationCommandInfo::isTicked) != 0,
iconToUse,
Colours::black,
false,
nullptr, nullptr,
commandManager));
Item i;
i.text = displayName.isNotEmpty() ? displayName : info.shortName;
i.itemID = (int) commandID;
i.commandManager = commandManager;
i.isEnabled = target != nullptr && (info.flags & ApplicationCommandInfo::isDisabled) == 0;
i.isTicked = (info.flags & ApplicationCommandInfo::isTicked) != 0;
i.image = iconToUse;
addItem (i);
}
}
void PopupMenu::addColouredItem (int itemResultID, const String& itemText, Colour itemTextColour,
bool isActive, bool isTicked, Drawable* iconToUse)
{
jassert (itemResultID != 0); // 0 is used as a return value to indicate that the user
// didn't pick anything, so you shouldn't use it as the id
// for an item..
items.add (new Item (itemResultID, itemText, isActive, isTicked, iconToUse,
itemTextColour, true, nullptr, nullptr, nullptr));
Item i;
i.text = itemText;
i.itemID = itemResultID;
i.colour = itemTextColour;
i.isEnabled = isActive;
i.isTicked = isTicked;
i.image = iconToUse;
addItem (i);
}
void PopupMenu::addColouredItem (int itemResultID, const String& itemText, Colour itemTextColour,
bool isActive, bool isTicked, const Image& iconToUse)
{
addColouredItem (itemResultID, itemText, itemTextColour, isActive, isTicked, createDrawableFromImage (iconToUse));
Item i;
i.text = itemText;
i.itemID = itemResultID;
i.colour = itemTextColour;
i.isEnabled = isActive;
i.isTicked = isTicked;
i.image = createDrawableFromImage (iconToUse);
addItem (i);
}
void PopupMenu::addCustomItem (int itemID, CustomComponent* cc, const PopupMenu* subMenu)
void PopupMenu::addCustomItem (int itemResultID, CustomComponent* cc, const PopupMenu* subMenu)
{
jassert (itemID != 0); // 0 is used as a return value to indicate that the user
// didn't pick anything, so you shouldn't use it as the id
// for an item..
items.add (new Item (itemID, String::empty, true, false, nullptr,
Colours::black, false, cc, subMenu, nullptr));
Item i;
i.itemID = itemResultID;
i.customComponent = cc;
i.subMenu = createCopyIfNotNull (subMenu);
addItem (i);
}
void PopupMenu::addCustomItem (int itemResultID, Component* customComponent, int idealWidth, int idealHeight,
bool triggerMenuItemAutomaticallyWhenClicked, const PopupMenu* subMenu)
{
items.add (new Item (itemResultID, String::empty, true, false, nullptr, Colours::black, false,
new HelperClasses::NormalComponentWrapper (customComponent, idealWidth, idealHeight,
triggerMenuItemAutomaticallyWhenClicked),
subMenu, nullptr));
addCustomItem (itemResultID,
new HelperClasses::NormalComponentWrapper (customComponent, idealWidth, idealHeight,
triggerMenuItemAutomaticallyWhenClicked),
subMenu);
}
void PopupMenu::addSubMenu (const String& subMenuName, const PopupMenu& subMenu, bool isActive)
@@ -1400,19 +1398,32 @@ void PopupMenu::addSubMenu (const String& subMenuName, const PopupMenu& subMenu,
void PopupMenu::addSubMenu (const String& subMenuName, const PopupMenu& subMenu, bool isActive,
Drawable* iconToUse, bool isTicked, int itemResultID)
{
items.add (new Item (itemResultID, subMenuName, isActive && (itemResultID != 0 || subMenu.getNumItems() > 0), isTicked,
iconToUse, Colours::black, false, nullptr, &subMenu, nullptr));
Item i;
i.text = subMenuName;
i.itemID = itemResultID;
i.subMenu = new PopupMenu (subMenu);
i.isEnabled = isActive && (itemResultID != 0 || subMenu.getNumItems() > 0);
i.isTicked = isTicked;
i.image = iconToUse;
addItem (i);
}
void PopupMenu::addSeparator()
{
if (items.size() > 0 && ! items.getLast()->isSeparator)
items.add (new Item());
{
Item i;
i.isSeparator = true;
addItem (i);
}
}
void PopupMenu::addSectionHeader (const String& title)
{
addCustomItem (PopupMenuSettings::sectionHeaderID, new HelperClasses::HeaderItemComponent (title));
Item i;
i.text = title;
i.isSectionHeader = true;
addItem (i);
}
//==============================================================================
@@ -1486,9 +1497,8 @@ Component* PopupMenu::createWindow (const Options& options,
//==============================================================================
// This invokes any command manager commands and deletes the menu window when it is dismissed
class PopupMenuCompletionCallback : public ModalComponentManager::Callback
struct PopupMenuCompletionCallback : public ModalComponentManager::Callback
{
public:
PopupMenuCompletionCallback()
: managerOfChosenCommand (nullptr),
prevFocused (Component::getCurrentlyFocusedComponent()),
@@ -1524,7 +1534,6 @@ public:
ScopedPointer<Component> component;
WeakReference<Component> prevFocused, prevTopLevel;
private:
JUCE_DECLARE_NON_COPYABLE (PopupMenuCompletionCallback)
};
@@ -1651,10 +1660,8 @@ bool PopupMenu::containsCommandItem (const int commandID) const
const Item& mi = *items.getUnchecked (i);
if ((mi.itemID == commandID && mi.commandManager != nullptr)
|| (mi.subMenu != nullptr && mi.subMenu->containsCommandItem (commandID)))
{
|| (mi.subMenu != nullptr && mi.subMenu->containsCommandItem (commandID)))
return true;
}
}
return false;
@@ -1671,7 +1678,7 @@ bool PopupMenu::containsAnyActiveItems() const noexcept
if (mi.subMenu->containsAnyActiveItems())
return true;
}
else if (mi.isActive)
else if (mi.isEnabled)
{
return true;
}
@@ -1708,7 +1715,7 @@ void PopupMenu::CustomComponent::triggerMenuItem()
{
if (HelperClasses::MenuWindow* const pmw = mic->findParentComponentOfClass<HelperClasses::MenuWindow>())
{
pmw->dismissMenu (&mic->itemInfo);
pmw->dismissMenu (&mic->item);
}
else
{
@@ -1725,53 +1732,21 @@ void PopupMenu::CustomComponent::triggerMenuItem()
}
//==============================================================================
PopupMenu::MenuItemIterator::MenuItemIterator (const PopupMenu& m)
: subMenu (nullptr),
itemId (0),
isSeparator (false),
isTicked (false),
isEnabled (false),
isCustomComponent (false),
isSectionHeader (false),
customColour (nullptr),
menu (m),
index (0)
{
}
PopupMenu::MenuItemIterator::~MenuItemIterator()
{
}
PopupMenu::MenuItemIterator::MenuItemIterator (const PopupMenu& m) : menu (m), index (0) {}
PopupMenu::MenuItemIterator::~MenuItemIterator() {}
bool PopupMenu::MenuItemIterator::next()
{
if (index >= menu.items.size())
return false;
const Item* const item = menu.items.getUnchecked (index);
++index;
if (item->isSeparator && index >= menu.items.size()) // (avoid showing a separator at the end)
return false;
const Item* const item = menu.items.getUnchecked (index++);
itemName = item->customComp != nullptr ? item->customComp->getName() : item->text;
subMenu = item->subMenu;
itemId = item->itemID;
isSeparator = item->isSeparator;
isTicked = item->isTicked;
isEnabled = item->isActive;
isSectionHeader = dynamic_cast<HelperClasses::HeaderItemComponent*> (static_cast<CustomComponent*> (item->customComp)) != nullptr;
isCustomComponent = (! isSectionHeader) && item->customComp != nullptr;
customColour = item->usesColour ? &(item->textColour) : nullptr;
icon = item->iconDrawable;
commandManager = item->commandManager;
return true;
return ! (item->isSeparator && index >= menu.items.size()); // (avoid showing a separator at the end)
}
void PopupMenu::MenuItemIterator::addItemTo (PopupMenu& targetMenu)
const PopupMenu::Item& PopupMenu::MenuItemIterator::getItem() const noexcept
{
targetMenu.items.add (new Item (itemId, itemName, isEnabled, isTicked, icon != nullptr ? icon->createCopy() : nullptr,
customColour != nullptr ? *customColour : Colours::black,
customColour != nullptr, nullptr, subMenu, commandManager));
jassert (isPositiveAndBelow (index - 1, menu.items.size()));
return *menu.items.getUnchecked (index - 1);
}

+ 69
- 19
libs/juce/source/modules/juce_gui_basics/menus/juce_PopupMenu.h View File

@@ -104,6 +104,71 @@ public:
/** Resets the menu, removing all its items. */
void clear();
/** Describes a popup menu item. */
struct JUCE_API Item
{
/** Creates a null item.
You'll need to set some fields after creating an Item before you
can add it to a PopupMenu
*/
Item() noexcept;
/** Creates a copy of an item. */
Item (const Item&);
/** Creates a copy of an item. */
Item& operator= (const Item&);
/** The menu item's name. */
String text;
/** The menu item's ID. This can not be 0 if you want the item to be triggerable! */
int itemID;
/** A sub-menu, or nullptr if there isn't one. */
ScopedPointer<PopupMenu> subMenu;
/** A drawable to use as an icon, or nullptr if there isn't one. */
ScopedPointer<Drawable> image;
/** A custom component for the item to display, or nullptr if there isn't one. */
ReferenceCountedObjectPtr<CustomComponent> customComponent;
/** A command manager to use to automatically invoke the command, or nullptr if none is specified. */
ApplicationCommandManager* commandManager;
/** An optional string describing the shortcut key for this item.
This is only used for displaying at the right-hand edge of a menu item - the
menu won't attempt to actually catch or process the key. If you supply a
commandManager parameter then the menu will attempt to fill-in this field
automatically.
*/
String shortcutKeyDescription;
/** A colour to use to draw the menu text.
By default this is transparent black, which means that the LookAndFeel should choose the colour.
*/
Colour colour;
/** True if this menu item is enabled. */
bool isEnabled;
/** True if this menu item should have a tick mark next to it. */
bool isTicked;
/** True if this menu item is a separator line. */
bool isSeparator;
/** True if this menu item is a section header. */
bool isSectionHeader;
};
/** Adds an item to the menu.
You can call this method for full control over the item that is added, or use the other
addItem helper methods if you want to pass arguments rather than creating an Item object.
*/
void addItem (const Item& newItem);
/** Appends a new text item for this menu to show.
@param itemResultID the number that will be returned from the show() method
@@ -274,7 +339,6 @@ public:
int itemResultID = 0);
/** Appends a separator to the menu, to help break it up into sections.
The menu class is smart enough not to display separators at the top or bottom
of the menu, and it will replace mutliple adjacent separators with a single
one, so your code can be quite free and easy about adding these, and it'll
@@ -283,14 +347,12 @@ public:
void addSeparator();
/** Adds a non-clickable text item to the menu.
This is a bold-font items which can be used as a header to separate the items
into named groups.
*/
void addSectionHeader (const String& title);
/** Returns the number of items that the menu currently contains.
(This doesn't count separators).
*/
int getNumItems() const noexcept;
@@ -486,21 +548,10 @@ public:
*/
bool next();
/** Adds an item to the target menu which has all the properties of this item. */
void addItemTo (PopupMenu& targetMenu);
//==============================================================================
String itemName;
const PopupMenu* subMenu;
int itemId;
bool isSeparator;
bool isTicked;
bool isEnabled;
bool isCustomComponent;
bool isSectionHeader;
const Colour* customColour;
const Drawable* icon;
ApplicationCommandManager* commandManager;
/** Returns a reference to the description of the current item.
It is only valid to call this after next() has returned true!
*/
const Item& getItem() const noexcept;
private:
//==============================================================================
@@ -621,7 +672,6 @@ public:
private:
//==============================================================================
JUCE_PUBLIC_IN_DLL_BUILD (class Item)
JUCE_PUBLIC_IN_DLL_BUILD (struct HelperClasses)
friend struct HelperClasses;
friend class MenuBarComponent;


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.h View File

@@ -86,7 +86,7 @@ public:
*/
void startDragging (const var& sourceDescription,
Component* sourceComponent,
Image dragImage = Image::null,
Image dragImage = Image(),
bool allowDraggingToOtherJuceWindows = false,
const Point<int>* imageOffsetFromMouse = nullptr);


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/native/juce_ios_Windowing.mm View File

@@ -351,7 +351,7 @@ bool juce_areThereAnyAlwaysOnTopWindows()
//==============================================================================
Image juce_createIconForFile (const File&)
{
return Image::null;
return Image();
}
//==============================================================================


+ 2
- 2
libs/juce/source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp View File

@@ -2568,7 +2568,7 @@ private:
else if (Time::getApproximateMillisecondCounter() > lastTimeImageUsed + 3000)
{
stopTimer();
image = Image::null;
image = Image();
}
}
@@ -4080,7 +4080,7 @@ void MouseCursor::showInAllWindows() const
//==============================================================================
Image juce_createIconForFile (const File& /* file */)
{
return Image::null;
return Image();
}
//==============================================================================


+ 16
- 15
libs/juce/source/modules/juce_gui_basics/native/juce_mac_MainMenu.mm View File

@@ -181,16 +181,17 @@ public:
void addMenuItem (PopupMenu::MenuItemIterator& iter, NSMenu* menuToAddTo,
const int topLevelMenuId, const int topLevelIndex)
{
NSString* text = juceStringToNS (iter.itemName.upToFirstOccurrenceOf ("<end>", false, true));
const PopupMenu::Item& i = iter.getItem();
NSString* text = juceStringToNS (i.text);
if (text == nil)
text = nsEmptyString();
if (iter.isSeparator)
if (i.isSeparator)
{
[menuToAddTo addItem: [NSMenuItem separatorItem]];
}
else if (iter.isSectionHeader)
else if (i.isSectionHeader)
{
NSMenuItem* item = [menuToAddTo addItemWithTitle: text
action: nil
@@ -198,9 +199,9 @@ public:
[item setEnabled: false];
}
else if (iter.subMenu != nullptr)
else if (i.subMenu != nullptr)
{
if (iter.itemName == recentItemsMenuName)
if (i.text == recentItemsMenuName)
{
if (recent == nullptr)
recent = new RecentFilesMenuItem();
@@ -219,10 +220,10 @@ public:
action: nil
keyEquivalent: nsEmptyString()];
[item setTag: iter.itemId];
[item setEnabled: iter.isEnabled];
[item setTag: i.itemID];
[item setEnabled: i.isEnabled];
NSMenu* sub = createMenu (*iter.subMenu, iter.itemName, topLevelMenuId, topLevelIndex, false);
NSMenu* sub = createMenu (*i.subMenu, i.text, topLevelMenuId, topLevelIndex, false);
[menuToAddTo setSubmenu: sub forItem: item];
[sub release];
}
@@ -232,19 +233,19 @@ public:
action: @selector (menuItemInvoked:)
keyEquivalent: nsEmptyString()];
[item setTag: iter.itemId];
[item setEnabled: iter.isEnabled];
[item setState: iter.isTicked ? NSOnState : NSOffState];
[item setTag: i.itemID];
[item setEnabled: i.isEnabled];
[item setState: i.isTicked ? NSOnState : NSOffState];
[item setTarget: (id) callback];
NSMutableArray* info = [NSMutableArray arrayWithObject: [NSNumber numberWithUnsignedLongLong: (pointer_sized_uint) (void*) iter.commandManager]];
NSMutableArray* info = [NSMutableArray arrayWithObject: [NSNumber numberWithUnsignedLongLong: (pointer_sized_uint) (void*) i.commandManager]];
[info addObject: [NSNumber numberWithInt: topLevelIndex]];
[item setRepresentedObject: info];
if (iter.commandManager != nullptr)
if (i.commandManager != nullptr)
{
const Array<KeyPress> keyPresses (iter.commandManager->getKeyMappings()
->getKeyPressesAssignedToCommand (iter.itemId));
const Array<KeyPress> keyPresses (i.commandManager->getKeyMappings()
->getKeyPressesAssignedToCommand (i.itemID));
if (keyPresses.size() > 0)
{


+ 32
- 4
libs/juce/source/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm View File

@@ -69,7 +69,6 @@ public:
view (nil),
isSharedWindow (viewToAttachTo != nil),
fullScreen (false),
insideDrawRect (false),
#if USE_COREGRAPHICS_RENDERING
usingCoreGraphics (true),
#else
@@ -793,6 +792,37 @@ public:
displayScale = (float) screen.backingScaleFactor;
#endif
#if USE_COREGRAPHICS_RENDERING && JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS
// This option invokes a separate paint call for each rectangle of the clip region.
// It's a long story, but this is a basically a workaround for a CGContext not having
// a way of finding whether a rectangle falls within its clip region
if (usingCoreGraphics)
{
const NSRect* rects = nullptr;
NSInteger numRects = 0;
[view getRectsBeingDrawn: &rects count: &numRects];
if (numRects > 1)
{
for (int i = 0; i < numRects; ++i)
{
NSRect rect = rects[i];
CGContextSaveGState (cg);
CGContextClipToRect (cg, CGRectMake (rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));
drawRect (cg, rect, displayScale);
CGContextRestoreGState (cg);
}
return;
}
}
#endif
drawRect (cg, r, displayScale);
}
void drawRect (CGContextRef cg, NSRect r, float displayScale)
{
#if USE_COREGRAPHICS_RENDERING
if (usingCoreGraphics)
{
@@ -872,9 +902,7 @@ public:
void invokePaint (LowLevelGraphicsContext& context)
{
lastRepaintTime = Time::getCurrentTime();
insideDrawRect = true;
handlePaint (context);
insideDrawRect = false;
}
void performAnyPendingRepaintsNow() override
@@ -1283,7 +1311,7 @@ public:
//==============================================================================
NSWindow* window;
NSView* view;
bool isSharedWindow, fullScreen, insideDrawRect;
bool isSharedWindow, fullScreen;
bool usingCoreGraphics, isZooming, textWasInserted;
String stringBeingComposed;
NSNotificationCenter* notificationCenter;


+ 2
- 2
libs/juce/source/modules/juce_gui_basics/native/juce_win32_Windowing.cpp View File

@@ -531,7 +531,7 @@ namespace IconConverters
}
}
return Image::null;
return Image();
}
HICON createHICONFromImage (const Image& image, const BOOL isIcon, int hotspotX, int hotspotY)
@@ -1186,7 +1186,7 @@ private:
void timerCallback() override
{
stopTimer();
image = Image::null;
image = Image();
}
private:


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/widgets/juce_ToolbarItemComponent.cpp View File

@@ -70,7 +70,7 @@ public:
if (DragAndDropContainer* const dnd = DragAndDropContainer::findParentDragContainerFor (this))
{
dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), Image::null, true);
dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), Image(), true);
if (ToolbarItemComponent* const tc = getToolbarItemComponent())
{


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/windows/juce_CallOutBox.cpp View File

@@ -230,7 +230,7 @@ void CallOutBox::updatePosition (const Rectangle<int>& newAreaToPointTo, const R
void CallOutBox::refreshPath()
{
repaint();
background = Image::null;
background = Image();
outline.clear();
const float gap = 4.5f;


+ 2
- 2
libs/juce/source/modules/juce_gui_extra/misc/juce_ColourSelector.cpp View File

@@ -125,7 +125,7 @@ public:
if (lastHue != h)
{
lastHue = h;
colours = Image::null;
colours = Image();
repaint();
}
@@ -134,7 +134,7 @@ public:
void resized() override
{
colours = Image::null;
colours = Image();
updateMarker();
}


+ 8
- 5
libs/juce/source/modules/juce_gui_extra/misc/juce_KeyMappingEditorComponent.cpp View File

@@ -176,13 +176,16 @@ public:
static void keyChosen (int result, ChangeKeyButton* button)
{
if (result != 0 && button != nullptr && button->currentKeyEntryWindow != nullptr)
if (button != nullptr && button->currentKeyEntryWindow != nullptr)
{
button->currentKeyEntryWindow->setVisible (false);
button->setNewKey (button->currentKeyEntryWindow->lastPress, false);
}
if (result != 0)
{
button->currentKeyEntryWindow->setVisible (false);
button->setNewKey (button->currentKeyEntryWindow->lastPress, false);
}
button->currentKeyEntryWindow = nullptr;
button->currentKeyEntryWindow = nullptr;
}
}
void assignNewKey()


Loading…
Cancel
Save