private void FillTreeView()
{
var nodeList = new List<TreeNode>();
var mpqFileSystem = fileSystem as MpqFileSystem;
var wowFileSystem = fileSystem as WoWMpqFileSystem;
if (mpqFileSystem == null && wowFileSystem == null) throw new InvalidOperationException();
int archiveCount = mpqFileSystem != null ? mpqFileSystem.Archives.Count : wowFileSystem.Archives.Count;
for (int i = 0; i < archiveCount; i++)
{
var archive = mpqFileSystem != null ? mpqFileSystem.Archives[i] : wowFileSystem.Archives[i].Archive;
var archiveKind = wowFileSystem != null ? wowFileSystem.Archives[i].Kind : WoWArchiveKind.Regular;
foreach (var file in archive.Files)
{
if (file.Name != null && file.Name.Length > 0 && (file.Flags & MpqFileFlags.Deleted) == 0)
{
if (archiveCount > 1 && file.Name == "(listfile)") continue;
string[] parts = file.Name.Split('\\');
string assembledPath = "";
TreeNode currentNode = null;
bool isGlobalPatch = (archiveKind & WoWArchiveKind.Global) == WoWArchiveKind.Global;
if (isGlobalPatch && parts[0] != "base" && parts[0] != wowFileSystem.Locale) continue;
for (int j = isGlobalPatch ? 1 : 0; j < parts.Length; j++)
{
string part = parts[j];
TreeNode newNode;
if (assembledPath.Length == 0)
assembledPath = part.ToUpperInvariant();
else
// Since MPQ file names are not case-sensitive,
// we can sort the files case-insensitively
assembledPath += '\\' + part.ToUpperInvariant();
if (nodeDictionnary.TryGetValue(assembledPath, out newNode))
{
string nodeText = newNode.Text;
// This code is for detecting case differences between the two names
if (nodeText[0] != part[0] || nodeText[1] != part[1])
{
// If we detect a difference, we try to choose the best one, which probably is not the one ALL IN CAPS
if (nodeText[1] == char.ToUpperInvariant(nodeText[1])) // If second character is capitalized, assume the name is capitalized
newNode.Text = part;
}
currentNode = newNode;
}
else
{
newNode = new TreeNode(part);
newNode.ContextMenuStrip = fileContextMenuStrip;
if (j == parts.Length - 1)
{
newNode.Tag = file;
}
else
{
newNode.ImageIndex = 1;
newNode.SelectedImageIndex = 2;
//newNode.Tag = false;
newNode.Tag = new List<TreeNode>();
}
if (currentNode == null)
{
nodeList.Add(newNode);
}
else
{
//currentNode.Nodes.Add(newNode);
(currentNode.Tag as List<TreeNode>).Add(newNode);
}
nodeDictionnary.Add(assembledPath, newNode);
currentNode = newNode;
}
}
}
}
}
// Sort top-level nodes alphabetically before adding them to the treeview
SortNodeList(nodeList);
Application.DoEvents();
// Add all the nodes in a single pass, avoiding any bottlenecks caused by repeated Win32 interop
treeView.BeginUpdate();
treeView.Nodes.AddRange(nodeList.ToArray());
treeView.EndUpdate();
Application.DoEvents();
// Garbage collection after this memory-intensive operation
GC.Collect();
}