| @@ -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::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; } | |||
| 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 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) | |||
| @@ -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 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; | |||
| *reinterpret_cast<int32*> (d) = sampleNumber; | |||
| @@ -221,9 +221,9 @@ bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePositio | |||
| return false; | |||
| 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; | |||
| } | |||
| @@ -1210,7 +1210,7 @@ private: | |||
| static String hintToString (const void* hints, const char* type) | |||
| { | |||
| char* const hint = snd_device_name_get_hint (hints, type); | |||
| const String s (hint); | |||
| const String s (String::fromUTF8 (hint)); | |||
| ::free (hint); | |||
| return s; | |||
| } | |||
| @@ -155,9 +155,7 @@ public: | |||
| bufferSize (512), | |||
| numInputChans (0), | |||
| numOutputChans (0), | |||
| callbacksAllowed (true), | |||
| numInputChannelInfos (0), | |||
| numOutputChannelInfos (0) | |||
| callbacksAllowed (true) | |||
| { | |||
| jassert (deviceID != 0); | |||
| @@ -199,9 +197,17 @@ public: | |||
| tempOutputBuffers[i] = audioBuffer + count++ * tempBufSize; | |||
| } | |||
| struct CallbackDetailsForChannel | |||
| { | |||
| int streamNum; | |||
| int dataOffsetSamples; | |||
| int dataStrideSamples; | |||
| }; | |||
| // 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; | |||
| UInt32 size; | |||
| @@ -212,7 +218,7 @@ public: | |||
| if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) | |||
| { | |||
| HeapBlock <AudioBufferList> bufList; | |||
| HeapBlock<AudioBufferList> bufList; | |||
| bufList.calloc (size, 1); | |||
| if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, bufList))) | |||
| @@ -237,82 +243,35 @@ public: | |||
| 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; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| return newNames; | |||
| } | |||
| void updateDetailsFromDevice() | |||
| Array<double> getSampleRatesFromDevice() const | |||
| { | |||
| stopTimer(); | |||
| if (deviceID == 0) | |||
| return; | |||
| const ScopedLock sl (callbackLock); | |||
| Array<double> newSampleRates; | |||
| String rates; | |||
| 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; | |||
| 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))) | |||
| { | |||
| @@ -321,33 +280,42 @@ public: | |||
| 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;) | |||
| { | |||
| 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; | |||
| } | |||
| } | |||
| } | |||
| 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))) | |||
| { | |||
| @@ -356,59 +324,98 @@ public: | |||
| 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;) | |||
| 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.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)); | |||
| 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;) | |||
| { | |||
| const CallbackDetailsForChannel& info = inputChannelInfo[i]; | |||
| const CallbackDetailsForChannel& info = inputChannelInfo.getReference(i); | |||
| float* dest = tempInputBuffers [i]; | |||
| const float* src = ((const float*) inInputData->mBuffers[info.streamNum].mData) | |||
| + info.dataOffsetSamples; | |||
| @@ -720,7 +727,7 @@ public: | |||
| for (int i = numOutputChans; --i >= 0;) | |||
| { | |||
| const CallbackDetailsForChannel& info = outputChannelInfo[i]; | |||
| const CallbackDetailsForChannel& info = outputChannelInfo.getReference(i); | |||
| const float* src = tempOutputBuffers [i]; | |||
| float* dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) | |||
| + info.dataOffsetSamples; | |||
| @@ -739,9 +746,9 @@ public: | |||
| } | |||
| 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) | |||
| + info.dataOffsetSamples; | |||
| const int stride = info.dataStrideSamples; | |||
| @@ -803,15 +810,7 @@ private: | |||
| int numInputChans, numOutputChans; | |||
| 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; | |||
| //============================================================================== | |||
| @@ -380,7 +380,7 @@ public: | |||
| 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 | |||
| @@ -186,7 +186,7 @@ public: | |||
| { | |||
| 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) | |||
| break; | |||
| @@ -100,6 +100,18 @@ bool AudioFormatReader::read (int* const* destSamples, | |||
| 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, | |||
| int startSample, | |||
| int numSamples, | |||
| @@ -113,49 +125,51 @@ void AudioFormatReader::read (AudioSampleBuffer* buffer, | |||
| if (numSamples > 0) | |||
| { | |||
| 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; | |||
| } | |||
| void changeProgramName (int index, const String& newName) override | |||
| void changeProgramName (int /*index*/, const String& /*newName*/) override | |||
| { | |||
| jassertfalse; // xxx not implemented! | |||
| } | |||
| @@ -1005,8 +1005,8 @@ private: | |||
| } | |||
| //============================================================================== | |||
| OSStatus renderGetInput (AudioUnitRenderActionFlags* ioActionFlags, | |||
| const AudioTimeStamp* inTimeStamp, | |||
| OSStatus renderGetInput (AudioUnitRenderActionFlags*, | |||
| const AudioTimeStamp*, | |||
| UInt32 inBusNumber, | |||
| UInt32 inNumberFrames, | |||
| AudioBufferList* ioData) const | |||
| @@ -1147,7 +1147,7 @@ private: | |||
| ->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) | |||
| { | |||
| return static_cast<AudioUnitPluginInstance*> (hostRef)->renderMidiOutput (pktlist); | |||
| @@ -1331,7 +1331,7 @@ public: | |||
| startTimer (jmin (713, getTimerInterval() + 51)); | |||
| } | |||
| void childBoundsChanged (Component* child) override | |||
| void childBoundsChanged (Component*) override | |||
| { | |||
| setSize (wrapper.getWidth(), wrapper.getHeight()); | |||
| startTimer (70); | |||
| @@ -1675,8 +1675,8 @@ private: | |||
| void setHostTimeFrameRate (long frameRateIndex, double frameRate, double currentTime) noexcept | |||
| { | |||
| 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) | |||
| @@ -2510,7 +2510,7 @@ private: | |||
| deleteWindow(); | |||
| } | |||
| HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) override | |||
| HIViewRef attachView (WindowRef windowRef, HIViewRef /*rootView*/) override | |||
| { | |||
| owner.openPluginWindow (windowRef); | |||
| return 0; | |||
| @@ -37,10 +37,7 @@ | |||
| #include "../juce_core/native/juce_BasicNativeHeaders.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 | |||
| @@ -287,8 +287,8 @@ XmlElement* KnownPluginList::createXml() const | |||
| { | |||
| 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) | |||
| e->createNewChildElement ("BLACKLISTED")->setAttribute ("id", blacklist[i]); | |||
| @@ -56,6 +56,11 @@ namespace TokenTypes | |||
| JUCE_DECLARE_JS_TOKEN (identifier, "$identifier") | |||
| } | |||
| #if JUCE_MSVC | |||
| #pragma warning (push) | |||
| #pragma warning (disable: 4702) | |||
| #endif | |||
| //============================================================================== | |||
| struct JavascriptEngine::RootObject : public DynamicObject | |||
| { | |||
| @@ -853,8 +858,8 @@ struct JavascriptEngine::RootObject : public DynamicObject | |||
| 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() | |||
| @@ -1211,6 +1216,9 @@ struct JavascriptEngine::RootObject : public DynamicObject | |||
| return parseSuffixes (s.release()); | |||
| } | |||
| if (matchIf (TokenTypes::plusplus)) return parsePostIncDec<AdditionOp> (input); | |||
| if (matchIf (TokenTypes::minusminus)) return parsePostIncDec<SubtractionOp> (input); | |||
| 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); } | |||
| 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; | |||
| } | |||
| @@ -1429,7 +1435,7 @@ struct JavascriptEngine::RootObject : public DynamicObject | |||
| } | |||
| 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(); } | |||
| }; | |||
| @@ -1681,3 +1687,7 @@ var JavascriptEngine::callFunction (Identifier function, const var::NativeFuncti | |||
| 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 | |||
| { | |||
| return String::fromUTF8 (data, size); | |||
| return String::fromUTF8 (data, (int) size); | |||
| } | |||
| //============================================================================== | |||
| @@ -220,7 +220,7 @@ public: | |||
| 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 | |||
| { | |||
| pthread_mutex_lock (&mutex); | |||
| triggered = true; | |||
| pthread_cond_broadcast (&condition); | |||
| if (! triggered) | |||
| { | |||
| triggered = true; | |||
| pthread_cond_broadcast (&condition); | |||
| } | |||
| 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() | |||
| @@ -36,7 +36,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 2 | |||
| #define JUCE_MINOR_VERSION 1 | |||
| #define JUCE_BUILDNUMBER 6 | |||
| #define JUCE_BUILDNUMBER 7 | |||
| /** Current Juce version number. | |||
| @@ -524,41 +524,42 @@ juce_wchar String::operator[] (int index) const noexcept | |||
| 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 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 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_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, 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; } | |||
| @@ -180,6 +180,9 @@ public: | |||
| /** Generates a probably-unique 64-bit hashcode from this string. */ | |||
| 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. */ | |||
| int length() const noexcept; | |||
| @@ -585,18 +585,36 @@ XmlElement* XmlElement::getChildByAttribute (StringRef attributeName, StringRef | |||
| void XmlElement::addChildElement (XmlElement* const newNode) noexcept | |||
| { | |||
| if (newNode != nullptr) | |||
| { | |||
| // The element being added must not be a child of another node! | |||
| jassert (newNode->nextListItem == nullptr); | |||
| firstChildElement.append (newNode); | |||
| } | |||
| } | |||
| void XmlElement::insertChildElement (XmlElement* const newNode, int indexToInsertAt) noexcept | |||
| { | |||
| 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); | |||
| } | |||
| } | |||
| 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* 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, | |||
| 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, | |||
| getChildElement, removeChildElement | |||
| */ | |||
| @@ -515,14 +519,28 @@ public: | |||
| 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. | |||
| @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 | |||
| below zero, it will be added to the end of the list | |||
| @see addChildElement, insertChildElement | |||
| */ | |||
| void insertChildElement (XmlElement* newChildNode, | |||
| void insertChildElement (XmlElement* newChildElement, | |||
| 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 | |||
| as a child element. | |||
| @@ -412,8 +412,9 @@ public: | |||
| XmlElement* const xml = new XmlElement (type.toString()); | |||
| 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; | |||
| } | |||
| @@ -89,7 +89,7 @@ public: | |||
| #else | |||
| #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) | |||
| #elif defined (_UNICODE) | |||
| #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() | |||
| { | |||
| 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); | |||
| } | |||
| #if JUCE_MODULE_AVAILABLE_juce_opengl | |||
| extern void clearOpenGLGlyphCache(); | |||
| #endif | |||
| void Typeface::clearTypefaceCache() | |||
| { | |||
| 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 x4 = 0; | |||
| float y4 = 0; | |||
| float type; | |||
| for (;;) | |||
| { | |||
| float type; | |||
| if (stackPos == stackBase) | |||
| { | |||
| if (index >= path.numElements) | |||
| { | |||
| 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; | |||
| } | |||
| else if (type == Path::quadMarker) | |||
| if (type == Path::quadMarker) | |||
| { | |||
| const size_t offset = (size_t) (stackPos - stackBase); | |||
| @@ -190,61 +190,73 @@ public: | |||
| 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. */ | |||
| 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. */ | |||
| 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. */ | |||
| 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. | |||
| 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 | |||
| */ | |||
| 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. | |||
| If the new x is beyond the right of the current right-hand edge, the width will be set to zero. | |||
| @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. | |||
| If the y is moved to be below the current bottom edge, the height will be set to zero. | |||
| @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. | |||
| If the new y is beyond the bottom of the current rectangle, the height will be set to zero. | |||
| @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. | |||
| If the new right is below the current X value, the X will be pushed down to match it. | |||
| @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. | |||
| If the new right edge is below the current left-hand edge, the width will be set to zero. | |||
| @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. | |||
| If the new bottom is lower than the current Y value, the Y will be pushed down to match it. | |||
| @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. | |||
| If the new y is beyond the bottom of the current rectangle, the height will be set to zero. | |||
| @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. */ | |||
| @@ -142,7 +142,7 @@ class GlyphCache : private DeletedAtShutdown | |||
| public: | |||
| GlyphCache() | |||
| { | |||
| addNewGlyphSlots (120); | |||
| reset(); | |||
| } | |||
| ~GlyphCache() | |||
| @@ -207,6 +207,15 @@ public: | |||
| glyph->draw (target, pos); | |||
| } | |||
| void reset() | |||
| { | |||
| const ScopedWriteLock swl (lock); | |||
| glyphs.clear(); | |||
| addNewGlyphSlots (120); | |||
| hits.set (0); | |||
| misses.set (0); | |||
| } | |||
| private: | |||
| friend struct ContainerDeletePolicy<CachedGlyphType>; | |||
| OwnedArray<CachedGlyphType> glyphs; | |||
| @@ -215,6 +224,8 @@ private: | |||
| void addNewGlyphSlots (int num) | |||
| { | |||
| glyphs.ensureStorageAllocated (glyphs.size() + num); | |||
| while (--num >= 0) | |||
| 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) | |||
| { | |||
| @@ -2426,8 +2444,6 @@ public: | |||
| { | |||
| if (trans.isOnlyTranslation() && ! transform.isRotated) | |||
| { | |||
| typedef GlyphCache <CachedGlyphEdgeTable <SoftwareRendererSavedState>, SoftwareRendererSavedState> GlyphCacheType; | |||
| GlyphCacheType& cache = GlyphCacheType::getInstance(); | |||
| Point<float> pos (trans.getTranslationX(), trans.getTranslationY()); | |||
| @@ -340,7 +340,7 @@ namespace CoreTextTypeLayout | |||
| CFArrayRef lines = CTFrameGetLines (frame); | |||
| const CFIndex numLines = CFArrayGetCount (lines); | |||
| glyphLayout.ensureStorageAllocated (numLines); | |||
| glyphLayout.ensureStorageAllocated ((int) numLines); | |||
| for (CFIndex i = 0; i < numLines; ++i) | |||
| { | |||
| @@ -309,7 +309,8 @@ void Button::internalClickCallback (const ModifierKeys& modifiers) | |||
| { | |||
| if (clickTogglesState) | |||
| setToggleState (radioGroupId != 0 || ! lastToggleState, sendNotification); | |||
| else | |||
| if (radioGroupId != 0 || ! clickTogglesState) | |||
| sendClickMessage (modifiers); | |||
| } | |||
| @@ -355,6 +355,33 @@ public: | |||
| // This method's parameters have changed - see the new version. | |||
| 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: | |||
| //============================================================================== | |||
| /** This method is called when the button has been clicked. | |||
| @@ -124,6 +124,17 @@ public: | |||
| */ | |||
| 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: | |||
| //============================================================================== | |||
| /** @internal */ | |||
| @@ -24,34 +24,32 @@ | |||
| ShapeButton::ShapeButton (const String& t, Colour n, Colour o, Colour d) | |||
| : Button (t), | |||
| normalColour (n), | |||
| overColour (o), | |||
| downColour (d), | |||
| normalColour (n), overColour (o), downColour (d), | |||
| maintainShapeProportions (false), | |||
| 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; | |||
| overColour = newOverColour; | |||
| downColour = newDownColour; | |||
| } | |||
| void ShapeButton::setOutline (Colour newOutlineColour, | |||
| const float newOutlineWidth) | |||
| void ShapeButton::setOutline (Colour newOutlineColour, const float newOutlineWidth) | |||
| { | |||
| outlineColour = newOutlineColour; | |||
| outlineWidth = newOutlineWidth; | |||
| } | |||
| void ShapeButton::setBorderSize (BorderSize<int> newBorder) | |||
| { | |||
| border = newBorder; | |||
| } | |||
| void ShapeButton::setShape (const Path& newShape, | |||
| const bool resizeNowToFitThisShape, | |||
| const bool maintainShapeProportions_, | |||
| @@ -73,8 +71,8 @@ void ShapeButton::setShape (const Path& newShape, | |||
| shape.applyTransform (AffineTransform::translation (-newBounds.getX(), | |||
| -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(); | |||
| @@ -88,7 +86,7 @@ void ShapeButton::paintButton (Graphics& g, bool isMouseOverButton, bool isButto | |||
| 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) | |||
| r = r.reduced (2.0f); | |||
| @@ -80,8 +80,12 @@ public: | |||
| @param outlineColour the colour to use | |||
| @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 */ | |||
| void paintButton (Graphics&, bool isMouseOverButton, bool isButtonDown) override; | |||
| @@ -91,6 +95,7 @@ private: | |||
| Colour normalColour, overColour, downColour, outlineColour; | |||
| DropShadowEffect shadow; | |||
| Path shape; | |||
| BorderSize<int> border; | |||
| bool maintainShapeProportions; | |||
| float outlineWidth; | |||
| @@ -89,7 +89,7 @@ LookAndFeel& Desktop::getDefaultLookAndFeel() noexcept | |||
| if (currentLookAndFeel == nullptr) | |||
| { | |||
| if (defaultLookAndFeel == nullptr) | |||
| defaultLookAndFeel = new LookAndFeel(); | |||
| defaultLookAndFeel = new LookAndFeel_V2(); | |||
| currentLookAndFeel = defaultLookAndFeel; | |||
| } | |||
| @@ -56,6 +56,7 @@ void DirectoryContentsList::setDirectory (const File& directory, | |||
| { | |||
| clear(); | |||
| root = directory; | |||
| changed(); | |||
| // (this forces a refresh when setTypeFlags() is called, rather than triggering two refreshes) | |||
| fileTypeFlags &= ~(File::findDirectories | File::findFiles); | |||
| @@ -177,6 +177,42 @@ public: | |||
| */ | |||
| 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 */ | |||
| void resized() override; | |||
| @@ -180,6 +180,16 @@ public: | |||
| /** Gives the component a tooltip. */ | |||
| 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 */ | |||
| void paintOverChildren (Graphics&) override; | |||
| @@ -198,6 +198,9 @@ extern bool juce_areThereAnyAlwaysOnTopWindows(); | |||
| #include "layout/juce_TabbedComponent.cpp" | |||
| #include "layout/juce_Viewport.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_MenuBarModel.cpp" | |||
| #include "menus/juce_PopupMenu.cpp" | |||
| @@ -113,6 +113,7 @@ class CaretComponent; | |||
| class BubbleComponent; | |||
| class KeyPressMappingSet; | |||
| class ApplicationCommandManagerListener; | |||
| class DrawableButton; | |||
| #include "mouse/juce_MouseCursor.h" | |||
| #include "mouse/juce_MouseListener.h" | |||
| @@ -215,7 +216,6 @@ class ApplicationCommandManagerListener; | |||
| #include "windows/juce_ThreadWithProgressWindow.h" | |||
| #include "windows/juce_TooltipWindow.h" | |||
| #include "layout/juce_MultiDocumentPanel.h" | |||
| #include "lookandfeel/juce_LookAndFeel.h" | |||
| #include "filebrowser/juce_FileFilter.h" | |||
| #include "filebrowser/juce_WildcardFileFilter.h" | |||
| #include "filebrowser/juce_FileBrowserListener.h" | |||
| @@ -239,6 +239,10 @@ class ApplicationCommandManagerListener; | |||
| #include "properties/juce_TextPropertyComponent.h" | |||
| #include "application/juce_Application.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. */ | |||
| 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: | |||
| void resized() override; | |||
| @@ -31,11 +31,8 @@ GroupComponent::GroupComponent (const String& name, | |||
| setInterceptsMouseClicks (false, true); | |||
| } | |||
| GroupComponent::~GroupComponent() | |||
| { | |||
| } | |||
| GroupComponent::~GroupComponent() {} | |||
| //============================================================================== | |||
| void GroupComponent::setText (const String& newText) | |||
| { | |||
| if (text != newText) | |||
| @@ -50,7 +47,6 @@ String GroupComponent::getText() const | |||
| return text; | |||
| } | |||
| //============================================================================== | |||
| void GroupComponent::setTextLabelPosition (Justification newJustification) | |||
| { | |||
| if (justification != newJustification) | |||
| @@ -62,18 +58,9 @@ void GroupComponent::setTextLabelPosition (Justification newJustification) | |||
| 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. */ | |||
| }; | |||
| //============================================================================== | |||
| /** 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 */ | |||
| void paint (Graphics&) override; | |||
| @@ -292,6 +292,73 @@ public: | |||
| /** Deregisters a previously-registered 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 */ | |||
| bool keyPressed (const KeyPress&) override; | |||
| @@ -72,6 +72,16 @@ public: | |||
| */ | |||
| 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 */ | |||
| void paint (Graphics&) override; | |||
| @@ -93,7 +93,26 @@ void TabBarButton::calcAreas (Rectangle<int>& extraComp, Rectangle<int>& textAre | |||
| } | |||
| if (extraComponent != nullptr) | |||
| { | |||
| 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 | |||
| @@ -293,6 +293,30 @@ public: | |||
| 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 */ | |||
| void paint (Graphics&) override; | |||
| @@ -25,14 +25,80 @@ | |||
| #ifndef 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 | |||
| 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: | |||
| //============================================================================== | |||
| @@ -60,7 +126,6 @@ public: | |||
| */ | |||
| static void setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) noexcept; | |||
| //============================================================================== | |||
| /** 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; | |||
| /** Registers a colour to be used for a particular purpose. | |||
| For more details, see the comments for findColour(). | |||
| @see findColour, Component::findColour, Component::setColour | |||
| */ | |||
| void setColour (int colourId, Colour colour) noexcept; | |||
| @@ -94,9 +157,12 @@ public: | |||
| */ | |||
| 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. | |||
| @@ -110,509 +176,38 @@ public: | |||
| /** Override this to get the chance to swap a component's mouse cursor for a | |||
| 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, | |||
| const Point<int>& origin, | |||
| 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); | |||
| 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. */ | |||
| virtual Path getTickShape (float height); | |||
| virtual Path getTickShape (float height) = 0; | |||
| /** 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(); | |||
| //============================================================================== | |||
| /** 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: | |||
| //============================================================================== | |||
| friend class WeakReference<LookAndFeel>; | |||
| @@ -628,40 +223,9 @@ private: | |||
| }; | |||
| SortedSet<ColourSetting> colours; | |||
| // default typeface names | |||
| String defaultSans, defaultSerif, defaultFixed; | |||
| ScopedPointer<Drawable> folderImage, documentImage; | |||
| 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) | |||
| }; | |||
| @@ -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, | |||
| 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: | |||
| //============================================================================== | |||
| JUCE_PUBLIC_IN_DLL_BUILD (class Item) | |||
| @@ -136,6 +136,19 @@ public: | |||
| 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: | |||
| //============================================================================== | |||
| /** 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) | |||
| @@ -461,7 +474,8 @@ public: | |||
| //============================================================================== | |||
| static ModifierKeys currentModifiers; | |||
| static Point<int> lastMousePos; | |||
| static Point<float> lastMousePos; | |||
| static int64 touchesDown; | |||
| private: | |||
| //============================================================================== | |||
| @@ -526,7 +540,8 @@ private: | |||
| }; | |||
| ModifierKeys AndroidComponentPeer::currentModifiers = 0; | |||
| Point<int> AndroidComponentPeer::lastMousePos; | |||
| Point<float> AndroidComponentPeer::lastMousePos; | |||
| int64 AndroidComponentPeer::touchesDown = 0; | |||
| //============================================================================== | |||
| #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, 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, 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)) | |||
| @@ -582,7 +597,7 @@ bool MouseInputSource::SourceList::addSource() | |||
| Point<int> MouseInputSource::getCurrentRawMousePosition() | |||
| { | |||
| return AndroidComponentPeer::lastMousePos; | |||
| return AndroidComponentPeer::lastMousePos.toInt(); | |||
| } | |||
| 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); | |||
| window = [[JuceUIWindow alloc] init]; | |||
| window.hidden = true; | |||
| window.autoresizesSubviews = NO; | |||
| window.transform = CGAffineTransformIdentity; | |||
| window.frame = r; | |||
| @@ -62,7 +62,6 @@ namespace MouseCursorHelpers | |||
| return CustomMouseCursorInfo (im, (int) (hx * im.getWidth()), | |||
| (int) (hy * im.getHeight())).create(); | |||
| jassertfalse; | |||
| return nullptr; | |||
| } | |||
| } | |||
| @@ -95,7 +94,16 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty | |||
| case LeftEdgeResizeCursor: c = [NSCursor resizeLeftCursor]; break; | |||
| case RightEdgeResizeCursor: c = [NSCursor resizeRightCursor]; 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 TopEdgeResizeCursor: | |||
| @@ -1686,7 +1686,7 @@ struct JuceNSWindowClass : public ObjCClass <NSWindow> | |||
| addMethod (@selector (canBecomeKeyWindow), canBecomeKeyWindow, "c@:"); | |||
| addMethod (@selector (becomeKeyWindow), becomeKeyWindow, "v@:"); | |||
| 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 (zoom:), zoom, "v@:@"); | |||
| addMethod (@selector (windowWillMove:), windowWillMove, "v@:@"); | |||
| @@ -1807,13 +1807,10 @@ private: | |||
| { | |||
| 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 | |||
| } | |||
| } | |||
| } | |||
| @@ -1821,7 +1818,7 @@ private: | |||
| 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; | |||
| const int touchIndex = currentTouches.getIndexOfTouch (touch.dwID); | |||
| @@ -1835,10 +1832,13 @@ private: | |||
| currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | |||
| 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) | |||
| { | |||
| @@ -1848,6 +1848,10 @@ private: | |||
| if (! currentTouches.areAnyTouchesActive()) | |||
| isCancel = true; | |||
| } | |||
| else | |||
| { | |||
| modsToSend = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | |||
| } | |||
| if (isCancel) | |||
| { | |||
| @@ -1855,13 +1859,16 @@ private: | |||
| 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)) | |||
| return false; | |||
| } | |||
| @@ -102,6 +102,18 @@ public: | |||
| /** By default, this just repaints the component. */ | |||
| 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: | |||
| /** 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 | |||
| @@ -333,6 +333,25 @@ public: | |||
| 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 */ | |||
| void labelTextChanged (Label*) override; | |||
| @@ -249,6 +249,18 @@ public: | |||
| /** Returns the currently-visible text editor, or nullptr if none is open. */ | |||
| 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: | |||
| //============================================================================== | |||
| /** 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. */ | |||
| }; | |||
| //============================================================================== | |||
| /** 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: | |||
| //============================================================================== | |||
| /** @internal */ | |||
| @@ -762,6 +762,57 @@ public: | |||
| 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: | |||
| //============================================================================== | |||
| /** @internal */ | |||
| @@ -366,6 +366,19 @@ public: | |||
| */ | |||
| 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 */ | |||
| void paint (Graphics&) override; | |||
| @@ -580,6 +580,20 @@ public: | |||
| void setInputRestrictions (int maxTextLength, | |||
| 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 */ | |||
| void paint (Graphics&) override; | |||
| @@ -267,6 +267,24 @@ public: | |||
| bool restoreFromString (ToolbarItemFactory& factoryToUse, | |||
| 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 */ | |||
| void paint (Graphics&) override; | |||
| @@ -439,7 +439,7 @@ TreeView::TreeView (const String& name) | |||
| : Component (name), | |||
| viewport (new TreeViewport()), | |||
| rootItem (nullptr), | |||
| indentSize (24), | |||
| indentSize (-1), | |||
| defaultOpenness (false), | |||
| needsRecalculating (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) | |||
| { | |||
| if (defaultOpenness != isOpenByDefault) | |||
| @@ -860,7 +866,7 @@ void TreeView::recalculateIfNeeded() | |||
| //============================================================================== | |||
| struct TreeView::InsertPoint | |||
| { | |||
| InsertPoint (const TreeView& view, const StringArray& files, | |||
| InsertPoint (TreeView& view, const StringArray& files, | |||
| const DragAndDropTarget::SourceDetails& dragSourceDetails) | |||
| : pos (dragSourceDetails.localPosition), | |||
| item (view.getItemAt (dragSourceDetails.localPosition.y)), | |||
| @@ -1125,7 +1131,8 @@ TreeViewItem::TreeViewItem() | |||
| totalWidth (0), | |||
| selected (false), | |||
| redrawNeeded (true), | |||
| drawLinesInside (true), | |||
| drawLinesInside (false), | |||
| drawLinesSet (false), | |||
| drawsInLeftMargin (false), | |||
| 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) | |||
| @@ -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) | |||
| { | |||
| jassert (ownerView != nullptr); | |||
| @@ -1510,7 +1523,12 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, | |||
| drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) | |||
| { | |||
| if (isSelected()) | |||
| g.fillAll (ownerView->findColour (TreeView::selectedItemBackgroundColourId)); | |||
| paintItem (g, itemW, itemHeight); | |||
| } | |||
| } | |||
| const float halfH = itemHeight * 0.5f; | |||
| @@ -1521,11 +1539,12 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| { | |||
| 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)); | |||
| if ((parentItem != nullptr && parentItem->drawLinesInside) | |||
| || (parentItem == nullptr && drawLinesInside)) | |||
| if (parentLinesDrawn || (parentItem == nullptr && areLinesDrawn())) | |||
| paintHorizontalConnectingLine (g, Line<float> (x, halfH, x + indentWidth / 2, halfH)); | |||
| { | |||
| @@ -1536,8 +1555,7 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| { | |||
| 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 = p->parentItem; | |||
| @@ -1545,15 +1563,9 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) | |||
| } | |||
| 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)); | |||
| } | |||
| } | |||
| if (isOpen()) | |||
| @@ -1731,6 +1743,7 @@ int TreeViewItem::getRowNumberInTree() const noexcept | |||
| void TreeViewItem::setLinesDrawnForSubItems (const bool drawLines) noexcept | |||
| { | |||
| drawLinesInside = drawLines; | |||
| drawLinesSet = true; | |||
| } | |||
| TreeViewItem* TreeViewItem::getNextVisibleItem (const bool recurse) const noexcept | |||
| @@ -1840,8 +1853,8 @@ XmlElement* TreeViewItem::getOpennessState (const bool canReturnNull) const | |||
| 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 | |||
| { | |||
| @@ -83,6 +83,20 @@ public: | |||
| */ | |||
| 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. | |||
| @param index the item to remove | |||
| @@ -178,7 +192,7 @@ public: | |||
| bool areAllParentsOpen() const noexcept; | |||
| /** 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; | |||
| @@ -299,11 +313,14 @@ public: | |||
| /** 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. */ | |||
| virtual void paintHorizontalConnectingLine (Graphics&, const Line<float>& line); | |||
| @@ -519,12 +536,13 @@ private: | |||
| //============================================================================== | |||
| TreeView* ownerView; | |||
| TreeViewItem* parentItem; | |||
| OwnedArray <TreeViewItem> subItems; | |||
| OwnedArray<TreeViewItem> subItems; | |||
| int y, itemHeight, totalHeight, itemWidth, totalWidth; | |||
| int uid; | |||
| bool selected : 1; | |||
| bool redrawNeeded : 1; | |||
| bool drawLinesInside : 1; | |||
| bool drawLinesSet : 1; | |||
| bool drawsInLeftMargin : 1; | |||
| unsigned int openness : 2; | |||
| @@ -549,6 +567,7 @@ private: | |||
| XmlElement* getOpennessState (bool canReturnNull) const; | |||
| bool removeSubItemFromList (int index, bool deleteItem); | |||
| void removeAllSubItemsFromList(); | |||
| bool areLinesDrawn() const; | |||
| #if JUCE_CATCH_DEPRECATED_CODE_MISUSE | |||
| // 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. | |||
| @see setIndentSize | |||
| */ | |||
| int getIndentSize() const noexcept { return indentSize; } | |||
| int getIndentSize() noexcept; | |||
| /** Changes the distance by which each nested level of the tree is indented. | |||
| @see getIndentSize | |||
| @@ -779,9 +798,25 @@ public: | |||
| */ | |||
| 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 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) | |||
| }; | |||
| @@ -417,6 +417,32 @@ public: | |||
| 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: | |||
| //============================================================================== | |||
| /** @internal */ | |||
| @@ -48,8 +48,11 @@ CallOutBox::~CallOutBox() | |||
| { | |||
| } | |||
| enum { callOutBoxDismissCommandId = 0x4f83a04b }; | |||
| //============================================================================== | |||
| class CallOutBoxCallback : public ModalComponentManager::Callback | |||
| class CallOutBoxCallback : public ModalComponentManager::Callback, | |||
| private Timer | |||
| { | |||
| public: | |||
| CallOutBoxCallback (Component* c, const Rectangle<int>& area, Component* parent) | |||
| @@ -57,9 +60,16 @@ public: | |||
| { | |||
| callout.setVisible (true); | |||
| 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; | |||
| CallOutBox callout; | |||
| @@ -110,8 +120,6 @@ bool CallOutBox::hitTest (int x, int y) | |||
| return outline.contains ((float) x, (float) y); | |||
| } | |||
| enum { callOutBoxDismissCommandId = 0x4f83a04b }; | |||
| void CallOutBox::inputAttemptWhenModal() | |||
| { | |||
| const Point<int> mousePos (getMouseXYRelative() + getBounds().getPosition()); | |||
| @@ -118,6 +118,15 @@ public: | |||
| const Rectangle<int>& areaToPointTo, | |||
| 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 */ | |||
| void paint (Graphics&) override; | |||
| @@ -298,15 +298,11 @@ void ComponentPeer::handleMovedOrResized() | |||
| Rectangle<int> newBounds (Component::ComponentHelpers::rawPeerPositionToLocal (component, getBounds())); | |||
| Rectangle<int> oldBounds (component.getBounds()); | |||
| // oldBounds = Component::ComponentHelpers::localPositionToRawPeerPos (component, oldBounds); | |||
| const bool wasMoved = (oldBounds.getPosition() != newBounds.getPosition()); | |||
| const bool wasResized = (oldBounds.getWidth() != newBounds.getWidth() || oldBounds.getHeight() != newBounds.getHeight()); | |||
| if (wasMoved || wasResized) | |||
| { | |||
| // newBounds = Component::ComponentHelpers::rawPeerPositionToLocal (component, newBounds); | |||
| component.bounds = newBounds; | |||
| if (wasResized) | |||
| @@ -223,6 +223,30 @@ public: | |||
| 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 | |||
| /** @internal */ | |||
| @@ -306,8 +306,23 @@ public: | |||
| bool resizeToFit = false)); | |||
| 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 */ | |||
| void paint (Graphics&) override; | |||
| /** (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. */ | |||
| }; | |||
| //============================================================================== | |||
| /** 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: | |||
| //============================================================================== | |||