| @@ -0,0 +1,13 @@ | |||||
| #!/bin/bash | |||||
| JUCE_MODULES_DIR="/home/falktx/Personal/FOSS/GIT/distrho/libs/juce-2.0/source/modules" | |||||
| CARLA_MODULES_DIR="/home/falktx/Personal/FOSS/GIT/Carla/source/modules" | |||||
| MODULES=("juce_audio_basics juce_audio_devices juce_audio_formats juce_audio_processors juce_core juce_data_structures juce_events juce_graphics juce_gui_basics") | |||||
| for M in $MODULES; do | |||||
| echo $M; | |||||
| cp -r -v $JUCE_MODULES_DIR/$M/* $CARLA_MODULES_DIR/$M/ | |||||
| done | |||||
| find $CARLA_MODULES_DIR -name juce_module_info -delete | |||||
| @@ -96,7 +96,7 @@ MidiBuffer::MidiBuffer (const MidiMessage& message) noexcept | |||||
| void MidiBuffer::swapWith (MidiBuffer& other) noexcept { data.swapWith (other.data); } | void MidiBuffer::swapWith (MidiBuffer& other) noexcept { data.swapWith (other.data); } | ||||
| void MidiBuffer::clear() noexcept { data.clearQuick(); } | void MidiBuffer::clear() noexcept { data.clearQuick(); } | ||||
| void MidiBuffer::ensureSize (size_t minimumNumBytes) { data.ensureStorageAllocated (minimumNumBytes); } | |||||
| void MidiBuffer::ensureSize (size_t minimumNumBytes) { data.ensureStorageAllocated ((int) minimumNumBytes); } | |||||
| bool MidiBuffer::isEmpty() const noexcept { return data.size() == 0; } | bool MidiBuffer::isEmpty() const noexcept { return data.size() == 0; } | ||||
| void MidiBuffer::clear (const int startSample, const int numSamples) | void MidiBuffer::clear (const int startSample, const int numSamples) | ||||
| @@ -104,7 +104,7 @@ void MidiBuffer::clear (const int startSample, const int numSamples) | |||||
| uint8* const start = MidiBufferHelpers::findEventAfter (data.begin(), data.end(), startSample - 1); | uint8* const start = MidiBufferHelpers::findEventAfter (data.begin(), data.end(), startSample - 1); | ||||
| uint8* const end = MidiBufferHelpers::findEventAfter (start, data.end(), startSample + numSamples - 1); | uint8* const end = MidiBufferHelpers::findEventAfter (start, data.end(), startSample + numSamples - 1); | ||||
| data.removeRange (start - data.begin(), end - data.begin()); | |||||
| data.removeRange ((int) (start - data.begin()), (int) (end - data.begin())); | |||||
| } | } | ||||
| void MidiBuffer::addEvent (const MidiMessage& m, const int sampleNumber) | void MidiBuffer::addEvent (const MidiMessage& m, const int sampleNumber) | ||||
| @@ -121,7 +121,7 @@ void MidiBuffer::addEvent (const void* const newData, const int maxBytes, const | |||||
| const size_t newItemSize = (size_t) numBytes + sizeof (int32) + sizeof (uint16); | const size_t newItemSize = (size_t) numBytes + sizeof (int32) + sizeof (uint16); | ||||
| const int offset = (int) (MidiBufferHelpers::findEventAfter (data.begin(), data.end(), sampleNumber) - data.begin()); | const int offset = (int) (MidiBufferHelpers::findEventAfter (data.begin(), data.end(), sampleNumber) - data.begin()); | ||||
| data.insertMultiple (offset, 0, newItemSize); | |||||
| data.insertMultiple (offset, 0, (int) newItemSize); | |||||
| uint8* const d = data.begin() + offset; | uint8* const d = data.begin() + offset; | ||||
| *reinterpret_cast<int32*> (d) = sampleNumber; | *reinterpret_cast<int32*> (d) = sampleNumber; | ||||
| @@ -221,9 +221,9 @@ bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePositio | |||||
| return false; | return false; | ||||
| samplePosition = MidiBufferHelpers::getEventTime (data); | samplePosition = MidiBufferHelpers::getEventTime (data); | ||||
| const int numBytes = MidiBufferHelpers::getEventDataSize (data); | |||||
| result = MidiMessage (data + sizeof (int32) + sizeof (uint16), numBytes, samplePosition); | |||||
| data += sizeof (int32) + sizeof (uint16) + numBytes; | |||||
| const int itemSize = MidiBufferHelpers::getEventDataSize (data); | |||||
| result = MidiMessage (data + sizeof (int32) + sizeof (uint16), itemSize, samplePosition); | |||||
| data += sizeof (int32) + sizeof (uint16) + itemSize; | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -1210,7 +1210,7 @@ private: | |||||
| static String hintToString (const void* hints, const char* type) | static String hintToString (const void* hints, const char* type) | ||||
| { | { | ||||
| char* const hint = snd_device_name_get_hint (hints, type); | char* const hint = snd_device_name_get_hint (hints, type); | ||||
| const String s (hint); | |||||
| const String s (String::fromUTF8 (hint)); | |||||
| ::free (hint); | ::free (hint); | ||||
| return s; | return s; | ||||
| } | } | ||||
| @@ -155,9 +155,7 @@ public: | |||||
| bufferSize (512), | bufferSize (512), | ||||
| numInputChans (0), | numInputChans (0), | ||||
| numOutputChans (0), | numOutputChans (0), | ||||
| callbacksAllowed (true), | |||||
| numInputChannelInfos (0), | |||||
| numOutputChannelInfos (0) | |||||
| callbacksAllowed (true) | |||||
| { | { | ||||
| jassert (deviceID != 0); | jassert (deviceID != 0); | ||||
| @@ -199,9 +197,17 @@ public: | |||||
| tempOutputBuffers[i] = audioBuffer + count++ * tempBufSize; | tempOutputBuffers[i] = audioBuffer + count++ * tempBufSize; | ||||
| } | } | ||||
| struct CallbackDetailsForChannel | |||||
| { | |||||
| int streamNum; | |||||
| int dataOffsetSamples; | |||||
| int dataStrideSamples; | |||||
| }; | |||||
| // returns the number of actual available channels | // returns the number of actual available channels | ||||
| void fillInChannelInfo (const bool input) | |||||
| StringArray getChannelInfo (const bool input, Array<CallbackDetailsForChannel>& newChannelInfo) const | |||||
| { | { | ||||
| StringArray newNames; | |||||
| int chanNum = 0; | int chanNum = 0; | ||||
| UInt32 size; | UInt32 size; | ||||
| @@ -212,7 +218,7 @@ public: | |||||
| if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) | if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) | ||||
| { | { | ||||
| HeapBlock <AudioBufferList> bufList; | |||||
| HeapBlock<AudioBufferList> bufList; | |||||
| bufList.calloc (size, 1); | bufList.calloc (size, 1); | ||||
| if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, bufList))) | if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, bufList))) | ||||
| @@ -237,82 +243,35 @@ public: | |||||
| name = String::fromUTF8 (channelName, (int) nameSize); | name = String::fromUTF8 (channelName, (int) nameSize); | ||||
| } | } | ||||
| if (input) | |||||
| if ((input ? activeInputChans : activeOutputChans) [chanNum]) | |||||
| { | { | ||||
| if (activeInputChans[chanNum]) | |||||
| { | |||||
| inputChannelInfo [numInputChannelInfos].streamNum = i; | |||||
| inputChannelInfo [numInputChannelInfos].dataOffsetSamples = (int) j; | |||||
| inputChannelInfo [numInputChannelInfos].dataStrideSamples = (int) b.mNumberChannels; | |||||
| ++numInputChannelInfos; | |||||
| } | |||||
| if (name.isEmpty()) | |||||
| name << "Input " << (chanNum + 1); | |||||
| inChanNames.add (name); | |||||
| } | |||||
| else | |||||
| { | |||||
| if (activeOutputChans[chanNum]) | |||||
| { | |||||
| outputChannelInfo [numOutputChannelInfos].streamNum = i; | |||||
| outputChannelInfo [numOutputChannelInfos].dataOffsetSamples = (int) j; | |||||
| outputChannelInfo [numOutputChannelInfos].dataStrideSamples = (int) b.mNumberChannels; | |||||
| ++numOutputChannelInfos; | |||||
| } | |||||
| if (name.isEmpty()) | |||||
| name << "Output " << (chanNum + 1); | |||||
| outChanNames.add (name); | |||||
| CallbackDetailsForChannel info = { i, (int) j, (int) b.mNumberChannels }; | |||||
| newChannelInfo.add (info); | |||||
| } | } | ||||
| if (name.isEmpty()) | |||||
| name << (input ? "Input " : "Output ") << (chanNum + 1); | |||||
| newNames.add (name); | |||||
| ++chanNum; | ++chanNum; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return newNames; | |||||
| } | } | ||||
| void updateDetailsFromDevice() | |||||
| Array<double> getSampleRatesFromDevice() const | |||||
| { | { | ||||
| stopTimer(); | |||||
| if (deviceID == 0) | |||||
| return; | |||||
| const ScopedLock sl (callbackLock); | |||||
| Array<double> newSampleRates; | |||||
| String rates; | |||||
| AudioObjectPropertyAddress pa; | AudioObjectPropertyAddress pa; | ||||
| pa.mScope = kAudioObjectPropertyScopeWildcard; | pa.mScope = kAudioObjectPropertyScopeWildcard; | ||||
| pa.mElement = kAudioObjectPropertyElementMaster; | pa.mElement = kAudioObjectPropertyElementMaster; | ||||
| UInt32 isAlive; | |||||
| UInt32 size = sizeof (isAlive); | |||||
| pa.mSelector = kAudioDevicePropertyDeviceIsAlive; | |||||
| if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &isAlive)) | |||||
| && isAlive == 0) | |||||
| return; | |||||
| Float64 sr; | |||||
| size = sizeof (sr); | |||||
| pa.mSelector = kAudioDevicePropertyNominalSampleRate; | |||||
| if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &sr))) | |||||
| sampleRate = sr; | |||||
| UInt32 framesPerBuf; | |||||
| size = sizeof (framesPerBuf); | |||||
| pa.mSelector = kAudioDevicePropertyBufferFrameSize; | |||||
| if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &framesPerBuf))) | |||||
| { | |||||
| bufferSize = (int) framesPerBuf; | |||||
| allocateTempBuffers(); | |||||
| } | |||||
| bufferSizes.clear(); | |||||
| pa.mSelector = kAudioDevicePropertyBufferFrameSizeRange; | |||||
| pa.mSelector = kAudioDevicePropertyAvailableNominalSampleRates; | |||||
| UInt32 size = 0; | |||||
| if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) | if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) | ||||
| { | { | ||||
| @@ -321,33 +280,42 @@ public: | |||||
| if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, ranges))) | if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, ranges))) | ||||
| { | { | ||||
| bufferSizes.add ((int) (ranges[0].mMinimum + 15) & ~15); | |||||
| static const double possibleRates[] = { 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 }; | |||||
| for (int i = 32; i < 2048; i += 32) | |||||
| for (int i = 0; i < numElementsInArray (possibleRates); ++i) | |||||
| { | { | ||||
| for (int j = size / (int) sizeof (AudioValueRange); --j >= 0;) | for (int j = size / (int) sizeof (AudioValueRange); --j >= 0;) | ||||
| { | { | ||||
| if (i >= ranges[j].mMinimum && i <= ranges[j].mMaximum) | |||||
| if (possibleRates[i] >= ranges[j].mMinimum - 2 && possibleRates[i] <= ranges[j].mMaximum + 2) | |||||
| { | { | ||||
| bufferSizes.addIfNotAlreadyThere (i); | |||||
| newSampleRates.add (possibleRates[i]); | |||||
| rates << possibleRates[i] << ' '; | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (bufferSize > 0) | |||||
| bufferSizes.addIfNotAlreadyThere (bufferSize); | |||||
| } | } | ||||
| } | } | ||||
| if (bufferSizes.size() == 0 && bufferSize > 0) | |||||
| bufferSizes.add (bufferSize); | |||||
| if (newSampleRates.size() == 0 && sampleRate > 0) | |||||
| { | |||||
| newSampleRates.add (sampleRate); | |||||
| rates << sampleRate; | |||||
| } | |||||
| JUCE_COREAUDIOLOG ("rates: " + rates); | |||||
| return newSampleRates; | |||||
| } | |||||
| sampleRates.clear(); | |||||
| const double possibleRates[] = { 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 }; | |||||
| String rates; | |||||
| Array<int> getBufferSizesFromDevice() const | |||||
| { | |||||
| Array<int> newBufferSizes; | |||||
| pa.mSelector = kAudioDevicePropertyAvailableNominalSampleRates; | |||||
| AudioObjectPropertyAddress pa; | |||||
| pa.mScope = kAudioObjectPropertyScopeWildcard; | |||||
| pa.mElement = kAudioObjectPropertyElementMaster; | |||||
| pa.mSelector = kAudioDevicePropertyBufferFrameSizeRange; | |||||
| UInt32 size = 0; | |||||
| if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) | if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) | ||||
| { | { | ||||
| @@ -356,59 +324,98 @@ public: | |||||
| if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, ranges))) | if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, ranges))) | ||||
| { | { | ||||
| for (int i = 0; i < numElementsInArray (possibleRates); ++i) | |||||
| { | |||||
| bool ok = false; | |||||
| newBufferSizes.add ((int) (ranges[0].mMinimum + 15) & ~15); | |||||
| for (int i = 32; i < 2048; i += 32) | |||||
| { | |||||
| for (int j = size / (int) sizeof (AudioValueRange); --j >= 0;) | for (int j = size / (int) sizeof (AudioValueRange); --j >= 0;) | ||||
| if (possibleRates[i] >= ranges[j].mMinimum - 2 && possibleRates[i] <= ranges[j].mMaximum + 2) | |||||
| ok = true; | |||||
| if (ok) | |||||
| { | { | ||||
| sampleRates.add (possibleRates[i]); | |||||
| rates << possibleRates[i] << ' '; | |||||
| if (i >= ranges[j].mMinimum && i <= ranges[j].mMaximum) | |||||
| { | |||||
| newBufferSizes.addIfNotAlreadyThere (i); | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| if (bufferSize > 0) | |||||
| newBufferSizes.addIfNotAlreadyThere (bufferSize); | |||||
| } | } | ||||
| } | } | ||||
| if (sampleRates.size() == 0 && sampleRate > 0) | |||||
| { | |||||
| sampleRates.add (sampleRate); | |||||
| rates << sampleRate; | |||||
| } | |||||
| if (newBufferSizes.size() == 0 && bufferSize > 0) | |||||
| newBufferSizes.add (bufferSize); | |||||
| JUCE_COREAUDIOLOG ("sr: " + rates); | |||||
| return newBufferSizes; | |||||
| } | |||||
| inputLatency = 0; | |||||
| outputLatency = 0; | |||||
| UInt32 lat; | |||||
| size = sizeof (lat); | |||||
| int getLatencyFromDevice (AudioObjectPropertyScope scope) const | |||||
| { | |||||
| UInt32 lat = 0; | |||||
| UInt32 size = sizeof (lat); | |||||
| AudioObjectPropertyAddress pa; | |||||
| pa.mElement = kAudioObjectPropertyElementMaster; | |||||
| pa.mSelector = kAudioDevicePropertyLatency; | pa.mSelector = kAudioDevicePropertyLatency; | ||||
| pa.mScope = kAudioDevicePropertyScopeInput; | |||||
| if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &lat) == noErr) | |||||
| inputLatency = (int) lat; | |||||
| pa.mScope = scope; | |||||
| AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &lat); | |||||
| return (int) lat; | |||||
| } | |||||
| pa.mScope = kAudioDevicePropertyScopeOutput; | |||||
| size = sizeof (lat); | |||||
| void updateDetailsFromDevice() | |||||
| { | |||||
| stopTimer(); | |||||
| if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &lat) == noErr) | |||||
| outputLatency = (int) lat; | |||||
| if (deviceID == 0) | |||||
| return; | |||||
| // this collects all the new details from the device without any locking, then | |||||
| // locks + swaps them afterwards. | |||||
| AudioObjectPropertyAddress pa; | |||||
| pa.mScope = kAudioObjectPropertyScopeWildcard; | |||||
| pa.mElement = kAudioObjectPropertyElementMaster; | |||||
| UInt32 isAlive; | |||||
| UInt32 size = sizeof (isAlive); | |||||
| pa.mSelector = kAudioDevicePropertyDeviceIsAlive; | |||||
| if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &isAlive)) && isAlive == 0) | |||||
| return; | |||||
| Float64 sr; | |||||
| size = sizeof (sr); | |||||
| pa.mSelector = kAudioDevicePropertyNominalSampleRate; | |||||
| if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &sr))) | |||||
| sampleRate = sr; | |||||
| UInt32 framesPerBuf = bufferSize; | |||||
| size = sizeof (framesPerBuf); | |||||
| pa.mSelector = kAudioDevicePropertyBufferFrameSize; | |||||
| AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &framesPerBuf); | |||||
| Array<int> newBufferSizes (getBufferSizesFromDevice()); | |||||
| Array<double> newSampleRates (getSampleRatesFromDevice()); | |||||
| inputLatency = getLatencyFromDevice (kAudioDevicePropertyScopeInput); | |||||
| outputLatency = getLatencyFromDevice (kAudioDevicePropertyScopeOutput); | |||||
| JUCE_COREAUDIOLOG ("lat: " + String (inputLatency) + " " + String (outputLatency)); | JUCE_COREAUDIOLOG ("lat: " + String (inputLatency) + " " + String (outputLatency)); | ||||
| inChanNames.clear(); | |||||
| outChanNames.clear(); | |||||
| Array<CallbackDetailsForChannel> newInChans, newOutChans; | |||||
| StringArray newInNames (getChannelInfo (true, newInChans)); | |||||
| StringArray newOutNames (getChannelInfo (false, newOutChans)); | |||||
| // after getting the new values, lock + apply them | |||||
| const ScopedLock sl (callbackLock); | |||||
| bufferSize = (int) framesPerBuf; | |||||
| allocateTempBuffers(); | |||||
| inputChannelInfo.calloc ((size_t) numInputChans + 2); | |||||
| numInputChannelInfos = 0; | |||||
| sampleRates.swapWith (newSampleRates); | |||||
| bufferSizes.swapWith (newBufferSizes); | |||||
| outputChannelInfo.calloc ((size_t) numOutputChans + 2); | |||||
| numOutputChannelInfos = 0; | |||||
| inChanNames.swapWith (newInNames); | |||||
| outChanNames.swapWith (newOutNames); | |||||
| fillInChannelInfo (true); | |||||
| fillInChannelInfo (false); | |||||
| inputChannelInfo.swapWith (newInChans); | |||||
| outputChannelInfo.swapWith (newOutChans); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -675,7 +682,7 @@ public: | |||||
| { | { | ||||
| for (int i = numInputChans; --i >= 0;) | for (int i = numInputChans; --i >= 0;) | ||||
| { | { | ||||
| const CallbackDetailsForChannel& info = inputChannelInfo[i]; | |||||
| const CallbackDetailsForChannel& info = inputChannelInfo.getReference(i); | |||||
| float* dest = tempInputBuffers [i]; | float* dest = tempInputBuffers [i]; | ||||
| const float* src = ((const float*) inInputData->mBuffers[info.streamNum].mData) | const float* src = ((const float*) inInputData->mBuffers[info.streamNum].mData) | ||||
| + info.dataOffsetSamples; | + info.dataOffsetSamples; | ||||
| @@ -720,7 +727,7 @@ public: | |||||
| for (int i = numOutputChans; --i >= 0;) | for (int i = numOutputChans; --i >= 0;) | ||||
| { | { | ||||
| const CallbackDetailsForChannel& info = outputChannelInfo[i]; | |||||
| const CallbackDetailsForChannel& info = outputChannelInfo.getReference(i); | |||||
| const float* src = tempOutputBuffers [i]; | const float* src = tempOutputBuffers [i]; | ||||
| float* dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) | float* dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) | ||||
| + info.dataOffsetSamples; | + info.dataOffsetSamples; | ||||
| @@ -739,9 +746,9 @@ public: | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| for (int i = jmin (numOutputChans, numOutputChannelInfos); --i >= 0;) | |||||
| for (int i = jmin (numOutputChans, outputChannelInfo.size()); --i >= 0;) | |||||
| { | { | ||||
| const CallbackDetailsForChannel& info = outputChannelInfo[i]; | |||||
| const CallbackDetailsForChannel& info = outputChannelInfo.getReference(i); | |||||
| float* dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) | float* dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) | ||||
| + info.dataOffsetSamples; | + info.dataOffsetSamples; | ||||
| const int stride = info.dataStrideSamples; | const int stride = info.dataStrideSamples; | ||||
| @@ -803,15 +810,7 @@ private: | |||||
| int numInputChans, numOutputChans; | int numInputChans, numOutputChans; | ||||
| bool callbacksAllowed; | bool callbacksAllowed; | ||||
| struct CallbackDetailsForChannel | |||||
| { | |||||
| int streamNum; | |||||
| int dataOffsetSamples; | |||||
| int dataStrideSamples; | |||||
| }; | |||||
| int numInputChannelInfos, numOutputChannelInfos; | |||||
| HeapBlock <CallbackDetailsForChannel> inputChannelInfo, outputChannelInfo; | |||||
| Array<CallbackDetailsForChannel> inputChannelInfo, outputChannelInfo; | |||||
| HeapBlock <float*> tempInputBuffers, tempOutputBuffers; | HeapBlock <float*> tempInputBuffers, tempOutputBuffers; | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -380,7 +380,7 @@ public: | |||||
| samplesToWrite = const_cast<const int**> (channels.getData()); | samplesToWrite = const_cast<const int**> (channels.getData()); | ||||
| } | } | ||||
| return FLAC__stream_encoder_process (encoder, (const FLAC__int32**) samplesToWrite, (size_t) numSamples) != 0; | |||||
| return FLAC__stream_encoder_process (encoder, (const FLAC__int32**) samplesToWrite, (unsigned) numSamples) != 0; | |||||
| } | } | ||||
| bool writeData (const void* const data, const int size) const | bool writeData (const void* const data, const int size) const | ||||
| @@ -186,7 +186,7 @@ public: | |||||
| { | { | ||||
| float** dataIn = nullptr; | float** dataIn = nullptr; | ||||
| const int samps = OggVorbisNamespace::ov_read_float (&ovFile, &dataIn, numToRead, &bitStream); | |||||
| const long samps = OggVorbisNamespace::ov_read_float (&ovFile, &dataIn, numToRead, &bitStream); | |||||
| if (samps <= 0) | if (samps <= 0) | ||||
| break; | break; | ||||
| @@ -100,6 +100,18 @@ bool AudioFormatReader::read (int* const* destSamples, | |||||
| return true; | return true; | ||||
| } | } | ||||
| static void readChannels (AudioFormatReader& reader, | |||||
| int** const chans, AudioSampleBuffer* const buffer, | |||||
| const int startSample, const int numSamples, | |||||
| const int64 readerStartSample, const int numTargetChannels) | |||||
| { | |||||
| for (int j = 0; j < numTargetChannels; ++j) | |||||
| chans[j] = reinterpret_cast<int*> (buffer->getSampleData (j, startSample)); | |||||
| chans[numTargetChannels] = nullptr; | |||||
| reader.read (chans, numTargetChannels, readerStartSample, numSamples, true); | |||||
| } | |||||
| void AudioFormatReader::read (AudioSampleBuffer* buffer, | void AudioFormatReader::read (AudioSampleBuffer* buffer, | ||||
| int startSample, | int startSample, | ||||
| int numSamples, | int numSamples, | ||||
| @@ -113,49 +125,51 @@ void AudioFormatReader::read (AudioSampleBuffer* buffer, | |||||
| if (numSamples > 0) | if (numSamples > 0) | ||||
| { | { | ||||
| const int numTargetChannels = buffer->getNumChannels(); | const int numTargetChannels = buffer->getNumChannels(); | ||||
| int* chans[3]; | |||||
| if (useReaderLeftChan == useReaderRightChan) | |||||
| if (numTargetChannels <= 2) | |||||
| { | { | ||||
| chans[0] = reinterpret_cast<int*> (buffer->getSampleData (0, startSample)); | |||||
| chans[1] = (numChannels > 1 && numTargetChannels > 1) ? reinterpret_cast<int*> (buffer->getSampleData (1, startSample)) : nullptr; | |||||
| } | |||||
| else if (useReaderLeftChan || (numChannels == 1)) | |||||
| { | |||||
| chans[0] = reinterpret_cast<int*> (buffer->getSampleData (0, startSample)); | |||||
| chans[1] = nullptr; | |||||
| } | |||||
| else if (useReaderRightChan) | |||||
| { | |||||
| chans[0] = nullptr; | |||||
| chans[1] = reinterpret_cast<int*> (buffer->getSampleData (0, startSample)); | |||||
| } | |||||
| int* const dest0 = reinterpret_cast<int*> (buffer->getSampleData (0, startSample)); | |||||
| int* const dest1 = reinterpret_cast<int*> (numTargetChannels > 1 ? buffer->getSampleData (1, startSample) : nullptr); | |||||
| int* chans[3]; | |||||
| chans[2] = nullptr; | |||||
| if (useReaderLeftChan == useReaderRightChan) | |||||
| { | |||||
| chans[0] = dest0; | |||||
| chans[1] = numChannels > 1 ? dest1 : nullptr; | |||||
| } | |||||
| else if (useReaderLeftChan || (numChannels == 1)) | |||||
| { | |||||
| chans[0] = dest0; | |||||
| chans[1] = nullptr; | |||||
| } | |||||
| else if (useReaderRightChan) | |||||
| { | |||||
| chans[0] = nullptr; | |||||
| chans[1] = dest0; | |||||
| } | |||||
| read (chans, 2, readerStartSample, numSamples, true); | |||||
| chans[2] = nullptr; | |||||
| read (chans, 2, readerStartSample, numSamples, true); | |||||
| if (! usesFloatingPointData) | |||||
| // if the target's stereo and the source is mono, dupe the first channel.. | |||||
| if (numTargetChannels > 1 && (chans[0] == nullptr || chans[1] == nullptr)) | |||||
| memcpy (dest1, dest0, sizeof (float) * (size_t) numSamples); | |||||
| } | |||||
| else if (numTargetChannels <= 64) | |||||
| { | { | ||||
| for (int j = 0; j < 2; ++j) | |||||
| { | |||||
| if (float* const d = reinterpret_cast <float*> (chans[j])) | |||||
| { | |||||
| const float multiplier = 1.0f / 0x7fffffff; | |||||
| for (int i = 0; i < numSamples; ++i) | |||||
| d[i] = *reinterpret_cast<int*> (d + i) * multiplier; | |||||
| } | |||||
| } | |||||
| int* chans[65]; | |||||
| readChannels (*this, chans, buffer, startSample, numSamples, readerStartSample, numTargetChannels); | |||||
| } | } | ||||
| if (numTargetChannels > 1 && (chans[0] == nullptr || chans[1] == nullptr)) | |||||
| else | |||||
| { | { | ||||
| // if this is a stereo buffer and the source was mono, dupe the first channel.. | |||||
| memcpy (buffer->getSampleData (1, startSample), | |||||
| buffer->getSampleData (0, startSample), | |||||
| sizeof (float) * (size_t) numSamples); | |||||
| HeapBlock<int*> chans (numTargetChannels); | |||||
| readChannels (*this, chans, buffer, startSample, numSamples, readerStartSample, numTargetChannels); | |||||
| } | } | ||||
| if (! usesFloatingPointData) | |||||
| for (int j = 0; j < numTargetChannels; ++j) | |||||
| if (float* const d = buffer->getSampleData (j, startSample)) | |||||
| FloatVectorOperations::convertFixedToFloat (d, reinterpret_cast<const int*> (d), 1.0f / 0x7fffffff, numSamples); | |||||
| } | } | ||||
| } | } | ||||
| @@ -733,7 +733,7 @@ public: | |||||
| return s; | return s; | ||||
| } | } | ||||
| void changeProgramName (int index, const String& newName) override | |||||
| void changeProgramName (int /*index*/, const String& /*newName*/) override | |||||
| { | { | ||||
| jassertfalse; // xxx not implemented! | jassertfalse; // xxx not implemented! | ||||
| } | } | ||||
| @@ -1005,8 +1005,8 @@ private: | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| OSStatus renderGetInput (AudioUnitRenderActionFlags* ioActionFlags, | |||||
| const AudioTimeStamp* inTimeStamp, | |||||
| OSStatus renderGetInput (AudioUnitRenderActionFlags*, | |||||
| const AudioTimeStamp*, | |||||
| UInt32 inBusNumber, | UInt32 inBusNumber, | ||||
| UInt32 inNumberFrames, | UInt32 inNumberFrames, | ||||
| AudioBufferList* ioData) const | AudioBufferList* ioData) const | ||||
| @@ -1147,7 +1147,7 @@ private: | |||||
| ->renderGetInput (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); | ->renderGetInput (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); | ||||
| } | } | ||||
| static OSStatus renderMidiOutputCallback (void* hostRef, const AudioTimeStamp* timeStamp, UInt32 midiOutNum, | |||||
| static OSStatus renderMidiOutputCallback (void* hostRef, const AudioTimeStamp*, UInt32 /*midiOutNum*/, | |||||
| const struct MIDIPacketList* pktlist) | const struct MIDIPacketList* pktlist) | ||||
| { | { | ||||
| return static_cast<AudioUnitPluginInstance*> (hostRef)->renderMidiOutput (pktlist); | return static_cast<AudioUnitPluginInstance*> (hostRef)->renderMidiOutput (pktlist); | ||||
| @@ -1331,7 +1331,7 @@ public: | |||||
| startTimer (jmin (713, getTimerInterval() + 51)); | startTimer (jmin (713, getTimerInterval() + 51)); | ||||
| } | } | ||||
| void childBoundsChanged (Component* child) override | |||||
| void childBoundsChanged (Component*) override | |||||
| { | { | ||||
| setSize (wrapper.getWidth(), wrapper.getHeight()); | setSize (wrapper.getWidth(), wrapper.getHeight()); | ||||
| startTimer (70); | startTimer (70); | ||||
| @@ -1675,8 +1675,8 @@ private: | |||||
| void setHostTimeFrameRate (long frameRateIndex, double frameRate, double currentTime) noexcept | void setHostTimeFrameRate (long frameRateIndex, double frameRate, double currentTime) noexcept | ||||
| { | { | ||||
| vstHostTime.flags |= kVstSmpteValid; | vstHostTime.flags |= kVstSmpteValid; | ||||
| vstHostTime.smpteFrameRate = frameRateIndex; | |||||
| vstHostTime.smpteOffset = (long) (currentTime * 80.0 * frameRate + 0.5); | |||||
| vstHostTime.smpteFrameRate = (VstInt32) frameRateIndex; | |||||
| vstHostTime.smpteOffset = (VstInt32) (currentTime * 80.0 * frameRate + 0.5); | |||||
| } | } | ||||
| bool restoreProgramSettings (const fxProgram* const prog) | bool restoreProgramSettings (const fxProgram* const prog) | ||||
| @@ -2510,7 +2510,7 @@ private: | |||||
| deleteWindow(); | deleteWindow(); | ||||
| } | } | ||||
| HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) override | |||||
| HIViewRef attachView (WindowRef windowRef, HIViewRef /*rootView*/) override | |||||
| { | { | ||||
| owner.openPluginWindow (windowRef); | owner.openPluginWindow (windowRef); | ||||
| return 0; | return 0; | ||||
| @@ -37,10 +37,7 @@ | |||||
| #include "../juce_core/native/juce_BasicNativeHeaders.h" | #include "../juce_core/native/juce_BasicNativeHeaders.h" | ||||
| #include "juce_audio_processors.h" | #include "juce_audio_processors.h" | ||||
| #if JUCE_MODULE_AVAILABLE_juce_gui_extra | |||||
| #include "../juce_gui_extra/juce_gui_extra.h" | |||||
| #endif | |||||
| #include "../juce_gui_extra/juce_gui_extra.h" | |||||
| //============================================================================== | //============================================================================== | ||||
| #if JUCE_MAC | #if JUCE_MAC | ||||
| @@ -287,8 +287,8 @@ XmlElement* KnownPluginList::createXml() const | |||||
| { | { | ||||
| XmlElement* const e = new XmlElement ("KNOWNPLUGINS"); | XmlElement* const e = new XmlElement ("KNOWNPLUGINS"); | ||||
| for (int i = 0; i < types.size(); ++i) | |||||
| e->addChildElement (types.getUnchecked(i)->createXml()); | |||||
| for (int i = types.size(); --i >= 0;) | |||||
| e->prependChildElement (types.getUnchecked(i)->createXml()); | |||||
| for (int i = 0; i < blacklist.size(); ++i) | for (int i = 0; i < blacklist.size(); ++i) | ||||
| e->createNewChildElement ("BLACKLISTED")->setAttribute ("id", blacklist[i]); | e->createNewChildElement ("BLACKLISTED")->setAttribute ("id", blacklist[i]); | ||||
| @@ -56,6 +56,11 @@ namespace TokenTypes | |||||
| JUCE_DECLARE_JS_TOKEN (identifier, "$identifier") | JUCE_DECLARE_JS_TOKEN (identifier, "$identifier") | ||||
| } | } | ||||
| #if JUCE_MSVC | |||||
| #pragma warning (push) | |||||
| #pragma warning (disable: 4702) | |||||
| #endif | |||||
| //============================================================================== | //============================================================================== | ||||
| struct JavascriptEngine::RootObject : public DynamicObject | struct JavascriptEngine::RootObject : public DynamicObject | ||||
| { | { | ||||
| @@ -853,8 +858,8 @@ struct JavascriptEngine::RootObject : public DynamicObject | |||||
| bool matchToken (TokenType name, const size_t len) noexcept | bool matchToken (TokenType name, const size_t len) noexcept | ||||
| { | { | ||||
| if (p.compareUpTo (String::CharPointerType (name), len) != 0) return false; | |||||
| p += len; return true; | |||||
| if (p.compareUpTo (CharPointer_ASCII (name), (int) len) != 0) return false; | |||||
| p += (int) len; return true; | |||||
| } | } | ||||
| void skipWhitespaceAndComments() | void skipWhitespaceAndComments() | ||||
| @@ -1211,6 +1216,9 @@ struct JavascriptEngine::RootObject : public DynamicObject | |||||
| return parseSuffixes (s.release()); | return parseSuffixes (s.release()); | ||||
| } | } | ||||
| if (matchIf (TokenTypes::plusplus)) return parsePostIncDec<AdditionOp> (input); | |||||
| if (matchIf (TokenTypes::minusminus)) return parsePostIncDec<SubtractionOp> (input); | |||||
| return input.release(); | return input.release(); | ||||
| } | } | ||||
| @@ -1339,8 +1347,6 @@ struct JavascriptEngine::RootObject : public DynamicObject | |||||
| { | { | ||||
| if (matchIf (TokenTypes::plus)) { ExpPtr b (parseMultiplyDivide()); a = new AdditionOp (location, a, b); } | if (matchIf (TokenTypes::plus)) { ExpPtr b (parseMultiplyDivide()); a = new AdditionOp (location, a, b); } | ||||
| else if (matchIf (TokenTypes::minus)) { ExpPtr b (parseMultiplyDivide()); a = new SubtractionOp (location, a, b); } | else if (matchIf (TokenTypes::minus)) { ExpPtr b (parseMultiplyDivide()); a = new SubtractionOp (location, a, b); } | ||||
| else if (matchIf (TokenTypes::plusplus)) a = parsePostIncDec<AdditionOp> (a); | |||||
| else if (matchIf (TokenTypes::minusminus)) a = parsePostIncDec<SubtractionOp> (a); | |||||
| else break; | else break; | ||||
| } | } | ||||
| @@ -1429,7 +1435,7 @@ struct JavascriptEngine::RootObject : public DynamicObject | |||||
| } | } | ||||
| static Identifier getClassName() { static const Identifier i ("Object"); return i; } | static Identifier getClassName() { static const Identifier i ("Object"); return i; } | ||||
| static var dump (Args a) { DBG (JSON::toString (a.thisObject)); return var::undefined(); } | |||||
| static var dump (Args a) { DBG (JSON::toString (a.thisObject)); (void) a; return var::undefined(); } | |||||
| static var clone (Args a) { return a.thisObject.clone(); } | static var clone (Args a) { return a.thisObject.clone(); } | ||||
| }; | }; | ||||
| @@ -1681,3 +1687,7 @@ var JavascriptEngine::callFunction (Identifier function, const var::NativeFuncti | |||||
| return var::undefined(); | return var::undefined(); | ||||
| } | } | ||||
| #if JUCE_MSVC | |||||
| #pragma warning (pop) | |||||
| #endif | |||||
| @@ -265,7 +265,7 @@ void MemoryBlock::copyTo (void* const dst, int offset, size_t num) const noexcep | |||||
| String MemoryBlock::toString() const | String MemoryBlock::toString() const | ||||
| { | { | ||||
| return String::fromUTF8 (data, size); | |||||
| return String::fromUTF8 (data, (int) size); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -220,7 +220,7 @@ public: | |||||
| initialised = true; | initialised = true; | ||||
| } | } | ||||
| void didSendBodyData (int /*totalBytesWritten*/, int /*totalBytesExpected*/) | |||||
| void didSendBodyData (NSInteger /*totalBytesWritten*/, NSInteger /*totalBytesExpected*/) | |||||
| { | { | ||||
| } | } | ||||
| @@ -114,8 +114,13 @@ bool WaitableEvent::wait (const int timeOutMillisecs) const noexcept | |||||
| void WaitableEvent::signal() const noexcept | void WaitableEvent::signal() const noexcept | ||||
| { | { | ||||
| pthread_mutex_lock (&mutex); | pthread_mutex_lock (&mutex); | ||||
| triggered = true; | |||||
| pthread_cond_broadcast (&condition); | |||||
| if (! triggered) | |||||
| { | |||||
| triggered = true; | |||||
| pthread_cond_broadcast (&condition); | |||||
| } | |||||
| pthread_mutex_unlock (&mutex); | pthread_mutex_unlock (&mutex); | ||||
| } | } | ||||
| @@ -175,7 +175,7 @@ String InputStream::readString() | |||||
| } | } | ||||
| } | } | ||||
| return String::fromUTF8 (data, i); | |||||
| return String::fromUTF8 (data, (int) i); | |||||
| } | } | ||||
| String InputStream::readNextLine() | String InputStream::readNextLine() | ||||
| @@ -36,7 +36,7 @@ | |||||
| */ | */ | ||||
| #define JUCE_MAJOR_VERSION 2 | #define JUCE_MAJOR_VERSION 2 | ||||
| #define JUCE_MINOR_VERSION 1 | #define JUCE_MINOR_VERSION 1 | ||||
| #define JUCE_BUILDNUMBER 6 | |||||
| #define JUCE_BUILDNUMBER 7 | |||||
| /** Current Juce version number. | /** Current Juce version number. | ||||
| @@ -524,41 +524,42 @@ juce_wchar String::operator[] (int index) const noexcept | |||||
| return text [index]; | return text [index]; | ||||
| } | } | ||||
| int String::hashCode() const noexcept | |||||
| template <typename Type> | |||||
| struct HashGenerator | |||||
| { | { | ||||
| int result = 0; | |||||
| template <typename CharPointer> | |||||
| static Type calculate (CharPointer t) noexcept | |||||
| { | |||||
| Type result = Type(); | |||||
| for (CharPointerType t (text); ! t.isEmpty();) | |||||
| result = 31 * result + (int) t.getAndAdvance(); | |||||
| while (! t.isEmpty()) | |||||
| result = multiplier * result + t.getAndAdvance(); | |||||
| return result; | |||||
| } | |||||
| return result; | |||||
| } | |||||
| int64 String::hashCode64() const noexcept | |||||
| { | |||||
| int64 result = 0; | |||||
| enum { multiplier = sizeof (Type) > 4 ? 101 : 31 }; | |||||
| }; | |||||
| for (CharPointerType t (text); ! t.isEmpty();) | |||||
| result = 101 * result + t.getAndAdvance(); | |||||
| return result; | |||||
| } | |||||
| int String::hashCode() const noexcept { return HashGenerator<int> ::calculate (text); } | |||||
| int64 String::hashCode64() const noexcept { return HashGenerator<int64> ::calculate (text); } | |||||
| std::size_t String::hash() const noexcept { return HashGenerator<std::size_t>::calculate (text); } | |||||
| //============================================================================== | //============================================================================== | ||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const String& s2) noexcept { return s1.compare (s2) == 0; } | JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const String& s2) noexcept { return s1.compare (s2) == 0; } | ||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const char* const s2) noexcept { return s1.compare (s2) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const wchar_t* const s2) noexcept { return s1.compare (s2) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const CharPointer_UTF8 s2) noexcept { return s1.getCharPointer().compare (s2) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const CharPointer_UTF16 s2) noexcept { return s1.getCharPointer().compare (s2) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const CharPointer_UTF32 s2) noexcept { return s1.getCharPointer().compare (s2) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, StringRef s2) noexcept { return s1.getCharPointer().compare (s2.text) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const String& s2) noexcept { return s1.compare (s2) != 0; } | JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const String& s2) noexcept { return s1.compare (s2) != 0; } | ||||
| JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const char* const s2) noexcept { return s1.compare (s2) != 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const wchar_t* const s2) noexcept { return s1.compare (s2) != 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const char* s2) noexcept { return s1.compare (s2) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const char* s2) noexcept { return s1.compare (s2) != 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const wchar_t* s2) noexcept { return s1.compare (s2) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const wchar_t* s2) noexcept { return s1.compare (s2) != 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, StringRef s2) noexcept { return s1.getCharPointer().compare (s2.text) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, StringRef s2) noexcept { return s1.getCharPointer().compare (s2.text) != 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const CharPointer_UTF8 s2) noexcept { return s1.getCharPointer().compare (s2) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const CharPointer_UTF8 s2) noexcept { return s1.getCharPointer().compare (s2) != 0; } | JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const CharPointer_UTF8 s2) noexcept { return s1.getCharPointer().compare (s2) != 0; } | ||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const CharPointer_UTF16 s2) noexcept { return s1.getCharPointer().compare (s2) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const CharPointer_UTF16 s2) noexcept { return s1.getCharPointer().compare (s2) != 0; } | JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const CharPointer_UTF16 s2) noexcept { return s1.getCharPointer().compare (s2) != 0; } | ||||
| JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const CharPointer_UTF32 s2) noexcept { return s1.getCharPointer().compare (s2) == 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const CharPointer_UTF32 s2) noexcept { return s1.getCharPointer().compare (s2) != 0; } | JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, const CharPointer_UTF32 s2) noexcept { return s1.getCharPointer().compare (s2) != 0; } | ||||
| JUCE_API bool JUCE_CALLTYPE operator!= (const String& s1, StringRef s2) noexcept { return s1.getCharPointer().compare (s2.text) != 0; } | |||||
| JUCE_API bool JUCE_CALLTYPE operator> (const String& s1, const String& s2) noexcept { return s1.compare (s2) > 0; } | JUCE_API bool JUCE_CALLTYPE operator> (const String& s1, const String& s2) noexcept { return s1.compare (s2) > 0; } | ||||
| JUCE_API bool JUCE_CALLTYPE operator< (const String& s1, const String& s2) noexcept { return s1.compare (s2) < 0; } | JUCE_API bool JUCE_CALLTYPE operator< (const String& s1, const String& s2) noexcept { return s1.compare (s2) < 0; } | ||||
| JUCE_API bool JUCE_CALLTYPE operator>= (const String& s1, const String& s2) noexcept { return s1.compare (s2) >= 0; } | JUCE_API bool JUCE_CALLTYPE operator>= (const String& s1, const String& s2) noexcept { return s1.compare (s2) >= 0; } | ||||
| @@ -180,6 +180,9 @@ public: | |||||
| /** Generates a probably-unique 64-bit hashcode from this string. */ | /** Generates a probably-unique 64-bit hashcode from this string. */ | ||||
| int64 hashCode64() const noexcept; | int64 hashCode64() const noexcept; | ||||
| /** Generates a probably-unique hashcode from this string. */ | |||||
| std::size_t hash() const noexcept; | |||||
| /** Returns the number of characters in the string. */ | /** Returns the number of characters in the string. */ | ||||
| int length() const noexcept; | int length() const noexcept; | ||||
| @@ -585,18 +585,36 @@ XmlElement* XmlElement::getChildByAttribute (StringRef attributeName, StringRef | |||||
| void XmlElement::addChildElement (XmlElement* const newNode) noexcept | void XmlElement::addChildElement (XmlElement* const newNode) noexcept | ||||
| { | { | ||||
| if (newNode != nullptr) | if (newNode != nullptr) | ||||
| { | |||||
| // The element being added must not be a child of another node! | |||||
| jassert (newNode->nextListItem == nullptr); | |||||
| firstChildElement.append (newNode); | firstChildElement.append (newNode); | ||||
| } | |||||
| } | } | ||||
| void XmlElement::insertChildElement (XmlElement* const newNode, int indexToInsertAt) noexcept | void XmlElement::insertChildElement (XmlElement* const newNode, int indexToInsertAt) noexcept | ||||
| { | { | ||||
| if (newNode != nullptr) | if (newNode != nullptr) | ||||
| { | { | ||||
| removeChildElement (newNode, false); | |||||
| // The element being added must not be a child of another node! | |||||
| jassert (newNode->nextListItem == nullptr); | |||||
| firstChildElement.insertAtIndex (indexToInsertAt, newNode); | firstChildElement.insertAtIndex (indexToInsertAt, newNode); | ||||
| } | } | ||||
| } | } | ||||
| void XmlElement::prependChildElement (XmlElement* newNode) noexcept | |||||
| { | |||||
| if (newNode != nullptr) | |||||
| { | |||||
| // The element being added must not be a child of another node! | |||||
| jassert (newNode->nextListItem == nullptr); | |||||
| firstChildElement.insertNext (newNode); | |||||
| } | |||||
| } | |||||
| XmlElement* XmlElement::createNewChildElement (const String& childTagName) | XmlElement* XmlElement::createNewChildElement (const String& childTagName) | ||||
| { | { | ||||
| XmlElement* const newElement = new XmlElement (childTagName); | XmlElement* const newElement = new XmlElement (childTagName); | ||||
| @@ -504,6 +504,10 @@ public: | |||||
| make sure the object that you pass in will not be deleted by anything else, | make sure the object that you pass in will not be deleted by anything else, | ||||
| and make sure it's not already the child of another element. | and make sure it's not already the child of another element. | ||||
| Note that due to the XmlElement using a singly-linked-list, prependChildElement() | |||||
| is an O(1) operation, but addChildElement() is an O(N) operation - so if | |||||
| you're adding large number of elements, you may prefer to do so in reverse order! | |||||
| @see getFirstChildElement, getNextElement, getNumChildElements, | @see getFirstChildElement, getNextElement, getNumChildElements, | ||||
| getChildElement, removeChildElement | getChildElement, removeChildElement | ||||
| */ | */ | ||||
| @@ -515,14 +519,28 @@ public: | |||||
| make sure the object that you pass in will not be deleted by anything else, | make sure the object that you pass in will not be deleted by anything else, | ||||
| and make sure it's not already the child of another element. | and make sure it's not already the child of another element. | ||||
| @param newChildNode the element to add | |||||
| @param newChildElement the element to add | |||||
| @param indexToInsertAt the index at which to insert the new element - if this is | @param indexToInsertAt the index at which to insert the new element - if this is | ||||
| below zero, it will be added to the end of the list | below zero, it will be added to the end of the list | ||||
| @see addChildElement, insertChildElement | @see addChildElement, insertChildElement | ||||
| */ | */ | ||||
| void insertChildElement (XmlElement* newChildNode, | |||||
| void insertChildElement (XmlElement* newChildElement, | |||||
| int indexToInsertAt) noexcept; | int indexToInsertAt) noexcept; | ||||
| /** Inserts an element at the beginning of this element's list of children. | |||||
| Child elements are deleted automatically when their parent is deleted, so | |||||
| make sure the object that you pass in will not be deleted by anything else, | |||||
| and make sure it's not already the child of another element. | |||||
| Note that due to the XmlElement using a singly-linked-list, prependChildElement() | |||||
| is an O(1) operation, but addChildElement() is an O(N) operation - so if | |||||
| you're adding large number of elements, you may prefer to do so in reverse order! | |||||
| @see addChildElement, insertChildElement | |||||
| */ | |||||
| void prependChildElement (XmlElement* newChildElement) noexcept; | |||||
| /** Creates a new element with the given name and returns it, after adding it | /** Creates a new element with the given name and returns it, after adding it | ||||
| as a child element. | as a child element. | ||||
| @@ -412,8 +412,9 @@ public: | |||||
| XmlElement* const xml = new XmlElement (type.toString()); | XmlElement* const xml = new XmlElement (type.toString()); | ||||
| properties.copyToXmlAttributes (*xml); | properties.copyToXmlAttributes (*xml); | ||||
| for (int i = 0; i < children.size(); ++i) | |||||
| xml->addChildElement (children.getObjectPointerUnchecked(i)->createXml()); | |||||
| // (NB: it's faster to add nodes to XML elements in reverse order) | |||||
| for (int i = children.size(); --i >= 0;) | |||||
| xml->prependChildElement (children.getObjectPointerUnchecked(i)->createXml()); | |||||
| return xml; | return xml; | ||||
| } | } | ||||
| @@ -89,7 +89,7 @@ public: | |||||
| #else | #else | ||||
| #if JUCE_WINDOWS | #if JUCE_WINDOWS | ||||
| #if defined (WINAPI) || defined (_WINDOWS_) | |||||
| #if defined (WINAPI) || defined (_WINDOWS_) || defined(JUCE_MINGW) | |||||
| #define JUCE_MAIN_FUNCTION int __stdcall WinMain (HINSTANCE, HINSTANCE, const LPSTR, int) | #define JUCE_MAIN_FUNCTION int __stdcall WinMain (HINSTANCE, HINSTANCE, const LPSTR, int) | ||||
| #elif defined (_UNICODE) | #elif defined (_UNICODE) | ||||
| #define JUCE_MAIN_FUNCTION int __stdcall WinMain (void*, void*, const wchar_t*, int) | #define JUCE_MAIN_FUNCTION int __stdcall WinMain (void*, void*, const wchar_t*, int) | ||||
| @@ -333,6 +333,18 @@ void MessageManager::broadcastMessage (const String& message) | |||||
| void repostCurrentNSEvent(); | void repostCurrentNSEvent(); | ||||
| void repostCurrentNSEvent() | void repostCurrentNSEvent() | ||||
| { | { | ||||
| NSEvent* e = [NSApp currentEvent]; | |||||
| [[NSOperationQueue mainQueue] addOperationWithBlock: ^{ [NSApp postEvent: e atStart: YES]; }]; | |||||
| struct EventReposter : public CallbackMessage | |||||
| { | |||||
| EventReposter() : e ([[NSApp currentEvent] retain]) {} | |||||
| ~EventReposter() { [e release]; } | |||||
| void messageCallback() override | |||||
| { | |||||
| [NSApp postEvent: e atStart: YES]; | |||||
| } | |||||
| NSEvent* e; | |||||
| }; | |||||
| (new EventReposter())->post(); | |||||
| } | } | ||||
| @@ -155,9 +155,19 @@ void Typeface::setTypefaceCacheSize (int numFontsToCache) | |||||
| TypefaceCache::getInstance()->setSize (numFontsToCache); | TypefaceCache::getInstance()->setSize (numFontsToCache); | ||||
| } | } | ||||
| #if JUCE_MODULE_AVAILABLE_juce_opengl | |||||
| extern void clearOpenGLGlyphCache(); | |||||
| #endif | |||||
| void Typeface::clearTypefaceCache() | void Typeface::clearTypefaceCache() | ||||
| { | { | ||||
| TypefaceCache::getInstance()->clear(); | TypefaceCache::getInstance()->clear(); | ||||
| RenderingHelpers::SoftwareRendererSavedState::clearGlyphCache(); | |||||
| #if JUCE_MODULE_AVAILABLE_juce_opengl | |||||
| clearOpenGLGlyphCache(); | |||||
| #endif | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -69,48 +69,45 @@ bool PathFlatteningIterator::next() | |||||
| float y3 = 0; | float y3 = 0; | ||||
| float x4 = 0; | float x4 = 0; | ||||
| float y4 = 0; | float y4 = 0; | ||||
| float type; | |||||
| for (;;) | for (;;) | ||||
| { | { | ||||
| float type; | |||||
| if (stackPos == stackBase) | if (stackPos == stackBase) | ||||
| { | { | ||||
| if (index >= path.numElements) | if (index >= path.numElements) | ||||
| { | |||||
| return false; | return false; | ||||
| } | |||||
| else | |||||
| type = points [index++]; | |||||
| if (type != Path::closeSubPathMarker) | |||||
| { | { | ||||
| type = points [index++]; | |||||
| x2 = points [index++]; | |||||
| y2 = points [index++]; | |||||
| if (type == Path::quadMarker) | |||||
| { | |||||
| x3 = points [index++]; | |||||
| y3 = points [index++]; | |||||
| if (! isIdentityTransform) | |||||
| transform.transformPoints (x2, y2, x3, y3); | |||||
| } | |||||
| else if (type == Path::cubicMarker) | |||||
| { | |||||
| x3 = points [index++]; | |||||
| y3 = points [index++]; | |||||
| x4 = points [index++]; | |||||
| y4 = points [index++]; | |||||
| if (type != Path::closeSubPathMarker) | |||||
| if (! isIdentityTransform) | |||||
| transform.transformPoints (x2, y2, x3, y3, x4, y4); | |||||
| } | |||||
| else | |||||
| { | { | ||||
| x2 = points [index++]; | |||||
| y2 = points [index++]; | |||||
| if (type == Path::quadMarker) | |||||
| { | |||||
| x3 = points [index++]; | |||||
| y3 = points [index++]; | |||||
| if (! isIdentityTransform) | |||||
| transform.transformPoints (x2, y2, x3, y3); | |||||
| } | |||||
| else if (type == Path::cubicMarker) | |||||
| { | |||||
| x3 = points [index++]; | |||||
| y3 = points [index++]; | |||||
| x4 = points [index++]; | |||||
| y4 = points [index++]; | |||||
| if (! isIdentityTransform) | |||||
| transform.transformPoints (x2, y2, x3, y3, x4, y4); | |||||
| } | |||||
| else | |||||
| { | |||||
| if (! isIdentityTransform) | |||||
| transform.transformPoint (x2, y2); | |||||
| } | |||||
| if (! isIdentityTransform) | |||||
| transform.transformPoint (x2, y2); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -150,7 +147,8 @@ bool PathFlatteningIterator::next() | |||||
| return true; | return true; | ||||
| } | } | ||||
| else if (type == Path::quadMarker) | |||||
| if (type == Path::quadMarker) | |||||
| { | { | ||||
| const size_t offset = (size_t) (stackPos - stackBase); | const size_t offset = (size_t) (stackPos - stackBase); | ||||
| @@ -190,61 +190,73 @@ public: | |||||
| Rectangle withZeroOrigin() const noexcept { return Rectangle (w, h); } | Rectangle withZeroOrigin() const noexcept { return Rectangle (w, h); } | ||||
| /** Returns a rectangle which has the same position and height as this one, but with a different width. */ | /** Returns a rectangle which has the same position and height as this one, but with a different width. */ | ||||
| Rectangle withWidth (const ValueType newWidth) const noexcept { return Rectangle (pos.x, pos.y, newWidth, h); } | |||||
| Rectangle withWidth (ValueType newWidth) const noexcept { return Rectangle (pos.x, pos.y, newWidth, h); } | |||||
| /** Returns a rectangle which has the same position and width as this one, but with a different height. */ | /** Returns a rectangle which has the same position and width as this one, but with a different height. */ | ||||
| Rectangle withHeight (const ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, w, newHeight); } | |||||
| Rectangle withHeight (ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, w, newHeight); } | |||||
| /** Returns a rectangle with the same position as this one, but a new size. */ | /** Returns a rectangle with the same position as this one, but a new size. */ | ||||
| Rectangle withSize (const ValueType newWidth, const ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, newWidth, newHeight); } | |||||
| Rectangle withSize (ValueType newWidth, const ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, newWidth, newHeight); } | |||||
| /** Moves the x position, adjusting the width so that the right-hand edge remains in the same place. | /** Moves the x position, adjusting the width so that the right-hand edge remains in the same place. | ||||
| If the x is moved to be on the right of the current right-hand edge, the width will be set to zero. | If the x is moved to be on the right of the current right-hand edge, the width will be set to zero. | ||||
| @see withLeft | @see withLeft | ||||
| */ | */ | ||||
| void setLeft (const ValueType newLeft) noexcept { w = jmax (ValueType(), pos.x + w - newLeft); pos.x = newLeft; } | |||||
| void setLeft (ValueType newLeft) noexcept { w = jmax (ValueType(), pos.x + w - newLeft); pos.x = newLeft; } | |||||
| /** Returns a new rectangle with a different x position, but the same right-hand edge as this one. | /** Returns a new rectangle with a different x position, but the same right-hand edge as this one. | ||||
| If the new x is beyond the right of the current right-hand edge, the width will be set to zero. | If the new x is beyond the right of the current right-hand edge, the width will be set to zero. | ||||
| @see setLeft | @see setLeft | ||||
| */ | */ | ||||
| Rectangle withLeft (const ValueType newLeft) const noexcept { return Rectangle (newLeft, pos.y, jmax (ValueType(), pos.x + w - newLeft), h); } | |||||
| Rectangle withLeft (ValueType newLeft) const noexcept { return Rectangle (newLeft, pos.y, jmax (ValueType(), pos.x + w - newLeft), h); } | |||||
| /** Moves the y position, adjusting the height so that the bottom edge remains in the same place. | /** Moves the y position, adjusting the height so that the bottom edge remains in the same place. | ||||
| If the y is moved to be below the current bottom edge, the height will be set to zero. | If the y is moved to be below the current bottom edge, the height will be set to zero. | ||||
| @see withTop | @see withTop | ||||
| */ | */ | ||||
| void setTop (const ValueType newTop) noexcept { h = jmax (ValueType(), pos.y + h - newTop); pos.y = newTop; } | |||||
| void setTop (ValueType newTop) noexcept { h = jmax (ValueType(), pos.y + h - newTop); pos.y = newTop; } | |||||
| /** Returns a new rectangle with a different y position, but the same bottom edge as this one. | /** Returns a new rectangle with a different y position, but the same bottom edge as this one. | ||||
| If the new y is beyond the bottom of the current rectangle, the height will be set to zero. | If the new y is beyond the bottom of the current rectangle, the height will be set to zero. | ||||
| @see setTop | @see setTop | ||||
| */ | */ | ||||
| Rectangle withTop (const ValueType newTop) const noexcept { return Rectangle (pos.x, newTop, w, jmax (ValueType(), pos.y + h - newTop)); } | |||||
| Rectangle withTop (ValueType newTop) const noexcept { return Rectangle (pos.x, newTop, w, jmax (ValueType(), pos.y + h - newTop)); } | |||||
| /** Adjusts the width so that the right-hand edge of the rectangle has this new value. | /** Adjusts the width so that the right-hand edge of the rectangle has this new value. | ||||
| If the new right is below the current X value, the X will be pushed down to match it. | If the new right is below the current X value, the X will be pushed down to match it. | ||||
| @see getRight, withRight | @see getRight, withRight | ||||
| */ | */ | ||||
| void setRight (const ValueType newRight) noexcept { pos.x = jmin (pos.x, newRight); w = newRight - pos.x; } | |||||
| void setRight (ValueType newRight) noexcept { pos.x = jmin (pos.x, newRight); w = newRight - pos.x; } | |||||
| /** Returns a new rectangle with a different right-hand edge position, but the same left-hand edge as this one. | /** Returns a new rectangle with a different right-hand edge position, but the same left-hand edge as this one. | ||||
| If the new right edge is below the current left-hand edge, the width will be set to zero. | If the new right edge is below the current left-hand edge, the width will be set to zero. | ||||
| @see setRight | @see setRight | ||||
| */ | */ | ||||
| Rectangle withRight (const ValueType newRight) const noexcept { return Rectangle (jmin (pos.x, newRight), pos.y, jmax (ValueType(), newRight - pos.x), h); } | |||||
| Rectangle withRight (ValueType newRight) const noexcept { return Rectangle (jmin (pos.x, newRight), pos.y, jmax (ValueType(), newRight - pos.x), h); } | |||||
| /** Adjusts the height so that the bottom edge of the rectangle has this new value. | /** Adjusts the height so that the bottom edge of the rectangle has this new value. | ||||
| If the new bottom is lower than the current Y value, the Y will be pushed down to match it. | If the new bottom is lower than the current Y value, the Y will be pushed down to match it. | ||||
| @see getBottom, withBottom | @see getBottom, withBottom | ||||
| */ | */ | ||||
| void setBottom (const ValueType newBottom) noexcept { pos.y = jmin (pos.y, newBottom); h = newBottom - pos.y; } | |||||
| void setBottom (ValueType newBottom) noexcept { pos.y = jmin (pos.y, newBottom); h = newBottom - pos.y; } | |||||
| /** Returns a new rectangle with a different bottom edge position, but the same top edge as this one. | /** Returns a new rectangle with a different bottom edge position, but the same top edge as this one. | ||||
| If the new y is beyond the bottom of the current rectangle, the height will be set to zero. | If the new y is beyond the bottom of the current rectangle, the height will be set to zero. | ||||
| @see setBottom | @see setBottom | ||||
| */ | */ | ||||
| Rectangle withBottom (const ValueType newBottom) const noexcept { return Rectangle (pos.x, jmin (pos.y, newBottom), w, jmax (ValueType(), newBottom - pos.y)); } | |||||
| Rectangle withBottom (ValueType newBottom) const noexcept { return Rectangle (pos.x, jmin (pos.y, newBottom), w, jmax (ValueType(), newBottom - pos.y)); } | |||||
| /** Returns a version of this rectangle with the given amount removed from its left-hand edge. */ | |||||
| Rectangle withTrimmedLeft (ValueType amountToRemove) const noexcept { return withLeft (pos.x + amountToRemove); } | |||||
| /** Returns a version of this rectangle with the given amount removed from its right-hand edge. */ | |||||
| Rectangle withTrimmedRight (ValueType amountToRemove) const noexcept { return withWidth (w - amountToRemove); } | |||||
| /** Returns a version of this rectangle with the given amount removed from its top edge. */ | |||||
| Rectangle withTrimmedTop (ValueType amountToRemove) const noexcept { return withTop (pos.y + amountToRemove); } | |||||
| /** Returns a version of this rectangle with the given amount removed from its bottom edge. */ | |||||
| Rectangle withTrimmedBottom (ValueType amountToRemove) const noexcept { return withHeight (h - amountToRemove); } | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Moves the rectangle's position by adding amount to its x and y coordinates. */ | /** Moves the rectangle's position by adding amount to its x and y coordinates. */ | ||||
| @@ -142,7 +142,7 @@ class GlyphCache : private DeletedAtShutdown | |||||
| public: | public: | ||||
| GlyphCache() | GlyphCache() | ||||
| { | { | ||||
| addNewGlyphSlots (120); | |||||
| reset(); | |||||
| } | } | ||||
| ~GlyphCache() | ~GlyphCache() | ||||
| @@ -207,6 +207,15 @@ public: | |||||
| glyph->draw (target, pos); | glyph->draw (target, pos); | ||||
| } | } | ||||
| void reset() | |||||
| { | |||||
| const ScopedWriteLock swl (lock); | |||||
| glyphs.clear(); | |||||
| addNewGlyphSlots (120); | |||||
| hits.set (0); | |||||
| misses.set (0); | |||||
| } | |||||
| private: | private: | ||||
| friend struct ContainerDeletePolicy<CachedGlyphType>; | friend struct ContainerDeletePolicy<CachedGlyphType>; | ||||
| OwnedArray<CachedGlyphType> glyphs; | OwnedArray<CachedGlyphType> glyphs; | ||||
| @@ -215,6 +224,8 @@ private: | |||||
| void addNewGlyphSlots (int num) | void addNewGlyphSlots (int num) | ||||
| { | { | ||||
| glyphs.ensureStorageAllocated (glyphs.size() + num); | |||||
| while (--num >= 0) | while (--num >= 0) | ||||
| glyphs.add (new CachedGlyphType()); | glyphs.add (new CachedGlyphType()); | ||||
| } | } | ||||
| @@ -2419,6 +2430,13 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| typedef GlyphCache<CachedGlyphEdgeTable <SoftwareRendererSavedState>, SoftwareRendererSavedState> GlyphCacheType; | |||||
| static void clearGlyphCache() | |||||
| { | |||||
| GlyphCacheType::getInstance().reset(); | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| void drawGlyph (int glyphNumber, const AffineTransform& trans) | void drawGlyph (int glyphNumber, const AffineTransform& trans) | ||||
| { | { | ||||
| @@ -2426,8 +2444,6 @@ public: | |||||
| { | { | ||||
| if (trans.isOnlyTranslation() && ! transform.isRotated) | if (trans.isOnlyTranslation() && ! transform.isRotated) | ||||
| { | { | ||||
| typedef GlyphCache <CachedGlyphEdgeTable <SoftwareRendererSavedState>, SoftwareRendererSavedState> GlyphCacheType; | |||||
| GlyphCacheType& cache = GlyphCacheType::getInstance(); | GlyphCacheType& cache = GlyphCacheType::getInstance(); | ||||
| Point<float> pos (trans.getTranslationX(), trans.getTranslationY()); | Point<float> pos (trans.getTranslationX(), trans.getTranslationY()); | ||||
| @@ -340,7 +340,7 @@ namespace CoreTextTypeLayout | |||||
| CFArrayRef lines = CTFrameGetLines (frame); | CFArrayRef lines = CTFrameGetLines (frame); | ||||
| const CFIndex numLines = CFArrayGetCount (lines); | const CFIndex numLines = CFArrayGetCount (lines); | ||||
| glyphLayout.ensureStorageAllocated (numLines); | |||||
| glyphLayout.ensureStorageAllocated ((int) numLines); | |||||
| for (CFIndex i = 0; i < numLines; ++i) | for (CFIndex i = 0; i < numLines; ++i) | ||||
| { | { | ||||
| @@ -309,7 +309,8 @@ void Button::internalClickCallback (const ModifierKeys& modifiers) | |||||
| { | { | ||||
| if (clickTogglesState) | if (clickTogglesState) | ||||
| setToggleState (radioGroupId != 0 || ! lastToggleState, sendNotification); | setToggleState (radioGroupId != 0 || ! lastToggleState, sendNotification); | ||||
| else | |||||
| if (radioGroupId != 0 || ! clickTogglesState) | |||||
| sendClickMessage (modifiers); | sendClickMessage (modifiers); | ||||
| } | } | ||||
| @@ -355,6 +355,33 @@ public: | |||||
| // This method's parameters have changed - see the new version. | // This method's parameters have changed - see the new version. | ||||
| JUCE_DEPRECATED (void setToggleState (bool, bool)); | JUCE_DEPRECATED (void setToggleState (bool, bool)); | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| button-drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawButtonBackground (Graphics&, Button& button, const Colour& backgroundColour, | |||||
| bool isMouseOverButton, bool isButtonDown) = 0; | |||||
| virtual Font getTextButtonFont (TextButton& button) = 0; | |||||
| /** Draws the text for a TextButton. */ | |||||
| virtual void drawButtonText (Graphics&, TextButton&, bool isMouseOverButton, bool isButtonDown) = 0; | |||||
| /** Draws the contents of a standard ToggleButton. */ | |||||
| virtual void drawToggleButton (Graphics&, ToggleButton&, bool isMouseOverButton, bool isButtonDown) = 0; | |||||
| virtual void changeToggleButtonWidthToFitText (ToggleButton&) = 0; | |||||
| virtual void drawTickBox (Graphics&, Component&, float x, float y, float w, float h, | |||||
| bool ticked, bool isEnabled, bool isMouseOverButton, bool isButtonDown) = 0; | |||||
| virtual void drawDrawableButton (Graphics&, DrawableButton&, bool isMouseOverButton, bool isButtonDown) = 0; | |||||
| }; | |||||
| protected: | protected: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** This method is called when the button has been clicked. | /** This method is called when the button has been clicked. | ||||
| @@ -124,6 +124,17 @@ public: | |||||
| */ | */ | ||||
| Image getDownImage() const; | Image getDownImage() const; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawImageButton (Graphics&, Image*, | |||||
| int imageX, int imageY, int imageW, int imageH, | |||||
| const Colour& overlayColour, float imageOpacity, ImageButton&) = 0; | |||||
| }; | |||||
| protected: | protected: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| @@ -24,34 +24,32 @@ | |||||
| ShapeButton::ShapeButton (const String& t, Colour n, Colour o, Colour d) | ShapeButton::ShapeButton (const String& t, Colour n, Colour o, Colour d) | ||||
| : Button (t), | : Button (t), | ||||
| normalColour (n), | |||||
| overColour (o), | |||||
| downColour (d), | |||||
| normalColour (n), overColour (o), downColour (d), | |||||
| maintainShapeProportions (false), | maintainShapeProportions (false), | ||||
| outlineWidth (0.0f) | outlineWidth (0.0f) | ||||
| { | { | ||||
| } | } | ||||
| ShapeButton::~ShapeButton() | |||||
| { | |||||
| } | |||||
| ShapeButton::~ShapeButton() {} | |||||
| void ShapeButton::setColours (Colour newNormalColour, | |||||
| Colour newOverColour, | |||||
| Colour newDownColour) | |||||
| void ShapeButton::setColours (Colour newNormalColour, Colour newOverColour, Colour newDownColour) | |||||
| { | { | ||||
| normalColour = newNormalColour; | normalColour = newNormalColour; | ||||
| overColour = newOverColour; | overColour = newOverColour; | ||||
| downColour = newDownColour; | downColour = newDownColour; | ||||
| } | } | ||||
| void ShapeButton::setOutline (Colour newOutlineColour, | |||||
| const float newOutlineWidth) | |||||
| void ShapeButton::setOutline (Colour newOutlineColour, const float newOutlineWidth) | |||||
| { | { | ||||
| outlineColour = newOutlineColour; | outlineColour = newOutlineColour; | ||||
| outlineWidth = newOutlineWidth; | outlineWidth = newOutlineWidth; | ||||
| } | } | ||||
| void ShapeButton::setBorderSize (BorderSize<int> newBorder) | |||||
| { | |||||
| border = newBorder; | |||||
| } | |||||
| void ShapeButton::setShape (const Path& newShape, | void ShapeButton::setShape (const Path& newShape, | ||||
| const bool resizeNowToFitThisShape, | const bool resizeNowToFitThisShape, | ||||
| const bool maintainShapeProportions_, | const bool maintainShapeProportions_, | ||||
| @@ -73,8 +71,8 @@ void ShapeButton::setShape (const Path& newShape, | |||||
| shape.applyTransform (AffineTransform::translation (-newBounds.getX(), | shape.applyTransform (AffineTransform::translation (-newBounds.getX(), | ||||
| -newBounds.getY())); | -newBounds.getY())); | ||||
| setSize (1 + (int) (newBounds.getWidth() + outlineWidth), | |||||
| 1 + (int) (newBounds.getHeight() + outlineWidth)); | |||||
| setSize (1 + (int) (newBounds.getWidth() + outlineWidth) + border.getLeftAndRight(), | |||||
| 1 + (int) (newBounds.getHeight() + outlineWidth) + border.getTopAndBottom()); | |||||
| } | } | ||||
| repaint(); | repaint(); | ||||
| @@ -88,7 +86,7 @@ void ShapeButton::paintButton (Graphics& g, bool isMouseOverButton, bool isButto | |||||
| isButtonDown = false; | isButtonDown = false; | ||||
| } | } | ||||
| Rectangle<float> r (getLocalBounds().toFloat().reduced (outlineWidth * 0.5f)); | |||||
| Rectangle<float> r (border.subtractedFrom (getLocalBounds()).toFloat().reduced (outlineWidth * 0.5f)); | |||||
| if (getComponentEffect() != nullptr) | if (getComponentEffect() != nullptr) | ||||
| r = r.reduced (2.0f); | r = r.reduced (2.0f); | ||||
| @@ -80,8 +80,12 @@ public: | |||||
| @param outlineColour the colour to use | @param outlineColour the colour to use | ||||
| @param outlineStrokeWidth the thickness of line to draw | @param outlineStrokeWidth the thickness of line to draw | ||||
| */ | */ | ||||
| void setOutline (Colour outlineColour, | |||||
| float outlineStrokeWidth); | |||||
| void setOutline (Colour outlineColour, float outlineStrokeWidth); | |||||
| /** This lets you specify a border to be left around the edge of the button when | |||||
| drawing the shape. | |||||
| */ | |||||
| void setBorderSize (BorderSize<int> border); | |||||
| /** @internal */ | /** @internal */ | ||||
| void paintButton (Graphics&, bool isMouseOverButton, bool isButtonDown) override; | void paintButton (Graphics&, bool isMouseOverButton, bool isButtonDown) override; | ||||
| @@ -91,6 +95,7 @@ private: | |||||
| Colour normalColour, overColour, downColour, outlineColour; | Colour normalColour, overColour, downColour, outlineColour; | ||||
| DropShadowEffect shadow; | DropShadowEffect shadow; | ||||
| Path shape; | Path shape; | ||||
| BorderSize<int> border; | |||||
| bool maintainShapeProportions; | bool maintainShapeProportions; | ||||
| float outlineWidth; | float outlineWidth; | ||||
| @@ -89,7 +89,7 @@ LookAndFeel& Desktop::getDefaultLookAndFeel() noexcept | |||||
| if (currentLookAndFeel == nullptr) | if (currentLookAndFeel == nullptr) | ||||
| { | { | ||||
| if (defaultLookAndFeel == nullptr) | if (defaultLookAndFeel == nullptr) | ||||
| defaultLookAndFeel = new LookAndFeel(); | |||||
| defaultLookAndFeel = new LookAndFeel_V2(); | |||||
| currentLookAndFeel = defaultLookAndFeel; | currentLookAndFeel = defaultLookAndFeel; | ||||
| } | } | ||||
| @@ -56,6 +56,7 @@ void DirectoryContentsList::setDirectory (const File& directory, | |||||
| { | { | ||||
| clear(); | clear(); | ||||
| root = directory; | root = directory; | ||||
| changed(); | |||||
| // (this forces a refresh when setTypeFlags() is called, rather than triggering two refreshes) | // (this forces a refresh when setTypeFlags() is called, rather than triggering two refreshes) | ||||
| fileTypeFlags &= ~(File::findDirectories | File::findFiles); | fileTypeFlags &= ~(File::findDirectories | File::findFiles); | ||||
| @@ -177,6 +177,42 @@ public: | |||||
| */ | */ | ||||
| static void getDefaultRoots (StringArray& rootNames, StringArray& rootPaths); | static void getDefaultRoots (StringArray& rootNames, StringArray& rootPaths); | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| various file-browser layout and drawing methods. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| // These return a pointer to an internally cached drawable - make sure you don't keep | |||||
| // a copy of this pointer anywhere, as it may become invalid in the future. | |||||
| virtual const Drawable* getDefaultFolderImage() = 0; | |||||
| virtual const Drawable* getDefaultDocumentFileImage() = 0; | |||||
| virtual AttributedString createFileChooserHeaderText (const String& title, | |||||
| const String& instructions) = 0; | |||||
| virtual void drawFileBrowserRow (Graphics&, int width, int height, | |||||
| const String& filename, | |||||
| Image* optionalIcon, | |||||
| const String& fileSizeDescription, | |||||
| const String& fileTimeDescription, | |||||
| bool isDirectory, | |||||
| bool isItemSelected, | |||||
| int itemIndex, | |||||
| DirectoryContentsDisplayComponent&) = 0; | |||||
| virtual Button* createFileBrowserGoUpButton() = 0; | |||||
| virtual void layoutFileBrowserComponent (FileBrowserComponent& browserComp, | |||||
| DirectoryContentsDisplayComponent* fileListComponent, | |||||
| FilePreviewComponent* previewComp, | |||||
| ComboBox* currentPathBox, | |||||
| TextEditor* filenameBox, | |||||
| Button* goUpButton) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void resized() override; | void resized() override; | ||||
| @@ -180,6 +180,16 @@ public: | |||||
| /** Gives the component a tooltip. */ | /** Gives the component a tooltip. */ | ||||
| void setTooltip (const String& newTooltip) override; | void setTooltip (const String& newTooltip) override; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual Button* createFilenameComponentBrowseButton (const String& text) = 0; | |||||
| virtual void layoutFilenameComponent (FilenameComponent&, ComboBox* filenameBox, Button* browseButton) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void paintOverChildren (Graphics&) override; | void paintOverChildren (Graphics&) override; | ||||
| @@ -198,6 +198,9 @@ extern bool juce_areThereAnyAlwaysOnTopWindows(); | |||||
| #include "layout/juce_TabbedComponent.cpp" | #include "layout/juce_TabbedComponent.cpp" | ||||
| #include "layout/juce_Viewport.cpp" | #include "layout/juce_Viewport.cpp" | ||||
| #include "lookandfeel/juce_LookAndFeel.cpp" | #include "lookandfeel/juce_LookAndFeel.cpp" | ||||
| #include "lookandfeel/juce_LookAndFeel_V2.cpp" | |||||
| #include "lookandfeel/juce_LookAndFeel_V1.cpp" | |||||
| #include "lookandfeel/juce_LookAndFeel_V3.cpp" | |||||
| #include "menus/juce_MenuBarComponent.cpp" | #include "menus/juce_MenuBarComponent.cpp" | ||||
| #include "menus/juce_MenuBarModel.cpp" | #include "menus/juce_MenuBarModel.cpp" | ||||
| #include "menus/juce_PopupMenu.cpp" | #include "menus/juce_PopupMenu.cpp" | ||||
| @@ -113,6 +113,7 @@ class CaretComponent; | |||||
| class BubbleComponent; | class BubbleComponent; | ||||
| class KeyPressMappingSet; | class KeyPressMappingSet; | ||||
| class ApplicationCommandManagerListener; | class ApplicationCommandManagerListener; | ||||
| class DrawableButton; | |||||
| #include "mouse/juce_MouseCursor.h" | #include "mouse/juce_MouseCursor.h" | ||||
| #include "mouse/juce_MouseListener.h" | #include "mouse/juce_MouseListener.h" | ||||
| @@ -215,7 +216,6 @@ class ApplicationCommandManagerListener; | |||||
| #include "windows/juce_ThreadWithProgressWindow.h" | #include "windows/juce_ThreadWithProgressWindow.h" | ||||
| #include "windows/juce_TooltipWindow.h" | #include "windows/juce_TooltipWindow.h" | ||||
| #include "layout/juce_MultiDocumentPanel.h" | #include "layout/juce_MultiDocumentPanel.h" | ||||
| #include "lookandfeel/juce_LookAndFeel.h" | |||||
| #include "filebrowser/juce_FileFilter.h" | #include "filebrowser/juce_FileFilter.h" | ||||
| #include "filebrowser/juce_WildcardFileFilter.h" | #include "filebrowser/juce_WildcardFileFilter.h" | ||||
| #include "filebrowser/juce_FileBrowserListener.h" | #include "filebrowser/juce_FileBrowserListener.h" | ||||
| @@ -239,6 +239,10 @@ class ApplicationCommandManagerListener; | |||||
| #include "properties/juce_TextPropertyComponent.h" | #include "properties/juce_TextPropertyComponent.h" | ||||
| #include "application/juce_Application.h" | #include "application/juce_Application.h" | ||||
| #include "misc/juce_BubbleComponent.h" | #include "misc/juce_BubbleComponent.h" | ||||
| #include "lookandfeel/juce_LookAndFeel.h" | |||||
| #include "lookandfeel/juce_LookAndFeel_V2.h" | |||||
| #include "lookandfeel/juce_LookAndFeel_V1.h" | |||||
| #include "lookandfeel/juce_LookAndFeel_V3.h" | |||||
| } | } | ||||
| @@ -93,6 +93,16 @@ public: | |||||
| /** Sets the height of the header section for one of the panels. */ | /** Sets the height of the header section for one of the panels. */ | ||||
| void setPanelHeaderSize (Component* panelComponent, int headerSize); | void setPanelHeaderSize (Component* panelComponent, int headerSize); | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawConcertinaPanelHeader (Graphics&, const Rectangle<int>& area, | |||||
| bool isMouseOver, bool isMouseDown, ConcertinaPanel&, Component&) = 0; | |||||
| }; | |||||
| private: | private: | ||||
| void resized() override; | void resized() override; | ||||
| @@ -31,11 +31,8 @@ GroupComponent::GroupComponent (const String& name, | |||||
| setInterceptsMouseClicks (false, true); | setInterceptsMouseClicks (false, true); | ||||
| } | } | ||||
| GroupComponent::~GroupComponent() | |||||
| { | |||||
| } | |||||
| GroupComponent::~GroupComponent() {} | |||||
| //============================================================================== | |||||
| void GroupComponent::setText (const String& newText) | void GroupComponent::setText (const String& newText) | ||||
| { | { | ||||
| if (text != newText) | if (text != newText) | ||||
| @@ -50,7 +47,6 @@ String GroupComponent::getText() const | |||||
| return text; | return text; | ||||
| } | } | ||||
| //============================================================================== | |||||
| void GroupComponent::setTextLabelPosition (Justification newJustification) | void GroupComponent::setTextLabelPosition (Justification newJustification) | ||||
| { | { | ||||
| if (justification != newJustification) | if (justification != newJustification) | ||||
| @@ -62,18 +58,9 @@ void GroupComponent::setTextLabelPosition (Justification newJustification) | |||||
| void GroupComponent::paint (Graphics& g) | void GroupComponent::paint (Graphics& g) | ||||
| { | { | ||||
| getLookAndFeel() | |||||
| .drawGroupComponentOutline (g, getWidth(), getHeight(), | |||||
| text, justification, | |||||
| *this); | |||||
| getLookAndFeel().drawGroupComponentOutline (g, getWidth(), getHeight(), | |||||
| text, justification, *this); | |||||
| } | } | ||||
| void GroupComponent::enablementChanged() | |||||
| { | |||||
| repaint(); | |||||
| } | |||||
| void GroupComponent::colourChanged() | |||||
| { | |||||
| repaint(); | |||||
| } | |||||
| void GroupComponent::enablementChanged() { repaint(); } | |||||
| void GroupComponent::colourChanged() { repaint(); } | |||||
| @@ -82,6 +82,16 @@ public: | |||||
| textColourId = 0x1005410 /**< The colour to use to draw the text label. */ | textColourId = 0x1005410 /**< The colour to use to draw the text label. */ | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawGroupComponentOutline (Graphics&, int w, int h, const String& text, | |||||
| const Justification&, GroupComponent&) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void paint (Graphics&) override; | void paint (Graphics&) override; | ||||
| @@ -292,6 +292,73 @@ public: | |||||
| /** Deregisters a previously-registered listener. */ | /** Deregisters a previously-registered listener. */ | ||||
| void removeListener (Listener* listener); | void removeListener (Listener* listener); | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| scrollbar-drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual bool areScrollbarButtonsVisible() = 0; | |||||
| /** Draws one of the buttons on a scrollbar. | |||||
| @param g the context to draw into | |||||
| @param scrollbar the bar itself | |||||
| @param width the width of the button | |||||
| @param height the height of the button | |||||
| @param buttonDirection the direction of the button, where 0 = up, 1 = right, 2 = down, 3 = left | |||||
| @param isScrollbarVertical true if it's a vertical bar, false if horizontal | |||||
| @param isMouseOverButton whether the mouse is currently over the button (also true if it's held down) | |||||
| @param isButtonDown whether the mouse button's held down | |||||
| */ | |||||
| virtual void drawScrollbarButton (Graphics& g, | |||||
| ScrollBar& scrollbar, | |||||
| int width, int height, | |||||
| int buttonDirection, | |||||
| bool isScrollbarVertical, | |||||
| bool isMouseOverButton, | |||||
| bool isButtonDown) = 0; | |||||
| /** Draws the thumb area of a scrollbar. | |||||
| @param g the context to draw into | |||||
| @param scrollbar the bar itself | |||||
| @param x the x position of the left edge of the thumb area to draw in | |||||
| @param y the y position of the top edge of the thumb area to draw in | |||||
| @param width the width of the thumb area to draw in | |||||
| @param height the height of the thumb area to draw in | |||||
| @param isScrollbarVertical true if it's a vertical bar, false if horizontal | |||||
| @param thumbStartPosition for vertical bars, the y coordinate of the top of the | |||||
| thumb, or its x position for horizontal bars | |||||
| @param thumbSize for vertical bars, the height of the thumb, or its width for | |||||
| horizontal bars. This may be 0 if the thumb shouldn't be drawn. | |||||
| @param isMouseOver whether the mouse is over the thumb area, also true if the mouse is | |||||
| currently dragging the thumb | |||||
| @param isMouseDown whether the mouse is currently dragging the scrollbar | |||||
| */ | |||||
| virtual void drawScrollbar (Graphics& g, ScrollBar& scrollbar, | |||||
| int x, int y, int width, int height, | |||||
| bool isScrollbarVertical, | |||||
| int thumbStartPosition, | |||||
| int thumbSize, | |||||
| bool isMouseOver, | |||||
| bool isMouseDown) = 0; | |||||
| /** Returns the component effect to use for a scrollbar */ | |||||
| virtual ImageEffectFilter* getScrollbarEffect() = 0; | |||||
| /** Returns the minimum length in pixels to use for a scrollbar thumb. */ | |||||
| virtual int getMinimumScrollbarThumbSize (ScrollBar&) = 0; | |||||
| /** Returns the default thickness to use for a scrollbar. */ | |||||
| virtual int getDefaultScrollbarWidth() = 0; | |||||
| /** Returns the length in pixels to use for a scrollbar button. */ | |||||
| virtual int getScrollbarButtonSize (ScrollBar&) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| bool keyPressed (const KeyPress&) override; | bool keyPressed (const KeyPress&) override; | ||||
| @@ -72,6 +72,16 @@ public: | |||||
| */ | */ | ||||
| virtual void hasBeenMoved(); | virtual void hasBeenMoved(); | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawStretchableLayoutResizerBar (Graphics&, int w, int h, | |||||
| bool isVerticalBar, bool isMouseOver, bool isMouseDragging) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void paint (Graphics&) override; | void paint (Graphics&) override; | ||||
| @@ -93,7 +93,26 @@ void TabBarButton::calcAreas (Rectangle<int>& extraComp, Rectangle<int>& textAre | |||||
| } | } | ||||
| if (extraComponent != nullptr) | if (extraComponent != nullptr) | ||||
| { | |||||
| extraComp = lf.getTabButtonExtraComponentBounds (*this, textArea, *extraComponent); | extraComp = lf.getTabButtonExtraComponentBounds (*this, textArea, *extraComponent); | ||||
| const TabbedButtonBar::Orientation orientation = owner.getOrientation(); | |||||
| if (orientation == TabbedButtonBar::TabsAtLeft || orientation == TabbedButtonBar::TabsAtRight) | |||||
| { | |||||
| if (extraComp.getCentreY() > textArea.getCentreY()) | |||||
| textArea.setBottom (jmin (textArea.getBottom(), extraComp.getY())); | |||||
| else | |||||
| textArea.setTop (jmax (textArea.getY(), extraComp.getBottom())); | |||||
| } | |||||
| else | |||||
| { | |||||
| if (extraComp.getCentreX() > textArea.getCentreX()) | |||||
| textArea.setRight (jmin (textArea.getRight(), extraComp.getX())); | |||||
| else | |||||
| textArea.setLeft (jmax (textArea.getX(), extraComp.getRight())); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| Rectangle<int> TabBarButton::getTextArea() const | Rectangle<int> TabBarButton::getTextArea() const | ||||
| @@ -293,6 +293,30 @@ public: | |||||
| colour. */ | colour. */ | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| window drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual int getTabButtonSpaceAroundImage() = 0; | |||||
| virtual int getTabButtonOverlap (int tabDepth) = 0; | |||||
| virtual int getTabButtonBestWidth (TabBarButton&, int tabDepth) = 0; | |||||
| virtual Rectangle<int> getTabButtonExtraComponentBounds (const TabBarButton&, Rectangle<int>& textArea, Component& extraComp) = 0; | |||||
| virtual void drawTabButton (TabBarButton&, Graphics&, bool isMouseOver, bool isMouseDown) = 0; | |||||
| virtual void drawTabButtonText (TabBarButton&, Graphics&, bool isMouseOver, bool isMouseDown) = 0; | |||||
| virtual void drawTabbedButtonBarBackground (TabbedButtonBar&, Graphics&) = 0; | |||||
| virtual void drawTabAreaBehindFrontButton (TabbedButtonBar&, Graphics&, int w, int h) = 0; | |||||
| virtual void createTabButtonShape (TabBarButton&, Path& path, bool isMouseOver, bool isMouseDown) = 0; | |||||
| virtual void fillTabButtonShape (TabBarButton&, Graphics&, const Path& path, bool isMouseOver, bool isMouseDown) = 0; | |||||
| virtual Button* createTabBarExtrasButton() = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void paint (Graphics&) override; | void paint (Graphics&) override; | ||||
| @@ -25,14 +25,80 @@ | |||||
| #ifndef JUCE_LOOKANDFEEL_H_INCLUDED | #ifndef JUCE_LOOKANDFEEL_H_INCLUDED | ||||
| #define JUCE_LOOKANDFEEL_H_INCLUDED | #define JUCE_LOOKANDFEEL_H_INCLUDED | ||||
| //============================================================================== | |||||
| /** This class is used to hold a few look and feel base classes which are associated | |||||
| with classes that may not be present because they're from modules other than | |||||
| juce_gui_basics. | |||||
| */ | |||||
| struct JUCE_API ExtraLookAndFeelBaseClasses | |||||
| { | |||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LassoComponentMethods | |||||
| { | |||||
| virtual ~LassoComponentMethods() {} | |||||
| virtual void drawLasso (Graphics&, Component& lassoComp) = 0; | |||||
| }; | |||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API KeyMappingEditorComponentMethods | |||||
| { | |||||
| virtual ~KeyMappingEditorComponentMethods() {} | |||||
| virtual void drawKeymapChangeButton (Graphics&, int width, int height, Button&, const String& keyDescription) = 0; | |||||
| }; | |||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API AudioDeviceSelectorComponentMethods | |||||
| { | |||||
| virtual ~AudioDeviceSelectorComponentMethods() {} | |||||
| virtual void drawLevelMeter (Graphics&, int width, int height, float level) = 0; | |||||
| }; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** | /** | ||||
| LookAndFeel objects define the appearance of all the JUCE widgets, and subclasses | LookAndFeel objects define the appearance of all the JUCE widgets, and subclasses | ||||
| can be used to apply different 'skins' to the application. | can be used to apply different 'skins' to the application. | ||||
| This class is an abstract base-class - for actual look-and-feels that you can | |||||
| instantiate, see LookAndFeel_V1, LookAndFeel_V2 and LookAndFeel_V3. | |||||
| @see LookAndFeel_V1, LookAndFeel_V2, LookAndFeel_V3 | |||||
| */ | */ | ||||
| class JUCE_API LookAndFeel | |||||
| class JUCE_API LookAndFeel : public ScrollBar::LookAndFeelMethods, | |||||
| public Button::LookAndFeelMethods, | |||||
| public ImageButton::LookAndFeelMethods, | |||||
| public TextEditor::LookAndFeelMethods, | |||||
| public FileBrowserComponent::LookAndFeelMethods, | |||||
| public TreeView::LookAndFeelMethods, | |||||
| public BubbleComponent::LookAndFeelMethods, | |||||
| public AlertWindow::LookAndFeelMethods, | |||||
| public PopupMenu::LookAndFeelMethods, | |||||
| public ComboBox::LookAndFeelMethods, | |||||
| public Label::LookAndFeelMethods, | |||||
| public Slider::LookAndFeelMethods, | |||||
| public ResizableWindow::LookAndFeelMethods, | |||||
| public DocumentWindow::LookAndFeelMethods, | |||||
| public TooltipWindow::LookAndFeelMethods, | |||||
| public TabbedButtonBar::LookAndFeelMethods, | |||||
| public PropertyComponent::LookAndFeelMethods, | |||||
| public FilenameComponent::LookAndFeelMethods, | |||||
| public GroupComponent::LookAndFeelMethods, | |||||
| public TableHeaderComponent::LookAndFeelMethods, | |||||
| public CallOutBox::LookAndFeelMethods, | |||||
| public Toolbar::LookAndFeelMethods, | |||||
| public ConcertinaPanel::LookAndFeelMethods, | |||||
| public ProgressBar::LookAndFeelMethods, | |||||
| public StretchableLayoutResizerBar::LookAndFeelMethods, | |||||
| public ExtraLookAndFeelBaseClasses::KeyMappingEditorComponentMethods, | |||||
| public ExtraLookAndFeelBaseClasses::AudioDeviceSelectorComponentMethods, | |||||
| public ExtraLookAndFeelBaseClasses::LassoComponentMethods | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -60,7 +126,6 @@ public: | |||||
| */ | */ | ||||
| static void setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) noexcept; | static void setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) noexcept; | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Looks for a colour that has been registered with the given colour ID number. | /** Looks for a colour that has been registered with the given colour ID number. | ||||
| @@ -82,9 +147,7 @@ public: | |||||
| Colour findColour (int colourId) const noexcept; | Colour findColour (int colourId) const noexcept; | ||||
| /** Registers a colour to be used for a particular purpose. | /** Registers a colour to be used for a particular purpose. | ||||
| For more details, see the comments for findColour(). | For more details, see the comments for findColour(). | ||||
| @see findColour, Component::findColour, Component::setColour | @see findColour, Component::findColour, Component::setColour | ||||
| */ | */ | ||||
| void setColour (int colourId, Colour colour) noexcept; | void setColour (int colourId, Colour colour) noexcept; | ||||
| @@ -94,9 +157,12 @@ public: | |||||
| */ | */ | ||||
| bool isColourSpecified (int colourId) const noexcept; | bool isColourSpecified (int colourId) const noexcept; | ||||
| //============================================================================== | //============================================================================== | ||||
| virtual Typeface::Ptr getTypefaceForFont (const Font& font); | |||||
| /** Returns the typeface that should be used for a given font. | |||||
| The default implementation just does what you'd expect it to, but you can override | |||||
| this if you want to intercept fonts and use your own custom typeface object. | |||||
| */ | |||||
| virtual Typeface::Ptr getTypefaceForFont (const Font&); | |||||
| /** Allows you to change the default sans-serif font. | /** Allows you to change the default sans-serif font. | ||||
| @@ -110,509 +176,38 @@ public: | |||||
| /** Override this to get the chance to swap a component's mouse cursor for a | /** Override this to get the chance to swap a component's mouse cursor for a | ||||
| customised one. | customised one. | ||||
| */ | */ | ||||
| virtual MouseCursor getMouseCursorFor (Component& component); | |||||
| virtual MouseCursor getMouseCursorFor (Component&); | |||||
| //============================================================================== | //============================================================================== | ||||
| // Creates a new graphics context object. | |||||
| /** Creates a new graphics context object. */ | |||||
| virtual LowLevelGraphicsContext* createGraphicsContext (const Image& imageToRenderOn, | virtual LowLevelGraphicsContext* createGraphicsContext (const Image& imageToRenderOn, | ||||
| const Point<int>& origin, | const Point<int>& origin, | ||||
| const RectangleList<int>& initialClip); | const RectangleList<int>& initialClip); | ||||
| //============================================================================== | |||||
| /** Draws the lozenge-shaped background for a standard button. */ | |||||
| virtual void drawButtonBackground (Graphics&, | |||||
| Button& button, | |||||
| const Colour& backgroundColour, | |||||
| bool isMouseOverButton, | |||||
| bool isButtonDown); | |||||
| virtual Font getTextButtonFont (TextButton& button); | |||||
| /** Draws the text for a TextButton. */ | |||||
| virtual void drawButtonText (Graphics&, | |||||
| TextButton& button, | |||||
| bool isMouseOverButton, | |||||
| bool isButtonDown); | |||||
| /** Draws the contents of a standard ToggleButton. */ | |||||
| virtual void drawToggleButton (Graphics&, | |||||
| ToggleButton& button, | |||||
| bool isMouseOverButton, | |||||
| bool isButtonDown); | |||||
| virtual void changeToggleButtonWidthToFitText (ToggleButton& button); | |||||
| virtual void drawTickBox (Graphics&, | |||||
| Component& component, | |||||
| float x, float y, float w, float h, | |||||
| bool ticked, | |||||
| bool isEnabled, | |||||
| bool isMouseOverButton, | |||||
| bool isButtonDown); | |||||
| virtual void drawDrawableButton (Graphics&, | |||||
| DrawableButton& button, | |||||
| bool isMouseOverButton, | |||||
| bool isButtonDown); | |||||
| //============================================================================== | |||||
| // AlertWindow handling.. | |||||
| virtual AlertWindow* createAlertWindow (const String& title, | |||||
| const String& message, | |||||
| const String& button1, | |||||
| const String& button2, | |||||
| const String& button3, | |||||
| AlertWindow::AlertIconType iconType, | |||||
| int numButtons, | |||||
| Component* associatedComponent); | |||||
| virtual void drawAlertBox (Graphics&, | |||||
| AlertWindow& alert, | |||||
| const Rectangle<int>& textArea, | |||||
| TextLayout& textLayout); | |||||
| virtual int getAlertBoxWindowFlags(); | |||||
| virtual int getAlertWindowButtonHeight(); | |||||
| virtual Font getAlertWindowMessageFont(); | |||||
| virtual Font getAlertWindowFont(); | |||||
| void setUsingNativeAlertWindows (bool shouldUseNativeAlerts); | void setUsingNativeAlertWindows (bool shouldUseNativeAlerts); | ||||
| bool isUsingNativeAlertWindows(); | bool isUsingNativeAlertWindows(); | ||||
| /** Draws a progress bar. | |||||
| If the progress value is less than 0 or greater than 1.0, this should draw a spinning | |||||
| bar that fills the whole space (i.e. to say that the app is still busy but the progress | |||||
| isn't known). It can use the current time as a basis for playing an animation. | |||||
| (Used by progress bars in AlertWindow). | |||||
| */ | |||||
| virtual void drawProgressBar (Graphics&, ProgressBar& progressBar, | |||||
| int width, int height, | |||||
| double progress, const String& textToShow); | |||||
| //============================================================================== | |||||
| // Draws a small image that spins to indicate that something's happening.. | |||||
| // This method should use the current time to animate itself, so just keep | |||||
| // repainting it every so often. | |||||
| virtual void drawSpinningWaitAnimation (Graphics&, const Colour& colour, | |||||
| int x, int y, int w, int h); | |||||
| //============================================================================== | //============================================================================== | ||||
| virtual bool areScrollbarButtonsVisible(); | |||||
| /** Draws one of the buttons on a scrollbar. | |||||
| @param g the context to draw into | |||||
| @param scrollbar the bar itself | |||||
| @param width the width of the button | |||||
| @param height the height of the button | |||||
| @param buttonDirection the direction of the button, where 0 = up, 1 = right, 2 = down, 3 = left | |||||
| @param isScrollbarVertical true if it's a vertical bar, false if horizontal | |||||
| @param isMouseOverButton whether the mouse is currently over the button (also true if it's held down) | |||||
| @param isButtonDown whether the mouse button's held down | |||||
| /** Draws a small image that spins to indicate that something's happening. | |||||
| This method should use the current time to animate itself, so just keep | |||||
| repainting it every so often. | |||||
| */ | */ | ||||
| virtual void drawScrollbarButton (Graphics& g, | |||||
| ScrollBar& scrollbar, | |||||
| int width, int height, | |||||
| int buttonDirection, | |||||
| bool isScrollbarVertical, | |||||
| bool isMouseOverButton, | |||||
| bool isButtonDown); | |||||
| /** Draws the thumb area of a scrollbar. | |||||
| @param g the context to draw into | |||||
| @param scrollbar the bar itself | |||||
| @param x the x position of the left edge of the thumb area to draw in | |||||
| @param y the y position of the top edge of the thumb area to draw in | |||||
| @param width the width of the thumb area to draw in | |||||
| @param height the height of the thumb area to draw in | |||||
| @param isScrollbarVertical true if it's a vertical bar, false if horizontal | |||||
| @param thumbStartPosition for vertical bars, the y coordinate of the top of the | |||||
| thumb, or its x position for horizontal bars | |||||
| @param thumbSize for vertical bars, the height of the thumb, or its width for | |||||
| horizontal bars. This may be 0 if the thumb shouldn't be drawn. | |||||
| @param isMouseOver whether the mouse is over the thumb area, also true if the mouse is | |||||
| currently dragging the thumb | |||||
| @param isMouseDown whether the mouse is currently dragging the scrollbar | |||||
| */ | |||||
| virtual void drawScrollbar (Graphics& g, | |||||
| ScrollBar& scrollbar, | |||||
| int x, int y, | |||||
| int width, int height, | |||||
| bool isScrollbarVertical, | |||||
| int thumbStartPosition, | |||||
| int thumbSize, | |||||
| bool isMouseOver, | |||||
| bool isMouseDown); | |||||
| /** Returns the component effect to use for a scrollbar */ | |||||
| virtual ImageEffectFilter* getScrollbarEffect(); | |||||
| /** Returns the minimum length in pixels to use for a scrollbar thumb. */ | |||||
| virtual int getMinimumScrollbarThumbSize (ScrollBar& scrollbar); | |||||
| /** Returns the default thickness to use for a scrollbar. */ | |||||
| virtual int getDefaultScrollbarWidth(); | |||||
| /** Returns the length in pixels to use for a scrollbar button. */ | |||||
| virtual int getScrollbarButtonSize (ScrollBar& scrollbar); | |||||
| virtual void drawSpinningWaitAnimation (Graphics&, const Colour& colour, | |||||
| int x, int y, int w, int h) = 0; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns a tick shape for use in yes/no boxes, etc. */ | /** Returns a tick shape for use in yes/no boxes, etc. */ | ||||
| virtual Path getTickShape (float height); | |||||
| virtual Path getTickShape (float height) = 0; | |||||
| /** Returns a cross shape for use in yes/no boxes, etc. */ | /** Returns a cross shape for use in yes/no boxes, etc. */ | ||||
| virtual Path getCrossShape (float height); | |||||
| //============================================================================== | |||||
| /** Draws the + or - box in a treeview. */ | |||||
| virtual void drawTreeviewPlusMinusBox (Graphics&, int x, int y, int w, int h, bool isPlus, bool isMouseOver); | |||||
| virtual Path getCrossShape (float height) = 0; | |||||
| //============================================================================== | //============================================================================== | ||||
| virtual void fillTextEditorBackground (Graphics&, int width, int height, TextEditor& textEditor); | |||||
| virtual void drawTextEditorOutline (Graphics&, int width, int height, TextEditor& textEditor); | |||||
| virtual CaretComponent* createCaretComponent (Component* keyFocusOwner); | |||||
| //============================================================================== | |||||
| // These return a pointer to an internally cached drawable - make sure you don't keep | |||||
| // a copy of this pointer anywhere, as it may become invalid in the future. | |||||
| virtual const Drawable* getDefaultFolderImage(); | |||||
| virtual const Drawable* getDefaultDocumentFileImage(); | |||||
| virtual AttributedString createFileChooserHeaderText (const String& title, | |||||
| const String& instructions); | |||||
| virtual void drawFileBrowserRow (Graphics&, int width, int height, | |||||
| const String& filename, Image* icon, | |||||
| const String& fileSizeDescription, | |||||
| const String& fileTimeDescription, | |||||
| bool isDirectory, | |||||
| bool isItemSelected, | |||||
| int itemIndex, | |||||
| DirectoryContentsDisplayComponent& component); | |||||
| virtual Button* createFileBrowserGoUpButton(); | |||||
| virtual void layoutFileBrowserComponent (FileBrowserComponent& browserComp, | |||||
| DirectoryContentsDisplayComponent* fileListComponent, | |||||
| FilePreviewComponent* previewComp, | |||||
| ComboBox* currentPathBox, | |||||
| TextEditor* filenameBox, | |||||
| Button* goUpButton); | |||||
| //============================================================================== | |||||
| virtual void drawBubble (Graphics&, BubbleComponent&, | |||||
| const Point<float>& tip, const Rectangle<float>& body); | |||||
| //============================================================================== | |||||
| virtual void drawLasso (Graphics&, Component& lassoComp); | |||||
| //============================================================================== | |||||
| /** Fills the background of a popup menu component. */ | |||||
| virtual void drawPopupMenuBackground (Graphics&, int width, int height); | |||||
| /** Draws one of the items in a popup menu. */ | |||||
| virtual void drawPopupMenuItem (Graphics&, | |||||
| int width, int height, | |||||
| bool isSeparator, | |||||
| bool isActive, | |||||
| bool isHighlighted, | |||||
| bool isTicked, | |||||
| bool hasSubMenu, | |||||
| const String& text, | |||||
| const String& shortcutKeyText, | |||||
| Image* image, | |||||
| const Colour* const textColour); | |||||
| /** Returns the size and style of font to use in popup menus. */ | |||||
| virtual Font getPopupMenuFont(); | |||||
| virtual void drawPopupMenuUpDownArrow (Graphics&, | |||||
| int width, int height, | |||||
| bool isScrollUpArrow); | |||||
| /** Finds the best size for an item in a popup menu. */ | |||||
| virtual void getIdealPopupMenuItemSize (const String& text, | |||||
| bool isSeparator, | |||||
| int standardMenuItemHeight, | |||||
| int& idealWidth, | |||||
| int& idealHeight); | |||||
| virtual int getMenuWindowFlags(); | |||||
| virtual void drawMenuBarBackground (Graphics&, int width, int height, | |||||
| bool isMouseOverBar, | |||||
| MenuBarComponent& menuBar); | |||||
| virtual int getMenuBarItemWidth (MenuBarComponent& menuBar, int itemIndex, const String& itemText); | |||||
| virtual Font getMenuBarFont (MenuBarComponent& menuBar, int itemIndex, const String& itemText); | |||||
| virtual void drawMenuBarItem (Graphics&, | |||||
| int width, int height, | |||||
| int itemIndex, | |||||
| const String& itemText, | |||||
| bool isMouseOverItem, | |||||
| bool isMenuOpen, | |||||
| bool isMouseOverBar, | |||||
| MenuBarComponent& menuBar); | |||||
| //============================================================================== | |||||
| virtual void drawComboBox (Graphics&, int width, int height, | |||||
| bool isButtonDown, | |||||
| int buttonX, int buttonY, | |||||
| int buttonW, int buttonH, | |||||
| ComboBox& box); | |||||
| virtual Font getComboBoxFont (ComboBox& box); | |||||
| virtual Label* createComboBoxTextBox (ComboBox& box); | |||||
| virtual void positionComboBoxText (ComboBox& box, Label& labelToPosition); | |||||
| virtual DropShadower* createDropShadowerForComponent (Component*) = 0; | |||||
| //============================================================================== | //============================================================================== | ||||
| virtual void drawLabel (Graphics&, Label&); | |||||
| virtual Font getLabelFont (Label&); | |||||
| //============================================================================== | |||||
| virtual void drawLinearSlider (Graphics&, | |||||
| int x, int y, | |||||
| int width, int height, | |||||
| float sliderPos, | |||||
| float minSliderPos, | |||||
| float maxSliderPos, | |||||
| const Slider::SliderStyle style, | |||||
| Slider& slider); | |||||
| virtual void drawLinearSliderBackground (Graphics&, | |||||
| int x, int y, | |||||
| int width, int height, | |||||
| float sliderPos, | |||||
| float minSliderPos, | |||||
| float maxSliderPos, | |||||
| const Slider::SliderStyle style, | |||||
| Slider& slider); | |||||
| virtual void drawLinearSliderThumb (Graphics&, | |||||
| int x, int y, | |||||
| int width, int height, | |||||
| float sliderPos, | |||||
| float minSliderPos, | |||||
| float maxSliderPos, | |||||
| const Slider::SliderStyle style, | |||||
| Slider& slider); | |||||
| virtual int getSliderThumbRadius (Slider& slider); | |||||
| virtual void drawRotarySlider (Graphics&, | |||||
| int x, int y, | |||||
| int width, int height, | |||||
| float sliderPosProportional, | |||||
| float rotaryStartAngle, | |||||
| float rotaryEndAngle, | |||||
| Slider& slider); | |||||
| virtual Button* createSliderButton (bool isIncrement); | |||||
| virtual Label* createSliderTextBox (Slider& slider); | |||||
| virtual ImageEffectFilter* getSliderEffect(); | |||||
| virtual Font getSliderPopupFont(); | |||||
| virtual int getSliderPopupPlacement(); | |||||
| //============================================================================== | |||||
| virtual void getTooltipSize (const String& tipText, int& width, int& height); | |||||
| virtual void drawTooltip (Graphics&, const String& text, int width, int height); | |||||
| //============================================================================== | |||||
| virtual Button* createFilenameComponentBrowseButton (const String& text); | |||||
| virtual void layoutFilenameComponent (FilenameComponent& filenameComp, | |||||
| ComboBox* filenameBox, Button* browseButton); | |||||
| //============================================================================== | |||||
| virtual void drawConcertinaPanelHeader (Graphics&, const Rectangle<int>& area, | |||||
| bool isMouseOver, bool isMouseDown, | |||||
| ConcertinaPanel&, Component& panel); | |||||
| //============================================================================== | |||||
| virtual void drawCornerResizer (Graphics&, | |||||
| int w, int h, | |||||
| bool isMouseOver, | |||||
| bool isMouseDragging); | |||||
| virtual void drawResizableFrame (Graphics&, | |||||
| int w, int h, | |||||
| const BorderSize<int>&); | |||||
| //============================================================================== | |||||
| virtual void fillResizableWindowBackground (Graphics&, int w, int h, | |||||
| const BorderSize<int>&, | |||||
| ResizableWindow& window); | |||||
| virtual void drawResizableWindowBorder (Graphics&, | |||||
| int w, int h, | |||||
| const BorderSize<int>& border, | |||||
| ResizableWindow& window); | |||||
| //============================================================================== | |||||
| virtual void drawDocumentWindowTitleBar (DocumentWindow& window, | |||||
| Graphics&, int w, int h, | |||||
| int titleSpaceX, int titleSpaceW, | |||||
| const Image* icon, | |||||
| bool drawTitleTextOnLeft); | |||||
| virtual Button* createDocumentWindowButton (int buttonType); | |||||
| virtual void positionDocumentWindowButtons (DocumentWindow& window, | |||||
| int titleBarX, int titleBarY, | |||||
| int titleBarW, int titleBarH, | |||||
| Button* minimiseButton, | |||||
| Button* maximiseButton, | |||||
| Button* closeButton, | |||||
| bool positionTitleBarButtonsOnLeft); | |||||
| virtual int getDefaultMenuBarHeight(); | |||||
| //============================================================================== | |||||
| virtual DropShadower* createDropShadowerForComponent (Component* component); | |||||
| //============================================================================== | |||||
| virtual void drawStretchableLayoutResizerBar (Graphics&, | |||||
| int w, int h, | |||||
| bool isVerticalBar, | |||||
| bool isMouseOver, | |||||
| bool isMouseDragging); | |||||
| //============================================================================== | |||||
| virtual void drawGroupComponentOutline (Graphics&, int w, int h, | |||||
| const String& text, | |||||
| const Justification& position, | |||||
| GroupComponent& group); | |||||
| //============================================================================== | |||||
| virtual int getTabButtonSpaceAroundImage(); | |||||
| virtual int getTabButtonOverlap (int tabDepth); | |||||
| virtual int getTabButtonBestWidth (TabBarButton&, int tabDepth); | |||||
| virtual Rectangle<int> getTabButtonExtraComponentBounds (const TabBarButton&, Rectangle<int>& textArea, Component& extraComp); | |||||
| virtual void drawTabButton (TabBarButton&, Graphics&, bool isMouseOver, bool isMouseDown); | |||||
| virtual void drawTabButtonText (TabBarButton&, Graphics&, bool isMouseOver, bool isMouseDown); | |||||
| virtual void drawTabbedButtonBarBackground (TabbedButtonBar&, Graphics&); | |||||
| virtual void drawTabAreaBehindFrontButton (TabbedButtonBar&, Graphics&, int w, int h); | |||||
| virtual void createTabButtonShape (TabBarButton&, Path& path, bool isMouseOver, bool isMouseDown); | |||||
| virtual void fillTabButtonShape (TabBarButton&, Graphics&, const Path& path, bool isMouseOver, bool isMouseDown); | |||||
| virtual Button* createTabBarExtrasButton(); | |||||
| //============================================================================== | |||||
| virtual void drawImageButton (Graphics&, Image* image, | |||||
| int imageX, int imageY, int imageW, int imageH, | |||||
| const Colour& overlayColour, | |||||
| float imageOpacity, | |||||
| ImageButton& button); | |||||
| //============================================================================== | |||||
| virtual void drawTableHeaderBackground (Graphics&, TableHeaderComponent&); | |||||
| virtual void drawTableHeaderColumn (Graphics&, const String& columnName, int columnId, | |||||
| int width, int height, | |||||
| bool isMouseOver, bool isMouseDown, | |||||
| int columnFlags); | |||||
| //============================================================================== | |||||
| virtual void paintToolbarBackground (Graphics&, int width, int height, Toolbar& toolbar); | |||||
| virtual Button* createToolbarMissingItemsButton (Toolbar& toolbar); | |||||
| virtual void paintToolbarButtonBackground (Graphics&, int width, int height, | |||||
| bool isMouseOver, bool isMouseDown, | |||||
| ToolbarItemComponent& component); | |||||
| virtual void paintToolbarButtonLabel (Graphics&, int x, int y, int width, int height, | |||||
| const String& text, ToolbarItemComponent& component); | |||||
| //============================================================================== | |||||
| virtual void drawPropertyPanelSectionHeader (Graphics&, const String& name, | |||||
| bool isOpen, int width, int height); | |||||
| virtual void drawPropertyComponentBackground (Graphics&, int width, int height, | |||||
| PropertyComponent& component); | |||||
| virtual void drawPropertyComponentLabel (Graphics&, int width, int height, | |||||
| PropertyComponent& component); | |||||
| virtual Rectangle<int> getPropertyComponentContentPosition (PropertyComponent& component); | |||||
| //============================================================================== | |||||
| virtual void drawCallOutBoxBackground (CallOutBox& box, Graphics&, const Path& path, Image& cachedImage); | |||||
| //============================================================================== | |||||
| virtual void drawLevelMeter (Graphics&, int width, int height, float level); | |||||
| virtual void drawKeymapChangeButton (Graphics&, int width, int height, Button& button, const String& keyDescription); | |||||
| //============================================================================== | |||||
| /** Plays the system's default 'beep' noise, to alert the user about something very important. | |||||
| */ | |||||
| /** Plays the system's default 'beep' noise, to alert the user about something very important. */ | |||||
| virtual void playAlertSound(); | virtual void playAlertSound(); | ||||
| //============================================================================== | |||||
| /** Draws a 3D raised (or indented) bevel using two colours. | |||||
| The bevel is drawn inside the given rectangle, and greater bevel thicknesses | |||||
| extend inwards. | |||||
| The top-left colour is used for the top- and left-hand edges of the | |||||
| bevel; the bottom-right colour is used for the bottom- and right-hand | |||||
| edges. | |||||
| If useGradient is true, then the bevel fades out to make it look more curved | |||||
| and less angular. If sharpEdgeOnOutside is true, the outside of the bevel is | |||||
| sharp, and it fades towards the centre; if sharpEdgeOnOutside is false, then | |||||
| the centre edges are sharp and it fades towards the outside. | |||||
| */ | |||||
| static void drawBevel (Graphics&, | |||||
| int x, int y, int width, int height, | |||||
| int bevelThickness, | |||||
| const Colour& topLeftColour = Colours::white, | |||||
| const Colour& bottomRightColour = Colours::black, | |||||
| bool useGradient = true, | |||||
| bool sharpEdgeOnOutside = true); | |||||
| /** Utility function to draw a shiny, glassy circle (for round LED-type buttons). */ | |||||
| static void drawGlassSphere (Graphics&, | |||||
| float x, float y, | |||||
| float diameter, | |||||
| const Colour& colour, | |||||
| float outlineThickness) noexcept; | |||||
| static void drawGlassPointer (Graphics&, | |||||
| float x, float y, | |||||
| float diameter, | |||||
| const Colour& colour, float outlineThickness, | |||||
| int direction) noexcept; | |||||
| /** Utility function to draw a shiny, glassy oblong (for text buttons). */ | |||||
| static void drawGlassLozenge (Graphics&, | |||||
| float x, float y, | |||||
| float width, float height, | |||||
| const Colour& colour, | |||||
| float outlineThickness, | |||||
| float cornerSize, | |||||
| bool flatOnLeft, bool flatOnRight, | |||||
| bool flatOnTop, bool flatOnBottom) noexcept; | |||||
| static Drawable* loadDrawableFromData (const void* data, size_t numBytes); | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| friend class WeakReference<LookAndFeel>; | friend class WeakReference<LookAndFeel>; | ||||
| @@ -628,40 +223,9 @@ private: | |||||
| }; | }; | ||||
| SortedSet<ColourSetting> colours; | SortedSet<ColourSetting> colours; | ||||
| // default typeface names | |||||
| String defaultSans, defaultSerif, defaultFixed; | String defaultSans, defaultSerif, defaultFixed; | ||||
| ScopedPointer<Drawable> folderImage, documentImage; | |||||
| bool useNativeAlertWindows; | bool useNativeAlertWindows; | ||||
| void drawShinyButtonShape (Graphics&, | |||||
| float x, float y, float w, float h, float maxCornerSize, | |||||
| const Colour& baseColour, | |||||
| float strokeWidth, | |||||
| bool flatOnLeft, | |||||
| bool flatOnRight, | |||||
| bool flatOnTop, | |||||
| bool flatOnBottom) noexcept; | |||||
| #if JUCE_CATCH_DEPRECATED_CODE_MISUSE | |||||
| // These methods have been deprecated - see their new parameter lists.. | |||||
| virtual int drawFileBrowserRow (Graphics&, int, int, const String&, Image*, const String&, const String&, bool, bool, int) { return 0; } | |||||
| virtual int drawTabButton (Graphics&, int, int, const Colour&, int, const String&, Button&, TabbedButtonBar::Orientation, bool, bool, bool) { return 0; } | |||||
| virtual int createTabButtonShape (Path&, int, int, int, const String&, Button&, TabbedButtonBar::Orientation, bool, bool, bool) { return 0; } | |||||
| virtual int fillTabButtonShape (Graphics&, const Path&, const Colour&, int, const String&, Button&, TabbedButtonBar::Orientation, bool, bool, bool) { return 0; } | |||||
| virtual int drawTabAreaBehindFrontButton (Graphics&, int, int, TabbedButtonBar&, TabbedButtonBar::Orientation) { return 0; } | |||||
| virtual int drawTabButtonText (Graphics&, int, int, int, int, const Colour&, int, const String&, Button&, TabbedButtonBar::Orientation, bool, bool, bool) { return 0; } | |||||
| virtual int getTabButtonBestWidth (int, const String&, int, Button&) { return 0; } | |||||
| virtual int drawBubble (Graphics&, float, float, float, float, float, float) { return 0; } | |||||
| virtual int getFontForTextButton (TextButton&) { return 0; } | |||||
| virtual int createFileChooserHeaderText (const String&, const String&, GlyphArrangement&, int) { return 0; } | |||||
| #endif | |||||
| class GlassWindowButton; | |||||
| class SliderLabelComp; | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel) | ||||
| }; | }; | ||||
| @@ -0,0 +1,567 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2013 - Raw Material Software Ltd. | |||||
| Permission is granted to use this software under the terms of either: | |||||
| a) the GPL v2 (or any later version) | |||||
| b) the Affero GPL v3 | |||||
| Details of these licenses can be found at: www.gnu.org/licenses | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.juce.com for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| LookAndFeel_V1::LookAndFeel_V1() | |||||
| { | |||||
| setColour (TextButton::buttonColourId, Colour (0xffbbbbff)); | |||||
| setColour (ListBox::outlineColourId, findColour (ComboBox::outlineColourId)); | |||||
| setColour (ScrollBar::thumbColourId, Colour (0xffbbbbdd)); | |||||
| setColour (ScrollBar::backgroundColourId, Colours::transparentBlack); | |||||
| setColour (Slider::thumbColourId, Colours::white); | |||||
| setColour (Slider::trackColourId, Colour (0x7f000000)); | |||||
| setColour (Slider::textBoxOutlineColourId, Colours::grey); | |||||
| setColour (ProgressBar::backgroundColourId, Colours::white.withAlpha (0.6f)); | |||||
| setColour (ProgressBar::foregroundColourId, Colours::green.withAlpha (0.7f)); | |||||
| setColour (PopupMenu::backgroundColourId, Colour (0xffeef5f8)); | |||||
| setColour (PopupMenu::highlightedBackgroundColourId, Colour (0xbfa4c2ce)); | |||||
| setColour (PopupMenu::highlightedTextColourId, Colours::black); | |||||
| setColour (TextEditor::focusedOutlineColourId, findColour (TextButton::buttonColourId)); | |||||
| scrollbarShadow.setShadowProperties (DropShadow (Colours::black.withAlpha (0.5f), 2, Point<int>())); | |||||
| } | |||||
| LookAndFeel_V1::~LookAndFeel_V1() | |||||
| { | |||||
| } | |||||
| //============================================================================== | |||||
| void LookAndFeel_V1::drawButtonBackground (Graphics& g, Button& button, const Colour& backgroundColour, | |||||
| bool isMouseOverButton, bool isButtonDown) | |||||
| { | |||||
| const int width = button.getWidth(); | |||||
| const int height = button.getHeight(); | |||||
| const float indent = 2.0f; | |||||
| const int cornerSize = jmin (roundToInt (width * 0.4f), | |||||
| roundToInt (height * 0.4f)); | |||||
| Path p; | |||||
| p.addRoundedRectangle (indent, indent, | |||||
| width - indent * 2.0f, | |||||
| height - indent * 2.0f, | |||||
| (float) cornerSize); | |||||
| Colour bc (backgroundColour.withMultipliedSaturation (0.3f)); | |||||
| if (isMouseOverButton) | |||||
| { | |||||
| if (isButtonDown) | |||||
| bc = bc.brighter(); | |||||
| else if (bc.getBrightness() > 0.5f) | |||||
| bc = bc.darker (0.1f); | |||||
| else | |||||
| bc = bc.brighter (0.1f); | |||||
| } | |||||
| g.setColour (bc); | |||||
| g.fillPath (p); | |||||
| g.setColour (bc.contrasting().withAlpha ((isMouseOverButton) ? 0.6f : 0.4f)); | |||||
| g.strokePath (p, PathStrokeType ((isMouseOverButton) ? 2.0f : 1.4f)); | |||||
| } | |||||
| void LookAndFeel_V1::drawTickBox (Graphics& g, Component& /*component*/, | |||||
| float x, float y, float w, float h, | |||||
| const bool ticked, | |||||
| const bool isEnabled, | |||||
| const bool /*isMouseOverButton*/, | |||||
| const bool isButtonDown) | |||||
| { | |||||
| Path box; | |||||
| box.addRoundedRectangle (0.0f, 2.0f, 6.0f, 6.0f, 1.0f); | |||||
| g.setColour (isEnabled ? Colours::blue.withAlpha (isButtonDown ? 0.3f : 0.1f) | |||||
| : Colours::lightgrey.withAlpha (0.1f)); | |||||
| AffineTransform trans (AffineTransform::scale (w / 9.0f, h / 9.0f).translated (x, y)); | |||||
| g.fillPath (box, trans); | |||||
| g.setColour (Colours::black.withAlpha (0.6f)); | |||||
| g.strokePath (box, PathStrokeType (0.9f), trans); | |||||
| if (ticked) | |||||
| { | |||||
| Path tick; | |||||
| tick.startNewSubPath (1.5f, 3.0f); | |||||
| tick.lineTo (3.0f, 6.0f); | |||||
| tick.lineTo (6.0f, 0.0f); | |||||
| g.setColour (isEnabled ? Colours::black : Colours::grey); | |||||
| g.strokePath (tick, PathStrokeType (2.5f), trans); | |||||
| } | |||||
| } | |||||
| void LookAndFeel_V1::drawToggleButton (Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) | |||||
| { | |||||
| if (button.hasKeyboardFocus (true)) | |||||
| { | |||||
| g.setColour (button.findColour (TextEditor::focusedOutlineColourId)); | |||||
| g.drawRect (0, 0, button.getWidth(), button.getHeight()); | |||||
| } | |||||
| const int tickWidth = jmin (20, button.getHeight() - 4); | |||||
| drawTickBox (g, button, 4.0f, (button.getHeight() - tickWidth) * 0.5f, | |||||
| (float) tickWidth, (float) tickWidth, | |||||
| button.getToggleState(), | |||||
| button.isEnabled(), | |||||
| isMouseOverButton, | |||||
| isButtonDown); | |||||
| g.setColour (button.findColour (ToggleButton::textColourId)); | |||||
| g.setFont (jmin (15.0f, button.getHeight() * 0.6f)); | |||||
| if (! button.isEnabled()) | |||||
| g.setOpacity (0.5f); | |||||
| const int textX = tickWidth + 5; | |||||
| g.drawFittedText (button.getButtonText(), | |||||
| textX, 4, | |||||
| button.getWidth() - textX - 2, button.getHeight() - 8, | |||||
| Justification::centredLeft, 10); | |||||
| } | |||||
| void LookAndFeel_V1::drawProgressBar (Graphics& g, ProgressBar& progressBar, | |||||
| int width, int height, | |||||
| double progress, const String& textToShow) | |||||
| { | |||||
| if (progress < 0 || progress >= 1.0) | |||||
| { | |||||
| LookAndFeel_V2::drawProgressBar (g, progressBar, width, height, progress, textToShow); | |||||
| } | |||||
| else | |||||
| { | |||||
| const Colour background (progressBar.findColour (ProgressBar::backgroundColourId)); | |||||
| const Colour foreground (progressBar.findColour (ProgressBar::foregroundColourId)); | |||||
| g.fillAll (background); | |||||
| g.setColour (foreground); | |||||
| g.fillRect (1, 1, | |||||
| jlimit (0, width - 2, roundToInt (progress * (width - 2))), | |||||
| height - 2); | |||||
| if (textToShow.isNotEmpty()) | |||||
| { | |||||
| g.setColour (Colour::contrasting (background, foreground)); | |||||
| g.setFont (height * 0.6f); | |||||
| g.drawText (textToShow, 0, 0, width, height, Justification::centred, false); | |||||
| } | |||||
| } | |||||
| } | |||||
| void LookAndFeel_V1::drawScrollbarButton (Graphics& g, ScrollBar& bar, | |||||
| int width, int height, int buttonDirection, | |||||
| bool isScrollbarVertical, | |||||
| bool isMouseOverButton, | |||||
| bool isButtonDown) | |||||
| { | |||||
| if (isScrollbarVertical) | |||||
| width -= 2; | |||||
| else | |||||
| height -= 2; | |||||
| Path p; | |||||
| if (buttonDirection == 0) | |||||
| p.addTriangle (width * 0.5f, height * 0.2f, | |||||
| width * 0.1f, height * 0.7f, | |||||
| width * 0.9f, height * 0.7f); | |||||
| else if (buttonDirection == 1) | |||||
| p.addTriangle (width * 0.8f, height * 0.5f, | |||||
| width * 0.3f, height * 0.1f, | |||||
| width * 0.3f, height * 0.9f); | |||||
| else if (buttonDirection == 2) | |||||
| p.addTriangle (width * 0.5f, height * 0.8f, | |||||
| width * 0.1f, height * 0.3f, | |||||
| width * 0.9f, height * 0.3f); | |||||
| else if (buttonDirection == 3) | |||||
| p.addTriangle (width * 0.2f, height * 0.5f, | |||||
| width * 0.7f, height * 0.1f, | |||||
| width * 0.7f, height * 0.9f); | |||||
| if (isButtonDown) | |||||
| g.setColour (Colours::white); | |||||
| else if (isMouseOverButton) | |||||
| g.setColour (Colours::white.withAlpha (0.7f)); | |||||
| else | |||||
| g.setColour (bar.findColour (ScrollBar::thumbColourId).withAlpha (0.5f)); | |||||
| g.fillPath (p); | |||||
| g.setColour (Colours::black.withAlpha (0.5f)); | |||||
| g.strokePath (p, PathStrokeType (0.5f)); | |||||
| } | |||||
| void LookAndFeel_V1::drawScrollbar (Graphics& g, ScrollBar& bar, | |||||
| int x, int y, int width, int height, | |||||
| bool isScrollbarVertical, int thumbStartPosition, int thumbSize, | |||||
| bool isMouseOver, bool isMouseDown) | |||||
| { | |||||
| g.fillAll (bar.findColour (ScrollBar::backgroundColourId)); | |||||
| g.setColour (bar.findColour (ScrollBar::thumbColourId) | |||||
| .withAlpha ((isMouseOver || isMouseDown) ? 0.4f : 0.15f)); | |||||
| if (thumbSize > 0.0f) | |||||
| { | |||||
| Rectangle<int> thumb; | |||||
| if (isScrollbarVertical) | |||||
| { | |||||
| width -= 2; | |||||
| g.fillRect (x + roundToInt (width * 0.35f), y, | |||||
| roundToInt (width * 0.3f), height); | |||||
| thumb.setBounds (x + 1, thumbStartPosition, | |||||
| width - 2, thumbSize); | |||||
| } | |||||
| else | |||||
| { | |||||
| height -= 2; | |||||
| g.fillRect (x, y + roundToInt (height * 0.35f), | |||||
| width, roundToInt (height * 0.3f)); | |||||
| thumb.setBounds (thumbStartPosition, y + 1, | |||||
| thumbSize, height - 2); | |||||
| } | |||||
| g.setColour (bar.findColour (ScrollBar::thumbColourId) | |||||
| .withAlpha ((isMouseOver || isMouseDown) ? 0.95f : 0.7f)); | |||||
| g.fillRect (thumb); | |||||
| g.setColour (Colours::black.withAlpha ((isMouseOver || isMouseDown) ? 0.4f : 0.25f)); | |||||
| g.drawRect (thumb.getX(), thumb.getY(), thumb.getWidth(), thumb.getHeight()); | |||||
| if (thumbSize > 16) | |||||
| { | |||||
| for (int i = 3; --i >= 0;) | |||||
| { | |||||
| const float linePos = thumbStartPosition + thumbSize / 2 + (i - 1) * 4.0f; | |||||
| g.setColour (Colours::black.withAlpha (0.15f)); | |||||
| if (isScrollbarVertical) | |||||
| { | |||||
| g.drawLine (x + width * 0.2f, linePos, width * 0.8f, linePos); | |||||
| g.setColour (Colours::white.withAlpha (0.15f)); | |||||
| g.drawLine (width * 0.2f, linePos - 1, width * 0.8f, linePos - 1); | |||||
| } | |||||
| else | |||||
| { | |||||
| g.drawLine (linePos, height * 0.2f, linePos, height * 0.8f); | |||||
| g.setColour (Colours::white.withAlpha (0.15f)); | |||||
| g.drawLine (linePos - 1, height * 0.2f, linePos - 1, height * 0.8f); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| ImageEffectFilter* LookAndFeel_V1::getScrollbarEffect() | |||||
| { | |||||
| return &scrollbarShadow; | |||||
| } | |||||
| //============================================================================== | |||||
| void LookAndFeel_V1::drawPopupMenuBackground (Graphics& g, int width, int height) | |||||
| { | |||||
| g.fillAll (findColour (PopupMenu::backgroundColourId)); | |||||
| g.setColour (Colours::black.withAlpha (0.6f)); | |||||
| g.drawRect (0, 0, width, height); | |||||
| } | |||||
| void LookAndFeel_V1::drawMenuBarBackground (Graphics& g, int /*width*/, int /*height*/, bool, MenuBarComponent& menuBar) | |||||
| { | |||||
| g.fillAll (menuBar.findColour (PopupMenu::backgroundColourId)); | |||||
| } | |||||
| //============================================================================== | |||||
| void LookAndFeel_V1::drawTextEditorOutline (Graphics& g, int width, int height, TextEditor& textEditor) | |||||
| { | |||||
| if (textEditor.isEnabled()) | |||||
| { | |||||
| g.setColour (textEditor.findColour (TextEditor::outlineColourId)); | |||||
| g.drawRect (0, 0, width, height); | |||||
| } | |||||
| } | |||||
| //============================================================================== | |||||
| void LookAndFeel_V1::drawComboBox (Graphics& g, int width, int height, | |||||
| const bool isButtonDown, | |||||
| int buttonX, int buttonY, int buttonW, int buttonH, | |||||
| ComboBox& box) | |||||
| { | |||||
| g.fillAll (box.findColour (ComboBox::backgroundColourId)); | |||||
| g.setColour (box.findColour ((isButtonDown) ? ComboBox::buttonColourId | |||||
| : ComboBox::backgroundColourId)); | |||||
| g.fillRect (buttonX, buttonY, buttonW, buttonH); | |||||
| g.setColour (box.findColour (ComboBox::outlineColourId)); | |||||
| g.drawRect (0, 0, width, height); | |||||
| const float arrowX = 0.2f; | |||||
| const float arrowH = 0.3f; | |||||
| if (box.isEnabled()) | |||||
| { | |||||
| Path p; | |||||
| p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.45f - arrowH), | |||||
| buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.45f, | |||||
| buttonX + buttonW * arrowX, buttonY + buttonH * 0.45f); | |||||
| p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.55f + arrowH), | |||||
| buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.55f, | |||||
| buttonX + buttonW * arrowX, buttonY + buttonH * 0.55f); | |||||
| g.setColour (box.findColour ((isButtonDown) ? ComboBox::backgroundColourId | |||||
| : ComboBox::buttonColourId)); | |||||
| g.fillPath (p); | |||||
| } | |||||
| } | |||||
| Font LookAndFeel_V1::getComboBoxFont (ComboBox& box) | |||||
| { | |||||
| Font f (jmin (15.0f, box.getHeight() * 0.85f)); | |||||
| f.setHorizontalScale (0.9f); | |||||
| return f; | |||||
| } | |||||
| //============================================================================== | |||||
| static void drawTriangle (Graphics& g, float x1, float y1, float x2, float y2, float x3, float y3, Colour fill, Colour outline) | |||||
| { | |||||
| Path p; | |||||
| p.addTriangle (x1, y1, x2, y2, x3, y3); | |||||
| g.setColour (fill); | |||||
| g.fillPath (p); | |||||
| g.setColour (outline); | |||||
| g.strokePath (p, PathStrokeType (0.3f)); | |||||
| } | |||||
| void LookAndFeel_V1::drawLinearSlider (Graphics& g, | |||||
| int x, int y, int w, int h, | |||||
| float sliderPos, float minSliderPos, float maxSliderPos, | |||||
| const Slider::SliderStyle style, | |||||
| Slider& slider) | |||||
| { | |||||
| g.fillAll (slider.findColour (Slider::backgroundColourId)); | |||||
| if (style == Slider::LinearBar) | |||||
| { | |||||
| g.setColour (slider.findColour (Slider::thumbColourId)); | |||||
| g.fillRect (x, y, (int) sliderPos - x, h); | |||||
| g.setColour (slider.findColour (Slider::textBoxTextColourId).withMultipliedAlpha (0.5f)); | |||||
| g.drawRect (x, y, (int) sliderPos - x, h); | |||||
| } | |||||
| else | |||||
| { | |||||
| g.setColour (slider.findColour (Slider::trackColourId) | |||||
| .withMultipliedAlpha (slider.isEnabled() ? 1.0f : 0.3f)); | |||||
| if (slider.isHorizontal()) | |||||
| { | |||||
| g.fillRect (x, y + roundToInt (h * 0.6f), | |||||
| w, roundToInt (h * 0.2f)); | |||||
| } | |||||
| else | |||||
| { | |||||
| g.fillRect (x + roundToInt (w * 0.5f - jmin (3.0f, w * 0.1f)), y, | |||||
| jmin (4, roundToInt (w * 0.2f)), h); | |||||
| } | |||||
| float alpha = 0.35f; | |||||
| if (slider.isEnabled()) | |||||
| alpha = slider.isMouseOverOrDragging() ? 1.0f : 0.7f; | |||||
| const Colour fill (slider.findColour (Slider::thumbColourId).withAlpha (alpha)); | |||||
| const Colour outline (Colours::black.withAlpha (slider.isEnabled() ? 0.7f : 0.35f)); | |||||
| if (style == Slider::TwoValueVertical || style == Slider::ThreeValueVertical) | |||||
| { | |||||
| drawTriangle (g, x + w * 0.5f + jmin (4.0f, w * 0.3f), minSliderPos, | |||||
| x + w * 0.5f - jmin (8.0f, w * 0.4f), minSliderPos - 7.0f, | |||||
| x + w * 0.5f - jmin (8.0f, w * 0.4f), minSliderPos, | |||||
| fill, outline); | |||||
| drawTriangle (g, x + w * 0.5f + jmin (4.0f, w * 0.3f), maxSliderPos, | |||||
| x + w * 0.5f - jmin (8.0f, w * 0.4f), maxSliderPos, | |||||
| x + w * 0.5f - jmin (8.0f, w * 0.4f), maxSliderPos + 7.0f, | |||||
| fill, outline); | |||||
| } | |||||
| else if (style == Slider::TwoValueHorizontal || style == Slider::ThreeValueHorizontal) | |||||
| { | |||||
| drawTriangle (g, minSliderPos, y + h * 0.6f - jmin (4.0f, h * 0.3f), | |||||
| minSliderPos - 7.0f, y + h * 0.9f , | |||||
| minSliderPos, y + h * 0.9f, | |||||
| fill, outline); | |||||
| drawTriangle (g, maxSliderPos, y + h * 0.6f - jmin (4.0f, h * 0.3f), | |||||
| maxSliderPos, y + h * 0.9f, | |||||
| maxSliderPos + 7.0f, y + h * 0.9f, | |||||
| fill, outline); | |||||
| } | |||||
| if (style == Slider::LinearHorizontal || style == Slider::ThreeValueHorizontal) | |||||
| { | |||||
| drawTriangle (g, sliderPos, y + h * 0.9f, | |||||
| sliderPos - 7.0f, y + h * 0.2f, | |||||
| sliderPos + 7.0f, y + h * 0.2f, | |||||
| fill, outline); | |||||
| } | |||||
| else if (style == Slider::LinearVertical || style == Slider::ThreeValueVertical) | |||||
| { | |||||
| drawTriangle (g, x + w * 0.5f - jmin (4.0f, w * 0.3f), sliderPos, | |||||
| x + w * 0.5f + jmin (8.0f, w * 0.4f), sliderPos - 7.0f, | |||||
| x + w * 0.5f + jmin (8.0f, w * 0.4f), sliderPos + 7.0f, | |||||
| fill, outline); | |||||
| } | |||||
| } | |||||
| } | |||||
| Button* LookAndFeel_V1::createSliderButton (const bool isIncrement) | |||||
| { | |||||
| if (isIncrement) | |||||
| return new ArrowButton ("u", 0.75f, Colours::white.withAlpha (0.8f)); | |||||
| else | |||||
| return new ArrowButton ("d", 0.25f, Colours::white.withAlpha (0.8f)); | |||||
| } | |||||
| ImageEffectFilter* LookAndFeel_V1::getSliderEffect() | |||||
| { | |||||
| return &scrollbarShadow; | |||||
| } | |||||
| int LookAndFeel_V1::getSliderThumbRadius (Slider&) | |||||
| { | |||||
| return 8; | |||||
| } | |||||
| //============================================================================== | |||||
| void LookAndFeel_V1::drawCornerResizer (Graphics& g, int w, int h, bool isMouseOver, bool isMouseDragging) | |||||
| { | |||||
| g.setColour ((isMouseOver || isMouseDragging) ? Colours::lightgrey | |||||
| : Colours::darkgrey); | |||||
| const float lineThickness = jmin (w, h) * 0.1f; | |||||
| for (float i = 0.0f; i < 1.0f; i += 0.3f) | |||||
| { | |||||
| g.drawLine (w * i, | |||||
| h + 1.0f, | |||||
| w + 1.0f, | |||||
| h * i, | |||||
| lineThickness); | |||||
| } | |||||
| } | |||||
| //============================================================================== | |||||
| Button* LookAndFeel_V1::createDocumentWindowButton (int buttonType) | |||||
| { | |||||
| Path shape; | |||||
| if (buttonType == DocumentWindow::closeButton) | |||||
| { | |||||
| shape.addLineSegment (Line<float> (0.0f, 0.0f, 1.0f, 1.0f), 0.35f); | |||||
| shape.addLineSegment (Line<float> (1.0f, 0.0f, 0.0f, 1.0f), 0.35f); | |||||
| ShapeButton* const b = new ShapeButton ("close", | |||||
| Colour (0x7fff3333), | |||||
| Colour (0xd7ff3333), | |||||
| Colour (0xf7ff3333)); | |||||
| b->setShape (shape, true, true, true); | |||||
| return b; | |||||
| } | |||||
| else if (buttonType == DocumentWindow::minimiseButton) | |||||
| { | |||||
| shape.addLineSegment (Line<float> (0.0f, 0.5f, 1.0f, 0.5f), 0.25f); | |||||
| DrawableButton* b = new DrawableButton ("minimise", DrawableButton::ImageFitted); | |||||
| DrawablePath dp; | |||||
| dp.setPath (shape); | |||||
| dp.setFill (Colours::black.withAlpha (0.3f)); | |||||
| b->setImages (&dp); | |||||
| return b; | |||||
| } | |||||
| else if (buttonType == DocumentWindow::maximiseButton) | |||||
| { | |||||
| shape.addLineSegment (Line<float> (0.5f, 0.0f, 0.5f, 1.0f), 0.25f); | |||||
| shape.addLineSegment (Line<float> (0.0f, 0.5f, 1.0f, 0.5f), 0.25f); | |||||
| DrawableButton* b = new DrawableButton ("maximise", DrawableButton::ImageFitted); | |||||
| DrawablePath dp; | |||||
| dp.setPath (shape); | |||||
| dp.setFill (Colours::black.withAlpha (0.3f)); | |||||
| b->setImages (&dp); | |||||
| return b; | |||||
| } | |||||
| jassertfalse; | |||||
| return nullptr; | |||||
| } | |||||
| void LookAndFeel_V1::positionDocumentWindowButtons (DocumentWindow&, | |||||
| int titleBarX, int titleBarY, int titleBarW, int titleBarH, | |||||
| Button* minimiseButton, | |||||
| Button* maximiseButton, | |||||
| Button* closeButton, | |||||
| bool positionTitleBarButtonsOnLeft) | |||||
| { | |||||
| titleBarY += titleBarH / 8; | |||||
| titleBarH -= titleBarH / 4; | |||||
| const int buttonW = titleBarH; | |||||
| int x = positionTitleBarButtonsOnLeft ? titleBarX + 4 | |||||
| : titleBarX + titleBarW - buttonW - 4; | |||||
| if (closeButton != nullptr) | |||||
| { | |||||
| closeButton->setBounds (x, titleBarY, buttonW, titleBarH); | |||||
| x += positionTitleBarButtonsOnLeft ? buttonW + buttonW / 5 | |||||
| : -(buttonW + buttonW / 5); | |||||
| } | |||||
| if (positionTitleBarButtonsOnLeft) | |||||
| std::swap (minimiseButton, maximiseButton); | |||||
| if (maximiseButton != nullptr) | |||||
| { | |||||
| maximiseButton->setBounds (x, titleBarY - 2, buttonW, titleBarH); | |||||
| x += positionTitleBarButtonsOnLeft ? buttonW : -buttonW; | |||||
| } | |||||
| if (minimiseButton != nullptr) | |||||
| minimiseButton->setBounds (x, titleBarY - 2, buttonW, titleBarH); | |||||
| } | |||||
| @@ -0,0 +1,101 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2013 - Raw Material Software Ltd. | |||||
| Permission is granted to use this software under the terms of either: | |||||
| a) the GPL v2 (or any later version) | |||||
| b) the Affero GPL v3 | |||||
| Details of these licenses can be found at: www.gnu.org/licenses | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.juce.com for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifndef JUCE_LOOKANDFEEL_V1_H_INCLUDED | |||||
| #define JUCE_LOOKANDFEEL_V1_H_INCLUDED | |||||
| //============================================================================== | |||||
| /** | |||||
| The original JUCE look-and-feel, as used back from 2002 to about 2007ish. | |||||
| @see LookAndFeel, LookAndFeel_V2, LookAndFeel_V3 | |||||
| */ | |||||
| class JUCE_API LookAndFeel_V1 : public LookAndFeel_V2 | |||||
| { | |||||
| public: | |||||
| LookAndFeel_V1(); | |||||
| ~LookAndFeel_V1(); | |||||
| //============================================================================== | |||||
| void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour, | |||||
| bool isMouseOverButton, bool isButtonDown) override; | |||||
| void drawToggleButton (Graphics&, ToggleButton&, bool isMouseOverButton, bool isButtonDown) override; | |||||
| void drawTickBox (Graphics&, Component&, float x, float y, float w, float h, | |||||
| bool ticked, bool isEnabled, bool isMouseOverButton, bool isButtonDown) override; | |||||
| void drawProgressBar (Graphics&, ProgressBar&, int width, int height, | |||||
| double progress, const String& textToShow) override; | |||||
| //============================================================================== | |||||
| void drawScrollbarButton (Graphics&, ScrollBar&, int width, int height, | |||||
| int buttonDirection, bool isScrollbarVertical, | |||||
| bool isMouseOverButton, bool isButtonDown) override; | |||||
| void drawScrollbar (Graphics&, ScrollBar&, int x, int y, int width, int height, | |||||
| bool isScrollbarVertical, int thumbStartPosition, int thumbSize, | |||||
| bool isMouseOver, bool isMouseDown) override; | |||||
| ImageEffectFilter* getScrollbarEffect() override; | |||||
| //============================================================================== | |||||
| void drawTextEditorOutline (Graphics&, int width, int height, TextEditor&) override; | |||||
| //============================================================================== | |||||
| void drawPopupMenuBackground (Graphics&, int width, int height) override; | |||||
| void drawMenuBarBackground (Graphics&, int width, int height, bool isMouseOverBar, MenuBarComponent&) override; | |||||
| //============================================================================== | |||||
| void drawComboBox (Graphics&, int width, int height, bool isButtonDown, | |||||
| int buttonX, int buttonY, int buttonW, int buttonH, ComboBox&) override; | |||||
| Font getComboBoxFont (ComboBox&) override; | |||||
| //============================================================================== | |||||
| void drawLinearSlider (Graphics&, int x, int y, int width, int height, | |||||
| float sliderPos, float minSliderPos, float maxSliderPos, | |||||
| const Slider::SliderStyle, Slider&) override; | |||||
| int getSliderThumbRadius (Slider&) override; | |||||
| Button* createSliderButton (bool isIncrement) override; | |||||
| ImageEffectFilter* getSliderEffect() override; | |||||
| //============================================================================== | |||||
| void drawCornerResizer (Graphics&, int w, int h, bool isMouseOver, bool isMouseDragging) override; | |||||
| Button* createDocumentWindowButton (int buttonType) override; | |||||
| void positionDocumentWindowButtons (DocumentWindow&, | |||||
| int titleBarX, int titleBarY, int titleBarW, int titleBarH, | |||||
| Button* minimiseButton, Button* maximiseButton, Button* closeButton, | |||||
| bool positionTitleBarButtonsOnLeft) override; | |||||
| private: | |||||
| DropShadowEffect scrollbarShadow; | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel_V1) | |||||
| }; | |||||
| #endif // JUCE_LOOKANDFEEL_H_INCLUDED | |||||
| @@ -0,0 +1,347 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2013 - Raw Material Software Ltd. | |||||
| Permission is granted to use this software under the terms of either: | |||||
| a) the GPL v2 (or any later version) | |||||
| b) the Affero GPL v3 | |||||
| Details of these licenses can be found at: www.gnu.org/licenses | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.juce.com for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifndef JUCE_LOOKANDFEEL_V2_H_INCLUDED | |||||
| #define JUCE_LOOKANDFEEL_V2_H_INCLUDED | |||||
| //============================================================================== | |||||
| /** | |||||
| This LookAndFeel subclass implements the juce style from around 2008-12. | |||||
| @see LookAndFeel, LookAndFeel_V1, LookAndFeel_V3 | |||||
| */ | |||||
| class JUCE_API LookAndFeel_V2 : public LookAndFeel | |||||
| { | |||||
| public: | |||||
| LookAndFeel_V2(); | |||||
| ~LookAndFeel_V2(); | |||||
| //============================================================================== | |||||
| void drawButtonBackground (Graphics&, Button& button, const Colour& backgroundColour, | |||||
| bool isMouseOverButton, bool isButtonDown) override; | |||||
| Font getTextButtonFont (TextButton&) override; | |||||
| void drawButtonText (Graphics&, TextButton& button, | |||||
| bool isMouseOverButton, bool isButtonDown) override; | |||||
| void drawToggleButton (Graphics&, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) override; | |||||
| void changeToggleButtonWidthToFitText (ToggleButton&) override; | |||||
| void drawTickBox (Graphics&, Component&, | |||||
| float x, float y, float w, float h, | |||||
| bool ticked, bool isEnabled, bool isMouseOverButton, bool isButtonDown) override; | |||||
| void drawDrawableButton (Graphics&, DrawableButton&, bool isMouseOverButton, bool isButtonDown) override; | |||||
| //============================================================================== | |||||
| AlertWindow* createAlertWindow (const String& title, const String& message, | |||||
| const String& button1, | |||||
| const String& button2, | |||||
| const String& button3, | |||||
| AlertWindow::AlertIconType iconType, | |||||
| int numButtons, Component* associatedComponent) override; | |||||
| void drawAlertBox (Graphics&, AlertWindow&, const Rectangle<int>& textArea, TextLayout&) override; | |||||
| int getAlertBoxWindowFlags() override; | |||||
| int getAlertWindowButtonHeight() override; | |||||
| Font getAlertWindowMessageFont() override; | |||||
| Font getAlertWindowFont() override; | |||||
| //============================================================================== | |||||
| void drawProgressBar (Graphics&, ProgressBar&, int width, int height, double progress, const String& textToShow) override; | |||||
| void drawSpinningWaitAnimation (Graphics&, const Colour& colour, int x, int y, int w, int h) override; | |||||
| //============================================================================== | |||||
| bool areScrollbarButtonsVisible() override; | |||||
| void drawScrollbarButton (Graphics& g, ScrollBar&, int width, int height, int buttonDirection, | |||||
| bool isScrollbarVertical, bool isMouseOverButton, bool isButtonDown) override; | |||||
| void drawScrollbar (Graphics& g, ScrollBar&, int x, int y, int width, int height, | |||||
| bool isScrollbarVertical, int thumbStartPosition, int thumbSize, | |||||
| bool isMouseOver, bool isMouseDown) override; | |||||
| ImageEffectFilter* getScrollbarEffect() override; | |||||
| int getMinimumScrollbarThumbSize (ScrollBar&) override; | |||||
| int getDefaultScrollbarWidth() override; | |||||
| int getScrollbarButtonSize (ScrollBar& scrollbar) override; | |||||
| //============================================================================== | |||||
| Path getTickShape (float height) override; | |||||
| Path getCrossShape (float height) override; | |||||
| //============================================================================== | |||||
| void drawTreeviewPlusMinusBox (Graphics&, const Rectangle<float>& area, | |||||
| Colour backgroundColour, bool isOpen, bool isMouseOver) override; | |||||
| bool areLinesDrawnForTreeView (TreeView&) override; | |||||
| int getTreeViewIndentSize (TreeView&) override; | |||||
| //============================================================================== | |||||
| void fillTextEditorBackground (Graphics&, int width, int height, TextEditor&) override; | |||||
| void drawTextEditorOutline (Graphics&, int width, int height, TextEditor&) override; | |||||
| CaretComponent* createCaretComponent (Component* keyFocusOwner) override; | |||||
| //============================================================================== | |||||
| const Drawable* getDefaultFolderImage() override; | |||||
| const Drawable* getDefaultDocumentFileImage() override; | |||||
| AttributedString createFileChooserHeaderText (const String& title, const String& instructions) override; | |||||
| void drawFileBrowserRow (Graphics&, int width, int height, | |||||
| const String& filename, Image* icon, | |||||
| const String& fileSizeDescription, const String& fileTimeDescription, | |||||
| bool isDirectory, bool isItemSelected, int itemIndex, | |||||
| DirectoryContentsDisplayComponent&) override; | |||||
| Button* createFileBrowserGoUpButton() override; | |||||
| void layoutFileBrowserComponent (FileBrowserComponent&, | |||||
| DirectoryContentsDisplayComponent*, | |||||
| FilePreviewComponent*, | |||||
| ComboBox* currentPathBox, | |||||
| TextEditor* filenameBox, | |||||
| Button* goUpButton) override; | |||||
| //============================================================================== | |||||
| void drawBubble (Graphics&, BubbleComponent&, const Point<float>& tip, const Rectangle<float>& body) override; | |||||
| void drawLasso (Graphics&, Component&) override; | |||||
| //============================================================================== | |||||
| void drawPopupMenuBackground (Graphics&, int width, int height) override; | |||||
| void drawPopupMenuItem (Graphics&, int width, int height, | |||||
| bool isSeparator, bool isActive, bool isHighlighted, bool isTicked, bool hasSubMenu, | |||||
| const String& text, const String& shortcutKeyText, | |||||
| Image* image, const Colour* textColour) override; | |||||
| Font getPopupMenuFont() override; | |||||
| void drawPopupMenuUpDownArrow (Graphics&, int width, int height, bool isScrollUpArrow) override; | |||||
| void getIdealPopupMenuItemSize (const String& text, bool isSeparator, int standardMenuItemHeight, | |||||
| int& idealWidth, int& idealHeight) override; | |||||
| int getMenuWindowFlags() override; | |||||
| void drawMenuBarBackground (Graphics&, int width, int height, bool isMouseOverBar, MenuBarComponent&) override; | |||||
| int getMenuBarItemWidth (MenuBarComponent&, int itemIndex, const String& itemText) override; | |||||
| Font getMenuBarFont (MenuBarComponent&, int itemIndex, const String& itemText) override; | |||||
| int getDefaultMenuBarHeight() override; | |||||
| void drawMenuBarItem (Graphics&, int width, int height, | |||||
| int itemIndex, const String& itemText, | |||||
| bool isMouseOverItem, bool isMenuOpen, bool isMouseOverBar, | |||||
| MenuBarComponent&) override; | |||||
| //============================================================================== | |||||
| void drawComboBox (Graphics&, int width, int height, bool isButtonDown, | |||||
| int buttonX, int buttonY, int buttonW, int buttonH, | |||||
| ComboBox&) override; | |||||
| Font getComboBoxFont (ComboBox&) override; | |||||
| Label* createComboBoxTextBox (ComboBox&) override; | |||||
| void positionComboBoxText (ComboBox&, Label&) override; | |||||
| //============================================================================== | |||||
| void drawLabel (Graphics&, Label&) override; | |||||
| Font getLabelFont (Label&) override; | |||||
| //============================================================================== | |||||
| void drawLinearSlider (Graphics&, int x, int y, int width, int height, | |||||
| float sliderPos, float minSliderPos, float maxSliderPos, | |||||
| const Slider::SliderStyle, Slider&) override; | |||||
| void drawLinearSliderBackground (Graphics&, int x, int y, int width, int height, | |||||
| float sliderPos, float minSliderPos, float maxSliderPos, | |||||
| const Slider::SliderStyle, Slider&) override; | |||||
| void drawLinearSliderThumb (Graphics&, int x, int y, int width, int height, | |||||
| float sliderPos, float minSliderPos, float maxSliderPos, | |||||
| const Slider::SliderStyle, Slider&) override; | |||||
| void drawRotarySlider (Graphics&, int x, int y, int width, int height, | |||||
| float sliderPosProportional, float rotaryStartAngle, float rotaryEndAngle, | |||||
| Slider&) override; | |||||
| int getSliderThumbRadius (Slider&) override; | |||||
| Button* createSliderButton (bool isIncrement) override; | |||||
| Label* createSliderTextBox (Slider&) override; | |||||
| ImageEffectFilter* getSliderEffect() override; | |||||
| Font getSliderPopupFont() override; | |||||
| int getSliderPopupPlacement() override; | |||||
| //============================================================================== | |||||
| void getTooltipSize (const String& tipText, int& width, int& height) override; | |||||
| void drawTooltip (Graphics&, const String& text, int width, int height) override; | |||||
| //============================================================================== | |||||
| Button* createFilenameComponentBrowseButton (const String& text) override; | |||||
| void layoutFilenameComponent (FilenameComponent& filenameComp, ComboBox* filenameBox, Button* browseButton) override; | |||||
| //============================================================================== | |||||
| void drawConcertinaPanelHeader (Graphics&, const Rectangle<int>& area, | |||||
| bool isMouseOver, bool isMouseDown, | |||||
| ConcertinaPanel&, Component& panel) override; | |||||
| //============================================================================== | |||||
| void drawCornerResizer (Graphics&, int w, int h, bool isMouseOver, bool isMouseDragging) override; | |||||
| void drawResizableFrame (Graphics&, int w, int h, const BorderSize<int>&) override; | |||||
| //============================================================================== | |||||
| void fillResizableWindowBackground (Graphics&, int w, int h, const BorderSize<int>&, ResizableWindow&) override; | |||||
| void drawResizableWindowBorder (Graphics&, int w, int h, const BorderSize<int>& border, ResizableWindow&) override; | |||||
| //============================================================================== | |||||
| void drawDocumentWindowTitleBar (DocumentWindow&, Graphics&, int w, int h, | |||||
| int titleSpaceX, int titleSpaceW, | |||||
| const Image* icon, bool drawTitleTextOnLeft) override; | |||||
| Button* createDocumentWindowButton (int buttonType) override; | |||||
| void positionDocumentWindowButtons (DocumentWindow&, | |||||
| int titleBarX, int titleBarY, int titleBarW, int titleBarH, | |||||
| Button* minimiseButton, | |||||
| Button* maximiseButton, | |||||
| Button* closeButton, | |||||
| bool positionTitleBarButtonsOnLeft) override; | |||||
| //============================================================================== | |||||
| DropShadower* createDropShadowerForComponent (Component*) override; | |||||
| //============================================================================== | |||||
| void drawStretchableLayoutResizerBar (Graphics&, int w, int h, bool isVerticalBar, | |||||
| bool isMouseOver, bool isMouseDragging) override; | |||||
| //============================================================================== | |||||
| void drawGroupComponentOutline (Graphics&, int w, int h, const String& text, | |||||
| const Justification&, GroupComponent&) override; | |||||
| //============================================================================== | |||||
| int getTabButtonSpaceAroundImage() override; | |||||
| int getTabButtonOverlap (int tabDepth) override; | |||||
| int getTabButtonBestWidth (TabBarButton&, int tabDepth) override; | |||||
| Rectangle<int> getTabButtonExtraComponentBounds (const TabBarButton&, Rectangle<int>& textArea, Component& extraComp) override; | |||||
| void drawTabButton (TabBarButton&, Graphics&, bool isMouseOver, bool isMouseDown) override; | |||||
| void drawTabButtonText (TabBarButton&, Graphics&, bool isMouseOver, bool isMouseDown) override; | |||||
| void drawTabbedButtonBarBackground (TabbedButtonBar&, Graphics&) override; | |||||
| void drawTabAreaBehindFrontButton (TabbedButtonBar&, Graphics&, int w, int h) override; | |||||
| void createTabButtonShape (TabBarButton&, Path& path, bool isMouseOver, bool isMouseDown) override; | |||||
| void fillTabButtonShape (TabBarButton&, Graphics&, const Path& path, bool isMouseOver, bool isMouseDown) override; | |||||
| Button* createTabBarExtrasButton() override; | |||||
| //============================================================================== | |||||
| void drawImageButton (Graphics&, Image*, | |||||
| int imageX, int imageY, int imageW, int imageH, | |||||
| const Colour& overlayColour, float imageOpacity, ImageButton&) override; | |||||
| //============================================================================== | |||||
| void drawTableHeaderBackground (Graphics&, TableHeaderComponent&) override; | |||||
| void drawTableHeaderColumn (Graphics&, const String& columnName, int columnId, | |||||
| int width, int height, bool isMouseOver, bool isMouseDown, | |||||
| int columnFlags) override; | |||||
| //============================================================================== | |||||
| void paintToolbarBackground (Graphics&, int width, int height, Toolbar&) override; | |||||
| Button* createToolbarMissingItemsButton (Toolbar&) override; | |||||
| void paintToolbarButtonBackground (Graphics&, int width, int height, | |||||
| bool isMouseOver, bool isMouseDown, | |||||
| ToolbarItemComponent&) override; | |||||
| void paintToolbarButtonLabel (Graphics&, int x, int y, int width, int height, | |||||
| const String& text, ToolbarItemComponent&) override; | |||||
| //============================================================================== | |||||
| void drawPropertyPanelSectionHeader (Graphics&, const String& name, bool isOpen, int width, int height) override; | |||||
| void drawPropertyComponentBackground (Graphics&, int width, int height, PropertyComponent&) override; | |||||
| void drawPropertyComponentLabel (Graphics&, int width, int height, PropertyComponent&) override; | |||||
| Rectangle<int> getPropertyComponentContentPosition (PropertyComponent&) override; | |||||
| //============================================================================== | |||||
| void drawCallOutBoxBackground (CallOutBox&, Graphics&, const Path& path, Image& cachedImage) override; | |||||
| //============================================================================== | |||||
| void drawLevelMeter (Graphics&, int width, int height, float level) override; | |||||
| void drawKeymapChangeButton (Graphics&, int width, int height, Button& button, const String& keyDescription) override; | |||||
| //============================================================================== | |||||
| /** Draws a 3D raised (or indented) bevel using two colours. | |||||
| The bevel is drawn inside the given rectangle, and greater bevel thicknesses | |||||
| extend inwards. | |||||
| The top-left colour is used for the top- and left-hand edges of the | |||||
| bevel; the bottom-right colour is used for the bottom- and right-hand | |||||
| edges. | |||||
| If useGradient is true, then the bevel fades out to make it look more curved | |||||
| and less angular. If sharpEdgeOnOutside is true, the outside of the bevel is | |||||
| sharp, and it fades towards the centre; if sharpEdgeOnOutside is false, then | |||||
| the centre edges are sharp and it fades towards the outside. | |||||
| */ | |||||
| static void drawBevel (Graphics&, | |||||
| int x, int y, int width, int height, | |||||
| int bevelThickness, | |||||
| const Colour& topLeftColour = Colours::white, | |||||
| const Colour& bottomRightColour = Colours::black, | |||||
| bool useGradient = true, | |||||
| bool sharpEdgeOnOutside = true); | |||||
| /** Utility function to draw a shiny, glassy circle (for round LED-type buttons). */ | |||||
| static void drawGlassSphere (Graphics&, float x, float y, float diameter, | |||||
| const Colour& colour, float outlineThickness) noexcept; | |||||
| static void drawGlassPointer (Graphics&, float x, float y, float diameter, | |||||
| const Colour& colour, float outlineThickness, int direction) noexcept; | |||||
| /** Utility function to draw a shiny, glassy oblong (for text buttons). */ | |||||
| static void drawGlassLozenge (Graphics&, | |||||
| float x, float y, float width, float height, | |||||
| const Colour& colour, float outlineThickness, float cornerSize, | |||||
| bool flatOnLeft, bool flatOnRight, bool flatOnTop, bool flatOnBottom) noexcept; | |||||
| private: | |||||
| //============================================================================== | |||||
| ScopedPointer<Drawable> folderImage, documentImage; | |||||
| void drawShinyButtonShape (Graphics&, | |||||
| float x, float y, float w, float h, float maxCornerSize, | |||||
| const Colour& baseColour, float strokeWidth, | |||||
| bool flatOnLeft, bool flatOnRight, bool flatOnTop, bool flatOnBottom) noexcept; | |||||
| class GlassWindowButton; | |||||
| class SliderLabelComp; | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LookAndFeel_V2) | |||||
| }; | |||||
| #endif // JUCE_LOOKANDFEEL_H_INCLUDED | |||||
| @@ -0,0 +1,361 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2013 - Raw Material Software Ltd. | |||||
| Permission is granted to use this software under the terms of either: | |||||
| a) the GPL v2 (or any later version) | |||||
| b) the Affero GPL v3 | |||||
| Details of these licenses can be found at: www.gnu.org/licenses | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.juce.com for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| LookAndFeel_V3::LookAndFeel_V3() | |||||
| { | |||||
| setColour (TreeView::selectedItemBackgroundColourId, Colour (0x301111ee)); | |||||
| const Colour textButtonColour (0xffeeeeff); | |||||
| setColour (TextButton::buttonColourId, textButtonColour); | |||||
| setColour (ComboBox::buttonColourId, textButtonColour); | |||||
| setColour (ScrollBar::thumbColourId, Colour::greyLevel (0.8f).contrasting().withAlpha (0.13f)); | |||||
| } | |||||
| LookAndFeel_V3::~LookAndFeel_V3() {} | |||||
| bool LookAndFeel_V3::areScrollbarButtonsVisible() { return false; } | |||||
| void LookAndFeel_V3::drawStretchableLayoutResizerBar (Graphics& g, int /*w*/, int /*h*/, bool /*isVerticalBar*/, | |||||
| bool isMouseOver, bool isMouseDragging) | |||||
| { | |||||
| if (isMouseOver || isMouseDragging) | |||||
| g.fillAll (Colours::yellow.withAlpha (0.4f)); | |||||
| } | |||||
| void LookAndFeel_V3::drawScrollbar (Graphics& g, ScrollBar& scrollbar, int x, int y, int width, int height, | |||||
| bool isScrollbarVertical, int thumbStartPosition, int thumbSize, bool isMouseOver, bool isMouseDown) | |||||
| { | |||||
| Path thumbPath; | |||||
| if (thumbSize > 0) | |||||
| { | |||||
| const float thumbIndent = (isScrollbarVertical ? width : height) * 0.25f; | |||||
| const float thumbIndentx2 = thumbIndent * 2.0f; | |||||
| if (isScrollbarVertical) | |||||
| thumbPath.addRoundedRectangle (x + thumbIndent, thumbStartPosition + thumbIndent, | |||||
| width - thumbIndentx2, thumbSize - thumbIndentx2, (width - thumbIndentx2) * 0.5f); | |||||
| else | |||||
| thumbPath.addRoundedRectangle (thumbStartPosition + thumbIndent, y + thumbIndent, | |||||
| thumbSize - thumbIndentx2, height - thumbIndentx2, (height - thumbIndentx2) * 0.5f); | |||||
| } | |||||
| Colour thumbCol (scrollbar.findColour (ScrollBar::thumbColourId, true)); | |||||
| if (isMouseOver || isMouseDown) | |||||
| thumbCol = thumbCol.withMultipliedAlpha (2.0f); | |||||
| g.setColour (thumbCol); | |||||
| g.fillPath (thumbPath); | |||||
| g.setColour (thumbCol.contrasting ((isMouseOver || isMouseDown) ? 0.2f : 0.1f)); | |||||
| g.strokePath (thumbPath, PathStrokeType (1.0f)); | |||||
| } | |||||
| void LookAndFeel_V3::drawConcertinaPanelHeader (Graphics& g, const Rectangle<int>& area, | |||||
| bool isMouseOver, bool /*isMouseDown*/, | |||||
| ConcertinaPanel&, Component& panel) | |||||
| { | |||||
| const Colour bkg (Colours::grey); | |||||
| g.setGradientFill (ColourGradient (Colours::white.withAlpha (isMouseOver ? 0.4f : 0.2f), 0, (float) area.getY(), | |||||
| Colours::darkgrey.withAlpha (0.2f), 0, (float) area.getBottom(), false)); | |||||
| g.fillAll(); | |||||
| g.setColour (bkg.contrasting().withAlpha (0.04f)); | |||||
| g.fillRect (area.withHeight (1)); | |||||
| g.fillRect (area.withTop (area.getBottom() - 1)); | |||||
| g.setColour (bkg.contrasting()); | |||||
| g.setFont (Font (area.getHeight() * 0.6f).boldened()); | |||||
| g.drawFittedText (panel.getName(), 4, 0, area.getWidth() - 6, area.getHeight(), Justification::centredLeft, 1); | |||||
| } | |||||
| static void drawButtonShape (Graphics& g, const Path& outline, Colour baseColour, float height) | |||||
| { | |||||
| const float mainBrightness = baseColour.getBrightness(); | |||||
| const float mainAlpha = baseColour.getFloatAlpha(); | |||||
| g.setGradientFill (ColourGradient (baseColour.brighter (0.2f), 0.0f, 0.0f, | |||||
| baseColour.darker (0.25f), 0.0f, height, false)); | |||||
| g.fillPath (outline); | |||||
| g.setColour (Colours::white.withAlpha (0.4f * mainAlpha * mainBrightness * mainBrightness)); | |||||
| g.strokePath (outline, PathStrokeType (1.0f), AffineTransform::translation (0.0f, 1.0f) | |||||
| .scaled (1.0f, (height - 1.6f) / height)); | |||||
| g.setColour (Colours::black.withAlpha (0.4f * mainAlpha)); | |||||
| g.strokePath (outline, PathStrokeType (1.0f)); | |||||
| } | |||||
| void LookAndFeel_V3::drawButtonBackground (Graphics& g, Button& button, const Colour& backgroundColour, | |||||
| bool isMouseOverButton, bool isButtonDown) | |||||
| { | |||||
| Colour baseColour (backgroundColour.withMultipliedSaturation (button.hasKeyboardFocus (true) ? 1.3f : 0.9f) | |||||
| .withMultipliedAlpha (button.isEnabled() ? 0.9f : 0.5f)); | |||||
| if (isButtonDown || isMouseOverButton) | |||||
| baseColour = baseColour.contrasting (isButtonDown ? 0.2f : 0.1f); | |||||
| const bool flatOnLeft = button.isConnectedOnLeft(); | |||||
| const bool flatOnRight = button.isConnectedOnRight(); | |||||
| const bool flatOnTop = button.isConnectedOnTop(); | |||||
| const bool flatOnBottom = button.isConnectedOnBottom(); | |||||
| const float width = button.getWidth() - 1.0f; | |||||
| const float height = button.getHeight() - 1.0f; | |||||
| const float cornerSize = 4.0f; | |||||
| Path outline; | |||||
| outline.addRoundedRectangle (0.5f, 0.5f, width, height, cornerSize, cornerSize, | |||||
| ! (flatOnLeft || flatOnTop), | |||||
| ! (flatOnRight || flatOnTop), | |||||
| ! (flatOnLeft || flatOnBottom), | |||||
| ! (flatOnRight || flatOnBottom)); | |||||
| drawButtonShape (g, outline, baseColour, height); | |||||
| } | |||||
| void LookAndFeel_V3::drawTableHeaderBackground (Graphics& g, TableHeaderComponent& header) | |||||
| { | |||||
| Rectangle<int> r (header.getLocalBounds()); | |||||
| g.setColour (Colours::black.withAlpha (0.5f)); | |||||
| g.fillRect (r.removeFromBottom (1)); | |||||
| g.setColour (Colours::white.withAlpha (0.6f)); | |||||
| g.fillRect (r); | |||||
| g.setColour (Colours::black.withAlpha (0.5f)); | |||||
| for (int i = header.getNumColumns (true); --i >= 0;) | |||||
| g.fillRect (header.getColumnPosition (i).removeFromRight (1)); | |||||
| } | |||||
| int LookAndFeel_V3::getTabButtonOverlap (int /*tabDepth*/) { return -1; } | |||||
| int LookAndFeel_V3::getTabButtonSpaceAroundImage() { return 1; } | |||||
| void LookAndFeel_V3::createTabTextLayout (const TabBarButton& button, float length, float depth, | |||||
| Colour colour, TextLayout& textLayout) | |||||
| { | |||||
| Font font (depth * 0.5f); | |||||
| font.setUnderline (button.hasKeyboardFocus (false)); | |||||
| AttributedString s; | |||||
| s.setJustification (Justification::centred); | |||||
| s.append (button.getButtonText().trim(), font, colour); | |||||
| textLayout.createLayout (s, length); | |||||
| } | |||||
| void LookAndFeel_V3::drawTabButton (TabBarButton& button, Graphics& g, bool isMouseOver, bool isMouseDown) | |||||
| { | |||||
| const Rectangle<int> activeArea (button.getActiveArea()); | |||||
| const TabbedButtonBar::Orientation o = button.getTabbedButtonBar().getOrientation(); | |||||
| const Colour bkg (button.getTabBackgroundColour()); | |||||
| if (button.getToggleState()) | |||||
| { | |||||
| g.setColour (bkg); | |||||
| g.fillRect (activeArea); | |||||
| } | |||||
| else | |||||
| { | |||||
| Point<int> p1, p2; | |||||
| switch (o) | |||||
| { | |||||
| case TabbedButtonBar::TabsAtBottom: p1 = activeArea.getBottomLeft(); p2 = activeArea.getTopLeft(); break; | |||||
| case TabbedButtonBar::TabsAtTop: p1 = activeArea.getTopLeft(); p2 = activeArea.getBottomLeft(); break; | |||||
| case TabbedButtonBar::TabsAtRight: p1 = activeArea.getTopRight(); p2 = activeArea.getTopLeft(); break; | |||||
| case TabbedButtonBar::TabsAtLeft: p1 = activeArea.getTopLeft(); p2 = activeArea.getTopRight(); break; | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| g.setGradientFill (ColourGradient (bkg.brighter (0.2f), (float) p1.x, (float) p1.y, | |||||
| bkg.darker (0.1f), (float) p2.x, (float) p2.y, false)); | |||||
| g.fillRect (activeArea); | |||||
| } | |||||
| g.setColour (bkg.contrasting (0.3f)); | |||||
| Rectangle<int> r (activeArea); | |||||
| if (o != TabbedButtonBar::TabsAtBottom) g.fillRect (r.removeFromTop (1)); | |||||
| if (o != TabbedButtonBar::TabsAtTop) g.fillRect (r.removeFromBottom (1)); | |||||
| if (o != TabbedButtonBar::TabsAtRight) g.fillRect (r.removeFromLeft (1)); | |||||
| if (o != TabbedButtonBar::TabsAtLeft) g.fillRect (r.removeFromRight (1)); | |||||
| const float alpha = button.isEnabled() ? ((isMouseOver || isMouseDown) ? 1.0f : 0.8f) : 0.3f; | |||||
| const Colour col (bkg.contrasting().withMultipliedAlpha (alpha)); | |||||
| const Rectangle<float> area (button.getTextArea().toFloat()); | |||||
| float length = area.getWidth(); | |||||
| float depth = area.getHeight(); | |||||
| if (button.getTabbedButtonBar().isVertical()) | |||||
| std::swap (length, depth); | |||||
| TextLayout textLayout; | |||||
| createTabTextLayout (button, length, depth, col, textLayout); | |||||
| AffineTransform t; | |||||
| switch (o) | |||||
| { | |||||
| case TabbedButtonBar::TabsAtLeft: t = t.rotated (float_Pi * -0.5f).translated (area.getX(), area.getBottom()); break; | |||||
| case TabbedButtonBar::TabsAtRight: t = t.rotated (float_Pi * 0.5f).translated (area.getRight(), area.getY()); break; | |||||
| case TabbedButtonBar::TabsAtTop: | |||||
| case TabbedButtonBar::TabsAtBottom: t = t.translated (area.getX(), area.getY()); break; | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| g.addTransform (t); | |||||
| textLayout.draw (g, Rectangle<float> (length, depth)); | |||||
| } | |||||
| void LookAndFeel_V3::drawTreeviewPlusMinusBox (Graphics& g, const Rectangle<float>& area, | |||||
| Colour backgroundColour, bool isOpen, bool isMouseOver) | |||||
| { | |||||
| Path p; | |||||
| p.addTriangle (0.0f, 0.0f, 1.0f, isOpen ? 0.0f : 0.5f, isOpen ? 0.5f : 0.0f, 1.0f); | |||||
| g.setColour (backgroundColour.contrasting().withAlpha (isMouseOver ? 0.5f : 0.3f)); | |||||
| g.fillPath (p, p.getTransformToScaleToFit (area.reduced (2, area.getHeight() / 4), true)); | |||||
| } | |||||
| bool LookAndFeel_V3::areLinesDrawnForTreeView (TreeView&) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| int LookAndFeel_V3::getTreeViewIndentSize (TreeView&) | |||||
| { | |||||
| return 20; | |||||
| } | |||||
| void LookAndFeel_V3::drawComboBox (Graphics& g, int width, int height, const bool isButtonDown, | |||||
| int buttonX, int buttonY, int buttonW, int buttonH, ComboBox& box) | |||||
| { | |||||
| g.fillAll (box.findColour (ComboBox::backgroundColourId)); | |||||
| const Colour buttonColour (box.findColour (ComboBox::buttonColourId)); | |||||
| if (box.isEnabled() && box.hasKeyboardFocus (false)) | |||||
| { | |||||
| g.setColour (buttonColour); | |||||
| g.drawRect (0, 0, width, height, 2); | |||||
| } | |||||
| else | |||||
| { | |||||
| g.setColour (box.findColour (ComboBox::outlineColourId)); | |||||
| g.drawRect (0, 0, width, height); | |||||
| } | |||||
| const float outlineThickness = box.isEnabled() ? (isButtonDown ? 1.2f : 0.5f) : 0.3f; | |||||
| Path buttonShape; | |||||
| buttonShape.addRectangle (buttonX + outlineThickness, | |||||
| buttonY + outlineThickness, | |||||
| buttonW - outlineThickness * 2.0f, | |||||
| buttonH - outlineThickness * 2.0f); | |||||
| drawButtonShape (g, buttonShape, | |||||
| buttonColour.withMultipliedSaturation (box.hasKeyboardFocus (true) ? 1.3f : 0.9f) | |||||
| .withMultipliedAlpha (box.isEnabled() ? 0.9f : 0.5f), | |||||
| (float) height); | |||||
| if (box.isEnabled()) | |||||
| { | |||||
| const float arrowX = 0.3f; | |||||
| const float arrowH = 0.2f; | |||||
| Path p; | |||||
| p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.45f - arrowH), | |||||
| buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.45f, | |||||
| buttonX + buttonW * arrowX, buttonY + buttonH * 0.45f); | |||||
| p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.55f + arrowH), | |||||
| buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.55f, | |||||
| buttonX + buttonW * arrowX, buttonY + buttonH * 0.55f); | |||||
| g.setColour (box.findColour (ComboBox::arrowColourId)); | |||||
| g.fillPath (p); | |||||
| } | |||||
| } | |||||
| void LookAndFeel_V3::drawPopupMenuBackground (Graphics& g, int width, int height) | |||||
| { | |||||
| g.fillAll (findColour (PopupMenu::backgroundColourId)); | |||||
| (void) width; (void) height; | |||||
| #if ! JUCE_MAC | |||||
| g.setColour (findColour (PopupMenu::textColourId).withAlpha (0.6f)); | |||||
| g.drawRect (0, 0, width, height); | |||||
| #endif | |||||
| } | |||||
| void LookAndFeel_V3::drawKeymapChangeButton (Graphics& g, int width, int height, | |||||
| Button& button, const String& keyDescription) | |||||
| { | |||||
| const Colour textColour (button.findColour (0x100ad01 /*KeyMappingEditorComponent::textColourId*/, true)); | |||||
| if (keyDescription.isNotEmpty()) | |||||
| { | |||||
| if (button.isEnabled()) | |||||
| { | |||||
| g.setColour (textColour.withAlpha (button.isDown() ? 0.4f : (button.isOver() ? 0.2f : 0.1f))); | |||||
| g.fillRoundedRectangle (button.getLocalBounds().toFloat(), 4.0f); | |||||
| g.drawRoundedRectangle (button.getLocalBounds().toFloat(), 4.0f, 1.0f); | |||||
| } | |||||
| g.setColour (textColour); | |||||
| g.setFont (height * 0.6f); | |||||
| g.drawFittedText (keyDescription, 4, 0, width - 8, height, Justification::centred, 1); | |||||
| } | |||||
| else | |||||
| { | |||||
| const float thickness = 7.0f; | |||||
| const float indent = 22.0f; | |||||
| Path p; | |||||
| p.addEllipse (0.0f, 0.0f, 100.0f, 100.0f); | |||||
| p.addRectangle (indent, 50.0f - thickness, 100.0f - indent * 2.0f, thickness * 2.0f); | |||||
| p.addRectangle (50.0f - thickness, indent, thickness * 2.0f, 50.0f - indent - thickness); | |||||
| p.addRectangle (50.0f - thickness, 50.0f + thickness, thickness * 2.0f, 50.0f - indent - thickness); | |||||
| p.setUsingNonZeroWinding (false); | |||||
| g.setColour (textColour.darker(0.1f).withAlpha (button.isDown() ? 0.7f : (button.isOver() ? 0.5f : 0.3f))); | |||||
| g.fillPath (p, p.getTransformToScaleToFit (2.0f, 2.0f, width - 4.0f, height - 4.0f, true)); | |||||
| } | |||||
| if (button.hasKeyboardFocus (false)) | |||||
| { | |||||
| g.setColour (textColour.withAlpha (0.4f)); | |||||
| g.drawRect (0, 0, width, height); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,79 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2013 - Raw Material Software Ltd. | |||||
| Permission is granted to use this software under the terms of either: | |||||
| a) the GPL v2 (or any later version) | |||||
| b) the Affero GPL v3 | |||||
| Details of these licenses can be found at: www.gnu.org/licenses | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.juce.com for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifndef JUCE_LOOKANDFEEL_V3_H_INCLUDED | |||||
| #define JUCE_LOOKANDFEEL_V3_H_INCLUDED | |||||
| //============================================================================== | |||||
| /** | |||||
| The latest JUCE look-and-feel style, as introduced in 2013. | |||||
| @see LookAndFeel, LookAndFeel_V1, LookAndFeel_V2 | |||||
| */ | |||||
| class JUCE_API LookAndFeel_V3 : public LookAndFeel_V2 | |||||
| { | |||||
| public: | |||||
| LookAndFeel_V3(); | |||||
| ~LookAndFeel_V3(); | |||||
| //============================================================================== | |||||
| void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour, | |||||
| bool isMouseOverButton, bool isButtonDown) override; | |||||
| void drawTableHeaderBackground (Graphics&, TableHeaderComponent&) override; | |||||
| void drawTreeviewPlusMinusBox (Graphics&, const Rectangle<float>& area, | |||||
| Colour backgroundColour, bool isOpen, bool isMouseOver) override; | |||||
| bool areLinesDrawnForTreeView (TreeView&) override; | |||||
| int getTreeViewIndentSize (TreeView&) override; | |||||
| void drawComboBox (Graphics& g, int width, int height, bool isButtonDown, | |||||
| int buttonX, int buttonY, int buttonW, int buttonH, ComboBox& box) override; | |||||
| void drawKeymapChangeButton (Graphics& g, int width, int height, Button& button, const String& keyDescription) override; | |||||
| void drawPopupMenuBackground (Graphics& g, int width, int height) override; | |||||
| int getTabButtonOverlap (int tabDepth) override; | |||||
| int getTabButtonSpaceAroundImage() override; | |||||
| void drawTabButton (TabBarButton&, Graphics&, bool isMouseOver, bool isMouseDown) override; | |||||
| void drawStretchableLayoutResizerBar (Graphics&, int w, int h, bool isVerticalBar, bool isMouseOver, bool isMouseDragging) override; | |||||
| bool areScrollbarButtonsVisible() override; | |||||
| void drawScrollbar (Graphics&, ScrollBar&, int x, int y, int width, int height, bool isScrollbarVertical, | |||||
| int thumbStartPosition, int thumbSize, bool isMouseOver, bool isMouseDown) override; | |||||
| void drawConcertinaPanelHeader (Graphics&, const Rectangle<int>& area, bool isMouseOver, bool isMouseDown, | |||||
| ConcertinaPanel&, Component&) override; | |||||
| static void createTabTextLayout (const TabBarButton& button, float length, float depth, Colour colour, TextLayout&); | |||||
| private: | |||||
| Image backgroundTexture; | |||||
| Colour backgroundTextureBaseColour; | |||||
| }; | |||||
| #endif // JUCE_LOOKANDFEEL_H_INCLUDED | |||||
| @@ -480,6 +480,62 @@ public: | |||||
| void addCustomItem (int itemResultID, CustomComponent* customComponent, | void addCustomItem (int itemResultID, CustomComponent* customComponent, | ||||
| const PopupMenu* optionalSubMenu = nullptr); | const PopupMenu* optionalSubMenu = nullptr); | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| menu drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| /** Fills the background of a popup menu component. */ | |||||
| virtual void drawPopupMenuBackground (Graphics&, int width, int height) = 0; | |||||
| /** Draws one of the items in a popup menu. */ | |||||
| virtual void drawPopupMenuItem (Graphics&, int width, int height, | |||||
| bool isSeparator, bool isActive, bool isHighlighted, | |||||
| bool isTicked, bool hasSubMenu, | |||||
| const String& text, | |||||
| const String& shortcutKeyText, | |||||
| Image* icon, | |||||
| const Colour* textColour) = 0; | |||||
| /** Returns the size and style of font to use in popup menus. */ | |||||
| virtual Font getPopupMenuFont() = 0; | |||||
| virtual void drawPopupMenuUpDownArrow (Graphics&, | |||||
| int width, int height, | |||||
| bool isScrollUpArrow) = 0; | |||||
| /** Finds the best size for an item in a popup menu. */ | |||||
| virtual void getIdealPopupMenuItemSize (const String& text, | |||||
| bool isSeparator, | |||||
| int standardMenuItemHeight, | |||||
| int& idealWidth, | |||||
| int& idealHeight) = 0; | |||||
| virtual int getMenuWindowFlags() = 0; | |||||
| virtual void drawMenuBarBackground (Graphics&, int width, int height, | |||||
| bool isMouseOverBar, | |||||
| MenuBarComponent&) = 0; | |||||
| virtual int getDefaultMenuBarHeight() = 0; | |||||
| virtual int getMenuBarItemWidth (MenuBarComponent&, int itemIndex, const String& itemText) = 0; | |||||
| virtual Font getMenuBarFont (MenuBarComponent&, int itemIndex, const String& itemText) = 0; | |||||
| virtual void drawMenuBarItem (Graphics&, int width, int height, | |||||
| int itemIndex, | |||||
| const String& itemText, | |||||
| bool isMouseOverItem, | |||||
| bool isMenuOpen, | |||||
| bool isMouseOverBar, | |||||
| MenuBarComponent&) = 0; | |||||
| }; | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| JUCE_PUBLIC_IN_DLL_BUILD (class Item) | JUCE_PUBLIC_IN_DLL_BUILD (class Item) | ||||
| @@ -136,6 +136,19 @@ public: | |||||
| outlineColourId = 0x1000af1 /**< The colour to use for an outline around the bubble. */ | outlineColourId = 0x1000af1 /**< The colour to use for an outline around the bubble. */ | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawBubble (Graphics&, BubbleComponent&, | |||||
| const Point<float>& positionOfTip, | |||||
| const Rectangle<float>& body) = 0; | |||||
| }; | |||||
| protected: | protected: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Subclasses should override this to return the size of the content they | /** Subclasses should override this to return the size of the content they | ||||
| @@ -315,26 +315,39 @@ public: | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void handleMouseDownCallback (int index, float x, float y, int64 time) | |||||
| void handleMouseDownCallback (int index, Point<float> pos, int64 time) | |||||
| { | { | ||||
| lastMousePos.setXY ((int) x, (int) y); | |||||
| currentModifiers = currentModifiers.withoutMouseButtons(); | |||||
| handleMouseEvent (index, lastMousePos, currentModifiers, time); | |||||
| currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | |||||
| handleMouseEvent (index, lastMousePos, currentModifiers, time); | |||||
| lastMousePos = pos; | |||||
| // this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before. | |||||
| handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons(), time); | |||||
| if (isValidPeer (this)) | |||||
| handleMouseDragCallback (index, pos, time); | |||||
| } | } | ||||
| void handleMouseDragCallback (int index, float x, float y, int64 time) | |||||
| void handleMouseDragCallback (int index, Point<float> pos, int64 time) | |||||
| { | { | ||||
| lastMousePos.setXY ((int) x, (int) y); | |||||
| handleMouseEvent (index, lastMousePos, currentModifiers, time); | |||||
| lastMousePos = pos; | |||||
| jassert (index < 64); | |||||
| touchesDown = (touchesDown | (1 << (index & 63))); | |||||
| currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | |||||
| handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons() | |||||
| .withFlags (ModifierKeys::leftButtonModifier), time); | |||||
| } | } | ||||
| void handleMouseUpCallback (int index, float x, float y, int64 time) | |||||
| void handleMouseUpCallback (int index, Point<float> pos, int64 time) | |||||
| { | { | ||||
| lastMousePos.setXY ((int) x, (int) y); | |||||
| currentModifiers = currentModifiers.withoutMouseButtons(); | |||||
| handleMouseEvent (index, lastMousePos, currentModifiers, time); | |||||
| lastMousePos = pos; | |||||
| jassert (index < 64); | |||||
| touchesDown = (touchesDown & ~(1 << (index & 63))); | |||||
| if (touchesDown == 0) | |||||
| currentModifiers = currentModifiers.withoutMouseButtons(); | |||||
| handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons(), time); | |||||
| } | } | ||||
| void handleKeyDownCallback (int k, int kc) | void handleKeyDownCallback (int k, int kc) | ||||
| @@ -461,7 +474,8 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| static ModifierKeys currentModifiers; | static ModifierKeys currentModifiers; | ||||
| static Point<int> lastMousePos; | |||||
| static Point<float> lastMousePos; | |||||
| static int64 touchesDown; | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -526,7 +540,8 @@ private: | |||||
| }; | }; | ||||
| ModifierKeys AndroidComponentPeer::currentModifiers = 0; | ModifierKeys AndroidComponentPeer::currentModifiers = 0; | ||||
| Point<int> AndroidComponentPeer::lastMousePos; | |||||
| Point<float> AndroidComponentPeer::lastMousePos; | |||||
| int64 AndroidComponentPeer::touchesDown = 0; | |||||
| //============================================================================== | //============================================================================== | ||||
| #define JUCE_VIEW_CALLBACK(returnType, javaMethodName, params, juceMethodInvocation) \ | #define JUCE_VIEW_CALLBACK(returnType, javaMethodName, params, juceMethodInvocation) \ | ||||
| @@ -537,9 +552,9 @@ Point<int> AndroidComponentPeer::lastMousePos; | |||||
| } | } | ||||
| JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jlong host, jobject canvas), handlePaintCallback (env, canvas)) | JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jlong host, jobject canvas), handlePaintCallback (env, canvas)) | ||||
| JUCE_VIEW_CALLBACK (void, handleMouseDown, (JNIEnv* env, jobject view, jlong host, jint i, jfloat x, jfloat y, jlong time), handleMouseDownCallback (i, (float) x, (float) y, (int64) time)) | |||||
| JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv* env, jobject view, jlong host, jint i, jfloat x, jfloat y, jlong time), handleMouseDragCallback (i, (float) x, (float) y, (int64) time)) | |||||
| JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv* env, jobject view, jlong host, jint i, jfloat x, jfloat y, jlong time), handleMouseUpCallback (i, (float) x, (float) y, (int64) time)) | |||||
| JUCE_VIEW_CALLBACK (void, handleMouseDown, (JNIEnv* env, jobject view, jlong host, jint i, jfloat x, jfloat y, jlong time), handleMouseDownCallback (i, Point<float> ((float) x, (float) y), (int64) time)) | |||||
| JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv* env, jobject view, jlong host, jint i, jfloat x, jfloat y, jlong time), handleMouseDragCallback (i, Point<float> ((float) x, (float) y), (int64) time)) | |||||
| JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv* env, jobject view, jlong host, jint i, jfloat x, jfloat y, jlong time), handleMouseUpCallback (i, Point<float> ((float) x, (float) y), (int64) time)) | |||||
| JUCE_VIEW_CALLBACK (void, viewSizeChanged, (JNIEnv* env, jobject view, jlong host), handleMovedOrResized()) | JUCE_VIEW_CALLBACK (void, viewSizeChanged, (JNIEnv* env, jobject view, jlong host), handleMovedOrResized()) | ||||
| JUCE_VIEW_CALLBACK (void, focusChanged, (JNIEnv* env, jobject view, jlong host, jboolean hasFocus), handleFocusChangeCallback (hasFocus)) | JUCE_VIEW_CALLBACK (void, focusChanged, (JNIEnv* env, jobject view, jlong host, jboolean hasFocus), handleFocusChangeCallback (hasFocus)) | ||||
| JUCE_VIEW_CALLBACK (void, handleKeyDown, (JNIEnv* env, jobject view, jlong host, jint k, jint kc), handleKeyDownCallback ((int) k, (int) kc)) | JUCE_VIEW_CALLBACK (void, handleKeyDown, (JNIEnv* env, jobject view, jlong host, jint k, jint kc), handleKeyDownCallback ((int) k, (int) kc)) | ||||
| @@ -582,7 +597,7 @@ bool MouseInputSource::SourceList::addSource() | |||||
| Point<int> MouseInputSource::getCurrentRawMousePosition() | Point<int> MouseInputSource::getCurrentRawMousePosition() | ||||
| { | { | ||||
| return AndroidComponentPeer::lastMousePos; | |||||
| return AndroidComponentPeer::lastMousePos.toInt(); | |||||
| } | } | ||||
| void MouseInputSource::setRawMousePosition (Point<int>) | void MouseInputSource::setRawMousePosition (Point<int>) | ||||
| @@ -499,6 +499,7 @@ UIViewComponentPeer::UIViewComponentPeer (Component& comp, const int windowStyle | |||||
| r.origin.y = [UIScreen mainScreen].bounds.size.height - (r.origin.y + r.size.height); | r.origin.y = [UIScreen mainScreen].bounds.size.height - (r.origin.y + r.size.height); | ||||
| window = [[JuceUIWindow alloc] init]; | window = [[JuceUIWindow alloc] init]; | ||||
| window.hidden = true; | |||||
| window.autoresizesSubviews = NO; | window.autoresizesSubviews = NO; | ||||
| window.transform = CGAffineTransformIdentity; | window.transform = CGAffineTransformIdentity; | ||||
| window.frame = r; | window.frame = r; | ||||
| @@ -62,7 +62,6 @@ namespace MouseCursorHelpers | |||||
| return CustomMouseCursorInfo (im, (int) (hx * im.getWidth()), | return CustomMouseCursorInfo (im, (int) (hx * im.getWidth()), | ||||
| (int) (hy * im.getHeight())).create(); | (int) (hy * im.getHeight())).create(); | ||||
| jassertfalse; | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| } | } | ||||
| @@ -95,7 +94,16 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty | |||||
| case LeftEdgeResizeCursor: c = [NSCursor resizeLeftCursor]; break; | case LeftEdgeResizeCursor: c = [NSCursor resizeLeftCursor]; break; | ||||
| case RightEdgeResizeCursor: c = [NSCursor resizeRightCursor]; break; | case RightEdgeResizeCursor: c = [NSCursor resizeRightCursor]; break; | ||||
| case CrosshairCursor: c = [NSCursor crosshairCursor]; break; | case CrosshairCursor: c = [NSCursor crosshairCursor]; break; | ||||
| case CopyingCursor: return MouseCursorHelpers::fromWebKitFile ("copyCursor.png", 0, 0); | |||||
| case CopyingCursor: | |||||
| { | |||||
| #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 | |||||
| if (void* m = MouseCursorHelpers::fromWebKitFile ("copyCursor.png", 0, 0)) | |||||
| return m; | |||||
| #endif | |||||
| c = [NSCursor dragCopyCursor]; // added in 10.6 | |||||
| break; | |||||
| } | |||||
| case UpDownResizeCursor: | case UpDownResizeCursor: | ||||
| case TopEdgeResizeCursor: | case TopEdgeResizeCursor: | ||||
| @@ -1686,7 +1686,7 @@ struct JuceNSWindowClass : public ObjCClass <NSWindow> | |||||
| addMethod (@selector (canBecomeKeyWindow), canBecomeKeyWindow, "c@:"); | addMethod (@selector (canBecomeKeyWindow), canBecomeKeyWindow, "c@:"); | ||||
| addMethod (@selector (becomeKeyWindow), becomeKeyWindow, "v@:"); | addMethod (@selector (becomeKeyWindow), becomeKeyWindow, "v@:"); | ||||
| addMethod (@selector (windowShouldClose:), windowShouldClose, "c@:@"); | addMethod (@selector (windowShouldClose:), windowShouldClose, "c@:@"); | ||||
| addMethod (@selector (constrainFrameRect:toScreen:), constrainFrameRect, @encode (NSRect), "@:", @encode (NSRect*), "@"); | |||||
| addMethod (@selector (constrainFrameRect:toScreen:), constrainFrameRect, @encode (NSRect), "@:", @encode (NSRect), "@"); | |||||
| addMethod (@selector (windowWillResize:toSize:), windowWillResize, @encode (NSSize), "@:@", @encode (NSSize)); | addMethod (@selector (windowWillResize:toSize:), windowWillResize, @encode (NSSize), "@:@", @encode (NSSize)); | ||||
| addMethod (@selector (zoom:), zoom, "v@:@"); | addMethod (@selector (zoom:), zoom, "v@:@"); | ||||
| addMethod (@selector (windowWillMove:), windowWillMove, "v@:@"); | addMethod (@selector (windowWillMove:), windowWillMove, "v@:@"); | ||||
| @@ -1807,13 +1807,10 @@ private: | |||||
| { | { | ||||
| const DWORD flags = inputInfo[i].dwFlags; | const DWORD flags = inputInfo[i].dwFlags; | ||||
| if ((flags & TOUCHEVENTF_PRIMARY) == 0 // primary events are handled by WM_LBUTTON etc | |||||
| && (flags & (TOUCHEVENTF_DOWN | TOUCHEVENTF_MOVE | TOUCHEVENTF_UP)) != 0) | |||||
| { | |||||
| if (! handleTouchInput (inputInfo[i], (flags & TOUCHEVENTF_DOWN) != 0, | |||||
| (flags & TOUCHEVENTF_UP) != 0)) | |||||
| if ((flags & (TOUCHEVENTF_DOWN | TOUCHEVENTF_MOVE | TOUCHEVENTF_UP)) != 0) | |||||
| if (! handleTouchInput (inputInfo[i], (flags & TOUCHEVENTF_PRIMARY) != 0, | |||||
| (flags & TOUCHEVENTF_DOWN) != 0, (flags & TOUCHEVENTF_UP) != 0)) | |||||
| return 0; // abandon method if this window was deleted by the callback | return 0; // abandon method if this window was deleted by the callback | ||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1821,7 +1818,7 @@ private: | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| bool handleTouchInput (const TOUCHINPUT& touch, const bool isDown, const bool isUp) | |||||
| bool handleTouchInput (const TOUCHINPUT& touch, const bool isPrimary, const bool isDown, const bool isUp) | |||||
| { | { | ||||
| bool isCancel = false; | bool isCancel = false; | ||||
| const int touchIndex = currentTouches.getIndexOfTouch (touch.dwID); | const int touchIndex = currentTouches.getIndexOfTouch (touch.dwID); | ||||
| @@ -1835,10 +1832,13 @@ private: | |||||
| currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | ||||
| modsToSend = currentModifiers; | modsToSend = currentModifiers; | ||||
| // this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before. | |||||
| handleMouseEvent (touchIndex + 1, pos, modsToSend.withoutMouseButtons(), time); | |||||
| if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||||
| return false; | |||||
| if (! isPrimary) | |||||
| { | |||||
| // this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before. | |||||
| handleMouseEvent (touchIndex, pos, modsToSend.withoutMouseButtons(), time); | |||||
| if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||||
| return false; | |||||
| } | |||||
| } | } | ||||
| else if (isUp) | else if (isUp) | ||||
| { | { | ||||
| @@ -1848,6 +1848,10 @@ private: | |||||
| if (! currentTouches.areAnyTouchesActive()) | if (! currentTouches.areAnyTouchesActive()) | ||||
| isCancel = true; | isCancel = true; | ||||
| } | } | ||||
| else | |||||
| { | |||||
| modsToSend = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | |||||
| } | |||||
| if (isCancel) | if (isCancel) | ||||
| { | { | ||||
| @@ -1855,13 +1859,16 @@ private: | |||||
| currentModifiers = currentModifiers.withoutMouseButtons(); | currentModifiers = currentModifiers.withoutMouseButtons(); | ||||
| } | } | ||||
| handleMouseEvent (touchIndex + 1, pos, modsToSend, time); | |||||
| if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||||
| return false; | |||||
| if (! isPrimary) | |||||
| { | |||||
| handleMouseEvent (touchIndex, pos, modsToSend, time); | |||||
| if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||||
| return false; | |||||
| } | |||||
| if (isUp || isCancel) | |||||
| if ((isUp || isCancel) && ! isPrimary) | |||||
| { | { | ||||
| handleMouseEvent (touchIndex + 1, Point<int> (-10, -10), currentModifiers, time); | |||||
| handleMouseEvent (touchIndex, Point<int> (-10, -10), currentModifiers, time); | |||||
| if (! isValidPeer (this)) | if (! isValidPeer (this)) | ||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -102,6 +102,18 @@ public: | |||||
| /** By default, this just repaints the component. */ | /** By default, this just repaints the component. */ | ||||
| void enablementChanged() override; | void enablementChanged() override; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawPropertyPanelSectionHeader (Graphics&, const String& name, bool isOpen, int width, int height) = 0; | |||||
| virtual void drawPropertyComponentBackground (Graphics&, int width, int height, PropertyComponent&) = 0; | |||||
| virtual void drawPropertyComponentLabel (Graphics&, int width, int height, PropertyComponent&) = 0; | |||||
| virtual Rectangle<int> getPropertyComponentContentPosition (PropertyComponent&) = 0; | |||||
| }; | |||||
| protected: | protected: | ||||
| /** Used by the PropertyPanel to determine how high this component needs to be. | /** Used by the PropertyPanel to determine how high this component needs to be. | ||||
| A subclass can update this value in its constructor but shouldn't alter it later | A subclass can update this value in its constructor but shouldn't alter it later | ||||
| @@ -333,6 +333,25 @@ public: | |||||
| arrowColourId = 0x1000e00, /**< The colour for the arrow shape that pops up the menu */ | arrowColourId = 0x1000e00, /**< The colour for the arrow shape that pops up the menu */ | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| ComboBox functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawComboBox (Graphics&, int width, int height, bool isButtonDown, | |||||
| int buttonX, int buttonY, int buttonW, int buttonH, | |||||
| ComboBox&) = 0; | |||||
| virtual Font getComboBoxFont (ComboBox&) = 0; | |||||
| virtual Label* createComboBoxTextBox (ComboBox&) = 0; | |||||
| virtual void positionComboBoxText (ComboBox&, Label& labelToPosition) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void labelTextChanged (Label*) override; | void labelTextChanged (Label*) override; | ||||
| @@ -249,6 +249,18 @@ public: | |||||
| /** Returns the currently-visible text editor, or nullptr if none is open. */ | /** Returns the currently-visible text editor, or nullptr if none is open. */ | ||||
| TextEditor* getCurrentTextEditor() const noexcept; | TextEditor* getCurrentTextEditor() const noexcept; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| label drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawLabel (Graphics&, Label&) = 0; | |||||
| virtual Font getLabelFont (Label&) = 0; | |||||
| }; | |||||
| protected: | protected: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Creates the TextEditor component that will be used when the user has clicked on the label. | /** Creates the TextEditor component that will be used when the user has clicked on the label. | ||||
| @@ -90,6 +90,24 @@ public: | |||||
| classes will probably use variations on this colour. */ | classes will probably use variations on this colour. */ | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| /** Draws a progress bar. | |||||
| If the progress value is less than 0 or greater than 1.0, this should draw a spinning | |||||
| bar that fills the whole space (i.e. to say that the app is still busy but the progress | |||||
| isn't known). It can use the current time as a basis for playing an animation. | |||||
| (Used by progress bars in AlertWindow). | |||||
| */ | |||||
| virtual void drawProgressBar (Graphics&, ProgressBar&, int width, int height, | |||||
| double progress, const String& textToShow) = 0; | |||||
| }; | |||||
| protected: | protected: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| @@ -762,6 +762,57 @@ public: | |||||
| textBoxOutlineColourId = 0x1001700 /**< The colour to use for a border around the text-editor box. */ | textBoxOutlineColourId = 0x1001700 /**< The colour to use for a border around the text-editor box. */ | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| slider drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| //============================================================================== | |||||
| virtual void drawLinearSlider (Graphics&, | |||||
| int x, int y, int width, int height, | |||||
| float sliderPos, | |||||
| float minSliderPos, | |||||
| float maxSliderPos, | |||||
| const Slider::SliderStyle, | |||||
| Slider&) = 0; | |||||
| virtual void drawLinearSliderBackground (Graphics&, | |||||
| int x, int y, int width, int height, | |||||
| float sliderPos, | |||||
| float minSliderPos, | |||||
| float maxSliderPos, | |||||
| const Slider::SliderStyle style, | |||||
| Slider&) = 0; | |||||
| virtual void drawLinearSliderThumb (Graphics&, | |||||
| int x, int y, int width, int height, | |||||
| float sliderPos, | |||||
| float minSliderPos, | |||||
| float maxSliderPos, | |||||
| const Slider::SliderStyle, | |||||
| Slider&) = 0; | |||||
| virtual int getSliderThumbRadius (Slider&) = 0; | |||||
| virtual void drawRotarySlider (Graphics&, | |||||
| int x, int y, int width, int height, | |||||
| float sliderPosProportional, | |||||
| float rotaryStartAngle, | |||||
| float rotaryEndAngle, | |||||
| Slider&) = 0; | |||||
| virtual Button* createSliderButton (bool isIncrement) = 0; | |||||
| virtual Label* createSliderTextBox (Slider&) = 0; | |||||
| virtual ImageEffectFilter* getSliderEffect() = 0; | |||||
| virtual Font getSliderPopupFont() = 0; | |||||
| virtual int getSliderPopupPlacement() = 0; | |||||
| }; | |||||
| protected: | protected: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| @@ -366,6 +366,19 @@ public: | |||||
| */ | */ | ||||
| virtual void reactToMenuItem (int menuReturnId, int columnIdClicked); | virtual void reactToMenuItem (int menuReturnId, int columnIdClicked); | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawTableHeaderBackground (Graphics&, TableHeaderComponent&) = 0; | |||||
| virtual void drawTableHeaderColumn (Graphics&, const String& columnName, int columnId, | |||||
| int width, int height, | |||||
| bool isMouseOver, bool isMouseDown, int columnFlags) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void paint (Graphics&) override; | void paint (Graphics&) override; | ||||
| @@ -580,6 +580,20 @@ public: | |||||
| void setInputRestrictions (int maxTextLength, | void setInputRestrictions (int maxTextLength, | ||||
| const String& allowedCharacters = String::empty); | const String& allowedCharacters = String::empty); | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| TextEditor drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void fillTextEditorBackground (Graphics&, int width, int height, TextEditor&) = 0; | |||||
| virtual void drawTextEditorOutline (Graphics&, int width, int height, TextEditor&) = 0; | |||||
| virtual CaretComponent* createCaretComponent (Component* keyFocusOwner) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void paint (Graphics&) override; | void paint (Graphics&) override; | ||||
| @@ -267,6 +267,24 @@ public: | |||||
| bool restoreFromString (ToolbarItemFactory& factoryToUse, | bool restoreFromString (ToolbarItemFactory& factoryToUse, | ||||
| const String& savedVersion); | const String& savedVersion); | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void paintToolbarBackground (Graphics&, int width, int height, Toolbar&) = 0; | |||||
| virtual Button* createToolbarMissingItemsButton (Toolbar&) = 0; | |||||
| virtual void paintToolbarButtonBackground (Graphics&, int width, int height, | |||||
| bool isMouseOver, bool isMouseDown, | |||||
| ToolbarItemComponent&) = 0; | |||||
| virtual void paintToolbarButtonLabel (Graphics&, int x, int y, int width, int height, | |||||
| const String& text, ToolbarItemComponent&) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void paint (Graphics&) override; | void paint (Graphics&) override; | ||||
| @@ -439,7 +439,7 @@ TreeView::TreeView (const String& name) | |||||
| : Component (name), | : Component (name), | ||||
| viewport (new TreeViewport()), | viewport (new TreeViewport()), | ||||
| rootItem (nullptr), | rootItem (nullptr), | ||||
| indentSize (24), | |||||
| indentSize (-1), | |||||
| defaultOpenness (false), | defaultOpenness (false), | ||||
| needsRecalculating (true), | needsRecalculating (true), | ||||
| rootItemVisible (true), | rootItemVisible (true), | ||||
| @@ -522,6 +522,12 @@ void TreeView::setIndentSize (const int newIndentSize) | |||||
| } | } | ||||
| } | } | ||||
| int TreeView::getIndentSize() noexcept | |||||
| { | |||||
| return indentSize >= 0 ? indentSize | |||||
| : getLookAndFeel().getTreeViewIndentSize (*this); | |||||
| } | |||||
| void TreeView::setDefaultOpenness (const bool isOpenByDefault) | void TreeView::setDefaultOpenness (const bool isOpenByDefault) | ||||
| { | { | ||||
| if (defaultOpenness != isOpenByDefault) | if (defaultOpenness != isOpenByDefault) | ||||
| @@ -860,7 +866,7 @@ void TreeView::recalculateIfNeeded() | |||||
| //============================================================================== | //============================================================================== | ||||
| struct TreeView::InsertPoint | struct TreeView::InsertPoint | ||||
| { | { | ||||
| InsertPoint (const TreeView& view, const StringArray& files, | |||||
| InsertPoint (TreeView& view, const StringArray& files, | |||||
| const DragAndDropTarget::SourceDetails& dragSourceDetails) | const DragAndDropTarget::SourceDetails& dragSourceDetails) | ||||
| : pos (dragSourceDetails.localPosition), | : pos (dragSourceDetails.localPosition), | ||||
| item (view.getItemAt (dragSourceDetails.localPosition.y)), | item (view.getItemAt (dragSourceDetails.localPosition.y)), | ||||
| @@ -1125,7 +1131,8 @@ TreeViewItem::TreeViewItem() | |||||
| totalWidth (0), | totalWidth (0), | ||||
| selected (false), | selected (false), | ||||
| redrawNeeded (true), | redrawNeeded (true), | ||||
| drawLinesInside (true), | |||||
| drawLinesInside (false), | |||||
| drawLinesSet (false), | |||||
| drawsInLeftMargin (false), | drawsInLeftMargin (false), | ||||
| openness (opennessDefault) | openness (opennessDefault) | ||||
| { | { | ||||
| @@ -1317,10 +1324,10 @@ void TreeViewItem::paintItem (Graphics&, int, int) | |||||
| { | { | ||||
| } | } | ||||
| void TreeViewItem::paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver) | |||||
| void TreeViewItem::paintOpenCloseButton (Graphics& g, const Rectangle<float>& area, Colour backgroundColour, bool isMouseOver) | |||||
| { | { | ||||
| ownerView->getLookAndFeel() | |||||
| .drawTreeviewPlusMinusBox (g, 0, 0, width, height, ! isOpen(), isMouseOver); | |||||
| getOwnerView()->getLookAndFeel() | |||||
| .drawTreeviewPlusMinusBox (g, area, backgroundColour, isOpen(), isMouseOver); | |||||
| } | } | ||||
| void TreeViewItem::paintHorizontalConnectingLine (Graphics& g, const Line<float>& line) | void TreeViewItem::paintHorizontalConnectingLine (Graphics& g, const Line<float>& line) | ||||
| @@ -1495,6 +1502,12 @@ namespace TreeViewHelpers | |||||
| } | } | ||||
| } | } | ||||
| bool TreeViewItem::areLinesDrawn() const | |||||
| { | |||||
| return drawLinesSet ? drawLinesInside | |||||
| : (ownerView != nullptr && ownerView->getLookAndFeel().areLinesDrawnForTreeView (*ownerView)); | |||||
| } | |||||
| void TreeViewItem::paintRecursively (Graphics& g, int width) | void TreeViewItem::paintRecursively (Graphics& g, int width) | ||||
| { | { | ||||
| jassert (ownerView != nullptr); | jassert (ownerView != nullptr); | ||||
| @@ -1510,7 +1523,12 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||||
| if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, | if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, | ||||
| drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) | drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) | ||||
| { | |||||
| if (isSelected()) | |||||
| g.fillAll (ownerView->findColour (TreeView::selectedItemBackgroundColourId)); | |||||
| paintItem (g, itemW, itemHeight); | paintItem (g, itemW, itemHeight); | ||||
| } | |||||
| } | } | ||||
| const float halfH = itemHeight * 0.5f; | const float halfH = itemHeight * 0.5f; | ||||
| @@ -1521,11 +1539,12 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||||
| { | { | ||||
| float x = (depth + 0.5f) * indentWidth; | float x = (depth + 0.5f) * indentWidth; | ||||
| if (parentItem != nullptr && parentItem->drawLinesInside) | |||||
| const bool parentLinesDrawn = parentItem != nullptr && parentItem->areLinesDrawn(); | |||||
| if (parentLinesDrawn) | |||||
| paintVerticalConnectingLine (g, Line<float> (x, 0, x, isLastOfSiblings() ? halfH : (float) itemHeight)); | paintVerticalConnectingLine (g, Line<float> (x, 0, x, isLastOfSiblings() ? halfH : (float) itemHeight)); | ||||
| if ((parentItem != nullptr && parentItem->drawLinesInside) | |||||
| || (parentItem == nullptr && drawLinesInside)) | |||||
| if (parentLinesDrawn || (parentItem == nullptr && areLinesDrawn())) | |||||
| paintHorizontalConnectingLine (g, Line<float> (x, halfH, x + indentWidth / 2, halfH)); | paintHorizontalConnectingLine (g, Line<float> (x, halfH, x + indentWidth / 2, halfH)); | ||||
| { | { | ||||
| @@ -1536,8 +1555,7 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||||
| { | { | ||||
| x -= (float) indentWidth; | x -= (float) indentWidth; | ||||
| if ((p->parentItem == nullptr || p->parentItem->drawLinesInside) | |||||
| && ! p->isLastOfSiblings()) | |||||
| if ((p->parentItem == nullptr || p->parentItem->areLinesDrawn()) && ! p->isLastOfSiblings()) | |||||
| p->paintVerticalConnectingLine (g, Line<float> (x, 0, x, (float) itemHeight)); | p->paintVerticalConnectingLine (g, Line<float> (x, 0, x, (float) itemHeight)); | ||||
| p = p->parentItem; | p = p->parentItem; | ||||
| @@ -1545,15 +1563,9 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||||
| } | } | ||||
| if (mightContainSubItems()) | if (mightContainSubItems()) | ||||
| { | |||||
| Graphics::ScopedSaveState ss (g); | |||||
| g.setOrigin (depth * indentWidth, 0); | |||||
| g.reduceClipRegion (0, 0, indentWidth, itemHeight); | |||||
| paintOpenCloseButton (g, indentWidth, itemHeight, | |||||
| paintOpenCloseButton (g, Rectangle<float> ((float) (depth * indentWidth), 0, (float) indentWidth, (float) itemHeight), | |||||
| Colours::white, | |||||
| ownerView->viewport->getContentComp()->isMouseOverButton (this)); | ownerView->viewport->getContentComp()->isMouseOverButton (this)); | ||||
| } | |||||
| } | } | ||||
| if (isOpen()) | if (isOpen()) | ||||
| @@ -1731,6 +1743,7 @@ int TreeViewItem::getRowNumberInTree() const noexcept | |||||
| void TreeViewItem::setLinesDrawnForSubItems (const bool drawLines) noexcept | void TreeViewItem::setLinesDrawnForSubItems (const bool drawLines) noexcept | ||||
| { | { | ||||
| drawLinesInside = drawLines; | drawLinesInside = drawLines; | ||||
| drawLinesSet = true; | |||||
| } | } | ||||
| TreeViewItem* TreeViewItem::getNextVisibleItem (const bool recurse) const noexcept | TreeViewItem* TreeViewItem::getNextVisibleItem (const bool recurse) const noexcept | ||||
| @@ -1840,8 +1853,8 @@ XmlElement* TreeViewItem::getOpennessState (const bool canReturnNull) const | |||||
| e = new XmlElement ("OPEN"); | e = new XmlElement ("OPEN"); | ||||
| for (int i = 0; i < subItems.size(); ++i) | |||||
| e->addChildElement (subItems.getUnchecked(i)->getOpennessState (true)); | |||||
| for (int i = subItems.size(); --i >= 0;) | |||||
| e->prependChildElement (subItems.getUnchecked(i)->getOpennessState (true)); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -83,6 +83,20 @@ public: | |||||
| */ | */ | ||||
| void addSubItem (TreeViewItem* newItem, int insertPosition = -1); | void addSubItem (TreeViewItem* newItem, int insertPosition = -1); | ||||
| /** Adds a sub-item with a sort-comparator, assuming that the existing items are already sorted. | |||||
| @param comparator the comparator object for sorting - see sortSubItems() for details about | |||||
| the methods this class must provide. | |||||
| @param newItem the object to add to the item's sub-item list. Once added, these can be | |||||
| found using getSubItem(). When the items are later removed with | |||||
| removeSubItem() (or when this item is deleted), they will be deleted. | |||||
| */ | |||||
| template <class ElementComparator> | |||||
| void addSubItemSorted (ElementComparator& comparator, TreeViewItem* newItem) | |||||
| { | |||||
| addSubItem (newItem, findInsertIndexInSortedArray (comparator, subItems.begin(), newItem, 0, subItems.size())); | |||||
| } | |||||
| /** Removes one of the sub-items. | /** Removes one of the sub-items. | ||||
| @param index the item to remove | @param index the item to remove | ||||
| @@ -178,7 +192,7 @@ public: | |||||
| bool areAllParentsOpen() const noexcept; | bool areAllParentsOpen() const noexcept; | ||||
| /** Changes whether lines are drawn to connect any sub-items to this item. | /** Changes whether lines are drawn to connect any sub-items to this item. | ||||
| By default, line-drawing is turned on. | |||||
| By default, line-drawing is turned on according to LookAndFeel::areLinesDrawnForTreeView(). | |||||
| */ | */ | ||||
| void setLinesDrawnForSubItems (bool shouldDrawLines) noexcept; | void setLinesDrawnForSubItems (bool shouldDrawLines) noexcept; | ||||
| @@ -299,11 +313,14 @@ public: | |||||
| /** Draws the item's open/close button. | /** Draws the item's open/close button. | ||||
| If you don't implement this method, the default behaviour is to | |||||
| call LookAndFeel::drawTreeviewPlusMinusBox(), but you can override | |||||
| it for custom effects. | |||||
| If you don't implement this method, the default behaviour is to call | |||||
| LookAndFeel::drawTreeviewPlusMinusBox(), but you can override it for custom | |||||
| effects. You may want to override it and call the base-class implementation | |||||
| with a different backgroundColour parameter, if your implementation has a | |||||
| background colour other than the default (white). | |||||
| */ | */ | ||||
| virtual void paintOpenCloseButton (Graphics&, int width, int height, bool isMouseOver); | |||||
| virtual void paintOpenCloseButton (Graphics&, const Rectangle<float>& area, | |||||
| Colour backgroundColour, bool isMouseOver); | |||||
| /** Draws the line that connects this item to the vertical line extending below its parent. */ | /** Draws the line that connects this item to the vertical line extending below its parent. */ | ||||
| virtual void paintHorizontalConnectingLine (Graphics&, const Line<float>& line); | virtual void paintHorizontalConnectingLine (Graphics&, const Line<float>& line); | ||||
| @@ -519,12 +536,13 @@ private: | |||||
| //============================================================================== | //============================================================================== | ||||
| TreeView* ownerView; | TreeView* ownerView; | ||||
| TreeViewItem* parentItem; | TreeViewItem* parentItem; | ||||
| OwnedArray <TreeViewItem> subItems; | |||||
| OwnedArray<TreeViewItem> subItems; | |||||
| int y, itemHeight, totalHeight, itemWidth, totalWidth; | int y, itemHeight, totalHeight, itemWidth, totalWidth; | ||||
| int uid; | int uid; | ||||
| bool selected : 1; | bool selected : 1; | ||||
| bool redrawNeeded : 1; | bool redrawNeeded : 1; | ||||
| bool drawLinesInside : 1; | bool drawLinesInside : 1; | ||||
| bool drawLinesSet : 1; | |||||
| bool drawsInLeftMargin : 1; | bool drawsInLeftMargin : 1; | ||||
| unsigned int openness : 2; | unsigned int openness : 2; | ||||
| @@ -549,6 +567,7 @@ private: | |||||
| XmlElement* getOpennessState (bool canReturnNull) const; | XmlElement* getOpennessState (bool canReturnNull) const; | ||||
| bool removeSubItemFromList (int index, bool deleteItem); | bool removeSubItemFromList (int index, bool deleteItem); | ||||
| void removeAllSubItemsFromList(); | void removeAllSubItemsFromList(); | ||||
| bool areLinesDrawn() const; | |||||
| #if JUCE_CATCH_DEPRECATED_CODE_MISUSE | #if JUCE_CATCH_DEPRECATED_CODE_MISUSE | ||||
| // The parameters for these methods have changed - please update your code! | // The parameters for these methods have changed - please update your code! | ||||
| @@ -721,7 +740,7 @@ public: | |||||
| /** Returns the number of pixels by which each nested level of the tree is indented. | /** Returns the number of pixels by which each nested level of the tree is indented. | ||||
| @see setIndentSize | @see setIndentSize | ||||
| */ | */ | ||||
| int getIndentSize() const noexcept { return indentSize; } | |||||
| int getIndentSize() noexcept; | |||||
| /** Changes the distance by which each nested level of the tree is indented. | /** Changes the distance by which each nested level of the tree is indented. | ||||
| @see getIndentSize | @see getIndentSize | ||||
| @@ -779,9 +798,25 @@ public: | |||||
| */ | */ | ||||
| enum ColourIds | enum ColourIds | ||||
| { | { | ||||
| backgroundColourId = 0x1000500, /**< A background colour to fill the component with. */ | |||||
| linesColourId = 0x1000501, /**< The colour to draw the lines with.*/ | |||||
| dragAndDropIndicatorColourId = 0x1000502 /**< The colour to use for the drag-and-drop target position indicator. */ | |||||
| backgroundColourId = 0x1000500, /**< A background colour to fill the component with. */ | |||||
| linesColourId = 0x1000501, /**< The colour to draw the lines with.*/ | |||||
| dragAndDropIndicatorColourId = 0x1000502, /**< The colour to use for the drag-and-drop target position indicator. */ | |||||
| selectedItemBackgroundColourId = 0x1000503 /**< The colour to use to fill the background of any selected items. */ | |||||
| }; | |||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| treeview drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawTreeviewPlusMinusBox (Graphics&, const Rectangle<float>& area, | |||||
| Colour backgroundColour, bool isItemOpen, bool isMouseOver) = 0; | |||||
| virtual bool areLinesDrawnForTreeView (TreeView&) = 0; | |||||
| virtual int getTreeViewIndentSize (TreeView&) = 0; | |||||
| }; | }; | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -849,6 +884,11 @@ private: | |||||
| void moveIntoSelectedItem(); | void moveIntoSelectedItem(); | ||||
| void moveByPages (int numPages); | void moveByPages (int numPages); | ||||
| #if JUCE_CATCH_DEPRECATED_CODE_MISUSE | |||||
| // this method has been deprecated - see the new version.. | |||||
| virtual int paintOpenCloseButton (Graphics&, int, int, bool) { return 0; } | |||||
| #endif | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeView) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeView) | ||||
| }; | }; | ||||
| @@ -417,6 +417,32 @@ public: | |||||
| outlineColourId = 0x1001820 /**< An optional colour to use to draw a border around the window. */ | outlineColourId = 0x1001820 /**< An optional colour to use to draw a border around the window. */ | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| alert-window drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual AlertWindow* createAlertWindow (const String& title, const String& message, | |||||
| const String& button1, | |||||
| const String& button2, | |||||
| const String& button3, | |||||
| AlertWindow::AlertIconType iconType, | |||||
| int numButtons, | |||||
| Component* associatedComponent) = 0; | |||||
| virtual void drawAlertBox (Graphics&, AlertWindow&, const Rectangle<int>& textArea, TextLayout&) = 0; | |||||
| virtual int getAlertBoxWindowFlags() = 0; | |||||
| virtual int getAlertWindowButtonHeight() = 0; | |||||
| virtual Font getAlertWindowMessageFont() = 0; | |||||
| virtual Font getAlertWindowFont() = 0; | |||||
| }; | |||||
| protected: | protected: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| @@ -48,8 +48,11 @@ CallOutBox::~CallOutBox() | |||||
| { | { | ||||
| } | } | ||||
| enum { callOutBoxDismissCommandId = 0x4f83a04b }; | |||||
| //============================================================================== | //============================================================================== | ||||
| class CallOutBoxCallback : public ModalComponentManager::Callback | |||||
| class CallOutBoxCallback : public ModalComponentManager::Callback, | |||||
| private Timer | |||||
| { | { | ||||
| public: | public: | ||||
| CallOutBoxCallback (Component* c, const Rectangle<int>& area, Component* parent) | CallOutBoxCallback (Component* c, const Rectangle<int>& area, Component* parent) | ||||
| @@ -57,9 +60,16 @@ public: | |||||
| { | { | ||||
| callout.setVisible (true); | callout.setVisible (true); | ||||
| callout.enterModalState (true, this); | callout.enterModalState (true, this); | ||||
| startTimer (200); | |||||
| } | } | ||||
| void modalStateFinished (int) {} | |||||
| void modalStateFinished (int) override {} | |||||
| void timerCallback() override | |||||
| { | |||||
| if (! Process::isForegroundProcess()) | |||||
| callout.postCommandMessage (callOutBoxDismissCommandId); | |||||
| } | |||||
| ScopedPointer<Component> content; | ScopedPointer<Component> content; | ||||
| CallOutBox callout; | CallOutBox callout; | ||||
| @@ -110,8 +120,6 @@ bool CallOutBox::hitTest (int x, int y) | |||||
| return outline.contains ((float) x, (float) y); | return outline.contains ((float) x, (float) y); | ||||
| } | } | ||||
| enum { callOutBoxDismissCommandId = 0x4f83a04b }; | |||||
| void CallOutBox::inputAttemptWhenModal() | void CallOutBox::inputAttemptWhenModal() | ||||
| { | { | ||||
| const Point<int> mousePos (getMouseXYRelative() + getBounds().getPosition()); | const Point<int> mousePos (getMouseXYRelative() + getBounds().getPosition()); | ||||
| @@ -118,6 +118,15 @@ public: | |||||
| const Rectangle<int>& areaToPointTo, | const Rectangle<int>& areaToPointTo, | ||||
| Component* parentComponent); | Component* parentComponent); | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes. */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawCallOutBoxBackground (CallOutBox&, Graphics&, const Path&, Image& cachedImage) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void paint (Graphics&) override; | void paint (Graphics&) override; | ||||
| @@ -298,15 +298,11 @@ void ComponentPeer::handleMovedOrResized() | |||||
| Rectangle<int> newBounds (Component::ComponentHelpers::rawPeerPositionToLocal (component, getBounds())); | Rectangle<int> newBounds (Component::ComponentHelpers::rawPeerPositionToLocal (component, getBounds())); | ||||
| Rectangle<int> oldBounds (component.getBounds()); | Rectangle<int> oldBounds (component.getBounds()); | ||||
| // oldBounds = Component::ComponentHelpers::localPositionToRawPeerPos (component, oldBounds); | |||||
| const bool wasMoved = (oldBounds.getPosition() != newBounds.getPosition()); | const bool wasMoved = (oldBounds.getPosition() != newBounds.getPosition()); | ||||
| const bool wasResized = (oldBounds.getWidth() != newBounds.getWidth() || oldBounds.getHeight() != newBounds.getHeight()); | const bool wasResized = (oldBounds.getWidth() != newBounds.getWidth() || oldBounds.getHeight() != newBounds.getHeight()); | ||||
| if (wasMoved || wasResized) | if (wasMoved || wasResized) | ||||
| { | { | ||||
| // newBounds = Component::ComponentHelpers::rawPeerPositionToLocal (component, newBounds); | |||||
| component.bounds = newBounds; | component.bounds = newBounds; | ||||
| if (wasResized) | if (wasResized) | ||||
| @@ -223,6 +223,30 @@ public: | |||||
| and feel class how this is used. */ | and feel class how this is used. */ | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| window drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void drawDocumentWindowTitleBar (DocumentWindow&, | |||||
| Graphics&, int w, int h, | |||||
| int titleSpaceX, int titleSpaceW, | |||||
| const Image* icon, | |||||
| bool drawTitleTextOnLeft) = 0; | |||||
| virtual Button* createDocumentWindowButton (int buttonType) = 0; | |||||
| virtual void positionDocumentWindowButtons (DocumentWindow&, | |||||
| int titleBarX, int titleBarY, int titleBarW, int titleBarH, | |||||
| Button* minimiseButton, | |||||
| Button* maximiseButton, | |||||
| Button* closeButton, | |||||
| bool positionTitleBarButtonsOnLeft) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| #ifndef DOXYGEN | #ifndef DOXYGEN | ||||
| /** @internal */ | /** @internal */ | ||||
| @@ -306,8 +306,23 @@ public: | |||||
| bool resizeToFit = false)); | bool resizeToFit = false)); | ||||
| using TopLevelWindow::addToDesktop; | using TopLevelWindow::addToDesktop; | ||||
| protected: | |||||
| //============================================================================== | //============================================================================== | ||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| window drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| //============================================================================== | |||||
| virtual void drawCornerResizer (Graphics&, int w, int h, bool isMouseOver, bool isMouseDragging) = 0; | |||||
| virtual void drawResizableFrame (Graphics&, int w, int h, const BorderSize<int>&) = 0; | |||||
| virtual void fillResizableWindowBackground (Graphics&, int w, int h, const BorderSize<int>&, ResizableWindow&) = 0; | |||||
| virtual void drawResizableWindowBorder (Graphics&, int w, int h, const BorderSize<int>& border, ResizableWindow&) = 0; | |||||
| }; | |||||
| protected: | |||||
| /** @internal */ | /** @internal */ | ||||
| void paint (Graphics&) override; | void paint (Graphics&) override; | ||||
| /** (if overriding this, make sure you call ResizableWindow::moved() in your subclass) */ | /** (if overriding this, make sure you call ResizableWindow::moved() in your subclass) */ | ||||
| @@ -96,6 +96,17 @@ public: | |||||
| outlineColourId = 0x1001c10 /**< The colour to use to draw an outline around the tooltip. */ | outlineColourId = 0x1001c10 /**< The colour to use to draw an outline around the tooltip. */ | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| /** This abstract base class is implemented by LookAndFeel classes to provide | |||||
| window drawing functionality. | |||||
| */ | |||||
| struct JUCE_API LookAndFeelMethods | |||||
| { | |||||
| virtual ~LookAndFeelMethods() {} | |||||
| virtual void getTooltipSize (const String& tipText, int& width, int& height) = 0; | |||||
| virtual void drawTooltip (Graphics&, const String& text, int width, int height) = 0; | |||||
| }; | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||