mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Replaced some old juce-style sort operations with std::sort and lambdas
This commit is contained in:
parent
3659742a3a
commit
d4a7afa73f
17 changed files with 132 additions and 269 deletions
|
|
@ -142,18 +142,12 @@ const ModuleDescription* ModuleList::getModuleWithID (const String& moduleID) co
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ModuleSorter
|
|
||||||
{
|
|
||||||
static int compareElements (const ModuleDescription* m1, const ModuleDescription* m2)
|
|
||||||
{
|
|
||||||
return m1->getID().compareIgnoreCase (m2->getID());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void ModuleList::sort()
|
void ModuleList::sort()
|
||||||
{
|
{
|
||||||
ModuleSorter sorter;
|
std::sort (modules.begin(), modules.end(), [] (const ModuleDescription* m1, const ModuleDescription* m2)
|
||||||
modules.sort (sorter);
|
{
|
||||||
|
return m1->getID().compareIgnoreCase (m2->getID()) < 0;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
StringArray ModuleList::getIDs() const
|
StringArray ModuleList::getIDs() const
|
||||||
|
|
|
||||||
|
|
@ -131,23 +131,6 @@ namespace MidiFileHelpers
|
||||||
return correctedTime + (time - lastTime) * secsPerTick;
|
return correctedTime + (time - lastTime) * secsPerTick;
|
||||||
}
|
}
|
||||||
|
|
||||||
// a comparator that puts all the note-offs before note-ons that have the same time
|
|
||||||
struct Sorter
|
|
||||||
{
|
|
||||||
static int compareElements (const MidiMessageSequence::MidiEventHolder* const first,
|
|
||||||
const MidiMessageSequence::MidiEventHolder* const second) noexcept
|
|
||||||
{
|
|
||||||
const double diff = (first->message.getTimeStamp() - second->message.getTimeStamp());
|
|
||||||
|
|
||||||
if (diff > 0) return 1;
|
|
||||||
if (diff < 0) return -1;
|
|
||||||
if (first->message.isNoteOff() && second->message.isNoteOn()) return -1;
|
|
||||||
if (first->message.isNoteOn() && second->message.isNoteOff()) return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename MethodType>
|
template <typename MethodType>
|
||||||
static void findAllMatchingEvents (const OwnedArray<MidiMessageSequence>& tracks,
|
static void findAllMatchingEvents (const OwnedArray<MidiMessageSequence>& tracks,
|
||||||
MidiMessageSequence& results,
|
MidiMessageSequence& results,
|
||||||
|
|
@ -335,9 +318,19 @@ void MidiFile::readNextTrack (const uint8* data, int size)
|
||||||
lastStatusByte = firstByte;
|
lastStatusByte = firstByte;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use a sort that puts all the note-offs before note-ons that have the same time
|
// sort so that we put all the note-offs before note-ons that have the same time
|
||||||
MidiFileHelpers::Sorter sorter;
|
std::stable_sort (result.list.begin(), result.list.end(),
|
||||||
result.list.sort (sorter, true);
|
[] (const MidiMessageSequence::MidiEventHolder* a,
|
||||||
|
const MidiMessageSequence::MidiEventHolder* b)
|
||||||
|
{
|
||||||
|
auto t1 = a->message.getTimeStamp();
|
||||||
|
auto t2 = b->message.getTimeStamp();
|
||||||
|
|
||||||
|
if (t1 < t2) return true;
|
||||||
|
if (t2 < t1) return false;
|
||||||
|
|
||||||
|
return a->message.isNoteOff() && b->message.isNoteOn();
|
||||||
|
});
|
||||||
|
|
||||||
addTrack (result);
|
addTrack (result);
|
||||||
tracks.getLast()->updateMatchedPairs();
|
tracks.getLast()->updateMatchedPairs();
|
||||||
|
|
|
||||||
|
|
@ -204,20 +204,10 @@ void MidiMessageSequence::addSequence (const MidiMessageSequence& other,
|
||||||
sort();
|
sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MidiMessageSequenceSorter
|
|
||||||
{
|
|
||||||
static int compareElements (const MidiMessageSequence::MidiEventHolder* first,
|
|
||||||
const MidiMessageSequence::MidiEventHolder* second) noexcept
|
|
||||||
{
|
|
||||||
auto diff = first->message.getTimeStamp() - second->message.getTimeStamp();
|
|
||||||
return (diff > 0) - (diff < 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void MidiMessageSequence::sort() noexcept
|
void MidiMessageSequence::sort() noexcept
|
||||||
{
|
{
|
||||||
MidiMessageSequenceSorter sorter;
|
std::stable_sort (list.begin(), list.end(),
|
||||||
list.sort (sorter, true);
|
[] (const MidiEventHolder* a, const MidiEventHolder* b) { return a->message.getTimeStamp() < b->message.getTimeStamp(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiMessageSequence::updateMatchedPairs() noexcept
|
void MidiMessageSequence::updateMatchedPairs() noexcept
|
||||||
|
|
|
||||||
|
|
@ -179,14 +179,6 @@ MPESynthesiserVoice* MPESynthesiser::findFreeVoice (MPENote noteToFindVoiceFor,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MPEVoiceAgeSorter
|
|
||||||
{
|
|
||||||
static int compareElements (MPESynthesiserVoice* v1, MPESynthesiserVoice* v2) noexcept
|
|
||||||
{
|
|
||||||
return v1->wasStartedBefore (*v2) ? -1 : (v2->wasStartedBefore (*v1) ? 1 : 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceFor) const
|
MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceFor) const
|
||||||
{
|
{
|
||||||
// This voice-stealing algorithm applies the following heuristics:
|
// This voice-stealing algorithm applies the following heuristics:
|
||||||
|
|
@ -205,17 +197,17 @@ MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceF
|
||||||
Array<MPESynthesiserVoice*> usableVoices;
|
Array<MPESynthesiserVoice*> usableVoices;
|
||||||
usableVoices.ensureStorageAllocated (voices.size());
|
usableVoices.ensureStorageAllocated (voices.size());
|
||||||
|
|
||||||
for (int i = 0; i < voices.size(); ++i)
|
for (auto* voice : voices)
|
||||||
{
|
{
|
||||||
MPESynthesiserVoice* const voice = voices.getUnchecked (i);
|
|
||||||
jassert (voice->isActive()); // We wouldn't be here otherwise
|
jassert (voice->isActive()); // We wouldn't be here otherwise
|
||||||
|
|
||||||
MPEVoiceAgeSorter sorter;
|
usableVoices.add (voice);
|
||||||
usableVoices.addSorted (sorter, voice);
|
std::sort (usableVoices.begin(), usableVoices.end(),
|
||||||
|
[] (const MPESynthesiserVoice* a, const MPESynthesiserVoice* b) { return a->wasStartedBefore (*b); });
|
||||||
|
|
||||||
if (! voice->isPlayingButReleased()) // Don't protect released notes
|
if (! voice->isPlayingButReleased()) // Don't protect released notes
|
||||||
{
|
{
|
||||||
const int noteNumber = voice->getCurrentlyPlayingNote().initialNote;
|
auto noteNumber = voice->getCurrentlyPlayingNote().initialNote;
|
||||||
|
|
||||||
if (low == nullptr || noteNumber < low->getCurrentlyPlayingNote().initialNote)
|
if (low == nullptr || noteNumber < low->getCurrentlyPlayingNote().initialNote)
|
||||||
low = voice;
|
low = voice;
|
||||||
|
|
@ -229,49 +221,29 @@ MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceF
|
||||||
if (top == low)
|
if (top == low)
|
||||||
top = nullptr;
|
top = nullptr;
|
||||||
|
|
||||||
const int numUsableVoices = usableVoices.size();
|
|
||||||
|
|
||||||
// If we want to re-use the voice to trigger a new note,
|
// If we want to re-use the voice to trigger a new note,
|
||||||
// then The oldest note that's playing the same note number is ideal.
|
// then The oldest note that's playing the same note number is ideal.
|
||||||
if (noteToStealVoiceFor.isValid())
|
if (noteToStealVoiceFor.isValid())
|
||||||
{
|
for (auto* voice : usableVoices)
|
||||||
for (int i = 0; i < numUsableVoices; ++i)
|
|
||||||
{
|
|
||||||
MPESynthesiserVoice* const voice = usableVoices.getUnchecked (i);
|
|
||||||
|
|
||||||
if (voice->getCurrentlyPlayingNote().initialNote == noteToStealVoiceFor.initialNote)
|
if (voice->getCurrentlyPlayingNote().initialNote == noteToStealVoiceFor.initialNote)
|
||||||
return voice;
|
return voice;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Oldest voice that has been released (no finger on it and not held by sustain pedal)
|
// Oldest voice that has been released (no finger on it and not held by sustain pedal)
|
||||||
for (int i = 0; i < numUsableVoices; ++i)
|
for (auto* voice : usableVoices)
|
||||||
{
|
|
||||||
MPESynthesiserVoice* const voice = usableVoices.getUnchecked (i);
|
|
||||||
|
|
||||||
if (voice != low && voice != top && voice->isPlayingButReleased())
|
if (voice != low && voice != top && voice->isPlayingButReleased())
|
||||||
return voice;
|
return voice;
|
||||||
}
|
|
||||||
|
|
||||||
// Oldest voice that doesn't have a finger on it:
|
// Oldest voice that doesn't have a finger on it:
|
||||||
for (int i = 0; i < numUsableVoices; ++i)
|
for (auto* voice : usableVoices)
|
||||||
{
|
|
||||||
MPESynthesiserVoice* const voice = usableVoices.getUnchecked (i);
|
|
||||||
|
|
||||||
if (voice != low && voice != top
|
if (voice != low && voice != top
|
||||||
&& voice->getCurrentlyPlayingNote().keyState != MPENote::keyDown
|
&& voice->getCurrentlyPlayingNote().keyState != MPENote::keyDown
|
||||||
&& voice->getCurrentlyPlayingNote().keyState != MPENote::keyDownAndSustained)
|
&& voice->getCurrentlyPlayingNote().keyState != MPENote::keyDownAndSustained)
|
||||||
return voice;
|
return voice;
|
||||||
}
|
|
||||||
|
|
||||||
// Oldest voice that isn't protected
|
// Oldest voice that isn't protected
|
||||||
for (int i = 0; i < numUsableVoices; ++i)
|
for (auto* voice : usableVoices)
|
||||||
{
|
|
||||||
MPESynthesiserVoice* const voice = usableVoices.getUnchecked (i);
|
|
||||||
|
|
||||||
if (voice != low && voice != top)
|
if (voice != low && voice != top)
|
||||||
return voice;
|
return voice;
|
||||||
}
|
|
||||||
|
|
||||||
// We've only got "protected" voices now: lowest note takes priority
|
// We've only got "protected" voices now: lowest note takes priority
|
||||||
jassert (low != nullptr);
|
jassert (low != nullptr);
|
||||||
|
|
|
||||||
|
|
@ -489,14 +489,6 @@ SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VoiceAgeSorter
|
|
||||||
{
|
|
||||||
static int compareElements (SynthesiserVoice* v1, SynthesiserVoice* v2) noexcept
|
|
||||||
{
|
|
||||||
return v1->wasStartedBefore (*v2) ? -1 : (v2->wasStartedBefore (*v1) ? 1 : 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
|
SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
|
||||||
int /*midiChannel*/, int midiNoteNumber) const
|
int /*midiChannel*/, int midiNoteNumber) const
|
||||||
{
|
{
|
||||||
|
|
@ -521,8 +513,9 @@ SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
|
||||||
{
|
{
|
||||||
jassert (voice->isVoiceActive()); // We wouldn't be here otherwise
|
jassert (voice->isVoiceActive()); // We wouldn't be here otherwise
|
||||||
|
|
||||||
VoiceAgeSorter sorter;
|
usableVoices.add (voice);
|
||||||
usableVoices.addSorted (sorter, voice);
|
std::sort (usableVoices.begin(), usableVoices.end(),
|
||||||
|
[] (const SynthesiserVoice* a, const SynthesiserVoice* b) { return a->wasStartedBefore (*b); });
|
||||||
|
|
||||||
if (! voice->isPlayingButReleased()) // Don't protect released notes
|
if (! voice->isPlayingButReleased()) // Don't protect released notes
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -266,8 +266,7 @@ struct PluginSorter
|
||||||
PluginSorter (KnownPluginList::SortMethod sortMethod, bool forwards) noexcept
|
PluginSorter (KnownPluginList::SortMethod sortMethod, bool forwards) noexcept
|
||||||
: method (sortMethod), direction (forwards ? 1 : -1) {}
|
: method (sortMethod), direction (forwards ? 1 : -1) {}
|
||||||
|
|
||||||
int compareElements (const PluginDescription* const first,
|
bool operator() (const PluginDescription* first, const PluginDescription* second) const
|
||||||
const PluginDescription* const second) const
|
|
||||||
{
|
{
|
||||||
int diff = 0;
|
int diff = 0;
|
||||||
|
|
||||||
|
|
@ -284,7 +283,7 @@ struct PluginSorter
|
||||||
if (diff == 0)
|
if (diff == 0)
|
||||||
diff = first->name.compareNatural (second->name, true);
|
diff = first->name.compareNatural (second->name, true);
|
||||||
|
|
||||||
return diff * direction;
|
return diff * direction < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -301,10 +300,8 @@ private:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const KnownPluginList::SortMethod method;
|
KnownPluginList::SortMethod method;
|
||||||
const int direction;
|
int direction;
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE (PluginSorter)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void KnownPluginList::sort (const SortMethod method, bool forwards)
|
void KnownPluginList::sort (const SortMethod method, bool forwards)
|
||||||
|
|
@ -317,10 +314,7 @@ void KnownPluginList::sort (const SortMethod method, bool forwards)
|
||||||
ScopedLock lock (typesArrayLock);
|
ScopedLock lock (typesArrayLock);
|
||||||
|
|
||||||
oldOrder.addArray (types);
|
oldOrder.addArray (types);
|
||||||
|
std::stable_sort (types.begin(), types.end(), PluginSorter (method, forwards));
|
||||||
PluginSorter sorter (method, forwards);
|
|
||||||
types.sort (sorter, true);
|
|
||||||
|
|
||||||
newOrder.addArray (types);
|
newOrder.addArray (types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -531,12 +525,11 @@ KnownPluginList::PluginTree* KnownPluginList::createTree (const SortMethod sortM
|
||||||
|
|
||||||
{
|
{
|
||||||
ScopedLock lock (typesArrayLock);
|
ScopedLock lock (typesArrayLock);
|
||||||
PluginSorter sorter (sortMethod, true);
|
sorted.addArray (types);
|
||||||
|
|
||||||
for (auto* t : types)
|
|
||||||
sorted.addSorted (sorter, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::stable_sort (sorted.begin(), sorted.end(), PluginSorter (sortMethod, true));
|
||||||
|
|
||||||
auto* tree = new PluginTree();
|
auto* tree = new PluginTree();
|
||||||
|
|
||||||
if (sortMethod == sortByCategory || sortMethod == sortByManufacturer || sortMethod == sortByFormat)
|
if (sortMethod == sortByCategory || sortMethod == sortByManufacturer || sortMethod == sortByFormat)
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ void StringArray::clearQuick()
|
||||||
strings.clearQuick();
|
strings.clearQuick();
|
||||||
}
|
}
|
||||||
|
|
||||||
const String& StringArray::operator[] (const int index) const noexcept
|
const String& StringArray::operator[] (int index) const noexcept
|
||||||
{
|
{
|
||||||
if (isPositiveAndBelow (index, strings.size()))
|
if (isPositiveAndBelow (index, strings.size()))
|
||||||
return strings.getReference (index);
|
return strings.getReference (index);
|
||||||
|
|
@ -128,7 +128,7 @@ const String& StringArray::operator[] (const int index) const noexcept
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
String& StringArray::getReference (const int index) noexcept
|
String& StringArray::getReference (int index) noexcept
|
||||||
{
|
{
|
||||||
return strings.getReference (index);
|
return strings.getReference (index);
|
||||||
}
|
}
|
||||||
|
|
@ -143,12 +143,12 @@ void StringArray::add (String&& stringToAdd)
|
||||||
strings.add (static_cast<String&&> (stringToAdd));
|
strings.add (static_cast<String&&> (stringToAdd));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringArray::insert (const int index, const String& newString)
|
void StringArray::insert (int index, const String& newString)
|
||||||
{
|
{
|
||||||
strings.insert (index, newString);
|
strings.insert (index, newString);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringArray::addIfNotAlreadyThere (const String& newString, const bool ignoreCase)
|
bool StringArray::addIfNotAlreadyThere (const String& newString, bool ignoreCase)
|
||||||
{
|
{
|
||||||
if (contains (newString, ignoreCase))
|
if (contains (newString, ignoreCase))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -172,23 +172,23 @@ void StringArray::addArray (const StringArray& otherArray, int startIndex, int n
|
||||||
strings.add (otherArray.strings.getReference (startIndex++));
|
strings.add (otherArray.strings.getReference (startIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringArray::mergeArray (const StringArray& otherArray, const bool ignoreCase)
|
void StringArray::mergeArray (const StringArray& otherArray, bool ignoreCase)
|
||||||
{
|
{
|
||||||
for (auto& s : otherArray)
|
for (auto& s : otherArray)
|
||||||
addIfNotAlreadyThere (s, ignoreCase);
|
addIfNotAlreadyThere (s, ignoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringArray::set (const int index, const String& newString)
|
void StringArray::set (int index, const String& newString)
|
||||||
{
|
{
|
||||||
strings.set (index, newString);
|
strings.set (index, newString);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringArray::contains (StringRef stringToLookFor, const bool ignoreCase) const
|
bool StringArray::contains (StringRef stringToLookFor, bool ignoreCase) const
|
||||||
{
|
{
|
||||||
return indexOf (stringToLookFor, ignoreCase) >= 0;
|
return indexOf (stringToLookFor, ignoreCase) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int StringArray::indexOf (StringRef stringToLookFor, const bool ignoreCase, int i) const
|
int StringArray::indexOf (StringRef stringToLookFor, bool ignoreCase, int i) const
|
||||||
{
|
{
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
@ -211,7 +211,7 @@ int StringArray::indexOf (StringRef stringToLookFor, const bool ignoreCase, int
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringArray::move (const int currentIndex, const int newIndex) noexcept
|
void StringArray::move (int currentIndex, int newIndex) noexcept
|
||||||
{
|
{
|
||||||
strings.move (currentIndex, newIndex);
|
strings.move (currentIndex, newIndex);
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +222,7 @@ void StringArray::remove (int index)
|
||||||
strings.remove (index);
|
strings.remove (index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringArray::removeString (StringRef stringToRemove, const bool ignoreCase)
|
void StringArray::removeString (StringRef stringToRemove, bool ignoreCase)
|
||||||
{
|
{
|
||||||
if (ignoreCase)
|
if (ignoreCase)
|
||||||
{
|
{
|
||||||
|
|
@ -244,7 +244,7 @@ void StringArray::removeRange (int startIndex, int numberToRemove)
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
void StringArray::removeEmptyStrings (const bool removeWhitespaceStrings)
|
void StringArray::removeEmptyStrings (bool removeWhitespaceStrings)
|
||||||
{
|
{
|
||||||
if (removeWhitespaceStrings)
|
if (removeWhitespaceStrings)
|
||||||
{
|
{
|
||||||
|
|
@ -267,39 +267,19 @@ void StringArray::trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
struct InternalStringArrayComparator_CaseSensitive
|
void StringArray::sort (bool ignoreCase)
|
||||||
{
|
|
||||||
static int compareElements (String& s1, String& s2) noexcept { return s1.compare (s2); }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InternalStringArrayComparator_CaseInsensitive
|
|
||||||
{
|
|
||||||
static int compareElements (String& s1, String& s2) noexcept { return s1.compareIgnoreCase (s2); }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InternalStringArrayComparator_Natural
|
|
||||||
{
|
|
||||||
static int compareElements (String& s1, String& s2) noexcept { return s1.compareNatural (s2); }
|
|
||||||
};
|
|
||||||
|
|
||||||
void StringArray::sort (const bool ignoreCase)
|
|
||||||
{
|
{
|
||||||
if (ignoreCase)
|
if (ignoreCase)
|
||||||
{
|
std::sort (strings.begin(), strings.end(),
|
||||||
InternalStringArrayComparator_CaseInsensitive comp;
|
[] (const String& a, const String& b) { return a.compareIgnoreCase (b) < 0; });
|
||||||
strings.sort (comp);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
std::sort (strings.begin(), strings.end());
|
||||||
InternalStringArrayComparator_CaseSensitive comp;
|
|
||||||
strings.sort (comp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringArray::sortNatural()
|
void StringArray::sortNatural()
|
||||||
{
|
{
|
||||||
InternalStringArrayComparator_Natural comp;
|
std::sort (strings.begin(), strings.end(),
|
||||||
strings.sort (comp);
|
[] (const String& a, const String& b) { return a.compareNatural (b) < 0; });
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
@ -340,7 +320,6 @@ String StringArray::joinIntoString (StringRef separator, int start, int numberTo
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.writeNull();
|
dest.writeNull();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -426,7 +405,7 @@ StringArray StringArray::fromLines (StringRef stringToBreakUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
void StringArray::removeDuplicates (const bool ignoreCase)
|
void StringArray::removeDuplicates (bool ignoreCase)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < size() - 1; ++i)
|
for (int i = 0; i < size() - 1; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -444,8 +423,8 @@ void StringArray::removeDuplicates (const bool ignoreCase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringArray::appendNumbersToDuplicates (const bool ignoreCase,
|
void StringArray::appendNumbersToDuplicates (bool ignoreCase,
|
||||||
const bool appendNumberToFirstInstance,
|
bool appendNumberToFirstInstance,
|
||||||
CharPointer_UTF8 preNumberString,
|
CharPointer_UTF8 preNumberString,
|
||||||
CharPointer_UTF8 postNumberString)
|
CharPointer_UTF8 postNumberString)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,6 @@ struct ZipFile::ZipEntryHolder
|
||||||
entry.filename = String::fromUTF8 (buffer + 46, fileNameLen);
|
entry.filename = String::fromUTF8 (buffer + 46, fileNameLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileNameComparator
|
|
||||||
{
|
|
||||||
static int compareElements (const ZipEntryHolder* e1, const ZipEntryHolder* e2) noexcept
|
|
||||||
{
|
|
||||||
return e1->entry.filename.compare (e2->entry.filename);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static Time parseFileTime (uint32 time, uint32 date) noexcept
|
static Time parseFileTime (uint32 time, uint32 date) noexcept
|
||||||
{
|
{
|
||||||
int year = 1980 + (date >> 9);
|
int year = 1980 + (date >> 9);
|
||||||
|
|
@ -321,8 +313,8 @@ InputStream* ZipFile::createStreamForEntry (const ZipEntry& entry)
|
||||||
|
|
||||||
void ZipFile::sortEntriesByFilename()
|
void ZipFile::sortEntriesByFilename()
|
||||||
{
|
{
|
||||||
ZipEntryHolder::FileNameComparator sorter;
|
std::sort (entries.begin(), entries.end(),
|
||||||
entries.sort (sorter);
|
[] (const ZipEntryHolder* e1, const ZipEntryHolder* e2) { return e1->entry.filename < e2->entry.filename; });
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,9 @@ struct FFT::Engine
|
||||||
{
|
{
|
||||||
Engine (int priorityToUse) : enginePriority (priorityToUse)
|
Engine (int priorityToUse) : enginePriority (priorityToUse)
|
||||||
{
|
{
|
||||||
EnginePriorityComparator comparator;
|
auto& list = getEngines();
|
||||||
getEngines().addSorted (comparator, this);
|
list.add (this);
|
||||||
|
std::sort (list.begin(), list.end(), [] (Engine* a, Engine* b) { return b->enginePriority < a->enginePriority; });
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Engine() {}
|
virtual ~Engine() {}
|
||||||
|
|
@ -61,15 +62,6 @@ struct FFT::Engine
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct EnginePriorityComparator
|
|
||||||
{
|
|
||||||
static int compareElements (Engine* first, Engine* second) noexcept
|
|
||||||
{
|
|
||||||
// sort in reverse order
|
|
||||||
return DefaultElementComparator<int>::compareElements (second->enginePriority, first->enginePriority);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static Array<Engine*>& getEngines()
|
static Array<Engine*>& getEngines()
|
||||||
{
|
{
|
||||||
static Array<Engine*> engines;
|
static Array<Engine*> engines;
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,9 @@ public:
|
||||||
*/
|
*/
|
||||||
PositionedGlyph& getGlyph (int index) const noexcept;
|
PositionedGlyph& getGlyph (int index) const noexcept;
|
||||||
|
|
||||||
|
const PositionedGlyph* begin() const { return glyphs.begin(); }
|
||||||
|
const PositionedGlyph* end() const { return glyphs.end(); }
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** Clears all text from the arrangement and resets it. */
|
/** Clears all text from the arrangement and resets it. */
|
||||||
void clear();
|
void clear();
|
||||||
|
|
|
||||||
|
|
@ -217,29 +217,29 @@ private:
|
||||||
GlyphArrangement ga;
|
GlyphArrangement ga;
|
||||||
ga.addLineOfText (font, chars, 0, 0);
|
ga.addLineOfText (font, chars, 0, 0);
|
||||||
|
|
||||||
Array<float> y;
|
Array<float> yValues;
|
||||||
DefaultElementComparator<float> sorter;
|
|
||||||
|
|
||||||
for (int i = 0; i < ga.getNumGlyphs(); ++i)
|
for (auto& glyph : ga)
|
||||||
{
|
{
|
||||||
Path p;
|
Path p;
|
||||||
ga.getGlyph (i).createPath (p);
|
glyph.createPath (p);
|
||||||
Rectangle<float> bounds (p.getBounds());
|
auto bounds = p.getBounds();
|
||||||
|
|
||||||
if (! p.isEmpty())
|
if (! p.isEmpty())
|
||||||
y.addSorted (sorter, getTop ? bounds.getY() : bounds.getBottom());
|
yValues.add (getTop ? bounds.getY() : bounds.getBottom());
|
||||||
}
|
}
|
||||||
|
|
||||||
float median = y[y.size() / 2];
|
std::sort (yValues.begin(), yValues.end());
|
||||||
|
|
||||||
|
auto median = yValues[yValues.size() / 2];
|
||||||
float total = 0;
|
float total = 0;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
for (int i = 0; i < y.size(); ++i)
|
for (auto y : yValues)
|
||||||
{
|
{
|
||||||
if (std::abs (median - y.getUnchecked(i)) < 0.05f * (float) standardHeight)
|
if (std::abs (median - y) < 0.05f * (float) standardHeight)
|
||||||
{
|
{
|
||||||
total += y.getUnchecked(i);
|
total += y;
|
||||||
++num;
|
++num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -363,15 +363,14 @@ Path DrawableText::getOutlineAsPath() const
|
||||||
|
|
||||||
Path pathOfAllGlyphs;
|
Path pathOfAllGlyphs;
|
||||||
|
|
||||||
for (int i = 0; i < arr.getNumGlyphs(); ++i)
|
for (auto& glyph : arr)
|
||||||
{
|
{
|
||||||
Path gylphPath;
|
Path gylphPath;
|
||||||
arr.getGlyph (i).createPath (gylphPath);
|
glyph.createPath (gylphPath);
|
||||||
pathOfAllGlyphs.addPath (gylphPath);
|
pathOfAllGlyphs.addPath (gylphPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
pathOfAllGlyphs.applyTransform (getTextTransform (w, h)
|
pathOfAllGlyphs.applyTransform (getTextTransform (w, h).followedBy (getTransform()));
|
||||||
.followedBy (getTransform()));
|
|
||||||
|
|
||||||
return pathOfAllGlyphs;
|
return pathOfAllGlyphs;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -216,20 +216,6 @@ bool DirectoryContentsList::checkNextFile (bool& hasChanged)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileInfoComparator
|
|
||||||
{
|
|
||||||
static int compareElements (const DirectoryContentsList::FileInfo* const first,
|
|
||||||
const DirectoryContentsList::FileInfo* const second)
|
|
||||||
{
|
|
||||||
#if JUCE_WINDOWS
|
|
||||||
if (first->isDirectory != second->isDirectory)
|
|
||||||
return first->isDirectory ? -1 : 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return first->filename.compareNatural (second->filename);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool DirectoryContentsList::addFile (const File& file, const bool isDir,
|
bool DirectoryContentsList::addFile (const File& file, const bool isDir,
|
||||||
const int64 fileSize,
|
const int64 fileSize,
|
||||||
Time modTime, Time creationTime,
|
Time modTime, Time creationTime,
|
||||||
|
|
@ -254,8 +240,18 @@ bool DirectoryContentsList::addFile (const File& file, const bool isDir,
|
||||||
if (files.getUnchecked(i)->filename == info->filename)
|
if (files.getUnchecked(i)->filename == info->filename)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FileInfoComparator comp;
|
files.add (info.release());
|
||||||
files.addSorted (comp, info.release());
|
|
||||||
|
std::sort (files.begin(), files.end(), [] (const FileInfo* a, const FileInfo* b)
|
||||||
|
{
|
||||||
|
#if JUCE_WINDOWS
|
||||||
|
if (a->isDirectory != b->isDirectory)
|
||||||
|
return a->isDirectory;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return a->filename.compareNatural (b->filename) < 0;
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,41 +29,38 @@ namespace juce
|
||||||
|
|
||||||
namespace KeyboardFocusHelpers
|
namespace KeyboardFocusHelpers
|
||||||
{
|
{
|
||||||
// This will sort a set of components, so that they are ordered in terms of
|
static int getOrder (const Component* c)
|
||||||
// left-to-right and then top-to-bottom.
|
|
||||||
struct ScreenPositionComparator
|
|
||||||
{
|
{
|
||||||
static int compareElements (const Component* first, const Component* second)
|
auto order = c->getExplicitFocusOrder();
|
||||||
{
|
return order > 0 ? order : (std::numeric_limits<int>::max() / 2);
|
||||||
auto explicitOrder1 = getOrder (first);
|
}
|
||||||
auto explicitOrder2 = getOrder (second);
|
|
||||||
|
|
||||||
if (explicitOrder1 != explicitOrder2)
|
|
||||||
return explicitOrder1 - explicitOrder2;
|
|
||||||
|
|
||||||
auto yDiff = first->getY() - second->getY();
|
|
||||||
|
|
||||||
return yDiff == 0 ? first->getX() - second->getX()
|
|
||||||
: yDiff;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getOrder (const Component* c)
|
|
||||||
{
|
|
||||||
auto order = c->getExplicitFocusOrder();
|
|
||||||
return order > 0 ? order : (std::numeric_limits<int>::max() / 2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void findAllFocusableComponents (Component* parent, Array<Component*>& comps)
|
static void findAllFocusableComponents (Component* parent, Array<Component*>& comps)
|
||||||
{
|
{
|
||||||
if (parent->getNumChildComponents() != 0)
|
if (parent->getNumChildComponents() != 0)
|
||||||
{
|
{
|
||||||
Array<Component*> localComps;
|
Array<Component*> localComps;
|
||||||
ScreenPositionComparator comparator;
|
|
||||||
|
|
||||||
for (auto* c : parent->getChildren())
|
for (auto* c : parent->getChildren())
|
||||||
if (c->isVisible() && c->isEnabled())
|
if (c->isVisible() && c->isEnabled())
|
||||||
localComps.addSorted (comparator, c);
|
localComps.add (c);
|
||||||
|
|
||||||
|
// This will sort so that they are ordered in terms of left-to-right
|
||||||
|
// and then top-to-bottom.
|
||||||
|
std::stable_sort (localComps.begin(), localComps.end(),
|
||||||
|
[] (const Component* a, const Component* b)
|
||||||
|
{
|
||||||
|
auto explicitOrder1 = getOrder (a);
|
||||||
|
auto explicitOrder2 = getOrder (b);
|
||||||
|
|
||||||
|
if (explicitOrder1 != explicitOrder2)
|
||||||
|
return explicitOrder1 < explicitOrder2;
|
||||||
|
|
||||||
|
if (a->getY() != b->getY())
|
||||||
|
return a->getY() < b->getY();
|
||||||
|
|
||||||
|
return a->getX() < b->getX();
|
||||||
|
});
|
||||||
|
|
||||||
for (auto* c : localComps)
|
for (auto* c : localComps)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,8 @@ struct FlexBoxLayoutCalculation
|
||||||
for (auto& item : owner.items)
|
for (auto& item : owner.items)
|
||||||
itemStates.add (item);
|
itemStates.add (item);
|
||||||
|
|
||||||
itemStates.sort (*this, true);
|
std::stable_sort (itemStates.begin(), itemStates.end(),
|
||||||
|
[] (const ItemWithState& i1, const ItemWithState& i2) { return i1.item->order < i2.item->order; });
|
||||||
|
|
||||||
for (auto& item : itemStates)
|
for (auto& item : itemStates)
|
||||||
{
|
{
|
||||||
|
|
@ -531,11 +532,6 @@ struct FlexBoxLayoutCalculation
|
||||||
reverseWrap();
|
reverseWrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int compareElements (const ItemWithState& i1, const ItemWithState& i2) noexcept
|
|
||||||
{
|
|
||||||
return i1.item->order < i2.item->order ? -1 : (i2.item->order < i1.item->order ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void resetRowItems (const int row) noexcept
|
void resetRowItems (const int row) noexcept
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -737,7 +737,8 @@ struct Grid::AutoPlacement
|
||||||
for (auto& item : grid.items)
|
for (auto& item : grid.items)
|
||||||
sortedItems.add (&item);
|
sortedItems.add (&item);
|
||||||
|
|
||||||
sortedItems.sort (*this, true);
|
std::stable_sort (sortedItems.begin(), sortedItems.end(),
|
||||||
|
[] (const GridItem* i1, const GridItem* i2) { return i1->order < i2->order; });
|
||||||
|
|
||||||
// place fixed items first
|
// place fixed items first
|
||||||
for (auto* item : sortedItems)
|
for (auto* item : sortedItems)
|
||||||
|
|
@ -843,12 +844,6 @@ struct Grid::AutoPlacement
|
||||||
return { implicitColumnTracks, implicitRowTracks };
|
return { implicitColumnTracks, implicitRowTracks };
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
static int compareElements (const GridItem* i1, const GridItem* i2) noexcept
|
|
||||||
{
|
|
||||||
return i1->order < i2->order ? -1 : (i2->order < i1->order ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
static void applySizeForAutoTracks (juce::Array<Grid::TrackInfo>& columns,
|
static void applySizeForAutoTracks (juce::Array<Grid::TrackInfo>& columns,
|
||||||
juce::Array<Grid::TrackInfo>& rows,
|
juce::Array<Grid::TrackInfo>& rows,
|
||||||
|
|
|
||||||
|
|
@ -1302,34 +1302,6 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
struct SortByCoordinate
|
|
||||||
{
|
|
||||||
bool sortByYCoordinate;
|
|
||||||
|
|
||||||
SortByCoordinate (bool byYCoordinate) : sortByYCoordinate (byYCoordinate)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int compareElements (const ExtendedInfo* a, const ExtendedInfo* b)
|
|
||||||
{
|
|
||||||
int coordinateA, coordinateB;
|
|
||||||
|
|
||||||
if (sortByYCoordinate)
|
|
||||||
{
|
|
||||||
coordinateA = a->totalBounds.getY();
|
|
||||||
coordinateB = b->totalBounds.getY();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
coordinateA = a->totalBounds.getX();
|
|
||||||
coordinateB = b->totalBounds.getX();
|
|
||||||
}
|
|
||||||
|
|
||||||
return coordinateA - coordinateB;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
void updateScaledDisplayCoordinate (bool updateYCoordinates)
|
void updateScaledDisplayCoordinate (bool updateYCoordinates)
|
||||||
{
|
{
|
||||||
|
|
@ -1337,11 +1309,17 @@ private:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Array<ExtendedInfo*> copy;
|
Array<ExtendedInfo*> copy;
|
||||||
|
|
||||||
|
for (auto& i : infos)
|
||||||
|
copy.add (&i);
|
||||||
|
|
||||||
|
std::sort (copy.begin(), copy.end(), [updateYCoordinates] (const ExtendedInfo* a, const ExtendedInfo* b)
|
||||||
{
|
{
|
||||||
SortByCoordinate sorter (updateYCoordinates);
|
if (updateYCoordinates)
|
||||||
for (int i = 0; i < infos.size(); ++i)
|
return a->totalBounds.getY() < b->totalBounds.getY();
|
||||||
copy.addSorted (sorter, &infos.getReference (i));
|
|
||||||
}
|
return a->totalBounds.getX() < b->totalBounds.getX();
|
||||||
|
});
|
||||||
|
|
||||||
for (int i = 1; i < copy.size(); ++i)
|
for (int i = 1; i < copy.size(); ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -1351,13 +1329,14 @@ private:
|
||||||
for (int j = i - 1; j >= 0; --j)
|
for (int j = i - 1; j >= 0; --j)
|
||||||
{
|
{
|
||||||
auto& other = *copy[j];
|
auto& other = *copy[j];
|
||||||
int prevCoordinate = updateYCoordinates ? other.totalBounds.getBottom() : other.totalBounds.getRight();
|
auto prevCoordinate = updateYCoordinates ? other.totalBounds.getBottom() : other.totalBounds.getRight();
|
||||||
int curCoordinate = updateYCoordinates ? current.totalBounds.getY() : current.totalBounds.getX();
|
auto curCoordinate = updateYCoordinates ? current.totalBounds.getY() : current.totalBounds.getX();
|
||||||
|
|
||||||
if (prevCoordinate == curCoordinate)
|
if (prevCoordinate == curCoordinate)
|
||||||
{
|
{
|
||||||
// both displays are aligned! As "other" comes before "current" in the array, it must already
|
// both displays are aligned! As "other" comes before "current" in the array, it must already
|
||||||
// have a valid topLeftScaled which we can use
|
// have a valid topLeftScaled which we can use
|
||||||
Point<int> topLeftScaled = other.topLeftScaled;
|
auto topLeftScaled = other.topLeftScaled;
|
||||||
topLeftScaled += Point<int> (other.totalBounds.getWidth(), other.totalBounds.getHeight()) / other.scale;
|
topLeftScaled += Point<int> (other.totalBounds.getWidth(), other.totalBounds.getHeight()) / other.scale;
|
||||||
|
|
||||||
if (updateYCoordinates)
|
if (updateYCoordinates)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue