mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
FileTreeComponent: Order items according to OS specific rules
This makes the ordering consistent with other view modes of the
FileBrowserComponent and restores the behaviour prior to a400d3ebe0.
This commit is contained in:
parent
587e07007d
commit
c79ca4e815
1 changed files with 178 additions and 6 deletions
|
|
@ -26,6 +26,56 @@
|
|||
namespace juce
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
int threeWayCompare (const T& a, const T& b)
|
||||
{
|
||||
if (a < b) return -1;
|
||||
if (b < a) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int threeWayCompare (const String& a, const String& b);
|
||||
int threeWayCompare (const String& a, const String& b)
|
||||
{
|
||||
return a.compare (b);
|
||||
}
|
||||
|
||||
struct ReverseCompareString
|
||||
{
|
||||
String value;
|
||||
};
|
||||
|
||||
int threeWayCompare (const ReverseCompareString& a, const ReverseCompareString& b);
|
||||
int threeWayCompare (const ReverseCompareString& a, const ReverseCompareString& b)
|
||||
{
|
||||
return b.value.compare (a.value);
|
||||
}
|
||||
|
||||
template <size_t position, typename... Ts>
|
||||
constexpr int threeWayCompareImpl (const std::tuple<Ts...>& a, const std::tuple<Ts...>& b)
|
||||
{
|
||||
if constexpr (position == sizeof... (Ts))
|
||||
{
|
||||
ignoreUnused (a, b);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto head = threeWayCompare (std::get<position> (a), std::get<position> (b));
|
||||
|
||||
if (head != 0)
|
||||
return head;
|
||||
|
||||
return threeWayCompareImpl<position + 1> (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
constexpr int threeWayCompare (const std::tuple<Ts...>& a, const std::tuple<Ts...>& b)
|
||||
{
|
||||
return threeWayCompareImpl<0> (a, b);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class FileListTreeItem : public TreeViewItem,
|
||||
private TimeSliceClient,
|
||||
|
|
@ -255,6 +305,56 @@ private:
|
|||
std::map<File, DirectoryContentsList> contentsLists;
|
||||
};
|
||||
|
||||
struct FileEntry
|
||||
{
|
||||
String path;
|
||||
bool isDirectory;
|
||||
|
||||
int compareWindows (const FileEntry& other) const
|
||||
{
|
||||
const auto toTuple = [] (const auto& x) { return std::tuple (! x.isDirectory, x.path.toLowerCase()); };
|
||||
return threeWayCompare (toTuple (*this), toTuple (other));
|
||||
}
|
||||
|
||||
int compareLinux (const FileEntry& other) const
|
||||
{
|
||||
const auto toTuple = [] (const auto& x) { return std::tuple (x.path.toUpperCase(), ReverseCompareString { x.path }); };
|
||||
return threeWayCompare (toTuple (*this), toTuple (other));
|
||||
}
|
||||
|
||||
int compareDefault (const FileEntry& other) const
|
||||
{
|
||||
return threeWayCompare (path.toLowerCase(), other.path.toLowerCase());
|
||||
}
|
||||
};
|
||||
|
||||
class OSDependentFileComparisonRules
|
||||
{
|
||||
public:
|
||||
explicit OSDependentFileComparisonRules (SystemStats::OperatingSystemType systemTypeIn)
|
||||
: systemType (systemTypeIn)
|
||||
{}
|
||||
|
||||
int compare (const FileEntry& first, const FileEntry& second) const
|
||||
{
|
||||
if ((systemType & SystemStats::OperatingSystemType::Windows) != 0)
|
||||
return first.compareWindows (second);
|
||||
|
||||
if ((systemType & SystemStats::OperatingSystemType::Linux) != 0)
|
||||
return first.compareLinux (second);
|
||||
|
||||
return first.compareDefault (second);
|
||||
}
|
||||
|
||||
bool operator() (const FileEntry& first, const FileEntry& second) const
|
||||
{
|
||||
return compare (first, second) < 0;
|
||||
}
|
||||
|
||||
private:
|
||||
SystemStats::OperatingSystemType systemType;
|
||||
};
|
||||
|
||||
class FileTreeComponent::Controller : private DirectoryScanner::Listener
|
||||
{
|
||||
public:
|
||||
|
|
@ -373,6 +473,10 @@ private:
|
|||
|
||||
struct Comparator
|
||||
{
|
||||
// The different OSes compare and order files in different ways. This function aims
|
||||
// to match these different rules of comparison to mimic other FileBrowserComponent
|
||||
// view modes where we don't need to order the results, and can just rely on the
|
||||
// ordering of the list provided by the OS.
|
||||
static int compareElements (TreeViewItem* first, TreeViewItem* second)
|
||||
{
|
||||
auto* item1 = dynamic_cast<FileListTreeItem*> (first);
|
||||
|
|
@ -381,13 +485,10 @@ private:
|
|||
if (item1 == nullptr || item2 == nullptr)
|
||||
return 0;
|
||||
|
||||
if (item1->file < item2->file)
|
||||
return -1;
|
||||
static const OSDependentFileComparisonRules comparisonRules { SystemStats::getOperatingSystemType() };
|
||||
|
||||
if (item1->file > item2->file)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return comparisonRules.compare ({ item1->file.getFullPathName(), item1->file.isDirectory() },
|
||||
{ item2->file.getFullPathName(), item2->file.isDirectory() });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -506,4 +607,75 @@ void FileTreeComponent::setItemHeight (int newHeight)
|
|||
}
|
||||
}
|
||||
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
class FileTreeComponentTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
FileTreeComponentTests() : UnitTest ("FileTreeComponentTests", UnitTestCategories::gui) {}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
const auto checkOrder = [] (const auto& orderedFiles, const std::vector<String>& expected)
|
||||
{
|
||||
return std::equal (orderedFiles.begin(), orderedFiles.end(),
|
||||
expected.begin(), expected.end(),
|
||||
[] (const auto& entry, const auto& expectedPath) { return entry.path == expectedPath; });
|
||||
};
|
||||
|
||||
const auto doSort = [] (const auto platform, auto& range)
|
||||
{
|
||||
std::sort (range.begin(), range.end(), OSDependentFileComparisonRules { platform });
|
||||
};
|
||||
|
||||
beginTest ("Test Linux filename ordering");
|
||||
{
|
||||
std::vector<FileEntry> filesToOrder { { "_test", false },
|
||||
{ "Atest", false },
|
||||
{ "atest", false } };
|
||||
|
||||
doSort (SystemStats::OperatingSystemType::Linux, filesToOrder);
|
||||
|
||||
expect (checkOrder (filesToOrder, { "atest", "Atest", "_test" }));
|
||||
}
|
||||
|
||||
beginTest ("Test Windows filename ordering");
|
||||
{
|
||||
std::vector<FileEntry> filesToOrder { { "cmake_install.cmake", false },
|
||||
{ "CMakeFiles", true },
|
||||
{ "JUCEConfig.cmake", false },
|
||||
{ "tools", true },
|
||||
{ "cmakefiles.cmake", false } };
|
||||
|
||||
doSort (SystemStats::OperatingSystemType::Windows, filesToOrder);
|
||||
|
||||
expect (checkOrder (filesToOrder, { "CMakeFiles",
|
||||
"tools",
|
||||
"cmake_install.cmake",
|
||||
"cmakefiles.cmake",
|
||||
"JUCEConfig.cmake" }));
|
||||
}
|
||||
|
||||
beginTest ("Test MacOS filename ordering");
|
||||
{
|
||||
std::vector<FileEntry> filesToOrder { { "cmake_install.cmake", false },
|
||||
{ "CMakeFiles", true },
|
||||
{ "tools", true },
|
||||
{ "JUCEConfig.cmake", false } };
|
||||
|
||||
doSort (SystemStats::OperatingSystemType::MacOSX, filesToOrder);
|
||||
|
||||
expect (checkOrder (filesToOrder, { "cmake_install.cmake",
|
||||
"CMakeFiles",
|
||||
"JUCEConfig.cmake",
|
||||
"tools" }));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static FileTreeComponentTests fileTreeComponentTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue